Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto band functionality #22

Merged
merged 8 commits into from
May 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ There are several features that can be added to the rig if you want to. This is
done by adding and removing `#define` lines to `settings.h`.

- `OPT_BAND_SELECT`: change the band by pressing RIT for 2s.
- `OPT_AUTO_BAND`: auto-select bands using a PCA9536 PIO (thanks VK3IL).
- `OPT_ERASE_EEPROM`: erase the EEPROM by holding RIT for 8s.
- `OPT_STORE_CW_SPEED`: store the CW speed in EEPROM.
- `OPT_DFE`: direct frequency entry by holding the encoder button for 1s.
Expand Down Expand Up @@ -209,6 +210,8 @@ Some images of the connections:

## Changelog

- 2017-05-16:
- `OPT_AUTO_BAND` (PR [#22](/../../pull/22) by VK3IL)
- 2017-05-12:
- VK band plans (PR [#21](/../../pull/21) by VK3IL)
- 2017-05-04:
Expand Down
5 changes: 5 additions & 0 deletions SODA_POP/SODA_POP.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ byte memory_index_character;
#define EEPROM_CW_SPEED 7 // 1 byte
#endif

#ifdef OPT_AUTO_BAND
#define PCA9536_BUS_ADDR 0x41 // I2C address for PCA9536
#undef OPT_BAND_SELECT
#endif

#endif

// vim: tabstop=2 shiftwidth=2 expandtab:
94 changes: 89 additions & 5 deletions SODA_POP/SODA_POP.ino
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ Si5351 si5351;
#define IF_DEFAULT 491480000

byte memory_pointer;
byte errno; // Global error number for S_ERROR

const int MUTE = A3;
const int TXEN = 13; // production A0
Expand Down Expand Up @@ -142,11 +143,18 @@ void setup()
TIMSK1 |= 1 << OCIE1A;
interrupts();

#ifdef OPT_AUTO_BAND
state.state = EEPROM.read(6) == 0xff ? S_CALIBRATION_CORRECTION : S_DEFAULT;
read_module_band();
#else
state.band = (enum band) EEPROM.read(6); // check for operating band
if (state.band == BAND_UNKNOWN) {
state.band = (enum band) 0;
state.state = S_CALIBRATION_CORRECTION;
} else {
state.state = S_DEFAULT;
}
#endif

fetch_calibration_data(); //load calibration data
si5351.set_correction(cal_value); //correct the clock chip error
Expand All @@ -155,7 +163,6 @@ void setup()
invalidate_display();
delay(1000);

state.state = S_DEFAULT;
invalidate_display();
digitalWrite(MUTE, LOW);

Expand Down Expand Up @@ -194,7 +201,7 @@ void loop()
case S_CALIBRATION_PEAK_RX: loop_calibration_peak_rx(); break;
case S_ERROR: loop_error(); break;
default:
error();
error(1);
break;
}

Expand Down Expand Up @@ -237,6 +244,11 @@ void loop_default()
state.idle_for = DISABLE_DISPLAY_AFTER - 500;
#endif

#ifdef OPT_AUTO_BAND
if (tcount % 5000 == 0) // Check the band module for changes every 5s
read_module_band();
#endif

if (key_active()) {
state.state = S_KEYING;
// Tuning with the rotary encoder
Expand Down Expand Up @@ -795,8 +807,12 @@ void loop_calibration_peak_if()
EEPROM.write(EEPROM_IF_FREQ + 1, state.op_freq >> 8);
EEPROM.write(EEPROM_IF_FREQ + 2, state.op_freq >> 16);
EEPROM.write(EEPROM_IF_FREQ + 3, state.op_freq >> 24);

#ifdef OPT_AUTO_BAND
EEPROM.write(6, 0); // Reset the "not calibrated" flag now that we've written the cal values
state.state = S_CALIBRATION_PEAK_RX;
#else
state.state = S_CALIBRATION_CHANGE_BAND;
#endif
invalidate_frequencies();
invalidate_display();

Expand Down Expand Up @@ -865,7 +881,7 @@ void key_handle_end()
state.state = S_DEFAULT;
} else if (state.state == S_MEM_ENTER) {
if (memory_pointer == MEMORY_LENGTH) {
error();
error(2);
return;
}
buffer[memory_pointer++] = morse_char;
Expand Down Expand Up @@ -1089,10 +1105,78 @@ void ee_erase()
* Enter the error state. This error is non-recoverable and should only be used
* in very rare cases.
*/
void error()
void error(byte er)
{
errno = er;
state.state = S_ERROR;
}

#ifdef OPT_AUTO_BAND
/*
* Read the input latch of the PCA9536 and return a 4-bit value
* If the band module can't be read or the value is out of range, display an error and wait for a valid band module
*/
byte PCA9536_read()
{
for (boolean err = true; err; err = false) {
Wire.beginTransmission(PCA9536_BUS_ADDR);
Wire.write(byte(0x00)); // We read only from register 0, the input latch
Wire.endTransmission(false); // Transmit repeated start rather than stop at end of transmission
Wire.requestFrom(PCA9536_BUS_ADDR, 1);
if (Wire.available() != 1) { // Unable to read the band module ID (most
// likely it's not plugged in properly, or being changed!)
err = true;
} else {
byte reg_val = Wire.read() & 0x0f;
if(reg_val < 2 || reg_val > 11) // Module has an un-supported configuration
err = true;
}
if (err) {
state.display.digits[3] = LED_N_6;
state.display.digits[2] = LED_n;
state.display.digits[1] = LED_E;
state.display.digits[0] = LED_r;
state.display.dots = 0x0;
delay(500);
}
}
invalidate_display();
return reg_val;
}

/*
* Check if the band module has changed and if it has, reset bandlimits and operating frequency
*/
void read_module_band()
{
enum band new_band;

switch (PCA9536_read()) { // Map returned value to current band table range
case 2: new_band = BAND_160; break;
case 3: new_band = BAND_80; break;
#ifdef BAND_60
case 4: new_band = BAND_60; break;
#endif
case 5: new_band = BAND_40; break;
case 6: new_band = BAND_30; break;
case 7: new_band = BAND_20; break;
case 8: new_band = BAND_17; break;
case 9: new_band = BAND_15; break;
case 10: new_band = BAND_12; break;
case 11: new_band = BAND_10; break;
default: new_band = BAND_UNKNOWN; error(3); break;
}

if (new_band != state.band) {
digitalWrite(MUTE, LOW); // Make sure we are in receive mode
state.band = new_band;
setup_band(); // Set the band limits and default
// operating frequency for the selected band
display_band();
delay(2000); // Allow time to view the band on the display
invalidate_display();
}
}
#endif

// vim: tabstop=2 shiftwidth=2 expandtab:
2 changes: 1 addition & 1 deletion SODA_POP/buttons.ino
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ unsigned int time_encoder_button()
}

/**
* Debounche the keyer button.
* Debounce the keyer button.
*/
void debounce_keyer()
{
Expand Down
4 changes: 2 additions & 2 deletions SODA_POP/display.ino
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ void invalidate_display()
case S_ERROR:
state.display.digits[3] = LED_E;
state.display.digits[2] = LED_r;
state.display.digits[1] = LED_r;
state.display.digits[0] = 0x00;
state.display.digits[0] = LED_DIGITS[errno / 10];
state.display.digits[0] = LED_DIGITS[errno % 10];
state.display.dots = 0x2;
break;
}
Expand Down
5 changes: 4 additions & 1 deletion SODA_POP/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
/* Band selection by pressing RIT for 2s */
#define OPT_BAND_SELECT

/* Autoband selection based on plugged in module with PCA9536 PIO */
//#define OPT_AUTO_BAND

/* Erase EEPROM by pressing RIT for 8s */
#define OPT_ERASE_EEPROM

Expand All @@ -48,7 +51,7 @@
#define OPT_DFE

/* Disable display when idle */
#define OPT_DISABLE_DISPLAY
//#define OPT_DISABLE_DISPLAY
#define DISABLE_DISPLAY_AFTER 2500 /* Time to disable display after, in ms */

/* More message memories. Select using the rotary encoder. */
Expand Down