All checks were successful
Build Firmware / build (push) Successful in 2m2s
699 lines
21 KiB
C
699 lines
21 KiB
C
/* Copyright 2023 Dual Tachyon
|
||
* https://github.com/DualTachyon
|
||
*
|
||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
* you may not use this file except in compliance with the License.
|
||
* You may obtain a copy of the License at
|
||
*
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*/
|
||
|
||
#ifdef ENABLE_FMRADIO
|
||
|
||
#include <string.h>
|
||
|
||
#include "app/action.h"
|
||
#include "app/fm.h"
|
||
#include "app/generic.h"
|
||
#include "audio.h"
|
||
#include "bsp/dp32g030/gpio.h"
|
||
#include "driver/bk1080.h"
|
||
#include "driver/eeprom.h"
|
||
#include "driver/gpio.h"
|
||
#include "functions.h"
|
||
#include "misc.h"
|
||
#include "settings.h"
|
||
#include "ui/inputbox.h"
|
||
#include "ui/ui.h"
|
||
#include "driver/systick.h"
|
||
|
||
#ifndef ARRAY_SIZE
|
||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||
#endif
|
||
|
||
uint16_t gFM_Channels[20];
|
||
bool gFmRadioMode;
|
||
uint8_t gFmRadioCountdown_500ms;
|
||
volatile uint16_t gFmPlayCountdown_10ms;
|
||
volatile int8_t gFM_ScanState;
|
||
bool gFM_AutoScan;
|
||
uint8_t gFM_ChannelPosition;
|
||
bool gFM_FoundFrequency;
|
||
bool gFM_AutoScan;
|
||
uint16_t gFM_RestoreCountdown_10ms;
|
||
|
||
|
||
const uint8_t BUTTON_STATE_PRESSED = 1 << 0;
|
||
const uint8_t BUTTON_STATE_HELD = 1 << 1;
|
||
|
||
const uint8_t BUTTON_EVENT_PRESSED = BUTTON_STATE_PRESSED;
|
||
const uint8_t BUTTON_EVENT_HELD = BUTTON_STATE_PRESSED | BUTTON_STATE_HELD;
|
||
const uint8_t BUTTON_EVENT_SHORT = 0;
|
||
const uint8_t BUTTON_EVENT_LONG = BUTTON_STATE_HELD;
|
||
|
||
|
||
static void Key_FUNC(KEY_Code_t Key, uint8_t state);
|
||
|
||
bool FM_CheckValidChannel(uint8_t Channel) {
|
||
return Channel < ARRAY_SIZE(gFM_Channels) &&
|
||
gFM_Channels[Channel] >= BK1080_GetFreqLoLimit(gEeprom.FM_Band) &&
|
||
gFM_Channels[Channel] < BK1080_GetFreqHiLimit(gEeprom.FM_Band);
|
||
}
|
||
|
||
uint8_t FM_FindNextChannel(uint8_t Channel, uint8_t Direction) {
|
||
for (unsigned i = 0; i < ARRAY_SIZE(gFM_Channels); i++) {
|
||
if (Channel == 0xFF)
|
||
Channel = ARRAY_SIZE(gFM_Channels) - 1;
|
||
else if (Channel >= ARRAY_SIZE(gFM_Channels))
|
||
Channel = 0;
|
||
if (FM_CheckValidChannel(Channel))
|
||
return Channel;
|
||
Channel += Direction;
|
||
}
|
||
|
||
return 0xFF;
|
||
}
|
||
|
||
int FM_ConfigureChannelState(void) {
|
||
gEeprom.FM_FrequencyPlaying = gEeprom.FM_SelectedFrequency;
|
||
|
||
if (gEeprom.FM_IsMrMode) {
|
||
const uint8_t Channel = FM_FindNextChannel(gEeprom.FM_SelectedChannel, FM_CHANNEL_UP);
|
||
if (Channel == 0xFF) {
|
||
gEeprom.FM_IsMrMode = false;
|
||
return -1;
|
||
}
|
||
gEeprom.FM_SelectedChannel = Channel;
|
||
gEeprom.FM_FrequencyPlaying = gFM_Channels[Channel];
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
void FM_TurnOff(void) {
|
||
gFmRadioMode = false;
|
||
gFM_ScanState = FM_SCAN_OFF;
|
||
gFM_RestoreCountdown_10ms = 0;
|
||
|
||
AUDIO_AudioPathOff();
|
||
gEnableSpeaker = false;
|
||
|
||
BK1080_Init0();
|
||
|
||
gUpdateStatus = true;
|
||
|
||
#ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
|
||
gEeprom.CURRENT_STATE = 0;
|
||
SETTINGS_WriteCurrentState();
|
||
#endif
|
||
}
|
||
|
||
void FM_EraseChannels(void) {
|
||
uint8_t Template[8];
|
||
memset(Template, 0xFF, sizeof(Template));
|
||
|
||
for (unsigned i = 0; i < 5; i++)
|
||
EEPROM_WriteBuffer(0x0E40 + (i * 8), Template);
|
||
|
||
memset(gFM_Channels, 0xFF, sizeof(gFM_Channels));
|
||
}
|
||
|
||
void FM_Tune(uint16_t Frequency, int8_t Step, bool bFlag) {
|
||
AUDIO_AudioPathOff();
|
||
|
||
gEnableSpeaker = false;
|
||
|
||
gFmPlayCountdown_10ms = (gFM_ScanState == FM_SCAN_OFF) ? fm_play_countdown_noscan_10ms
|
||
: fm_play_countdown_scan_10ms;
|
||
|
||
gScheduleFM = false;
|
||
gFM_FoundFrequency = false;
|
||
gAskToSave = false;
|
||
gAskToDelete = false;
|
||
gEeprom.FM_FrequencyPlaying = Frequency;
|
||
|
||
if (!bFlag) {
|
||
Frequency += Step;
|
||
if (Frequency < BK1080_GetFreqLoLimit(gEeprom.FM_Band))
|
||
Frequency = BK1080_GetFreqHiLimit(gEeprom.FM_Band);
|
||
else if (Frequency > BK1080_GetFreqHiLimit(gEeprom.FM_Band))
|
||
Frequency = BK1080_GetFreqLoLimit(gEeprom.FM_Band);
|
||
|
||
gEeprom.FM_FrequencyPlaying = Frequency;
|
||
}
|
||
|
||
gFM_ScanState = Step;
|
||
|
||
BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||
}
|
||
|
||
void FM_PlayAndUpdate(void) {
|
||
gFM_ScanState = FM_SCAN_OFF;
|
||
|
||
if (gFM_AutoScan) {
|
||
gEeprom.FM_IsMrMode = true;
|
||
gEeprom.FM_SelectedChannel = 0;
|
||
}
|
||
|
||
FM_ConfigureChannelState();
|
||
BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||
SETTINGS_SaveFM();
|
||
|
||
gFmPlayCountdown_10ms = 0;
|
||
gScheduleFM = false;
|
||
gAskToSave = false;
|
||
|
||
AUDIO_AudioPathOn();
|
||
|
||
gEnableSpeaker = true;
|
||
}
|
||
|
||
int FM_CheckFrequencyLock(uint16_t Frequency, uint16_t LowerLimit) {
|
||
int ret = -1;
|
||
|
||
const uint16_t Test2 = BK1080_ReadRegister(BK1080_REG_07_TEST1);
|
||
|
||
// This is supposed to be a signed value, but above function is unsigned
|
||
const uint16_t Deviation = BK1080_REG_07_GET_FREQD(Test2);
|
||
|
||
if (BK1080_REG_07_GET_SNR(Test2) <= 2) {
|
||
BK1080_FrequencyDeviation = Deviation;
|
||
BK1080_BaseFrequency = Frequency;
|
||
|
||
return ret;
|
||
}
|
||
|
||
const uint16_t Status = BK1080_ReadRegister(BK1080_REG_10_RSSI_STATUS);
|
||
|
||
if ((Status & BK1080_REG_10_MASK_AFCRL) != BK1080_REG_10_AFCRL_NOT_RAILED || BK1080_REG_10_GET_RSSI(Status) < 10) {
|
||
BK1080_FrequencyDeviation = Deviation;
|
||
BK1080_BaseFrequency = Frequency;
|
||
|
||
return ret;
|
||
}
|
||
|
||
//if (Deviation > -281 && Deviation < 280)
|
||
if (Deviation >= 280 && Deviation <= 3815) {
|
||
BK1080_FrequencyDeviation = Deviation;
|
||
BK1080_BaseFrequency = Frequency;
|
||
|
||
return ret;
|
||
}
|
||
|
||
// not BLE(less than or equal)
|
||
if (Frequency > LowerLimit && (Frequency - BK1080_BaseFrequency) == 1) {
|
||
if (BK1080_FrequencyDeviation & 0x800 || (BK1080_FrequencyDeviation < 20)) {
|
||
BK1080_FrequencyDeviation = Deviation;
|
||
BK1080_BaseFrequency = Frequency;
|
||
|
||
return ret;
|
||
}
|
||
}
|
||
|
||
// not BLT(less than)
|
||
|
||
if (Frequency >= LowerLimit && (BK1080_BaseFrequency - Frequency) == 1) {
|
||
if ((BK1080_FrequencyDeviation & 0x800) == 0 || (BK1080_FrequencyDeviation > 4075)) {
|
||
BK1080_FrequencyDeviation = Deviation;
|
||
BK1080_BaseFrequency = Frequency;
|
||
|
||
return ret;
|
||
}
|
||
}
|
||
|
||
ret = 0;
|
||
BK1080_FrequencyDeviation = Deviation;
|
||
BK1080_BaseFrequency = Frequency;
|
||
|
||
return ret;
|
||
}
|
||
|
||
static void Key_DIGITS(KEY_Code_t Key, uint8_t state) {
|
||
enum {
|
||
STATE_FREQ_MODE, STATE_MR_MODE, STATE_SAVE
|
||
};
|
||
|
||
if (state == BUTTON_EVENT_SHORT && !gWasFKeyPressed) {
|
||
uint8_t State;
|
||
|
||
if (gAskToDelete) {
|
||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||
return;
|
||
}
|
||
|
||
if (gAskToSave) {
|
||
State = STATE_SAVE;
|
||
} else {
|
||
if (gFM_ScanState != FM_SCAN_OFF) {
|
||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||
return;
|
||
}
|
||
|
||
State = gEeprom.FM_IsMrMode ? STATE_MR_MODE : STATE_FREQ_MODE;
|
||
}
|
||
|
||
INPUTBOX_Append(Key);
|
||
|
||
gRequestDisplayScreen = DISPLAY_FM;
|
||
|
||
if (State == STATE_FREQ_MODE) {
|
||
if (gInputBoxIndex == 1) {
|
||
if (gInputBox[0] > 1) {
|
||
gInputBox[1] = gInputBox[0];
|
||
gInputBox[0] = 0;
|
||
gInputBoxIndex = 2;
|
||
}
|
||
} else if (gInputBoxIndex > 3) {
|
||
uint32_t Frequency;
|
||
|
||
gInputBoxIndex = 0;
|
||
Frequency = StrToUL(INPUTBOX_GetAscii());
|
||
|
||
if (Frequency < BK1080_GetFreqLoLimit(gEeprom.FM_Band) ||
|
||
BK1080_GetFreqHiLimit(gEeprom.FM_Band) < Frequency) {
|
||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||
gRequestDisplayScreen = DISPLAY_FM;
|
||
return;
|
||
}
|
||
|
||
gEeprom.FM_SelectedFrequency = (uint16_t) Frequency;
|
||
#ifdef ENABLE_VOICE
|
||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||
#endif
|
||
gEeprom.FM_FrequencyPlaying = gEeprom.FM_SelectedFrequency;
|
||
BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||
gRequestSaveFM = true;
|
||
return;
|
||
}
|
||
} else if (gInputBoxIndex == 2) {
|
||
uint8_t Channel;
|
||
|
||
gInputBoxIndex = 0;
|
||
Channel = ((gInputBox[0] * 10) + gInputBox[1]) - 1;
|
||
|
||
if (State == STATE_MR_MODE) {
|
||
if (FM_CheckValidChannel(Channel)) {
|
||
#ifdef ENABLE_VOICE
|
||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||
#endif
|
||
gEeprom.FM_SelectedChannel = Channel;
|
||
gEeprom.FM_FrequencyPlaying = gFM_Channels[Channel];
|
||
BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||
gRequestSaveFM = true;
|
||
return;
|
||
}
|
||
} else if (Channel < 20) {
|
||
#ifdef ENABLE_VOICE
|
||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||
#endif
|
||
gRequestDisplayScreen = DISPLAY_FM;
|
||
gInputBoxIndex = 0;
|
||
gFM_ChannelPosition = Channel;
|
||
return;
|
||
}
|
||
|
||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||
return;
|
||
}
|
||
|
||
#ifdef ENABLE_VOICE
|
||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||
#endif
|
||
} else
|
||
Key_FUNC(Key, state);
|
||
}
|
||
|
||
static void Key_FUNC(KEY_Code_t Key, uint8_t state) {
|
||
if (state == BUTTON_EVENT_SHORT || state == BUTTON_EVENT_HELD) {
|
||
bool autoScan = gWasFKeyPressed || (state == BUTTON_EVENT_HELD);
|
||
|
||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||
gWasFKeyPressed = false;
|
||
gUpdateStatus = true;
|
||
gRequestDisplayScreen = DISPLAY_FM;
|
||
|
||
switch (Key) {
|
||
case KEY_0:
|
||
ACTION_FM();
|
||
break;
|
||
|
||
case KEY_1:
|
||
gEeprom.FM_Band++;
|
||
gRequestSaveFM = true;
|
||
break;
|
||
|
||
// case KEY_2:
|
||
// gEeprom.FM_Space = (gEeprom.FM_Space + 1) % 3;
|
||
// gRequestSaveFM = true;
|
||
// break;
|
||
|
||
case KEY_3:
|
||
gEeprom.FM_IsMrMode = !gEeprom.FM_IsMrMode;
|
||
|
||
if (!FM_ConfigureChannelState()) {
|
||
BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||
gRequestSaveFM = true;
|
||
} else
|
||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||
break;
|
||
|
||
case KEY_4:
|
||
gEeprom.BK1080_AGC_ENABLED = !gEeprom.BK1080_AGC_ENABLED;
|
||
BK1080_UpdateSysconf();
|
||
gRequestSaveSettings = true;
|
||
gRequestSaveFM = true;
|
||
break;
|
||
|
||
case KEY_5:
|
||
gEeprom.BK1080_DEEMPHASIS_CONFIG++;
|
||
BK1080_UpdateSysconf();
|
||
gRequestSaveSettings = true;
|
||
gRequestSaveFM = true;
|
||
break;
|
||
|
||
case KEY_6:
|
||
gEeprom.BK1080_BLEND_CONFIG++;
|
||
BK1080_UpdateSysconf();
|
||
gRequestSaveSettings = true;
|
||
gRequestSaveFM = true;
|
||
break;
|
||
|
||
case KEY_7:
|
||
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, true);
|
||
|
||
// mask just in case
|
||
uint32_t id24 = 0x00A38C;
|
||
uint8_t btn = 0x04;
|
||
uint8_t out[10];
|
||
|
||
// 3-byte big-endian ID
|
||
out[0] = (id24 >> 16) & 0xFF;
|
||
out[1] = (id24 >> 8) & 0xFF;
|
||
out[2] = (id24 >> 0) & 0xFF;
|
||
|
||
// first nibble<6C>\redundancy copy: 0xBB if btn=0xB
|
||
out[3] = (btn << 4) | 0x04;
|
||
|
||
// second copy with MSB flipped (btn ^ 0x8) in the high nibble
|
||
out[4] = ((btn ^ 0x8) << 4);
|
||
|
||
BK4819_EnterTxMute();
|
||
RADIO_SetTxParameters();
|
||
|
||
BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 |
|
||
((127 & 0x7f) << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
|
||
uint16_t datX = BK4819_REG_30_ENABLE_VCO_CALIB |
|
||
BK4819_REG_30_ENABLE_UNKNOWN |
|
||
BK4819_REG_30_DISABLE_RX_LINK |
|
||
BK4819_REG_30_DISABLE_AF_DAC |
|
||
BK4819_REG_30_ENABLE_DISC_MODE |
|
||
BK4819_REG_30_ENABLE_PLL_VCO |
|
||
BK4819_REG_30_ENABLE_PA_GAIN |
|
||
BK4819_REG_30_DISABLE_MIC_ADC |
|
||
BK4819_REG_30_ENABLE_TX_DSP |
|
||
BK4819_REG_30_DISABLE_RX_DSP;
|
||
BK4819_WriteRegister(BK4819_REG_30,
|
||
datX);
|
||
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false);
|
||
SYSTEM_DelayMs(20);
|
||
|
||
for (unsigned int x = 0; x < 24; x++) {
|
||
for (unsigned int y = 0; y < sizeof(out); y++) {
|
||
for (unsigned char i = 7; i < 8; i--) {
|
||
if ((out[y] >> i) & 1) {
|
||
// datX |= BK4819_REG_30_ENABLE_PA_GAIN;
|
||
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, true);
|
||
SYSTICK_DelayUs(400 * 3 - 350);
|
||
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false);
|
||
// datX &= ~BK4819_REG_30_ENABLE_PA_GAIN;
|
||
SYSTICK_DelayUs(400 * 1 - 350);
|
||
} else {
|
||
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, true);
|
||
// datX |= BK4819_REG_30_ENABLE_PA_GAIN;
|
||
SYSTICK_DelayUs(400 * 1 - 350);
|
||
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false);
|
||
// datX &= ~BK4819_REG_30_ENABLE_PA_GAIN;
|
||
SYSTICK_DelayUs(400 * 3 - 350);
|
||
}
|
||
}
|
||
}
|
||
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false);
|
||
SYSTEM_DelayMs(3);
|
||
}
|
||
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false);
|
||
SYSTEM_DelayMs(100);
|
||
BK4819_WriteRegister(BK4819_REG_30, 0xC1FE);
|
||
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false);
|
||
break;
|
||
|
||
case KEY_STAR:
|
||
ACTION_Scan(autoScan);
|
||
break;
|
||
|
||
default:
|
||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void Key_EXIT(uint8_t state) {
|
||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||
|
||
if (state == BUTTON_EVENT_SHORT) {
|
||
return;
|
||
}
|
||
|
||
if (gFM_ScanState == FM_SCAN_OFF || state == BUTTON_EVENT_LONG) {
|
||
if (gInputBoxIndex == 0) {
|
||
if (!gAskToSave && !gAskToDelete) {
|
||
ACTION_FM();
|
||
return;
|
||
}
|
||
|
||
gAskToSave = false;
|
||
gAskToDelete = false;
|
||
} else {
|
||
gInputBox[--gInputBoxIndex] = 10;
|
||
|
||
if (gInputBoxIndex) {
|
||
if (gInputBoxIndex != 1) {
|
||
gRequestDisplayScreen = DISPLAY_FM;
|
||
return;
|
||
}
|
||
|
||
if (gInputBox[0] != 0) {
|
||
gRequestDisplayScreen = DISPLAY_FM;
|
||
return;
|
||
}
|
||
}
|
||
gInputBoxIndex = 0;
|
||
}
|
||
|
||
#ifdef ENABLE_VOICE
|
||
gAnotherVoiceID = VOICE_ID_CANCEL;
|
||
#endif
|
||
} else {
|
||
FM_PlayAndUpdate();
|
||
#ifdef ENABLE_VOICE
|
||
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
|
||
#endif
|
||
}
|
||
|
||
gRequestDisplayScreen = DISPLAY_FM;
|
||
}
|
||
|
||
static void Key_MENU(uint8_t state) {
|
||
if (state != BUTTON_EVENT_SHORT)
|
||
return;
|
||
|
||
|
||
gRequestDisplayScreen = DISPLAY_FM;
|
||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||
|
||
if (gFM_ScanState == FM_SCAN_OFF) {
|
||
if (!gEeprom.FM_IsMrMode) {
|
||
if (gAskToSave) {
|
||
gFM_Channels[gFM_ChannelPosition] = gEeprom.FM_FrequencyPlaying;
|
||
gRequestSaveFM = true;
|
||
}
|
||
gAskToSave = !gAskToSave;
|
||
} else {
|
||
if (gAskToDelete) {
|
||
gFM_Channels[gEeprom.FM_SelectedChannel] = 0xFFFF;
|
||
|
||
FM_ConfigureChannelState();
|
||
BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||
|
||
gRequestSaveFM = true;
|
||
}
|
||
gAskToDelete = !gAskToDelete;
|
||
}
|
||
} else {
|
||
if (gFM_AutoScan || !gFM_FoundFrequency) {
|
||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||
gInputBoxIndex = 0;
|
||
return;
|
||
}
|
||
|
||
if (gAskToSave) {
|
||
gFM_Channels[gFM_ChannelPosition] = gEeprom.FM_FrequencyPlaying;
|
||
gRequestSaveFM = true;
|
||
}
|
||
gAskToSave = !gAskToSave;
|
||
}
|
||
}
|
||
|
||
static void Key_UP_DOWN(uint8_t state, int8_t Step) {
|
||
if (state == BUTTON_EVENT_PRESSED) {
|
||
if (gInputBoxIndex) {
|
||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||
return;
|
||
}
|
||
|
||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||
} else if (gInputBoxIndex || state != BUTTON_EVENT_HELD) {
|
||
return;
|
||
}
|
||
|
||
if (gAskToSave) {
|
||
gRequestDisplayScreen = DISPLAY_FM;
|
||
gFM_ChannelPosition = NUMBER_AddWithWraparound(gFM_ChannelPosition, Step, 0, 19);
|
||
return;
|
||
}
|
||
|
||
if (gFM_ScanState != FM_SCAN_OFF) {
|
||
if (gFM_AutoScan) {
|
||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||
return;
|
||
}
|
||
|
||
FM_Tune(gEeprom.FM_FrequencyPlaying, Step, false);
|
||
gRequestDisplayScreen = DISPLAY_FM;
|
||
return;
|
||
}
|
||
|
||
if (gEeprom.FM_IsMrMode) {
|
||
const uint8_t Channel = FM_FindNextChannel(gEeprom.FM_SelectedChannel + Step, Step);
|
||
if (Channel == 0xFF || gEeprom.FM_SelectedChannel == Channel)
|
||
goto Bail;
|
||
|
||
gEeprom.FM_SelectedChannel = Channel;
|
||
gEeprom.FM_FrequencyPlaying = gFM_Channels[Channel];
|
||
} else {
|
||
uint16_t Frequency = gEeprom.FM_SelectedFrequency + Step;
|
||
|
||
if (Frequency < BK1080_GetFreqLoLimit(gEeprom.FM_Band))
|
||
Frequency = BK1080_GetFreqHiLimit(gEeprom.FM_Band);
|
||
else if (Frequency > BK1080_GetFreqHiLimit(gEeprom.FM_Band))
|
||
Frequency = BK1080_GetFreqLoLimit(gEeprom.FM_Band);
|
||
|
||
gEeprom.FM_FrequencyPlaying = Frequency;
|
||
gEeprom.FM_SelectedFrequency = gEeprom.FM_FrequencyPlaying;
|
||
}
|
||
|
||
gRequestSaveFM = true;
|
||
|
||
Bail:
|
||
BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||
|
||
gRequestDisplayScreen = DISPLAY_FM;
|
||
}
|
||
|
||
void FM_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld) {
|
||
uint8_t state = bKeyPressed + 2 * bKeyHeld;
|
||
|
||
switch (Key) {
|
||
case KEY_0...KEY_9:
|
||
Key_DIGITS(Key, state);
|
||
break;
|
||
case KEY_STAR:
|
||
Key_FUNC(Key, state);
|
||
break;
|
||
case KEY_MENU:
|
||
Key_MENU(state);
|
||
break;
|
||
case KEY_UP:
|
||
Key_UP_DOWN(state, 1);
|
||
break;
|
||
case KEY_DOWN:
|
||
Key_UP_DOWN(state, -1);
|
||
break;;
|
||
case KEY_EXIT:
|
||
Key_EXIT(state);
|
||
break;
|
||
case KEY_F:
|
||
GENERIC_Key_F(bKeyPressed, bKeyHeld);
|
||
break;
|
||
case KEY_PTT:
|
||
GENERIC_Key_PTT(bKeyPressed);
|
||
break;
|
||
default:
|
||
if (!bKeyHeld && bKeyPressed)
|
||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||
break;
|
||
}
|
||
GUI_DisplayScreen();
|
||
}
|
||
|
||
void FM_Play(void) {
|
||
if (!FM_CheckFrequencyLock(gEeprom.FM_FrequencyPlaying, BK1080_GetFreqLoLimit(gEeprom.FM_Band))) {
|
||
if (!gFM_AutoScan) {
|
||
gFmPlayCountdown_10ms = 0;
|
||
gFM_FoundFrequency = true;
|
||
|
||
if (!gEeprom.FM_IsMrMode)
|
||
gEeprom.FM_SelectedFrequency = gEeprom.FM_FrequencyPlaying;
|
||
|
||
AUDIO_AudioPathOn();
|
||
gEnableSpeaker = true;
|
||
|
||
GUI_SelectNextDisplay(DISPLAY_FM);
|
||
return;
|
||
}
|
||
|
||
if (gFM_ChannelPosition < 20)
|
||
gFM_Channels[gFM_ChannelPosition++] = gEeprom.FM_FrequencyPlaying;
|
||
|
||
if (gFM_ChannelPosition >= 20) {
|
||
FM_PlayAndUpdate();
|
||
GUI_SelectNextDisplay(DISPLAY_FM);
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (gFM_AutoScan && gEeprom.FM_FrequencyPlaying >= BK1080_GetFreqHiLimit(1))
|
||
FM_PlayAndUpdate();
|
||
else
|
||
FM_Tune(gEeprom.FM_FrequencyPlaying, gFM_ScanState, false);
|
||
|
||
GUI_SelectNextDisplay(DISPLAY_FM);
|
||
}
|
||
|
||
void FM_Start(void) {
|
||
gDualWatchActive = false;
|
||
gFmRadioMode = true;
|
||
gFM_ScanState = FM_SCAN_OFF;
|
||
gFM_RestoreCountdown_10ms = 0;
|
||
|
||
BK1080_Init(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||
|
||
AUDIO_AudioPathOn();
|
||
|
||
gEnableSpeaker = true;
|
||
gUpdateStatus = true;
|
||
|
||
#ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
|
||
gEeprom.CURRENT_STATE = 3;
|
||
SETTINGS_WriteCurrentState();
|
||
#endif
|
||
}
|
||
|
||
#endif
|