From 54d9c85f166bb82fd9e3b7dd2ea020bf31391e16 Mon Sep 17 00:00:00 2001 From: guido Date: Fri, 27 Sep 2019 15:13:00 +0200 Subject: [PATCH] Added schematic, layout and description for T1 replacement. Added experimental menu. --- QCX-SSB.ino | 373 ++++++++++++++++++++++++++++++++------------------ README.md | 3 +- layout.png | Bin 160138 -> 162284 bytes schematic.png | Bin 301362 -> 298948 bytes 4 files changed, 238 insertions(+), 138 deletions(-) mode change 100755 => 100644 layout.png diff --git a/QCX-SSB.ino b/QCX-SSB.ino index 11d5a81..031c617 100644 --- a/QCX-SSB.ino +++ b/QCX-SSB.ino @@ -362,7 +362,7 @@ public: static SI5351 si5351; enum mode_t { LSB, USB, CW, AM, FM }; -volatile uint8_t mode = USB; +volatile int8_t mode = USB; const char* mode_label[] = { "LSB", "USB", "CW ", "AM ", "FM " }; volatile bool change = true; volatile int32_t freq = 7074000; @@ -492,6 +492,9 @@ void dsp_tx() numSamples++; } + +volatile int8_t cwdec = 0; + static int32_t signal; static int16_t avg = 0; static int16_t maxpk=0; @@ -555,7 +558,7 @@ volatile bool cw_event = false; //#define F_SAMP_RX 28409 #define F_ADC_CONV 192307 -volatile uint8_t volume = 8; +volatile int8_t volume = 8; volatile bool agc = true; volatile bool nr = false; @@ -582,7 +585,7 @@ inline int16_t process_nr(int16_t ac) return ac; } -#define JUNK 1 +//#define JUNK 1 #ifdef JUNK // Having this function included here and referenced makes sdr_rx faster 15% faster (normally including filt_cwn() in sdr_rx() makes the thing slower for an unknown reason) void junk() @@ -591,14 +594,16 @@ void junk() } #endif -volatile int8_t filt = -1; +#define N_FILT 6 +volatile int8_t filt = 0; +const char* filt_label[] = { "All", "4000", "2500", "1700", "200", "100", "50" }; inline int16_t filt_var(int16_t v) { int16_t zx0 = v; static int16_t za1,za2; - if(filt < 3){ + if(filt < 4){ // 1st Order (SR=8kHz) IIR in Direct Form I, 8x8:16 static int16_t zz1,zz2; zx0=(29*(zx0-zz1)+50*za1)/64; //300-Hz @@ -608,23 +613,22 @@ inline int16_t filt_var(int16_t v) za2=za1; za1=zx0; - #define N_FILT 6 // 4th Order (SR=8kHz) IIR in Direct Form I, 8x8:16 //static int16_t za1,za2; static int16_t zb1,zb2; switch(filt){ - case 0: break; //0-4000Hz (pass-through) - //case 1: zx0=(13*(zx0+2*za1+za2)-30*zb1-13*zb2)/64; break; //0-2500Hz 1st-order butterworth - //case 1: zx0=(12*(zx0+2*za1+za2)-26*zb1-5*zb2)/64; break; //0-2500Hz butterworth - //case 1: zx0=(12*(zx0+2*za1+za2)+2*zb1-11*zb2)/64; break; //0-2500Hz elliptic - //case 1: zx0=(10*(zx0+2*za1+za2)+7*zb1-11*zb2)/32; break; //0-2500Hz elliptic slower roll-off but deep - case 1: zx0=(10*(zx0+2*za1+za2)+16*zb1-17*zb2)/32; break; //0-2500Hz elliptic -60dB@3kHz - //case 2: zx0=(7*(zx0+2*za1+za2)+18*zb1-12*zb2)/64; break; //0-1700Hz 1st-order - //case 2: zx0=(7*(zx0+2*za1+za2)+16*zb1-3*zb2)/64; break; //0-1700Hz butterworth - case 2: zx0=(7*(zx0+2*za1+za2)+48*zb1-18*zb2)/32; break; //0-1700Hz elliptic - case 3: zx0=(5*(zx0-2*za1+za2)+105*zb1-58*zb2)/64; break; //650-840Hz - case 4: zx0=(3*(zx0-2*za1+za2)+108*zb1-61*zb2)/64; break; //650-750Hz - case 5: zx0=((2*zx0-3*za1+2*za2)+111*zb1-62*zb2)/64; break; //630-680Hz + case 1: break; //0-4000Hz (pass-through) + //case 2: zx0=(13*(zx0+2*za1+za2)-30*zb1-13*zb2)/64; break; //0-2500Hz 1st-order butterworth + //case 2: zx0=(12*(zx0+2*za1+za2)-26*zb1-5*zb2)/64; break; //0-2500Hz butterworth + //case 2: zx0=(12*(zx0+2*za1+za2)+2*zb1-11*zb2)/64; break; //0-2500Hz elliptic + //case 2: zx0=(10*(zx0+2*za1+za2)+7*zb1-11*zb2)/32; break; //0-2500Hz elliptic slower roll-off but deep + case 2: zx0=(10*(zx0+2*za1+za2)+16*zb1-17*zb2)/32; break; //0-2500Hz elliptic -60dB@3kHz + //case 3: zx0=(7*(zx0+2*za1+za2)+18*zb1-12*zb2)/64; break; //0-1700Hz 1st-order + //case 3: zx0=(7*(zx0+2*za1+za2)+16*zb1-3*zb2)/64; break; //0-1700Hz butterworth + case 3: zx0=(7*(zx0+2*za1+za2)+48*zb1-18*zb2)/32; break; //0-1700Hz elliptic + case 4: zx0=(5*(zx0-2*za1+za2)+105*zb1-58*zb2)/64; break; //650-840Hz + case 5: zx0=(3*(zx0-2*za1+za2)+108*zb1-61*zb2)/64; break; //650-750Hz + case 6: zx0=((2*zx0-3*za1+2*za2)+111*zb1-62*zb2)/64; break; //630-680Hz } //za2=za1; //za1=v; @@ -633,18 +637,18 @@ inline int16_t filt_var(int16_t v) static int16_t zc1,zc2; switch(filt){ - case 0: break; //0-4000Hz (pass-through) - //case 1: break; - //case 1: zx0=(16*(zx0+2*zb1+zb2)-36*zc1-31*zc2)/64; break; //0-2500Hz butterworth - //case 1: zx0=(8*(zx0+zb2)+13*zb1-46*zc1-48*zc2)/64; break; //0-2500Hz elliptic - //case 1: zx0=(8*(zx0+2*zb1+zb2)-46*(zc1+zc2))/64; break; //0-2500Hz elliptic slower roll-off but deep - case 1: zx0=(8*(zx0+zb2)+13*zb1-43*zc1-52*zc2)/64; break; //0-2500Hz elliptic -60dB@3kHz + case 1: break; //0-4000Hz (pass-through) //case 2: break; - //case 2: zx0=(16*(zx0+2*zb1+zb2)+22*zc1-29*zc2)/64; break; //0-1700Hz butterworth - case 2: zx0=(4*(zx0+zb1+zb2)+22*zc1-47*zc2)/64; break; //0-1700Hz elliptic - case 3: zx0=((zx0+2*zb1+zb2)+97*zc1-57*zc2)/64; break; //650-840Hz - case 4: zx0=((zx0+zb1+zb2)+104*zc1-60*zc2)/64; break; //650-750Hz - case 5: zx0=((zb1)+109*zc1-62*zc2)/64; break; //630-680Hz + //case 2: zx0=(16*(zx0+2*zb1+zb2)-36*zc1-31*zc2)/64; break; //0-2500Hz butterworth + //case 2: zx0=(8*(zx0+zb2)+13*zb1-46*zc1-48*zc2)/64; break; //0-2500Hz elliptic + //case 2: zx0=(8*(zx0+2*zb1+zb2)-46*(zc1+zc2))/64; break; //0-2500Hz elliptic slower roll-off but deep + case 2: zx0=(8*(zx0+zb2)+13*zb1-43*zc1-52*zc2)/64; break; //0-2500Hz elliptic -60dB@3kHz + //case 3: break; + //case 3: zx0=(16*(zx0+2*zb1+zb2)+22*zc1-29*zc2)/64; break; //0-1700Hz butterworth + case 3: zx0=(4*(zx0+zb1+zb2)+22*zc1-47*zc2)/64; break; //0-1700Hz elliptic + case 4: zx0=((zx0+2*zb1+zb2)+97*zc1-57*zc2)/64; break; //650-840Hz + case 5: zx0=((zx0+zb1+zb2)+104*zc1-60*zc2)/64; break; //650-750Hz + case 6: zx0=((zb1)+109*zc1-62*zc2)/64; break; //630-680Hz } zc2=zc1; zc1=zx0; @@ -748,21 +752,22 @@ void sdr_rx() ac = ac >> (16-volume); if(nr) ac = process_nr(ac); if(mode == USB || mode == LSB){ - if(filt != -1) ac = filt_var(ac << 0); + if(filt) ac = filt_var(ac << 0); } if(mode == CW){ - if(filt != -1) ac = filt_var(ac << 6); -#define CW_DECODER 1 -#ifdef CW_DECODER - char ch = cw(ac >> 0); - if(ch){ - for(int i=0; i!=15;i++) out[i]=out[i+1]; - out[15] = ch; - cw_event = true; + if(filt) ac = filt_var(ac << 6); + + if(cwdec){ // CW decoder enabled? + char ch = cw(ac >> 0); + if(ch){ + for(int i=0; i!=15;i++) out[i]=out[i+1]; + out[15] = ch; + cw_event = true; + } } -#endif + } - + //if(!(absavg256cnt--)){ _absavg256 = absavg256; absavg256 = 0; } else absavg256 += abs(ac); //hack //static int16_t dc; //dc += (ac - dc) / 2; @@ -1019,6 +1024,8 @@ byte font[][8] = { 0b10101 } }; +const char* cap_label[] = { "SSB", "DSP", "SDR" }; + void customDelay(uint32_t _micros) //_micros=100000 is 132052us delay { uint32_t i; for(i = 0; i != _micros * 3; i++) wdt_reset(); @@ -1065,9 +1072,15 @@ public: pinMode(AUDIO1, INPUT); pinMode(AUDIO2, INPUT); } + + int8_t smode = 1; + const char* smode_label[4] = { "none", "dBm", "S", "S-bar" }; float smeter(float ref = 5.1) //= 10*log(F_SAMP_RX/R/2400) ref to 2.4kHz BW. { + if(smode == 0){ // none + return 0; + } float rms = _absavg256 / 256; //sqrt(256.0); if(dsp_cap == SDR) rms = (float)rms * 1.1 / (1024.0 * (float)R * 100.0 * 50.0); // rmsV = ADC value * AREF / [ADC DR * processing gain * receiver gain * audio gain] else rms = (float)rms * 5.0 / (1024.0 * (float)R * 100.0 * 120.0 / 1.750); @@ -1077,30 +1090,28 @@ public: static uint8_t cnt; cnt++; if((cnt % 8) == 0){ - #define DBM_METER 1 - #ifdef DBM_METER - lcd.setCursor(9, 0); lcd.print((int16_t)dbm_max); lcd.print((ref == 0.0) ? "dBm " : "dB "); - #endif - //#define SNR_METER 1 - #ifdef SNR_METER - uint8_t s = (dbm_max < -63) ? ((dbm_max - -127) / 6) : (uint8_t)(dbm_max - -63 + 10) % 10; // dBm to S - lcd.setCursor(14, 0); if(s < 10){ lcd.print("S"); } lcd.print(s); - #endif + + if(smode == 1){ // dBm meter + lcd.setCursor(9, 0); lcd.print((int16_t)dbm_max); lcd.print((ref == 0.0) ? "dBm " : "dB "); + } + if(smode == 2){ // S-meter + uint8_t s = (dbm_max < -63) ? ((dbm_max - -127) / 6) : (uint8_t)(dbm_max - -63 + 10) % 10; // dBm to S + lcd.setCursor(14, 0); if(s < 10){ lcd.print("S"); } lcd.print(s); + } dbm_max = -174.0 + 34.0; } - //#define SNR_BAR 1 - #ifdef SNR_BAR - int8_t s = (dbm < -63) ? ((dbm - -127) / 6) : (uint8_t)(dbm - -63 + 10) % 10; // dBm to S - lcd.setCursor(12, 0); - char tmp[5]; - tmp[0] = (char)(s<1?0x02:s<2?0x03:s<3?0x04:0x05); s = s - 3; - tmp[1] = (char)(s<1?0x02:s<2?0x03:s<3?0x04:0x05); s = s - 3; - tmp[2] = (char)(s<1?0x02:s<2?0x03:s<3?0x04:0x05); s = s - 3; - tmp[3] = (char)(s<1?0x02:s<2?0x03:s<3?0x04:0x05); s = s - 3; - tmp[4] = 0; - lcd.print(tmp); - //for(i = 0; i != 4; i++){ lcd.print((char)(s<1?0x02:s<2?0x03:s<3?0x04:0x05)); s = s - 3; } - #endif + if(smode == 3){ // S-bar + int8_t s = (dbm < -63) ? ((dbm - -127) / 6) : (uint8_t)(dbm - -63 + 10) % 10; // dBm to S + lcd.setCursor(12, 0); + char tmp[5]; + tmp[0] = (char)(s<1?0x02:s<2?0x03:s<3?0x04:0x05); s = s - 3; + tmp[1] = (char)(s<1?0x02:s<2?0x03:s<3?0x04:0x05); s = s - 3; + tmp[2] = (char)(s<1?0x02:s<2?0x03:s<3?0x04:0x05); s = s - 3; + tmp[3] = (char)(s<1?0x02:s<2?0x03:s<3?0x04:0x05); s = s - 3; + tmp[4] = 0; + lcd.print(tmp); + //for(i = 0; i != 4; i++){ lcd.print((char)(s<1?0x02:s<2?0x03:s<3?0x04:0x05)); s = s - 3; } + } return dbm; } @@ -1316,10 +1327,12 @@ public: timer1_start(39250); //if(!vox_enable) txen(true); } - - uint8_t bandval = 2; + + int8_t prev_bandval = 2; + int8_t bandval = 2; #define N_BANDS 11 uint32_t band[N_BANDS] = { /*472000, 1840000,*/ 3573000, 5357000, 7074000, 10136000, 14074000, 18100000, 21074000, 24915000, 28074000, 50313000, 70101000/*, 144125000*/ }; // { 3573000, 5357000, 7074000, 10136000, 14074000, 18100000, 21074000 }; + const char* band_label[N_BANDS] = { /*"600", "160m",*/ "80m", "60m", "40m", "30m", "20m", "17m", "15m", "12m", "10m", "6m", "4m" /*, "2m"*/}; enum step_t { STEP_10M, STEP_1M, STEP_500k, STEP_100k, STEP_10k, STEP_1k, STEP_500, STEP_100, STEP_10, STEP_1 }; int32_t stepsizes[10] = { 10000000, 1000000, 500000, 100000, 10000, 1000, 500, 100, 10, 1 }; @@ -1391,6 +1404,13 @@ public: sleep_disable(); resetFunc(); } + + void show_banner(){ + lcd.setCursor(0, 0); + lcd.print("QCX"); + if(ssb_cap || dsp_cap){ lcd.print("-"); lcd.print(cap_label[dsp_cap]); } + lcd.print("\x01 "); lcd.print(blanks); + } }; QCX qcx; @@ -1483,14 +1503,12 @@ void setup() // Test if QCX has SSB capability: DVM is biased ssb_cap = analogRead(DVM) > 369; - const char* cap_label[] = { "SSB", "DSP", "SDR" }; - lcd.setCursor(0, 0); lcd.print("QCX"); if(ssb_cap || dsp_cap){ lcd.print("-"); lcd.print(cap_label[dsp_cap]); } + qcx.show_banner(); lcd.setCursor(8, 0); lcd.print("R"); lcd.print(VERSION); lcd.print(blanks); - //lcd.setCursor(0, 0); lcd.print(String("QCX-") + (String[]){"SSB", "DSP", "SDR" }[dsp_cap] + F(" R") + F(VERSION) + blanks ); #ifdef SAFE // Measure CPU loads - if(!(load_tx < 100.0)) + if(!(load_tx <= 100.0)) { lcd.setCursor(0, 1); lcd.print("!!CPU_tx="); lcd.print(load_tx); lcd.print("%"); lcd.print(blanks); delay(1500); wdt_reset(); @@ -1500,13 +1518,13 @@ void setup() lcd.setCursor(0, 1); lcd.print("!!CPU_rx"); lcd.print(0); lcd.print("="); lcd.print(load_rx[0]); lcd.print("%"); lcd.print(blanks); delay(1500); wdt_reset(); } - if(!(load_rx_avg < 100.0)) + if(!(load_rx_avg <= 100.0)) { lcd.setCursor(0, 1); lcd.print("!!CPU_rx"); lcd.print("="); lcd.print(load_rx_avg); lcd.print("%"); lcd.print(blanks); delay(1500); wdt_reset(); // and specify indivual timings for each of the eight alternating processing functions: for(i = 1; i != 8; i++){ - if(!(load_rx[i] < 100.0)) + if(!(load_rx[i] <= 100.0)) { lcd.setCursor(0, 1); lcd.print("!!CPU_rx"); lcd.print(i); lcd.print("="); lcd.print(load_rx[i]); lcd.print("%"); lcd.print(blanks); delay(1500); wdt_reset(); @@ -1586,19 +1604,65 @@ void setup() #endif //delay(800); wdt_reset(); // Display banner - lcd.setCursor(7, 0); lcd.print("\x01"); lcd.print(blanks); + //lcd.setCursor(7, 0); lcd.print("\x01"); lcd.print(blanks); // remove release number + qcx.show_banner(); volume = (dsp_cap) ? ((dsp_cap == SDR) ? 8 : 14) : 0; mode = (dsp_cap || ssb_cap) ? USB : CW; qcx.start_rx(); } - + +class ParamClass { +public: + template void update(T& value, const char* label, const char* enumArray[], int _min, int _max, bool continuous){ + value += encoder_val; + encoder_val = 0; + if(continuous){ + value = (value % (_max+1)); + if((int)value < _min) value += _min; + } else + value = max(_min, min((int)value, _max)); + lcd.setCursor(0, 1); if(label != NULL){ lcd.print(label); lcd.print(": "); } + if(enumArray == NULL) + lcd.print(value); + else + lcd.print(enumArray[value]); + lcd.print(blanks); + } + + template void updateMenu(T& value, const char* label, const char* enumArray[], int _min, int _max, bool continuous, bool cursor){ + value += encoder_val; + encoder_val = 0; + if(continuous){ + value = (value % (_max+1)); + if((int)value < _min) value += _min; + } else + value = max(_min, min((int)value, _max)); + lcd.setCursor(0, 0); if(label != NULL){ lcd.print(label); lcd.print(blanks); lcd.print(blanks); } + lcd.setCursor(0, 1); + if(enumArray == NULL) + lcd.print(value); + else + lcd.print(enumArray[value]); + lcd.print(blanks); lcd.print(blanks); + if(cursor){ lcd.setCursor(0, 1); lcd.cursor(); } + } +}; +ParamClass Param; + +#define N_PARAMS 8 +volatile int8_t menumode = 0; +volatile int8_t menu = 0; +const char* offon_label[] = {"OFF", "ON"}; + void loop() { - //delay(10); - delay(100); + delay(10); + //delay(100); + + if(menumode == 0) + qcx.smeter(); - qcx.smeter(); if(mode == CW && cw_event){ cw_event = false; lcd.setCursor(0, 1); lcd.print(out); @@ -1634,48 +1698,54 @@ void loop() } event |= (v < 862) ? BL : (v < 1023) ? BR : BE; // determine which button pressed based on threshold levels switch(event){ + case BL|PL: // Called when menu button released + menumode = 2; + + //calibrate_predistortion(); + //qcx.powermeter(); + //test_tx_amp(); + break; + case BL|PT: + menumode = 1; + if(menu == 0) menu = 1; + break; case BL|SC: //calibrate_iq(); + /* if(dsp_cap){ - att_enable = !att_enable; - lcd.setCursor(0, 1); lcd.print("Attenuate: "); lcd.print(att_enable ? "ON" : "OFF"); lcd.print(blanks); + encoder_val = 1; Param.update(att_enable, "Attenuate", offon_label, 0, sizeof(offon_label)/sizeof(char *), true); txen(false); // submit attenuator setting - wdt_reset(); delay(1500); wdt_reset(); - change = true; // refresh display - } + wdt_reset(); delay(1500); wdt_reset(); change = true; // wait & refresh display + }*/ + int8_t _menumode; + if(menumode == 0){ _menumode = 1; if(menu == 0) menu = 1; } + if(menumode == 1){ _menumode = 2; } + if(menumode == 2){ _menumode = 0; qcx.show_banner(); } // Return menu to default screen + menumode = _menumode; + change = true; break; case BL|DC: //qcx.powerDown(); - filt++; - _init = true; - //if(filt > N_FILT) filt = -1; - if(mode == CW && filt > N_FILT-1) filt = 3; - if(mode != CW && filt > 2) filt = -1; - lcd.setCursor(0, 1); lcd.print("Filter: "); lcd.print(filt); lcd.print(blanks); - wdt_reset(); delay(1500); wdt_reset(); - change = true; // refresh display break; - case BL|PL: - //calibrate_predistortion(); - qcx.powermeter(); - //test_tx_amp(); - break; - case BL|PT: break; case BR|SC: - mode++; // mode change + encoder_val = 1; Param.update(mode, "Mode", mode_label, 0, sizeof(mode_label)/sizeof(char*), true); if(mode != CW) qcx.stepsize = qcx.STEP_1k; else qcx.stepsize = qcx.STEP_100; - if(mode > FM) mode = LSB; - if(mode == CW) filt = 3; else filt = -1; + //if(mode > FM) mode = LSB; + if(mode > CW) mode = LSB; // skip all other modes (only LSB, USB, CW) + if(mode == CW) filt = 4; else filt = 0; si5351.prev_pll_freq = 0; // enforce PLL reset change = true; break; case BR|DC: - if(drive == 0) drive = 1; - else drive += 1; - if(drive > 8) drive = 0; - lcd.setCursor(0, 1); lcd.print("Drive: "); lcd.print(drive); lcd.print(blanks); - agc = (drive == 4); - nr = (drive % 2); + //encoder_val = 1; Param.update(drive, "Drive", NULL, 0, 8, true); + filt++; + _init = true; + if(mode == CW && filt > N_FILT) filt = 4; + if(mode != CW && filt > 3) filt = 0; + lcd.setCursor(0, 1); lcd.print("Filter: "); lcd.print(filt); lcd.print(blanks); + wdt_reset(); delay(1500); wdt_reset(); + change = true; // refresh display + break; case BR|PL: vox_enable = true; @@ -1694,7 +1764,6 @@ void loop() delay(100); qcx.bandval++; if(qcx.bandval >= N_BANDS) qcx.bandval = 0; - freq = qcx.band[qcx.bandval]; qcx.stepsize = qcx.STEP_1k; change = true; break; @@ -1702,46 +1771,76 @@ void loop() case BE|PT: for(; digitalRead(BUTTONS);){ // process encoder changes until released wdt_reset(); - if(encoder_val != 0 && (dsp_cap)){ - int16_t tmp = volume; - tmp += encoder_val; - encoder_val = 0; - if(tmp < 0) qcx.powerDown(); // powerDown when volume < 0 - volume = max(0, min(tmp, 255)); - lcd.setCursor(0, 1); lcd.print("Volume "); lcd.print(volume); lcd.print(blanks); + if(dsp_cap && encoder_val){ + Param.update(volume, "Volume", NULL, -1, 32, false); + if(volume == -1) qcx.powerDown(); // powerDown when volume < 0 } } change = true; // refresh display break; } } - if(encoder_val){ // process encoder tuning steps - qcx.process_encoder_tuning_step(encoder_val); - encoder_val = 0; - } - if(change){ - change = false; - uint32_t n = freq / 1000000; // lcd.print(f) with commas - uint32_t n2 = freq % 1000000; - uint32_t scale = 1000000; - char buf[16]; - sprintf(buf, "%2u", n); lcd.setCursor(0, 1); lcd.print(buf); - while(scale != 1){ - scale /= 1000; - n = n2 / scale; - n2 = n2 % scale; - if(scale == 1) sprintf(buf, ",%02u", n / 10); else // leave last digit out - sprintf(buf, ",%03u", n); - lcd.print(buf); - } - lcd.print(" "); lcd.print(mode_label[mode]); lcd.print(" "); - lcd.setCursor(15, 1); lcd.print("R"); - if(mode == LSB) - si5351.freq(freq, 90, 0); // RX in LSB - else - si5351.freq(freq, 0, 90); // RX in USB + if(menumode == 1){ + menu += encoder_val; // Navigate through menu of parameters and values + encoder_val = 0; + menu = max(0, min(menu, N_PARAMS)); + change = true; // refresh (in case menu=0) } - qcx.stepsize_showcursor(); + + if((menumode != 0) && (change == true)){ // Show parameter and value + switch(menu){ + case 0: menumode = 0; qcx.show_banner(); break; + case 1: Param.updateMenu(volume, "1.1 Volume", NULL, 0, 32, false, menumode == 2); break; + case 2: Param.updateMenu(mode, "1.2 Mode", mode_label, 0, sizeof(mode_label)/sizeof(char*) - 1, false, menumode == 2); break; + case 3: Param.updateMenu(filt, "1.3 Filter BW", filt_label, 0, sizeof(filt_label)/sizeof(char*) - 1, false, menumode == 2); break; + case 4: Param.updateMenu(qcx.bandval, "1.4 Band", qcx.band_label, 0, sizeof(qcx.band_label)/sizeof(char*) - 1, false, menumode == 2); break; + case 5: Param.updateMenu(agc, "1.5 AGC", offon_label, 0, 1, false, menumode == 2); break; + case 6: Param.updateMenu(nr, "1.6 NR", offon_label, 0, 1, false, menumode == 2); break; + case 7: Param.updateMenu(qcx.smode, "1.7 S-meter", qcx.smode_label, 0, sizeof(qcx.smode_label)/sizeof(char*) - 1, false, menumode == 2); break; + case 8: Param.updateMenu(cwdec, "2,1 CW Decoder", offon_label, 0, 1, false, menumode == 2); break; + case 9: Param.updateMenu(drive, "3.1 TX Drive", NULL, 0, 8, false, menumode == 2); break; + } + } + + if(menumode == 0){ + if(encoder_val){ // process encoder tuning steps + qcx.process_encoder_tuning_step(encoder_val); + encoder_val = 0; + } + + if(change){ + change = false; + if(qcx.prev_bandval != qcx.bandval){ freq = qcx.band[qcx.bandval]; qcx.prev_bandval = qcx.bandval; } + + uint32_t n = freq / 1000000; // lcd.print(f) with commas + uint32_t n2 = freq % 1000000; + uint32_t scale = 1000000; + char buf[16]; + sprintf(buf, "%2u", n); lcd.setCursor(0, 1); lcd.print(buf); + while(scale != 1){ + scale /= 1000; + n = n2 / scale; + n2 = n2 % scale; + if(scale == 1) sprintf(buf, ",%02u", n / 10); else // leave last digit out + sprintf(buf, ",%03u", n); + lcd.print(buf); + } + lcd.print(" "); lcd.print(mode_label[mode]); lcd.print(" "); + lcd.setCursor(15, 1); lcd.print("R"); + + if(mode == LSB) + si5351.freq(freq, 90, 0); // RX in LSB + else + si5351.freq(freq, 0, 90); // RX in USB + + // The following is a hack for SWR measurement: + //si5351.alt_clk2(freq + 2400); + //si5351.SendRegister(SI_CLK_OE, 0b11111000); // CLK2_EN=1, CLK1_EN,CLK0_EN=1 + //digitalWrite(SIG_OUT, HIGH); // inject CLK2 on antenna input via 120K + } + qcx.stepsize_showcursor(); + } + wdt_reset(); } diff --git a/README.md b/README.md index d4bfd70..389af8b 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ The following performance measurements were made with QCX-SSB R1.01, a modified ### Notes: -1. To support multi-band operation, the RX BPF can be omitted (C1,C5,C8, secondary 3 of T1), and a switchable LPF-bank could replace the existing LPF C25-28,L1-L3 and matching network C29-30,L4. The Arduino sketch could be extended to switch the filter-bank. When using external filters the on-board LPF may be bypassed with a wire. +1. To support multi-band operation, the RX BPF can be omitted (C1,C5,C8, secondary 3 of T1). To improve RX sensitivity on higher bands, T1 and R64 should be removed and on the original wire-endings of T1 (see [original Assembly instruction] chapter 3.56 for PC Board pattern) the following components should be installed: resistor 1K over 6-8 and 3-4; capacitor 10nF over 4-8. A switchable LPF-bank could replace the existing LPF C25-28,L1-L3, or a wire may bypass if external LPFs are present; the matching network C30,L4 should be set to 30pF and 1uH (16 turns). A switchable filter-bank could potentialy be controlled via I2C I/O port. 2. The QCX-SSB firmware can be uploaded to ATMEGA328P chip placed in the QCX via ISP programming on an Arduino Uno board. To do so, istall an [Arduino] environment, connect an Arduino Uno board to PC, upload this [ArduinoISP] sketch to Uno, install a new ATMEGA328P chip in QCX, connect Arduino Uno to QCX via [ISP jumper] wiring, power on QCX, in Arduino select "Tools > Programmer > Arduino as ISP", select "Tools > Board > Arduino/Genuino Uno", select "Tools > Port > /dev/ttyUSB0 or ttyACM0", select "Tools > Burn Bootloader", upload [QCX-SSB Sketch] by opening and selecting "Sketch > Upload Using Programmer". Once upload succeeds the LCD should display "QCX-SSB". Make sure that the Microphone is not connected during programming. 3. The occupied SSB bandwidth can be further reduced by restricting the maximum phase change (set MAX_DP to half a unit-circle _UA/2 (equivalent to 180 degrees)). The sensitivity of the VOX switching can be set with parameter VOX_THRESHOLD. Audio-input can be attenuated by increasing parameter MIC_ATTEN (6dB per step). 4. To implement the SDR stage, the 17 component changes of installation step 1 are easiest to be implemented on a newly to be build QCX. Alternatively, on an already built QCX it is easier to bypass the CW filter (see [note 4](#note4)), this maintains the hardware compatibility with the original QCX firmware. Optionally this can be extended with a Arduino based DSP filter stage (see [note 5](#note5)). @@ -203,4 +203,5 @@ The following performance measurements were made with QCX-SSB R1.01, a modified [phase shift in the SI5351 clocks]: https://www.silabs.com/community/timing/forum.topic.html/difficulty_settingp-LchG +[original Assembly instruction]: https://www.qrp-labs.com/images/qcx/assembly_A4_Rev_4b.pdf diff --git a/layout.png b/layout.png old mode 100755 new mode 100644 index a6fff60a8c148b53f42c6ddc9443eb073fea59fa..e4ad9e1e20c7c0f53d2ce1f9528915f5c972889e GIT binary patch delta 146604 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