diff --git a/Makefile b/Makefile index 911000e..86f46b6 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ ENABLE_BOOT_BEEPS := 0 ENABLE_COMPANDER := 1 ENABLE_SHOW_CHARGE_LEVEL := 0 ENABLE_REVERSE_BAT_SYMBOL := 1 +ENABLE_AM_AGC_GAIN := 1 ENABLE_AUDIO_BAR := 0 #ENABLE_SINGLE_VFO_CHAN := 1 #ENABLE_BAND_SCOPE := 1 @@ -196,6 +197,9 @@ endif ifeq ($(ENABLE_REVERSE_BAT_SYMBOL),1) CFLAGS += -DENABLE_REVERSE_BAT_SYMBOL endif +ifeq ($(ENABLE_AM_AGC_GAIN),1) + CFLAGS += -DENABLE_AM_AGC_GAIN +endif ifeq ($(ENABLE_AUDIO_BAR),1) CFLAGS += -DENABLE_AUDIO_BAR endif @@ -253,4 +257,4 @@ bsp/dp32g030/%.h: hardware/dp32g030/%.def -include $(DEPS) clean: - rm -f $(TARGET).bin $(TARGET) $(OBJS) $(DEPS) + rm -f $(TARGET).bin $(TARGET).packed.bin $(TARGET) $(OBJS) $(DEPS) \ No newline at end of file diff --git a/app/app.c b/app/app.c index 21ccc03..7fbb68e 100644 --- a/app/app.c +++ b/app/app.c @@ -69,17 +69,22 @@ static void APP_CheckForIncoming(void) if (!g_SquelchLost) return; + // squelch is open + if (gScanState == SCAN_OFF) - { + { // not RF scanning + if (gCssScanMode != CSS_SCAN_MODE_OFF && gRxReceptionMode == RX_MODE_NONE) - { + { // CTCSS/DTS scanning + ScanPauseDelayIn_10ms = 100; // 1 second gScheduleScanListen = false; gRxReceptionMode = RX_MODE_DETECTED; } if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF) - { + { // dual watch is disabled + #ifdef ENABLE_NOAA if (gIsNoaaMode) { @@ -92,14 +97,16 @@ static void APP_CheckForIncoming(void) return; } + // dual watch is enabled and we're RX'ing a signal + if (gRxReceptionMode != RX_MODE_NONE) { FUNCTION_Select(FUNCTION_INCOMING); return; } - gDualWatchCountdown_10ms = dual_watch_count_after_rx_10ms; - gScheduleDualWatch = false; + gDualWatchCountdown_10ms = dual_watch_count_after_rx_10ms; + gScheduleDualWatch = false; // let the user see DW is not active gDualWatchActive = false; @@ -127,7 +134,7 @@ static void APP_HandleIncoming(void) bool bFlag; if (!g_SquelchLost) - { + { // squelch is closed FUNCTION_Select(FUNCTION_FOREGROUND); gUpdateDisplay = true; return; @@ -160,15 +167,15 @@ static void APP_HandleIncoming(void) DTMF_HandleRequest(); if (gScanState == SCAN_OFF && gCssScanMode == CSS_SCAN_MODE_OFF) - { + { // not scanning if (gRxVfo->DTMF_DECODING_ENABLE || gSetting_KILLED) - { + { // DTMF is enabled if (gDTMF_CallState == DTMF_CALL_STATE_NONE) { if (gRxReceptionMode == RX_MODE_DETECTED) { gDualWatchCountdown_10ms = dual_watch_count_after_1_10ms; - gScheduleDualWatch = false; + gScheduleDualWatch = false; gRxReceptionMode = RX_MODE_LISTENING; @@ -398,344 +405,151 @@ static void APP_HandleFunction(void) void APP_StartListening(FUNCTION_Type_t Function) { - if (!gSetting_KILLED) + if (gSetting_KILLED) + return; + + #ifdef ENABLE_FMRADIO + if (gFmRadioMode) + BK1080_Init(0, false); + #endif + + gVFO_RSSI_Level[gEeprom.RX_CHANNEL == 0] = 0; + + GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH); + + gEnableSpeaker = true; + + BACKLIGHT_TurnOn(); + + if (gScanState != SCAN_OFF) { - #ifdef ENABLE_FMRADIO - if (gFmRadioMode) - BK1080_Init(0, false); - #endif - - gVFO_RSSI_Level[gEeprom.RX_CHANNEL == 0] = 0; - - GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH); - - gEnableSpeaker = true; - - BACKLIGHT_TurnOn(); - - if (gScanState != SCAN_OFF) + switch (gEeprom.SCAN_RESUME_MODE) { - switch (gEeprom.SCAN_RESUME_MODE) - { - case SCAN_RESUME_TO: - if (!gScanPauseMode) - { - ScanPauseDelayIn_10ms = 500; - gScheduleScanListen = false; - gScanPauseMode = true; - } - break; - - case SCAN_RESUME_CO: - case SCAN_RESUME_SE: - ScanPauseDelayIn_10ms = 0; + case SCAN_RESUME_TO: + if (!gScanPauseMode) + { + ScanPauseDelayIn_10ms = 500; gScheduleScanListen = false; - break; - } + gScanPauseMode = true; + } + break; - bScanKeepFrequency = true; + case SCAN_RESUME_CO: + case SCAN_RESUME_SE: + ScanPauseDelayIn_10ms = 0; + gScheduleScanListen = false; + break; } - #ifdef ENABLE_NOAA - if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gIsNoaaMode) - { - gRxVfo->CHANNEL_SAVE = gNoaaChannel + NOAA_CHANNEL_FIRST; - gRxVfo->pRX->Frequency = NoaaFrequencyTable[gNoaaChannel]; - gRxVfo->pTX->Frequency = NoaaFrequencyTable[gNoaaChannel]; - gEeprom.ScreenChannel[gEeprom.RX_CHANNEL] = gRxVfo->CHANNEL_SAVE; - gNOAA_Countdown_10ms = 500; // 5 sec - gScheduleNOAA = false; - } - #endif + bScanKeepFrequency = true; + } - if (gCssScanMode != CSS_SCAN_MODE_OFF) - gCssScanMode = CSS_SCAN_MODE_FOUND; - - if (gScanState == SCAN_OFF && gCssScanMode == CSS_SCAN_MODE_OFF && gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + #ifdef ENABLE_NOAA + if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gIsNoaaMode) { - gDualWatchCountdown_10ms = dual_watch_count_after_2_10ms; - gScheduleDualWatch = false; - - gRxVfoIsActive = true; - - // let the user see DW is not active - gDualWatchActive = false; - gUpdateStatus = true; + gRxVfo->CHANNEL_SAVE = gNoaaChannel + NOAA_CHANNEL_FIRST; + gRxVfo->pRX->Frequency = NoaaFrequencyTable[gNoaaChannel]; + gRxVfo->pTX->Frequency = NoaaFrequencyTable[gNoaaChannel]; + gEeprom.ScreenChannel[gEeprom.RX_CHANNEL] = gRxVfo->CHANNEL_SAVE; + gNOAA_Countdown_10ms = 500; // 5 sec + gScheduleNOAA = false; } + #endif + + if (gCssScanMode != CSS_SCAN_MODE_OFF) + gCssScanMode = CSS_SCAN_MODE_FOUND; + + if (gScanState == SCAN_OFF && gCssScanMode == CSS_SCAN_MODE_OFF && gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + { // not scanning, dual watch is enabled + + gDualWatchCountdown_10ms = dual_watch_count_after_2_10ms; + gScheduleDualWatch = false; + + gRxVfoIsActive = true; + + // let the user see DW is not active + gDualWatchActive = false; + gUpdateStatus = true; + } + + if (gRxVfo->IsAM) + { // AM const uint32_t rx_frequency = gRxVfo->pRX->Frequency; -/* - if (gRxVfo->IsAM) - { // AM - // RX AF level - // - // REG_48 <15:12> 11 ??? - // - // REG_48 <11:10> 0 AF Rx Gain-1 - // 0 = 0dB - // 1 = -6dB - // 2 = -12dB - // 3 = -18dB - // - // REG_48 <9:4> 60 AF Rx Gain-2 -26dB ~ 5.5dB 0.5dB/step - // 63 = max - // 0 = min = mute - // - // REG_48 <3:0> 15 AF DAC Gain (after Gain-1 and Gain-2) approx 2dB/step - // 15 = max - // 0 = min - // - BK4819_WriteRegister(BK4819_REG_48, - #if 0 - // QS calibrated RX AF gain - (11u << 12) | // ??? - ( 0u << 10) | // AF Rx Gain-1 - (gEeprom.VOLUME_GAIN << 4) | // AF Rx Gain-2 - (gEeprom.DAC_GAIN << 0)); // AF DAC Gain (after Gain-1 and Gain-2) - #else - // max RX AF gain - (11u << 12) | // ??? - ( 0u << 10) | // AF Rx Gain-1 - (63u << 4) | // AF Rx Gain-2 - (15u << 0)); // AF DAC Gain (after Gain-1 and Gain-2) - #endif + uint16_t lna_short; // whats "LNA SHORT" mean ? + uint16_t lna; + uint16_t mixer; + uint16_t pga; -// BK4819_WriteRegister(0x4B, BK4819_ReadRegister(0x4B) & ~(1u << 5)); // enable RX ALC - - // help improve AM RX distorted audio by reducing the PGA gain (still very bad with stronge signals) - // - // I think a solution is to dynamically change these values as the RSSI moves up/down ? - // without a detailed datasheet on the chip it's difficult/impossible to fix things - // - // REG_10 <15:0> 0x0038 Rx AGC Gain Table[0]. (Index Max->Min is 3,2,1,0,-1) - // - // <9:8> = LNA Gain Short - // 3 = 0dB - // 2 = -11dB - // 1 = -16dB - // 0 = -19dB - // - // <7:5> = LNA Gain - // 7 = 0dB - // 6 = -2dB - // 5 = -4dB - // 4 = -6dB - // 3 = -9dB - // 2 = -14dB - // 1 = -19dB - // 0 = -24dB - // - // <4:3> = MIXER Gain - // 3 = 0dB - // 2 = -3dB - // 1 = -6dB - // 0 = -8dB - // - // <2:0> = PGA Gain - // 7 = 0dB - // 6 = -3dB - // 5 = -6dB - // 4 = -9dB - // 3 = -15dB - // 2 = -21dB - // 1 = -27dB - // 0 = -33dB - // - // LNA_SHORT .. 0dB - // LNA ........ 14dB - // MIXER ...... 0dB - // PGA ........ -15dB - // - { - uint16_t lna_short; // whats "LNA SHORT" mean ? - uint16_t lna; - uint16_t mixer; - uint16_t pga; - // seems the RX gain abrutly reduces above this frequency, why ? - if (rx_frequency <= 22640000) - { - lna_short = 3; // original - lna = 2; // original - mixer = 3; // original - pga = 3; // reduced - seems to help reduce the AM demodulation distortion - } - else - { - lna_short = 3; // original - lna = 4; // increased - mixer = 3; // original - // pga = 6; // original - pga = 7; // increased - } - - BK4819_WriteRegister(BK4819_REG_13, (lna_short << 8) | (lna << 5) | (mixer << 3) | (pga << 0)); - - // what do these 4 other gain tables do ??? - //BK4819_WriteRegister(BK4819_REG_12, 0x037B); // 000000 11 011 11 011 - //BK4819_WriteRegister(BK4819_REG_11, 0x027B); // 000000 10 011 11 011 - //BK4819_WriteRegister(BK4819_REG_10, 0x007A); // 000000 00 011 11 010 - //BK4819_WriteRegister(BK4819_REG_14, 0x0019); // 000000 00 000 11 001 - } - - gNeverUsed = 0; + // the RX gain abrutly reduces above this frequency, why ? + if (rx_frequency <= 22640000) + { // decrease front end gain = better AM demodulation + lna_short = 3; // 3 original + lna = 2; // 2 original + mixer = 3; // 3 original + pga = 3; // 6 original, 3 reduced } else - { // FM - - // RX AF level - // - // REG_48 <15:12> 11 ??? - // - // REG_48 <11:10> 0 AF Rx Gain-1 - // 0 = 0dB - // 1 = -6dB - // 2 = -12dB - // 3 = -18dB - // - // REG_48 <9:4> 60 AF Rx Gain-2 -26dB ~ 5.5dB 0.5dB/step - // 63 = max - // 0 = min = mute - // - // REG_48 <3:0> 15 AF DAC Gain (after Gain-1 and Gain-2) approx 2dB/step - // 15 = max - // 0 = min - // - BK4819_WriteRegister(BK4819_REG_48, - (11u << 12) | // ??? - ( 0u << 10) | // AF Rx Gain-1 - (gEeprom.VOLUME_GAIN << 4) | // AF Rx Gain-2 - (gEeprom.DAC_GAIN << 0)); // AF DAC Gain (after Gain-1 and Gain-2) - -// BK4819_WriteRegister(0x4B, BK4819_ReadRegister(0x4B) | (1u << 5)); // disable RX ALC - - // REG_10 <15:0> 0x0038 Rx AGC Gain Table[0]. (Index Max->Min is 3,2,1,0,-1) - // - // <9:8> = LNA Gain Short - // 3 = 0dB - // 2 = -11dB - // 1 = -16dB - // 0 = -19dB - // - // <7:5> = LNA Gain - // 7 = 0dB - // 6 = -2dB - // 5 = -4dB - // 4 = -6dB - // 3 = -9dB - // 2 = -14dB - // 1 = -19dB - // 0 = -24dB - // - // <4:3> = MIXER Gain - // 3 = 0dB - // 2 = -3dB - // 1 = -6dB - // 0 = -8dB - // - // <2:0> = PGA Gain - // 7 = 0dB - // 6 = -3dB - // 5 = -6dB - // 4 = -9dB - // 3 = -15dB - // 2 = -21dB - // 1 = -27dB - // 0 = -33dB - // - // LNA_SHORT .. 0dB - // LNA ........ 14dB - // MIXER ...... 0dB - // PGA ........ -3dB - // LNA SHORT LNA MIXER PGA - BK4819_WriteRegister(BK4819_REG_13, (3u << 8) | (2u << 5) | (3u << 3) | (6u << 0)); + { // increasing the front end to compensate the reduced gain, but more gain decreases dynamic range + lna_short = 3; // 3 original + lna = 4; // 2 original, 4 increased + mixer = 3; // 3 original + pga = 7; // 6 original, 7 increased } -*/ - if (gRxVfo->IsAM) - { // AM - { - uint16_t lna_short; // whats "LNA SHORT" mean ? - uint16_t lna; - uint16_t mixer; - uint16_t pga; + BK4819_WriteRegister(BK4819_REG_13, (lna_short << 8) | (lna << 5) | (mixer << 3) | (pga << 0)); - // seems the RX gain abrutly reduces above this frequency, why ? - if (rx_frequency <= 22640000) - { - lna_short = 3; // original - lna = 2; // original - mixer = 3; // original - pga = 3; // reduced - seems to help reduce the AM demodulation distortion - } - else - { // increasing the front ends gain decreases the dynamic range - lna_short = 3; // original - lna = 4; // increased - mixer = 3; // original - // pga = 6; // original - pga = 7; // increased - } + // what do these 4 other gain settings do ??? + //BK4819_WriteRegister(BK4819_REG_12, 0x037B); // 000000 11 011 11 011 + //BK4819_WriteRegister(BK4819_REG_11, 0x027B); // 000000 10 011 11 011 + //BK4819_WriteRegister(BK4819_REG_10, 0x007A); // 000000 00 011 11 010 + //BK4819_WriteRegister(BK4819_REG_14, 0x0019); // 000000 00 000 11 001 - BK4819_WriteRegister(BK4819_REG_13, (lna_short << 8) | (lna << 5) | (mixer << 3) | (pga << 0)); + // AF gain (max it out) - see below FM mode bit for original setting + BK4819_WriteRegister(BK4819_REG_48, + (11u << 12) | // ??? .. 0 to 15, doesn't seem to make any difference + ( 0u << 10) | // AF Rx Gain-1 + (63u << 4) | // AF Rx Gain-2 + (15u << 0)); // AF DAC Gain (after Gain-1 and Gain-2) - // what do these 4 other gain tables do ??? - //BK4819_WriteRegister(BK4819_REG_12, 0x037B); // 000000 11 011 11 011 - //BK4819_WriteRegister(BK4819_REG_11, 0x027B); // 000000 10 011 11 011 - //BK4819_WriteRegister(BK4819_REG_10, 0x007A); // 000000 00 011 11 010 - //BK4819_WriteRegister(BK4819_REG_14, 0x0019); // 000000 00 000 11 001 - } - - BK4819_WriteRegister(BK4819_REG_48, - // max RX AF gain - (11u << 12) | // ??? - ( 0u << 10) | // AF Rx Gain-1 - (63u << 4) | // AF Rx Gain-2 - (15u << 0)); // AF DAC Gain (after Gain-1 and Gain-2) - - gNeverUsed = 0; - } - else - { // FM - - uint16_t lna_short; // whats "LNA SHORT" mean ? - uint16_t lna; - uint16_t mixer; - uint16_t pga; - - // original - lna_short = 3; - lna = 2; - mixer = 3; - pga = 6; - - BK4819_WriteRegister(BK4819_REG_13, (lna_short << 8) | (lna << 5) | (mixer << 3) | (pga << 0)); - - BK4819_WriteRegister(BK4819_REG_48, - (11u << 12) | // ??? - ( 0u << 10) | // AF Rx Gain-1 - (gEeprom.VOLUME_GAIN << 4) | // AF Rx Gain-2 - (gEeprom.DAC_GAIN << 0)); // AF DAC Gain (after Gain-1 and Gain-2) - } - - #ifdef ENABLE_VOICE - if (gVoiceWriteIndex == 0) - #endif - BK4819_SetAF(gRxVfo->IsAM ? BK4819_AF_AM : BK4819_AF_OPEN); - - FUNCTION_Select(Function); - - #ifdef ENABLE_FMRADIO - if (Function == FUNCTION_MONITOR || gFmRadioMode) - #else - if (Function == FUNCTION_MONITOR) - #endif - { - GUI_SelectNextDisplay(DISPLAY_MAIN); - return; - } - - gUpdateDisplay = true; + gNeverUsed = 0; } + else + { // FM + + // original + const uint16_t lna_short = 3; // whats 'LNA short' mean ? + const uint16_t lna = 2; + const uint16_t mixer = 3; + const uint16_t pga = 6; + BK4819_WriteRegister(BK4819_REG_13, (lna_short << 8) | (lna << 5) | (mixer << 3) | (pga << 0)); + + // AF gain - original + BK4819_WriteRegister(BK4819_REG_48, + (11u << 12) | // ??? .. 0 to 15, doesn't seem to make any difference + ( 0u << 10) | // AF Rx Gain-1 + (gEeprom.VOLUME_GAIN << 4) | // AF Rx Gain-2 + (gEeprom.DAC_GAIN << 0)); // AF DAC Gain (after Gain-1 and Gain-2) + } + + #ifdef ENABLE_VOICE + if (gVoiceWriteIndex == 0) + #endif + BK4819_SetAF(gRxVfo->IsAM ? BK4819_AF_AM : BK4819_AF_OPEN); + + FUNCTION_Select(Function); + + #ifdef ENABLE_FMRADIO + if (Function == FUNCTION_MONITOR || gFmRadioMode) + #else + if (Function == FUNCTION_MONITOR) + #endif + { // squelch is disabled + GUI_SelectNextDisplay(DISPLAY_MAIN); + return; + } + + gUpdateDisplay = true; } void APP_SetFrequencyByStep(VFO_Info_t *pInfo, int8_t Step) @@ -851,7 +665,7 @@ static void DUALWATCH_Alternate(void) if (gIsNoaaMode) { if (IS_NOT_NOAA_CHANNEL(gEeprom.ScreenChannel[0]) || IS_NOT_NOAA_CHANNEL(gEeprom.ScreenChannel[1])) - gEeprom.RX_CHANNEL = 1 - gEeprom.RX_CHANNEL; + gEeprom.RX_CHANNEL = (gEeprom.RX_CHANNEL + 1) & 1; else gEeprom.RX_CHANNEL = 0; @@ -863,7 +677,7 @@ static void DUALWATCH_Alternate(void) else #endif { // toggle between VFO's - gEeprom.RX_CHANNEL = (1 - gEeprom.RX_CHANNEL) & 1; + gEeprom.RX_CHANNEL = (gEeprom.RX_CHANNEL + 1) & 1; gRxVfo = &gEeprom.VfoInfo[gEeprom.RX_CHANNEL]; if (!gDualWatchActive) @@ -965,8 +779,8 @@ void APP_CheckRadioInterrupts(void) { if (gCurrentFunction == FUNCTION_POWER_SAVE && !gRxIdleMode) { - gBatterySave_10ms = 20; // 200ms - gBatterySaveCountdownExpired = 0; + gPowerSave_10ms = power_save2_10ms; + gPowerSaveCountdownExpired = 0; } if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF && (gScheduleDualWatch || gDualWatchCountdown_10ms < dual_watch_count_after_vox_10ms)) @@ -1124,16 +938,14 @@ void APP_Update(void) #endif if (gCurrentFunction == FUNCTION_TRANSMIT && gTxTimeoutReached) - { + { // transmitting, but just timed out + gTxTimeoutReached = false; gFlagEndTransmission = true; APP_EndTransmission(); - AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP); - RADIO_SetVfoState(VFO_STATE_TIMEOUT); - GUI_DisplayScreen(); } @@ -1291,17 +1103,18 @@ void APP_Update(void) { FUNCTION_Select(FUNCTION_POWER_SAVE); } - + gSchedulePowerSave = false; #endif } #ifdef ENABLE_VOICE - if (gBatterySaveCountdownExpired && gCurrentFunction == FUNCTION_POWER_SAVE && gVoiceWriteIndex == 0) + if (gPowerSaveCountdownExpired && gCurrentFunction == FUNCTION_POWER_SAVE && gVoiceWriteIndex == 0) #else - if (gBatterySaveCountdownExpired && gCurrentFunction == FUNCTION_POWER_SAVE) + if (gPowerSaveCountdownExpired && gCurrentFunction == FUNCTION_POWER_SAVE) #endif - { + { // wake up, enable RX then go back to sleep + if (gRxIdleMode) { BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable(); @@ -1310,25 +1123,29 @@ void APP_Update(void) BK4819_EnableVox(gEeprom.VOX1_THRESHOLD, gEeprom.VOX0_THRESHOLD); if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF && gScanState == SCAN_OFF && gCssScanMode == CSS_SCAN_MODE_OFF) - { - DUALWATCH_Alternate(); // toggle between the two VFO's + { // dual watch mode, toggle between the two VFO's + DUALWATCH_Alternate(); gUpdateRSSI = false; } FUNCTION_Init(); - gBatterySave_10ms = 10; // 100ms - gRxIdleMode = false; + gPowerSave_10ms = power_save1_10ms; // come back here in a bit + gRxIdleMode = false; // RX is awake } else if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF || gScanState != SCAN_OFF || gCssScanMode != CSS_SCAN_MODE_OFF || gUpdateRSSI) - { + { // dual watch mode, go back to sleep + + // sample the RSSI gCurrentRSSI = BK4819_GetRSSI(); UI_UpdateRSSI(gCurrentRSSI); - gBatterySave_10ms = gEeprom.BATTERY_SAVE * 10; - gRxIdleMode = true; + // go back to sleep + + gPowerSave_10ms = gEeprom.BATTERY_SAVE * 10; + gRxIdleMode = true; BK4819_DisableVox(); BK4819_Sleep(); @@ -1338,14 +1155,16 @@ void APP_Update(void) } else - { - DUALWATCH_Alternate(); // toggle between the two VFO's + { // no yet in power save mode - gUpdateRSSI = true; - gBatterySave_10ms = 10; // 100ms + // toggle between the two VFO's + DUALWATCH_Alternate(); + + gUpdateRSSI = true; + gPowerSave_10ms = power_save1_10ms; } - gBatterySaveCountdownExpired = false; + gPowerSaveCountdownExpired = false; } } @@ -1495,6 +1314,130 @@ void APP_CheckKeys(void) } } +#ifdef ENABLE_AM_AGC_GAIN + void adjustAMFrontEnd10ms(void) + { + if (!gRxVfo->IsAM) + return; // FM + + switch (gCurrentFunction) + { + case FUNCTION_TRANSMIT: + case FUNCTION_BAND_SCOPE: + case FUNCTION_POWER_SAVE: + return; + + case FUNCTION_FOREGROUND: + case FUNCTION_RECEIVE: + case FUNCTION_MONITOR: + case FUNCTION_INCOMING: + break; + } + + // AM + + // REG_10 <15:0> 0x0038 Rx AGC Gain Table[0]. (Index Max->Min is 3,2,1,0,-1) + // + // <9:8> = LNA Gain Short + // 3 = 0dB + // 2 = -11dB + // 1 = -16dB + // 0 = -19dB + // + // <7:5> = LNA Gain + // 7 = 0dB + // 6 = -2dB + // 5 = -4dB + // 4 = -6dB + // 3 = -9dB + // 2 = -14dB + // 1 = -19dB + // 0 = -24dB + // + // <4:3> = MIXER Gain + // 3 = 0dB + // 2 = -3dB + // 1 = -6dB + // 0 = -8dB + // + // <2:0> = PGA Gain + // 7 = 0dB + // 6 = -3dB + // 5 = -6dB + // 4 = -9dB + // 3 = -15dB + // 2 = -21dB + // 1 = -27dB + // 0 = -33dB + // + // LNA_SHORT .. 0dB + // LNA ........ 14dB + // MIXER ...... 0dB + // PGA ........ -3dB + + // original settings + static uint16_t lna_short = 3; + static uint16_t lna = 2; + static uint16_t mixer = 3; + static uint16_t pga = 6; + + static unsigned int counter = 0; + static unsigned int avg_rssi = 0; + + register uint16_t new_lna_short = lna_short; + register uint16_t new_lna = lna; + register uint16_t new_mixer = mixer; + register uint16_t new_pga = pga; + + { + const uint16_t desired_rssi = (-86 + 160) * 2; // -86dBm + + gCurrentRSSI = BK4819_GetRSSI(); + + avg_rssi += gCurrentRSSI; + if (++counter < 16) // 160ms + return; + + avg_rssi /= counter; + counter = 0; + + if (avg_rssi < (desired_rssi - 4)) + { // increase gain + if (new_pga < 7) + new_pga++; + else + if (new_mixer < 3) + new_mixer++; + else + if (new_lna < 7) + new_lna++; + } + else + if (avg_rssi > (desired_rssi + 4)) + { // decrease gain + if (new_pga > 0) + new_pga--; + else + if (new_mixer > 0) + new_mixer--; + else + if (new_lna > 0) + new_lna--; + } + } + + if (lna_short == new_lna_short && lna == new_lna && mixer == new_mixer && pga == new_pga) + return; // no change + + lna_short = new_lna_short; + lna = new_lna; + mixer = new_mixer; + pga = new_pga; + + BK4819_WriteRegister(BK4819_REG_13, (lna_short << 8) | (lna << 5) | (mixer << 3) | (pga << 0)); + } +#endif + void APP_TimeSlice10ms(void) { gFlashLightBlinkCounter++; @@ -1505,6 +1448,11 @@ void APP_TimeSlice10ms(void) AUDIO_PlayBeep(BEEP_880HZ_40MS_OPTIONAL); #endif + #ifdef ENABLE_AM_AGC_GAIN + if (gSetting_AM_fix) + adjustAMFrontEnd10ms(); + #endif + if (UART_IsCommandAvailable()) { __disable_irq(); @@ -1931,7 +1879,8 @@ void APP_TimeSlice500ms(void) UI_DisplayBattery(gLowBatteryCountdown); if (gCurrentFunction != FUNCTION_TRANSMIT) - { + { // not transmitting + if (gLowBatteryCountdown < 30) { if (gLowBatteryCountdown == 29 && !gChargingWithTypeC) @@ -1942,7 +1891,8 @@ void APP_TimeSlice500ms(void) gLowBatteryCountdown = 0; if (!gChargingWithTypeC) - { + { // not on charge + AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP); #ifdef ENABLE_VOICE @@ -1961,7 +1911,7 @@ void APP_TimeSlice500ms(void) ST7565_Configure_GPIO_B11(); - //if (gEeprom.BACKLIGHT < (ARRAY_SIZE(gSubMenu_BACKLIGHT) - 1)) + if (gEeprom.BACKLIGHT < (ARRAY_SIZE(gSubMenu_BACKLIGHT) - 1)) GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_BACKLIGHT); // turn the backlight off } #ifdef ENABLE_VOICE diff --git a/app/menu.c b/app/menu.c index d73c5ca..feb1165 100644 --- a/app/menu.c +++ b/app/menu.c @@ -186,6 +186,9 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax) case MENU_D_DCD: case MENU_D_LIVE_DEC: case MENU_AM: + #ifdef ENABLE_AM_AGC_GAIN + case MENU_AM_FIX: + #endif #ifdef ENABLE_NOAA case MENU_NOAA_S: #endif @@ -606,6 +609,14 @@ void MENU_AcceptSetting(void) gRequestSaveChannel = 2; return; + #ifdef ENABLE_AM_AGC_GAIN + case MENU_AM_FIX: + gSetting_AM_fix = gSubMenuSelection; + gVfoConfigureMode = VFO_CONFIGURE_RELOAD; + gFlagResetVfos = true; + break; + #endif + #ifdef ENABLE_NOAA case MENU_NOAA_S: gEeprom.NOAA_AUTO_SCAN = gSubMenuSelection; @@ -976,6 +987,12 @@ void MENU_ShowCurrentSetting(void) gSubMenuSelection = gTxVfo->AM_CHANNEL_MODE; break; + #ifdef ENABLE_AM_AGC_GAIN + case MENU_AM_FIX: + gSubMenuSelection = gSetting_AM_fix; + break; + #endif + #ifdef ENABLE_NOAA case MENU_NOAA_S: gSubMenuSelection = gEeprom.NOAA_AUTO_SCAN; diff --git a/board.c b/board.c index b9bab24..ebf1401 100644 --- a/board.c +++ b/board.c @@ -710,6 +710,9 @@ void BOARD_EEPROM_Init(void) #ifdef ENABLE_AUDIO_BAR gSetting_mic_bar = (Data[7] & (1u << 4)) ? true : false; #endif + #ifdef ENABLE_AM_AGC_GAIN + gSetting_AM_fix = (Data[7] & (1u << 5)) ? true : false; + #endif if (!gEeprom.VFO_OPEN) { diff --git a/driver/bk4819.c b/driver/bk4819.c index beff0cf..91ef2d0 100644 --- a/driver/bk4819.c +++ b/driver/bk4819.c @@ -59,7 +59,7 @@ void BK4819_Init(void) // RX AF level // - // REG_48 <15:12> 11 ??? + // REG_48 <15:12> 11 ??? 0 to 15 // // REG_48 <11:10> 0 AF Rx Gain-1 // 0 = 0dB @@ -76,7 +76,7 @@ void BK4819_Init(void) // 0 = min // BK4819_WriteRegister(BK4819_REG_48, // 0xB3A8); // 1011 00 111010 1000 - (11u << 12) | // ??? + (11u << 12) | // ??? 0..15 ( 0u << 10) | // AF Rx Gain-1 (58u << 4) | // AF Rx Gain-2 ( 8u << 0)); // AF DAC Gain (after Gain-1 and Gain-2) diff --git a/firmware b/firmware index 0b6edca..b68641c 100644 Binary files a/firmware and b/firmware differ diff --git a/firmware.bin b/firmware.bin index 67337c0..297d7b2 100644 Binary files a/firmware.bin and b/firmware.bin differ diff --git a/firmware.packed.bin b/firmware.packed.bin index e77e679..73cee22 100644 Binary files a/firmware.packed.bin and b/firmware.packed.bin differ diff --git a/functions.c b/functions.c index 250a2fc..9f0406c 100644 --- a/functions.c +++ b/functions.c @@ -130,9 +130,8 @@ void FUNCTION_Select(FUNCTION_Type_t Function) break; case FUNCTION_POWER_SAVE: - gBatterySave_10ms = gEeprom.BATTERY_SAVE * 10; - - gBatterySaveCountdownExpired = false; + gPowerSave_10ms = gEeprom.BATTERY_SAVE * 10; + gPowerSaveCountdownExpired = false; gRxIdleMode = true; @@ -199,7 +198,7 @@ void FUNCTION_Select(FUNCTION_Type_t Function) } gBatterySaveCountdown_10ms = battery_save_count_10ms; - gSchedulePowerSave = false; + gSchedulePowerSave = false; #if defined(ENABLE_FMRADIO) gFM_RestoreCountdown = 0; diff --git a/functions.h b/functions.h index cc63dd8..4194d86 100644 --- a/functions.h +++ b/functions.h @@ -21,13 +21,13 @@ enum FUNCTION_Type_t { - FUNCTION_FOREGROUND = 0, - FUNCTION_TRANSMIT, - FUNCTION_MONITOR, - FUNCTION_INCOMING, - FUNCTION_RECEIVE, - FUNCTION_POWER_SAVE, - FUNCTION_BAND_SCOPE + FUNCTION_FOREGROUND = 0, // ??? + FUNCTION_TRANSMIT, // transmitting + FUNCTION_MONITOR, // receiving with squelch forced open + FUNCTION_INCOMING, // receiving a signal (squelch is open) + FUNCTION_RECEIVE, // RX mode, squelch closed + FUNCTION_POWER_SAVE, // sleeping + FUNCTION_BAND_SCOPE // bandscope mode (panadpter/spectrum) .. not yet implemented }; typedef enum FUNCTION_Type_t FUNCTION_Type_t; diff --git a/helper/battery.c b/helper/battery.c index ca4285f..b6f7754 100644 --- a/helper/battery.c +++ b/helper/battery.c @@ -32,7 +32,7 @@ bool gLowBattery; bool gLowBatteryBlink; uint16_t gBatteryCheckCounter; -volatile uint16_t gBatterySave_10ms; +volatile uint16_t gPowerSave_10ms; void BATTERY_GetReadings(bool bDisplayBatteryLevel) { diff --git a/helper/battery.h b/helper/battery.h index 26a4b90..ea0d1b0 100644 --- a/helper/battery.h +++ b/helper/battery.h @@ -31,7 +31,7 @@ extern bool gLowBattery; extern bool gLowBatteryBlink; extern uint16_t gBatteryCheckCounter; -extern volatile uint16_t gBatterySave_10ms; +extern volatile uint16_t gPowerSave_10ms; void BATTERY_GetReadings(bool bDisplayBatteryLevel); diff --git a/main.c b/main.c index d5c2c70..5da17fa 100644 --- a/main.c +++ b/main.c @@ -67,6 +67,8 @@ void Main(void) BOARD_Init(); UART_Init(); + boot_counter_10ms = 250; // 2.5 sec + UART_Send(UART_Version, strlen(UART_Version)); // Not implementing authentic device checks @@ -99,19 +101,14 @@ void Main(void) { // count the number of menu list items unsigned int hidden = 0; gMenuListCount = 0; -// while (MenuList[gMenuListCount].name != NULL) while (MenuList[gMenuListCount].name[0] != '\0') - { if (MenuList[++gMenuListCount].hidden != 0) hidden++; - } // disable the items marked hidden - //gMenuListCount -= 8; - gMenuListCount -= hidden; + gMenuListCount -= 8; + //gMenuListCount -= hidden; } - boot_counter_10ms = 250; // 2.5 sec - if (!gChargingWithTypeC && !gBatteryDisplayLevel) { FUNCTION_Select(FUNCTION_POWER_SAVE); diff --git a/misc.c b/misc.c index b2b2572..1ce5a83 100644 --- a/misc.c +++ b/misc.c @@ -49,6 +49,9 @@ const uint16_t dual_watch_count_toggle_10ms = 100 / 10; // 100ms betw const uint16_t battery_save_count_10ms = 10000 / 10; // 10 seconds +const uint16_t power_save1_10ms = 100 / 10; // 100ms +const uint16_t power_save2_10ms = 200 / 10; // 200ms + const uint16_t gMax_bat_v = 843; // 8.43V const uint16_t gMin_bat_v = 660; // 6.6V //const uint16_t gMin_bat_v = 690; // 6.9V @@ -66,6 +69,9 @@ bool gSetting_TX_EN; uint8_t gSetting_F_LOCK; bool gSetting_ScrambleEnable; +#ifdef ENABLE_AM_AGC_GAIN + bool gSetting_AM_fix; +#endif #ifdef ENABLE_AUDIO_BAR bool gSetting_mic_bar; #endif @@ -90,7 +96,8 @@ uint16_t gEEPROM_1F8C; uint8_t gMR_ChannelAttributes[FREQ_CHANNEL_LAST + 1]; volatile uint16_t gBatterySaveCountdown_10ms = battery_save_count_10ms; -volatile bool gBatterySaveCountdownExpired; + +volatile bool gPowerSaveCountdownExpired; volatile bool gSchedulePowerSave; volatile bool gScheduleDualWatch = true; diff --git a/misc.h b/misc.h index 1161f58..9ceff3d 100644 --- a/misc.h +++ b/misc.h @@ -67,9 +67,9 @@ enum AlarmState_t { typedef enum AlarmState_t AlarmState_t; enum ReceptionMode_t { - RX_MODE_NONE = 0, - RX_MODE_DETECTED, - RX_MODE_LISTENING + RX_MODE_NONE = 0, // squelch close ? + RX_MODE_DETECTED, // signal detected + RX_MODE_LISTENING // }; typedef enum ReceptionMode_t ReceptionMode_t; @@ -105,6 +105,9 @@ extern const uint8_t scan_delay_10ms; extern const uint16_t battery_save_count_10ms; +extern const uint16_t power_save1_10ms; +extern const uint16_t power_save2_10ms; + extern const uint16_t dual_watch_count_after_tx_10ms; extern const uint16_t dual_watch_count_after_rx_10ms; extern const uint16_t dual_watch_count_after_1_10ms; @@ -127,6 +130,9 @@ extern bool gSetting_TX_EN; extern uint8_t gSetting_F_LOCK; extern bool gSetting_ScrambleEnable; +#ifdef ENABLE_AM_AGC_GAIN + extern bool gSetting_AM_fix; +#endif #ifdef ENABLE_AUDIO_BAR extern bool gSetting_mic_bar; #endif @@ -152,8 +158,9 @@ extern uint16_t gEEPROM_1F8C; extern uint8_t gMR_ChannelAttributes[207]; extern volatile uint16_t gBatterySaveCountdown_10ms; + +extern volatile bool gPowerSaveCountdownExpired; extern volatile bool gSchedulePowerSave; -extern volatile bool gBatterySaveCountdownExpired; extern volatile bool gScheduleDualWatch; diff --git a/radio.c b/radio.c index b7e3750..978ea81 100644 --- a/radio.c +++ b/radio.c @@ -443,6 +443,7 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo) pInfo->SquelchOpenRSSIThresh = 0x00; pInfo->SquelchOpenNoiseThresh = 0x7F; pInfo->SquelchCloseGlitchThresh = 0xFF; + pInfo->SquelchCloseRSSIThresh = 0x00; pInfo->SquelchCloseNoiseThresh = 0x7F; pInfo->SquelchOpenGlitchThresh = 0xFF; @@ -450,10 +451,13 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo) else { Base += gEeprom.SQUELCH_LEVEL; + EEPROM_ReadBuffer(Base + 0x00, &pInfo->SquelchOpenRSSIThresh, 1); EEPROM_ReadBuffer(Base + 0x10, &pInfo->SquelchCloseRSSIThresh, 1); + EEPROM_ReadBuffer(Base + 0x20, &pInfo->SquelchOpenNoiseThresh, 1); EEPROM_ReadBuffer(Base + 0x30, &pInfo->SquelchCloseNoiseThresh, 1); + EEPROM_ReadBuffer(Base + 0x40, &pInfo->SquelchCloseGlitchThresh, 1); EEPROM_ReadBuffer(Base + 0x50, &pInfo->SquelchOpenGlitchThresh, 1); diff --git a/scheduler.c b/scheduler.c index 6444851..780c246 100644 --- a/scheduler.c +++ b/scheduler.c @@ -73,7 +73,7 @@ void SystickHandler(void) DECREMENT_AND_TRIGGER(gBatterySaveCountdown_10ms, gSchedulePowerSave); if (gCurrentFunction == FUNCTION_POWER_SAVE) - DECREMENT_AND_TRIGGER(gBatterySave_10ms, gBatterySaveCountdownExpired); + DECREMENT_AND_TRIGGER(gPowerSave_10ms, gPowerSaveCountdownExpired); if (gScanState == SCAN_OFF && gCssScanMode == CSS_SCAN_MODE_OFF && gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) if (gCurrentFunction != FUNCTION_MONITOR && gCurrentFunction != FUNCTION_TRANSMIT && gCurrentFunction != FUNCTION_RECEIVE) diff --git a/settings.c b/settings.c index 9866f60..8516af4 100644 --- a/settings.c +++ b/settings.c @@ -171,6 +171,9 @@ void SETTINGS_SaveSettings(void) #ifdef ENABLE_AUDIO_BAR if (!gSetting_mic_bar) State[7] &= ~(1u << 4); #endif + #ifdef ENABLE_AM_AGC_GAIN + if (!gSetting_AM_fix) State[7] &= ~(1u << 5); + #endif EEPROM_WriteBuffer(0x0F40, State); } diff --git a/ui/menu.c b/ui/menu.c index c65b42b..b9e0d39 100644 --- a/ui/menu.c +++ b/ui/menu.c @@ -101,6 +101,9 @@ const t_menu_item MenuList[] = {"BATVOL", 0, VOICE_ID_INVALID, MENU_VOL }, // was "VOL" {"BATTXT", 0, VOICE_ID_INVALID, MENU_BAT_TXT }, {"MODE", 0, VOICE_ID_INVALID, MENU_AM }, // was "AM" +#ifdef ENABLE_AM_AGC_GAIN + {"AM-FIX", 0, VOICE_ID_INVALID, MENU_AM_FIX }, +#endif #ifdef ENABLE_NOAA {"NOAA-S", 0, VOICE_ID_INVALID, MENU_NOAA_S }, #endif @@ -416,6 +419,12 @@ void UI_DisplayMenu(void) strcpy(String, (gSubMenuSelection == 0) ? "FM" : "AM"); break; + #ifdef ENABLE_AM_AGC_GAIN + case MENU_AM_FIX: + strcpy(String, (gSubMenuSelection == 0) ? "OFF" : "FIXED"); + break; + #endif + case MENU_AUTOLK: strcpy(String, (gSubMenuSelection == 0) ? "OFF" : "AUTO"); break; diff --git a/ui/menu.h b/ui/menu.h index bb194ac..e6859be 100644 --- a/ui/menu.h +++ b/ui/menu.h @@ -93,6 +93,9 @@ enum MENU_VOL, MENU_BAT_TXT, MENU_AM, + #ifdef ENABLE_AM_AGC_GAIN + MENU_AM_FIX, + #endif #ifdef ENABLE_NOAA MENU_NOAA_S, #endif diff --git a/ui/rssi.c b/ui/rssi.c index cb7e015..762650e 100644 --- a/ui/rssi.c +++ b/ui/rssi.c @@ -111,13 +111,19 @@ void UI_UpdateRSSI(uint16_t RSSI) //const int16_t dBm = (int16_t)(RSSI / 2) - 160; - //const unsigned int band = gRxVfo->Band; - const unsigned int band = 0; - - const uint16_t level0 = gEEPROM_RSSI_CALIB[band][0]; - const uint16_t level1 = gEEPROM_RSSI_CALIB[band][1]; - const uint16_t level2 = gEEPROM_RSSI_CALIB[band][2]; - const uint16_t level3 = gEEPROM_RSSI_CALIB[band][3]; + #if 0 + //const unsigned int band = gRxVfo->Band; + const unsigned int band = 0; + const uint16_t level0 = gEEPROM_RSSI_CALIB[band][0]; + const uint16_t level1 = gEEPROM_RSSI_CALIB[band][1]; + const uint16_t level2 = gEEPROM_RSSI_CALIB[band][2]; + const uint16_t level3 = gEEPROM_RSSI_CALIB[band][3]; + #else + const uint16_t level0 = (-115 + 160) * 2; // dB + const uint16_t level1 = ( -89 + 160) * 2; // dB + const uint16_t level2 = ( -64 + 160) * 2; // dB + const uint16_t level3 = ( -39 + 160) * 2; // dB + #endif const uint16_t level01 = (level0 + level1) / 2; const uint16_t level12 = (level1 + level2) / 2; const uint16_t level23 = (level2 + level3) / 2; diff --git a/win_make.bat b/win_make.bat index 17a4a04..51c48c0 100644 --- a/win_make.bat +++ b/win_make.bat @@ -1,32 +1,45 @@ -:: download "gcc-arm-none-eabi-10.3-2021.10-win32.exe" for windows .. -:: https://developer.arm.com/downloads/-/gnu-rm +:: Cmpile directly in windows without the need of a linux virtual machine: +:: +:: 1. Download and install "gcc-arm-none-eabi-10.3-2021.10-win32.exe" from https://developer.arm.com/downloads/-/gnu-rm +:: 2. Download and install "gnu_make-3.81.exe" from https://gnuwin32.sourceforge.net/packages/make.htm +:: 3. You may (or not) need to manualy add gcc path to you OS environment PATH, ie .. +:: C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.10\bin +:: 4. You may (or not) need to reboot your PC after installing the above +:: +:: Then you can run this bat from the directory you saved this source code too. :: -:: download "gnu_make-3.81.exe" for windows .. -:: https://gnuwin32.sourceforge.net/packages/make.htm +:: You will need to edit the line below that runs the make.exe file to point to it's actual location if +:: it's different from mine. +:: delete any left over files from any previous compile del /S /Q *.o >nul 2>nul del /S /Q *.d >nul 2>nul del /S /Q *.bin >nul 2>nul + +:: do the compile ! "C:\Program Files (x86)\GnuWin32\bin\make" + +:: delete the unused created when compiling files del /S /Q *.o >nul 2>nul del /S /Q *.d >nul 2>nul :: If you have python installed, you can create a 'packed' .bin from the compiled firmware.bin file. :: The Quansheng windows upload-to-radio program requires a 'packed' .bin file. :: -:: if you don't have python installed, then comment out the python line(s) below, in which case you'll need -:: to upload the standard unpacked firmware.bin file another way. +:: if you don't have python installed, then you can still upload the standard unpacked firmware.bin +:: file another way ... :: -:: I wrote a windows version of k5prog to do this easily in windows .. +:: I wrote a GUI version of k5prog to do this easily in windows .. :: https://github.com/OneOfEleven/k5prog-win +:: these just install the required initial python module if you want to create the packed firmware bin file, either +:: only needs running once, ever. +:: ::python -m pip install --upgrade pip crcmod ::python3 -m pip install --upgrade pip crcmod -::python fw-pack.py firmware.bin 230921 firmware.packed.bin -::python3 fw-pack.py firmware.bin 230921 firmware.packed.bin - +:: show the compiled .bin file size ::arm-none-eabi-size firmware pause