I never created the interrupt, it was a part of the original code. I know it was pretty amateur to mix up the input pins but I am very familiar with buttons. The other radio runs a series of relays, cooling fans, etc. and that was no problem to program. I'm just struggling to understand parts of the code since the chip has a specific sequence to communicate with the Arduino. I didn't post the most recent code because of the length but if it helps here is everything that I have so far. Also just a side note that I'm using a flip dot display instead of an LCD.Just curious? Why are you using an interrupt?
Have you read the Arduino reference pages on interrupts?
And it’s not clear to me what the original key press code was and what you replaced it with.
Did you find the buttonPress sample code and understand what it does? Walk before you can run. If you don’t understand the basic concepts (including debouncing), then no one here can explain it to you.
BTW, your last comment implied that we haven’t seen your latest code. Isn’t it then reasonable to assume we have no chance to fix something we’ve never seen?
- Teach yourself the basics by reading the sample code and running it on your Arduino. Otherwise, you won’t be able to understand what we’re telling you
- Take small steps. Get one button working Toggle an LED with a button
- Add buttons, one by one until they work with a test program
- Learn what switch bounce us and write a couple of sketches, One without debouncing that counts the number of times a switch input toggled from high to low you might be surprised! The second switch uses the BOUNCE2 library. Count the number of times s switch input changed state with the bounce functions
- By the time you’ve done this, you’ll know what’s wrong with this program.
Code:
#include <Wire.h> // for the Arduino wire library (I2C)
// chip I2C address is hard coded
#define Si_ADDRESS 0x11
// Si Commands in their nomenclature
#define ATDD_POWER_DOWN 0x11
#define ATDD_POWER_UP 0xE1
#define ATDD_XOWAIT 0x40
#define SET_PROPERTY 0x12
#define RX_VOLUME 0x40
#define ATDD_GET_STATUS 0xE0
// Globals
//input pins
const int FM_Input = 3;
const int AM_Input = 4;
const int SW_Input = 5;
int bandsetting = 0;
int FM_Mode;
int AM_Mode;
int SW_Mode;
// Arduino Pins D2=IRQ D12=reset
const byte INTpin = 2;
const byte RESETpin = 12;
// for the ISR
volatile byte IRQflag;
// Default bands within FM/AM/SW - the band we start with when switching modes
byte d_FM_band = 8;
byte d_AM_band = 22;
byte d_SW_band = 31;
byte status_rsp[4]; // holds response bytes following commands
byte current_band = 0; // 0=FM 1-AM 2=SW if there has been no power down we will start with 0
byte current_bandix; // current band index
byte current_vol = 50; // default boot up value is 63
byte current_BT = 4; // default boot up value is 4 or 3 FM/AM
byte power_mode = 1; // denotes if we are in power down mode (1=power on 0=power off (powered down))
byte mute_mode = 0; // denotes mute mode (1=on 0=off)
char buf2[3]; // for itoa conversion up to two characters
int d1, d2, d3, d4; // for an easy print
// Band Range strings to make display easy and fast
char * BandRange[] = {" 87-108 ", " 87-108 ", " 87-108 ", " 87-108 ", " 86.5-109 ", " 86.5-109 ", " 86.5-109 ", " 86.5-109 ",
"87.3-108.25", "87.3-108.25", "87.3-108.25", "87.3-108.25", " 76-90 ", " 76-90 ", " 76-90 ", " 76-90 ", " 64-87 ", " 64-87 ",
" 64-87 ", " 64-87 ", " 520-1710 ", " 522-1620 ", " 504-1665 ", " 520-1730 ", " 510-1750 ", " 5.6-6.4 ", " 5.95-6.2 ", " 6.8-7.6 ",
" 7.1-7.6 ", " 9.2-10 ", " 9.2-9.9 ", "11.45-12.25", " 11.6-12.2 ", " 13.4-14.2 ", "13.57-13.87", " 15-15.9 ", " 15.1-15.8 ", " 17.1-18 ",
" 17.48-17.9", " 21.2-22 ", "21.45-21.85"
};
// flip dots control pin
int txden = 8;
byte data_prefix[] = {0x80, 0x83, 0xFF};
byte data_suffix[] = {0x8F};
// numbers font
byte zero[] = {B0011100, B0100010, B0100010, B0011100};
byte one[] = {B0111110, B0000000, B0000000, B0000000};
byte two[] = {B0010010, B0101010, B0100110, B0010010};
byte three[] = {B0010100, B0101010, B0101010, B0100010};
byte four[] = {B0000100, B0111110, B0010100, B0001100};
byte five[] = {B0000100, B0101010, B0101010, B0111010};
byte six[] = {B0000100, B0101010, B0101010, B0011100};
byte seven[] = {B0110000, B0101000, B0100110, B0100000};
byte eight[] = {B0010100, B0101010, B0101010, B0010100};
byte nine[] = {B0011100, B0101010, B0101010, B0010000};
// first digit
byte side_one[] = {B0000000, B0111110, B0000000};
byte side_zero[] = {B0000000, B0000000, B0000000};
// blank space
byte space[] = {B0000000};
byte black[] = {B1111111};
byte dot[] = {B0000010};
// 28 byte data
byte built_by[] = {B0000000,
B0111000, B001110, B0111000, //Y
B0000000,
B0110110, B0101010, B0111110, //B
B0000000,
B0000000,
B0100000, B0111110, B0100000, //T
B0000000,
B0000010, B000010, B0111110, //L
B0000000,
B0111110, //I
B0000000,
B0111110, B0000010, B0111110, //U
B0000000,
B0110110, B0101010, B0111110, //B
B0000000
};
byte Trey_A[] = {B0000000,
B0000000,
B0000000,
B0000000,
B0000000,
B0000010,
B0000000,
B0011110, B0101000, B0011110, // A
B000000,
B0000000,
B0111000, B001110, B0111000, //Y
B0000000,
B0100010, B0101010, B0111110, //E
B0000000,
B0110110, B0101000, B0111110, //R
B0000000,
B0100000, B0111110, B0100000, //T
B0000000
};
byte AM[] = {B0000000,
B0000000,
B0000000,
B0000000,
B0000010,
B0000000,
B0000000,
B0000000,
B0000010,
B0000000,
B0111110, B0010000, B0111110, // M
B000000,
B0000000,
B0011110, B0101000, B0011110, // A
B0000000,
B0000000,
B0000000,
B0000010,
B0000000,
B0000000,
B0000000,
B0000010,
B0000000,
B0000000
};
byte FM[] = {B0000000,
B0000000,
B0000000,
B0000000,
B0000010,
B0000000,
B0000000,
B0000000,
B0000010,
B0000000,
B0111110, B0010000, B0111110, // M
B000000,
B0000000,
B0100000, B0101000, B0111110, // F
B0000000,
B0000000,
B0000000,
B0000010,
B0000000,
B0000000,
B0000000,
B0000010,
B0000000,
B0000000
};
byte SW[] = {B0000000,
B0000000,
B0000000,
B0000000,
B0000010,
B0000000,
B0000000,
B0000000,
B0000010,
B0000000,
B0111110, B0000100, B0111110, // W
B000000,
B0000000,
B0101110, B0101010, B0111010, // S
B0000000,
B0000000,
B0000000,
B0000010,
B0000000,
B0000000,
B0000000,
B0000010,
B0000000,
B0000000
};
void setup() {
Serial.begin(57600);
pinMode (INTpin, INPUT);
pinMode(RESETpin, OUTPUT);
digitalWrite(RESETpin, HIGH);
attachInterrupt(0, SiISR, RISING);
SiReset();
current_bandix = d_FM_band;
SiSetBand();
get_status();
current_band = (status_rsp[1] >> 6);
current_bandix = (status_rsp[1] & B00111111);
//display_frequency();
go_current(); // will set up for default VOL
//input selector
pinMode(FM_Input, INPUT);
pinMode(AM_Input, INPUT);
pinMode(SW_Input, INPUT);
//flip dots
pinMode(txden, OUTPUT);
digitalWrite(txden, HIGH); // master
//Display author name
Serial.write(data_prefix, 3);
Serial.write(built_by, 28);
Serial.write(data_suffix, 1);
delay(4000);
Serial.write(data_prefix, 3);
Serial.write(Trey_A, 28);
Serial.write(data_suffix, 1);
delay(40000);
}
void loop() {
// Check for tuning changes and keypresses
if (IRQflag)
{
Wire.beginTransmission(Si_ADDRESS);
Wire.write(ATDD_GET_STATUS);
Wire.endTransmission();
Wire.requestFrom(Si_ADDRESS, 0x04);
status_rsp[0] = Wire.read();
status_rsp[1] = Wire.read();
status_rsp[2] = Wire.read();
status_rsp[3] = Wire.read();
display_frequency();
IRQflag = 0;
}
FM_Mode = digitalRead(FM_Input);
AM_Mode = digitalRead(AM_Input);
SW_Mode = digitalRead(SW_Input);
if (FM_Mode = HIGH) {
bandsetting = 0;
}
else if (AM_Mode = HIGH) {
bandsetting = 1;
}
else if (SW_Mode = HIGH) {
bandsetting = 2;
}
if (bandsetting != current_band) {
switch (bandsetting) {
case 0:
Go_AM();
break;
case 1:
Go_FM();
break;
case 2:
Go_SW();
break;
default:
break;
}
current_band = bandsetting;
}
// Get and process a keypress when present
// if(key=keypad.getKey())
// {
// switch(key)
// {
// case '1':
// Go_AM();
// break;
// case '2':
// Go_FM();
// break;
// case '3':
// Go_SW();
// break;
// case '4':
// Vol_up();
// break;
// case '7':
// Vol_down();
// break;
// case '5':
// Band_up();
// break;
// case '8':
// Band_down();
// break;
// case '6':
// BT_up();
// break;
// case '9':
// BT_down();
// break;
// case '0':
// Mute();
// break;
// default:
// break;
// }
// }
}
void SiReset()
{
// reset Si4844 and back up
// switch I2C to 10kHz
I2C_10kHz();
IRQflag = 0;
digitalWrite(RESETpin, LOW);
delayMicroseconds(200);
digitalWrite(RESETpin, HIGH);
delayMicroseconds(200);
// wait for an IRQ rising edge
while (!IRQflag);
// wait for 2.5 ms
delayMicroseconds(2500);
}
void SiGetStatus()
{
// send a get status command and wait for 2 ms before testing response byte
Wire.beginTransmission(Si_ADDRESS);
Wire.write(ATDD_GET_STATUS);
Wire.endTransmission();
delayMicroseconds(2000);
// test response byte
Wire.requestFrom(Si_ADDRESS, 0x04);
for (int x = 0; x < 4; x++)
{
status_rsp[x] = Wire.read();
}
}
void SiSetBand()
{
// assuming CTS is ok to send, assume current_band is set
// will do a power up AND a get status setting status_rsp[0-4]
byte cb;
cb = current_bandix;
bitSet(cb, 7); // bit 7=1 for external crystal
bitClear(cb, 6); // bit 6=0 for normal crystal time
// arg[2]-[7] are not used in this mode
IRQflag = 0;
// send it
Wire.beginTransmission(Si_ADDRESS);
Wire.write(ATDD_POWER_UP);
Wire.write(cb);
Wire.endTransmission();
// wait for an IRQ for tune wheel frequency ready
delayMicroseconds(2500);
while (!IRQflag);
// wait for 2.5 ms because our IRQ is rising edge
delayMicroseconds(2500);
I2C_50kHz();
// send a get status and wait for 2 ms before testing response byte
get_status();
}
void Vol_up()
{
// we operate in the audio default Mixed Mode 2
// assume that current_vol is accurate
if (current_vol < 63)
{
current_vol++;
Wire.beginTransmission(Si_ADDRESS);
Wire.write(SET_PROPERTY);
Wire.write(0x00); // ARG1
Wire.write(RX_VOLUME); // ARG2 RX_VOLUME 0x40
Wire.write(0x00); // ARG3
Wire.write(0x00); // ARG4
Wire.write(current_vol); // ARG5 is actual volume 0-63
Wire.endTransmission();
}
}
void Vol_down()
{
// we operate in the default Mixed Mode 2
// assume that current_vol is accurate
if (current_vol > 0)
{
current_vol--;
Wire.beginTransmission(Si_ADDRESS);
Wire.write(SET_PROPERTY);
Wire.write(0x00); // ARG1
Wire.write(RX_VOLUME); // ARG2 RX_VOLUME 0x40
Wire.write(0x00); // ARG3
Wire.write(0x00); // ARG4
Wire.write(current_vol); // ARG5 is actual volume 0-63
Wire.endTransmission();
}
}
void Go_FM()
{
// switch to the FM band with the default band_idx
SiReset();
current_bandix = d_FM_band;
SiSetBand();
get_status();
// power up is completed so get the values from the chip
current_band = (status_rsp[1] >> 6);
current_bandix = (status_rsp[1] & B00111111);
display_frequency();
go_current();
}
void Go_AM()
{
// switch to the AM band with the default band_idx
SiReset();
current_bandix = d_AM_band;
SiSetBand();
// in testing the this never loops
get_status();
// power up is completed so get the values from the chip
current_band = (status_rsp[1] >> 6);
current_bandix = (status_rsp[1] & B00111111);
display_frequency();
go_current();
}
void Go_SW()
{
// switch to the SW band with the default band_idx
SiReset();
current_bandix = d_SW_band;
SiSetBand();
get_status();
// power up is completed so get the values from the chip
current_band = (status_rsp[1] >> 6);
current_bandix = (status_rsp[1] & B00111111);
display_frequency();
go_current();
}
void go_current()
{
// restore current settings when we switch AM/FM/SW
// set the Vol to whatever current_vol is
Wire.beginTransmission(Si_ADDRESS);
Wire.write(SET_PROPERTY);
Wire.write(0x00); // ARG1
Wire.write(RX_VOLUME); // ARG2 RX_VOLUME 0x40
Wire.write(0x00); // ARG3
Wire.write(0x00); // ARG4
Wire.write(current_vol); // ARG5 is actual volume 0-63
Wire.endTransmission();
}
void Band_up()
{
// increase the band index by 1
// assume current_band and current_bandix are accurate
switch (current_band)
{
case 0: // FM is 0 19
if (current_bandix < 19)
{
current_bandix++;
}
break;
case 1: // AM is 20-24
if (current_bandix < 24)
{
current_bandix++;
}
break;
case 2: // SW is 25-40
if (current_bandix < 40)
{
current_bandix++;
}
break;
default:
// error - take no action
break;
}
SiReset();
SiSetBand();
get_status();
// power up is completed so get the values from the chip
current_band = (status_rsp[1] >> 6);
current_bandix = (status_rsp[1] & B00111111);
display_frequency();
go_current();
}
void Band_down()
{
// decrease the band index by 1
// assume current_band and current_bandix are accurate
switch (current_band)
{
case 0: // FM is 0 19
if (current_bandix > 0)
{
current_bandix--;
}
break;
case 1: // AM is 20-24
if (current_bandix > 20)
{
current_bandix--;
}
break;
case 2: // SW is 25-40
if (current_bandix > 25)
{
current_bandix--;
}
break;
default:
// error - take no action
break;
}
SiReset();
SiSetBand();
get_status();
// power up is completed so get the values from the chip
current_band = (status_rsp[1] >> 6);
current_bandix = (status_rsp[1] & B00111111);
display_frequency();
go_current();
}
void get_status()
{
// do SiGetStatus until we have valid frequency info in status_rsp
// note: in testing we don't loop but it is a good practice
// also, an error out routine can be added here so it can escape
// after a certain number of attempts
Waitforgo:
SiGetStatus();
if ( ((bitRead(status_rsp[0], 4) == 0) || ( (status_rsp[2] == 0) && (status_rsp[3] == 0))) )
{
goto Waitforgo;
}
}
void display_frequency()
{
int add;
// assume that current_band AND status_rsp[2] and status_rsp[3] are accurate
// calculate the four digits and get their string equivalents for display
// If CHFREQ[15] is set in the SW band it
// indicates an add of 5 kHz to the frequency
// i.e., freq=freq+.005 mHz
// This is NOT implemented currently but is here if I
// want to do something with it at a later date
add = 0;
if ((current_band == 2) && (bitRead(status_rsp[2], 7) == 1))
{
add = 1;
bitClear(status_rsp[2], 7);
}
d1 = status_rsp[2] >> 4;
d2 = status_rsp[2] % 16;
d3 = status_rsp[3] >> 4;
d4 = status_rsp[3] % 16;
switch (current_band)
{
// FM is mhz 012.3
case 0:
Serial.write(data_prefix, 3);
Serial.write(space, 4);
displayNumber(Serial.write(d4) % 10);
Serial.write(space, 1);
Serial.write(dot, 1);
Serial.write(space, 1);
displayNumber(Serial.write(d3) % 10);
Serial.write(space, 1);
displayNumber(Serial.write(d2) % 10);
Serial.write(space, 1);
displayNumber(Serial.write(d1) % 10);
Serial.write(space, 3);
Serial.write(data_suffix, 1);
case 1:
// AM is 1234 kHz so pad a space
Serial.write(data_prefix, 3);
Serial.write(space, 5);
displayNumber(Serial.write(d4) % 10);
Serial.write(space, 1);
displayNumber(Serial.write(d3) % 10);
Serial.write(space, 1);
displayNumber(Serial.write(d2) % 10);
Serial.write(space, 1);
displayNumber(Serial.write(d1) % 10);
Serial.write(space, 4);
Serial.write(data_suffix, 1);
break;
case 2:
// SW is mHz 01.23
Serial.write(data_prefix, 3);
Serial.write(space, 4);
displayNumber(Serial.write(d4) % 10);
Serial.write(space, 1);
displayNumber(Serial.write(d3) % 10);
Serial.write(space, 1);
Serial.write(dot, 1);
Serial.write(space, 1);
displayNumber(Serial.write(d2) % 10);
Serial.write(space, 1);
displayNumber(Serial.write(d1) % 10);
Serial.write(space, 3);
Serial.write(data_suffix, 1);
break;
default:
// error
break;
}
}
void displayNumber(int n) {
switch (n) {
case 0:
Serial.write(zero, 4);
break;
case 1:
Serial.write(one, 4);
break;
case 2:
Serial.write(two, 4);
break;
case 3:
Serial.write(three, 4);
break;
case 4:
Serial.write(four, 4);
break;
case 5:
Serial.write(five, 4);
break;
case 6:
Serial.write(six, 4);
break;
case 7:
Serial.write(seven, 4);
break;
case 8:
Serial.write(eight, 4);
break;
case 9:
Serial.write(nine, 4);
break;
default:
Serial.write(zero, 4);
}
return;
}
// NOTE: These speed routines for I2C are for an 8mhz, 3.3v Pro Mini
// They need to be changed for a 16 mHz UNO or other Arduinos
void I2C_10kHz()
{
// set I2C speed to 10Khz on an 8mHz chip
TWBR = 98;
TWSR |= bit(TWPS0);
}
void I2C_50kHz()
{
// set I2C speed to 50Khz on an 8mHz chip
TWBR = 18;
TWSR |= bit(TWPS0);
}
// The interrupt service routine
void SiISR()
{
IRQflag = 1;
}


