diff --git a/libs/k5_uv_system/hardware/adc.hpp b/libs/k5_uv_system/hardware/adc.hpp new file mode 100644 index 0000000..e78925d --- /dev/null +++ b/libs/k5_uv_system/hardware/adc.hpp @@ -0,0 +1,18 @@ +#pragma once +#include "registers.hpp" +#include "system.hpp" + +namespace Adc +{ + inline unsigned short ReadSingleChannelSync(unsigned char u8Channel) + { + ADC->ADC_START |= 1; + + while(!(ADC->CHANNEL[u8Channel].STAT & 1)) + { + } + + ADC->ADC_IF = 1 << u8Channel; + return ADC->CHANNEL[u8Channel].DATA & 0xFFF; + } +}; \ No newline at end of file diff --git a/libs/k5_uv_system/registers.hpp b/libs/k5_uv_system/registers.hpp index 8f066eb..e6314de 100644 --- a/libs/k5_uv_system/registers.hpp +++ b/libs/k5_uv_system/registers.hpp @@ -60,6 +60,24 @@ struct TSysCon unsigned int PLL_ST; }; +struct TAdc +{ + unsigned int ADC_CFG; + unsigned int ADC_START; + unsigned int ADC_IE; + unsigned int ADC_IF; + struct + { + unsigned int STAT; + unsigned int DATA; + }CHANNEL[16]; + unsigned int ADC_FIFO_STAT; + unsigned int ADC_FIFO_DATA; + unsigned int EXTTRIG_SEL; + unsigned int ADC_CALIB_OFFSET; + unsigned int ADC_CALIB_KD; +}; + #define GPIO_BASE 0x400B0000 #define GPIO ((TPort*)GPIO_BASE) #define __BKPT(value) __asm volatile ("bkpt "#value) @@ -94,4 +112,7 @@ struct TSysCon #define SYSCON_BASE 0x40000000 #define SYSCON ((TSysCon*)SYSCON_BASE) +#define ADC_BASE 0x400BA000 +#define ADC ((TAdc*)ADC_BASE) + diff --git a/libs/radio/radio.hpp b/libs/radio/radio.hpp index 7688655..2c04c3d 100644 --- a/libs/radio/radio.hpp +++ b/libs/radio/radio.hpp @@ -4,246 +4,291 @@ #include "system.hpp" #include -static constexpr auto operator""_Hz(unsigned long long Hertz) { - return Hertz / 10; +static constexpr auto operator""_Hz(unsigned long long Hertz) +{ + return Hertz / 10; } -static constexpr auto operator""_KHz(unsigned long long KiloHertz) { - return KiloHertz * 1000_Hz; +static constexpr auto operator""_KHz(unsigned long long KiloHertz) +{ + return KiloHertz * 1000_Hz; } -static constexpr auto operator""_MHz(unsigned long long KiloHertz) { - return KiloHertz * 1000_KHz; +static constexpr auto operator""_MHz(unsigned long long KiloHertz) +{ + return KiloHertz * 1000_KHz; } -namespace Radio { -enum eIrq : unsigned short { - FifoAlmostFull = 1 << 12, - RxDone = 1 << 13, -}; - -enum class eFskMode : unsigned char { - Fsk1200 = 0, - Ffsk1200_1200_1800, - Ffsk1200_1200_2400, - NoaaSame, - ModesCount, -}; - -struct TFskModeBits { - unsigned char u8TxModeBits; - unsigned char u8RxBandWidthBits; - unsigned char u8RxModeBits; -}; - -constexpr TFskModeBits ModesBits[(int)eFskMode::ModesCount] = { - // Tx mode Rx badwitdh Rx Mode - {0b000, 0b000, 0b000}, // Fsk1200 - {0b001, 0b001, 0b111}, // Ffsk1200_1200_1800 - {0b011, 0b100, 0b100}, // Ffsk1200_1200_2400 - {0b101, 0b010, 0b000}, // NoaaSame -}; - -enum class eState : unsigned char { - Idle, - RxPending, -}; - -using CallbackRxDoneType = CCallback; -template class CBK4819 { - CallbackRxDoneType CallbackRxDone; - unsigned char *p8RxBuff; - unsigned char u8RxBuffSize; - -public: - CBK4819() : State(eState::Idle), u16RxDataLen(0){}; - - // void SetFrequency(unsigned int u32FrequencyD10) - // { - // Fw.BK4819WriteFrequency(u32FrequencyD10); - // } - - static unsigned int GetFrequency() { - return (Fw.BK4819Read(0x39) << 16) | Fw.BK4819Read(0x38); - } - - static signed short GetRssi() { - short s16Rssi = ((Fw.BK4819Read(0x67) >> 1) & 0xFF); - return s16Rssi - 160; - } - - bool IsTx() { return Fw.BK4819Read(0x30) & 0b10; } - - bool IsSqlOpen() { return Fw.BK4819Read(0x0C) & 0b10; } - - static void SetFrequency(unsigned int u32Freq) { - Fw.BK4819Write(0x39, ((u32Freq >> 16) & 0xFFFF)); - Fw.BK4819Write(0x38, (u32Freq & 0xFFFF)); - auto OldReg = Fw.BK4819Read(0x30); - Fw.BK4819Write(0x30, 0); - Fw.BK4819Write(0x30, OldReg); - } - - void SetAgcTable(unsigned short *p16AgcTable) { - for (unsigned char i = 0; i < 5; i++) { - Fw.BK4819Write(0x10 + i, p16AgcTable[i]); - } - } - - void GetAgcTable(unsigned short *p16AgcTable) { - for (unsigned char i = 0; i < 5; i++) { - p16AgcTable[i] = Fw.BK4819Read(0x10 + i); - } - } - - void SetDeviationPresent(unsigned char u8Present) { - auto Reg40 = Fw.BK4819Read(0x40); - Reg40 &= ~(1 << 12); - Reg40 |= (u8Present << 12); - Fw.BK4819Write(0x40, Reg40); - } - - void SetCalibration(unsigned char bOn) { - auto Reg30 = Fw.BK4819Read(0x31); - Reg30 &= ~(1 << 3); - Reg30 |= (bOn << 3); - Fw.BK4819Write(0x31, Reg30); - } - - unsigned char GetAFAmplitude() { return Fw.BK4819Read(0x6F) & 0b1111111; } - - static void ToggleAFDAC(bool enabled) { - auto Reg = Fw.BK4819Read(0x30); - Reg &= ~(1 << 9); - if (enabled) - Reg |= (1 << 9); - Fw.BK4819Write(0x30, Reg); - } - - static void ToggleRXDSP(bool enabled) { - auto Reg = Fw.BK4819Read(0x30); - Reg &= ~1; - if (enabled) - Reg |= 1; - Fw.BK4819Write(0x30, Reg); - } - - void SendSyncAirCopyMode72(unsigned char *p8Data) { - Fw.BK4819ConfigureAndStartTxFsk(); - Fw.AirCopyFskSetup(); - Fw.AirCopy72(p8Data); - Fw.BK4819SetGpio(1, false); - } - - void DisablePa() { Fw.BK4819Write(0x30, Fw.BK4819Read(0x30) & ~0b1010); } - - void SetFskMode(eFskMode Mode) { - auto const &ModeParams = ModesBits[(int)Mode]; - auto Reg58 = Fw.BK4819Read(0x58); - Reg58 &= ~((0b111 << 1) | (0b111 << 10) | (0b111 << 13)); - Reg58 |= (ModeParams.u8RxBandWidthBits << 1) | - (ModeParams.u8RxModeBits << 10) | (ModeParams.u8TxModeBits << 13); - Fw.BK4819Write(0x58, 0); - Fw.BK4819Write(0x58, Reg58); - } - - void FixIrqEnRegister() // original firmware overrides IRQ_EN reg, so we need - // to reenable it - { - auto const OldIrqEnReg = Fw.BK4819Read(0x3F); - if ((OldIrqEnReg & (eIrq::FifoAlmostFull | eIrq::RxDone)) != - (eIrq::FifoAlmostFull | eIrq::RxDone)) { - Fw.BK4819Write(0x3F, OldIrqEnReg | eIrq::FifoAlmostFull | eIrq::RxDone); - } - } - - void RecieveAsyncAirCopyMode(unsigned char *p8Data, unsigned char u8DataLen, - CallbackRxDoneType Callback) { - if (!p8Data || !u8DataLen) { - return; - } - - CallbackRxDone = Callback; - p8RxBuff = p8Data; - u8RxBuffSize = u8DataLen; - u16RxDataLen = 0; - - Fw.AirCopyFskSetup(); - Fw.BK4819ConfigureAndStartRxFsk(); - State = eState::RxPending; - } - - void DisableFskModem() { - auto const FskSettings = Fw.BK4819Read(0x58); - Fw.BK4819Write(0x58, FskSettings & ~1); - } - - void ClearRxFifoBuff() { - auto const Reg59 = Fw.BK4819Read(0x59); - Fw.BK4819Write(0x59, 1 << 14); - Fw.BK4819Write(0x59, Reg59); - } - - unsigned short GetIrqReg() { - Fw.BK4819Write(0x2, 0); - return Fw.BK4819Read(0x2); - } - - bool CheckCrc() { return Fw.BK4819Read(0x0B) & (1 << 4); } - - bool IsLockedByOrgFw() { return !(GPIOC->DATA & 0b1); } - - unsigned short u16DebugIrq; - - void HandleRxDone() { - ClearRxFifoBuff(); - DisableFskModem(); - State = eState::Idle; - CallbackRxDone(u16RxDataLen, CheckCrc()); - } - - void InterruptHandler() { - if (IsLockedByOrgFw()) { - return; - } - - if (State == eState::RxPending) { - FixIrqEnRegister(); - if (!(Fw.BK4819Read(0x0C) & 1)) // irq request indicator - { - return; - } - - auto const IrqReg = GetIrqReg(); - - if (IrqReg & eIrq::RxDone) { - // HandleRxDone(); - } - - if (IrqReg & eIrq::FifoAlmostFull) { - HandleFifoAlmostFull(); - } - } - } - - eState State; - unsigned short u16RxDataLen; - -private: - void HandleFifoAlmostFull() { - for (unsigned char i = 0; i < 4; i++) { - auto const RxData = Fw.BK4819Read(0x5F); - if (p8RxBuff && u16RxDataLen < u8RxBuffSize - 2) { - memcpy(p8RxBuff + u16RxDataLen, &RxData, 2); - } - - u16RxDataLen += 2; - } - - if (u16RxDataLen >= u8RxBuffSize) { - State = eState::Idle; - CallbackRxDone(u8RxBuffSize, CheckCrc()); - } - } -}; +namespace Radio +{ + enum eIrq : unsigned short + { + FifoAlmostFull = 1 << 12, + RxDone = 1 << 13, + }; + + enum class eFskMode : unsigned char + { + Fsk1200 = 0, + Ffsk1200_1200_1800, + Ffsk1200_1200_2400, + NoaaSame, + ModesCount, + }; + + struct TFskModeBits + { + unsigned char u8TxModeBits; + unsigned char u8RxBandWidthBits; + unsigned char u8RxModeBits; + }; + + constexpr TFskModeBits ModesBits[(int)eFskMode::ModesCount] = { + // Tx mode Rx badwitdh Rx Mode + {0b000, 0b000, 0b000}, // Fsk1200 + {0b001, 0b001, 0b111}, // Ffsk1200_1200_1800 + {0b011, 0b100, 0b100}, // Ffsk1200_1200_2400 + {0b101, 0b010, 0b000}, // NoaaSame + }; + + enum class eState : unsigned char + { + Idle, + RxPending, + }; + + using CallbackRxDoneType = CCallback; + template + class CBK4819 + { + CallbackRxDoneType CallbackRxDone; + unsigned char *p8RxBuff; + unsigned char u8RxBuffSize; + + public: + CBK4819() : State(eState::Idle), u16RxDataLen(0){}; + + // void SetFrequency(unsigned int u32FrequencyD10) + // { + // Fw.BK4819WriteFrequency(u32FrequencyD10); + // } + + static unsigned int GetFrequency() + { + return (Fw.BK4819Read(0x39) << 16) | Fw.BK4819Read(0x38); + } + + static signed short GetRssi() + { + short s16Rssi = ((Fw.BK4819Read(0x67) >> 1) & 0xFF); + return s16Rssi - 160; + } + + bool IsTx() { return Fw.BK4819Read(0x30) & 0b10; } + + bool IsSqlOpen() { return Fw.BK4819Read(0x0C) & 0b10; } + + static void SetFrequency(unsigned int u32Freq) + { + Fw.BK4819Write(0x39, ((u32Freq >> 16) & 0xFFFF)); + Fw.BK4819Write(0x38, (u32Freq & 0xFFFF)); + auto OldReg = Fw.BK4819Read(0x30); + Fw.BK4819Write(0x30, 0); + Fw.BK4819Write(0x30, OldReg); + } + + void SetAgcTable(unsigned short *p16AgcTable) + { + for (unsigned char i = 0; i < 5; i++) + { + Fw.BK4819Write(0x10 + i, p16AgcTable[i]); + } + } + + void GetAgcTable(unsigned short *p16AgcTable) + { + for (unsigned char i = 0; i < 5; i++) + { + p16AgcTable[i] = Fw.BK4819Read(0x10 + i); + } + } + + void SetDeviationPresent(unsigned char u8Present) + { + auto Reg40 = Fw.BK4819Read(0x40); + Reg40 &= ~(1 << 12); + Reg40 |= (u8Present << 12); + Fw.BK4819Write(0x40, Reg40); + } + + void SetCalibration(unsigned char bOn) + { + auto Reg30 = Fw.BK4819Read(0x31); + Reg30 &= ~(1 << 3); + Reg30 |= (bOn << 3); + Fw.BK4819Write(0x31, Reg30); + } + + unsigned char GetAFAmplitude() { return Fw.BK4819Read(0x6F) & 0b1111111; } + + unsigned short GetVoiceAmplitude() + { + // Fw.BK4819Write(0x64, 0); + return Fw.BK4819Read(0x64); + } + + static void ToggleAFDAC(bool enabled) + { + auto Reg = Fw.BK4819Read(0x30); + Reg &= ~(1 << 9); + if (enabled) + Reg |= (1 << 9); + Fw.BK4819Write(0x30, Reg); + } + + static void ToggleRXDSP(bool enabled) + { + auto Reg = Fw.BK4819Read(0x30); + Reg &= ~1; + if (enabled) + Reg |= 1; + Fw.BK4819Write(0x30, Reg); + } + + void SendSyncAirCopyMode72(unsigned char *p8Data) + { + Fw.BK4819ConfigureAndStartTxFsk(); + Fw.AirCopyFskSetup(); + Fw.AirCopy72(p8Data); + Fw.BK4819SetGpio(1, false); + } + + void DisablePa() { Fw.BK4819Write(0x30, Fw.BK4819Read(0x30) & ~0b1010); } + + void SetFskMode(eFskMode Mode) + { + auto const &ModeParams = ModesBits[(int)Mode]; + auto Reg58 = Fw.BK4819Read(0x58); + Reg58 &= ~((0b111 << 1) | (0b111 << 10) | (0b111 << 13)); + Reg58 |= (ModeParams.u8RxBandWidthBits << 1) | + (ModeParams.u8RxModeBits << 10) | (ModeParams.u8TxModeBits << 13); + Fw.BK4819Write(0x58, 0); + Fw.BK4819Write(0x58, Reg58); + } + + void FixIrqEnRegister() // original firmware overrides IRQ_EN reg, so we need + // to reenable it + { + auto const OldIrqEnReg = Fw.BK4819Read(0x3F); + if ((OldIrqEnReg & (eIrq::FifoAlmostFull | eIrq::RxDone)) != + (eIrq::FifoAlmostFull | eIrq::RxDone)) + { + Fw.BK4819Write(0x3F, OldIrqEnReg | eIrq::FifoAlmostFull | eIrq::RxDone); + } + } + + void RecieveAsyncAirCopyMode(unsigned char *p8Data, unsigned char u8DataLen, + CallbackRxDoneType Callback) + { + if (!p8Data || !u8DataLen) + { + return; + } + + CallbackRxDone = Callback; + p8RxBuff = p8Data; + u8RxBuffSize = u8DataLen; + u16RxDataLen = 0; + + Fw.AirCopyFskSetup(); + Fw.BK4819ConfigureAndStartRxFsk(); + State = eState::RxPending; + } + + void DisableFskModem() + { + auto const FskSettings = Fw.BK4819Read(0x58); + Fw.BK4819Write(0x58, FskSettings & ~1); + } + + void ClearRxFifoBuff() + { + auto const Reg59 = Fw.BK4819Read(0x59); + Fw.BK4819Write(0x59, 1 << 14); + Fw.BK4819Write(0x59, Reg59); + } + + unsigned short GetIrqReg() + { + Fw.BK4819Write(0x2, 0); + return Fw.BK4819Read(0x2); + } + + bool CheckCrc() { return Fw.BK4819Read(0x0B) & (1 << 4); } + + bool IsLockedByOrgFw() { return !(GPIOC->DATA & 0b1); } + + unsigned short u16DebugIrq; + + void HandleRxDone() + { + ClearRxFifoBuff(); + DisableFskModem(); + State = eState::Idle; + CallbackRxDone(u16RxDataLen, CheckCrc()); + } + + void InterruptHandler() + { + if (IsLockedByOrgFw()) + { + return; + } + + if (State == eState::RxPending) + { + FixIrqEnRegister(); + if (!(Fw.BK4819Read(0x0C) & 1)) // irq request indicator + { + return; + } + + auto const IrqReg = GetIrqReg(); + + if (IrqReg & eIrq::RxDone) + { + // HandleRxDone(); + } + + if (IrqReg & eIrq::FifoAlmostFull) + { + HandleFifoAlmostFull(); + } + } + } + + eState State; + unsigned short u16RxDataLen; + + private: + void HandleFifoAlmostFull() + { + for (unsigned char i = 0; i < 4; i++) + { + auto const RxData = Fw.BK4819Read(0x5F); + if (p8RxBuff && u16RxDataLen < u8RxBuffSize - 2) + { + memcpy(p8RxBuff + u16RxDataLen, &RxData, 2); + } + + u16RxDataLen += 2; + } + + if (u16RxDataLen >= u8RxBuffSize) + { + State = eState::Idle; + CallbackRxDone(u8RxBuffSize, CheckCrc()); + } + } + }; } // namespace Radio diff --git a/libs/views/am_tx.hpp b/libs/views/am_tx.hpp index f484be4..722363c 100644 --- a/libs/views/am_tx.hpp +++ b/libs/views/am_tx.hpp @@ -1,6 +1,7 @@ #pragma once #include "manager.hpp" #include "registers.hpp" +#include "hardware/adc.hpp" template < const System::TOrgFunctions &Fw, @@ -16,8 +17,10 @@ class CAmTx : public IView bool bAmMode = false; bool bEnabled = false; unsigned short u16OldAmp = 0; + unsigned short u16ActualAmp = 0; int s32DeltaAmp = 0; unsigned int u32StartFreq = 0; + bool bInit = false; // unsigned short U16OldAgcTable[5]; // unsigned short U16NewAgcTable[5] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; @@ -29,37 +32,22 @@ class CAmTx : public IView return eScreenRefreshFlag::NoRefresh; } - if constexpr (bAmpTests) + if(bInit) { - // Fw.BK4819Write(0x29, 0); - // Fw.BK4819Write(0x2B, 0); - // Fw.BK4819Write(0x19, 0); - // RadioDriver.SetDeviationPresent(0); - HandleTests(); - if (!CheckForPtt()) - { - RadioDriver.SetDeviationPresent(1); - Context.ViewStack.Pop(); - } - - return eScreenRefreshFlag::MainScreen; + bInit = false; + RadioDriver.SetDeviationPresent(0); + u32StartFreq = RadioDriver.GetFrequency(); } - RadioDriver.SetDeviationPresent(0); - auto InitialBias = Fw.BK4819Read(0x36); - - u32StartFreq = RadioDriver.GetFrequency(); + HandleTests(); - while (CheckForPtt()) + if (CheckForPtt()) { - HandleMicInput(); - HandleTxAm(); - //HandleTxWfm(); + return eScreenRefreshFlag::MainScreen; } RadioDriver.SetFrequency(u32StartFreq); RadioDriver.SetDeviationPresent(1); - Fw.BK4819Write(0x36, InitialBias); Context.ViewStack.Pop(); return eScreenRefreshFlag::NoRefresh; @@ -67,25 +55,55 @@ class CAmTx : public IView void HandleTests() { - HandleMicInput(); - char S8DebugStr[20]; - // int MicAmp = s32DeltaAmp / 8; // RadioDriver.GetAFAmplitude(); - // MicAmp = 4 + MicAmp; - // if (MicAmp > 0b111) - // MicAmp = 0b111; - // if (MicAmp < 0) - // MicAmp = 0; - unsigned short U16AdcData[2]; - Fw.AdcReadout(U16AdcData, U16AdcData+1); - Fw.FormatString(S8DebugStr, "in 1: %05i ", U16AdcData[0]); + if constexpr(!bAmpTests) + { + return; + } + + // HandleMicInput(); + char S8DebugStr[6 * 40 + 1]; + // static constexpr auto reg = 0x6F; + DisplayBuff.ClearAll(); + + Fw.FormatString(S8DebugStr, "%05i %05i ", RadioDriver.GetVoiceAmplitude(), RadioDriver.GetAFAmplitude()); Fw.PrintTextOnScreen(S8DebugStr, 0, 127, 0, 8, 0); - Fw.FormatString(S8DebugStr, "in 2: %05i ", U16AdcData[1]); - Fw.PrintTextOnScreen(S8DebugStr, 0, 127, 2, 8, 0); + DrawMicInChart(); + } + + void DrawMicInChart() + { + static constexpr auto chartBottomY = 55; + static constexpr auto chartTopY = 16; + unsigned char u8LastYpoint; + for(unsigned short x = 0; x < 128; x++) + { + auto ypoint = RadioDriver.GetVoiceAmplitude(); + ypoint >>= 6; + if(ypoint >= chartBottomY - chartTopY) + { + ypoint = chartTopY; + } + else + { + ypoint = chartBottomY - ypoint; + } + + if(!x) u8LastYpoint = ypoint; + DisplayBuff.SetPixel(x, ypoint); + while (ypoint != u8LastYpoint) + { + u8LastYpoint += u8LastYpoint < ypoint ? 1 : -1; + DisplayBuff.SetPixel(x, u8LastYpoint); + } + + u8LastYpoint = ypoint; + } } void HandleMicInput() { - unsigned short u16ActualAmp = Fw.BK4819Read(0x64); + u16ActualAmp = Fw.BK4819Read(0x64); + // u16ActualAmp = Fw.BK4819Read(0x6F) & 0b1111111; s32DeltaAmp = u16OldAmp - u16ActualAmp; u16OldAmp = u16ActualAmp; } @@ -131,6 +149,7 @@ class CAmTx : public IView return eScreenRefreshFlag::StatusBar; } + bInit = true; Context.ViewStack.Push(*this); return eScreenRefreshFlag::StatusBar; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8882f60..c16e9ef 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,3 +8,4 @@ add_subdirectory(spectrum_fagci) add_subdirectory(t9_texting) add_subdirectory(messenger) add_subdirectory(rssi_sbar_hot) +add_subdirectory(am_tx) \ No newline at end of file diff --git a/src/am_tx/CMakeLists.txt b/src/am_tx/CMakeLists.txt new file mode 100644 index 0000000..ac7f111 --- /dev/null +++ b/src/am_tx/CMakeLists.txt @@ -0,0 +1,78 @@ +set(NAME am_tx) +set(MCU_TARGET_FILES_DIR ../mcu_target_common) + +add_executable(${NAME} + main.cpp + hardware/hardware.cpp + dp32g030.s +) + +target_link_libraries(${NAME} + orginal_fw + uv_k5_system + lcd + views +) + +target_include_directories(${NAME} PUBLIC + ./ + Drivers/CMSIS/Device/ST/STM32G0xx/Include + Drivers/CMSIS/DSP/Include + Drivers/CMSIS/Include +) + +target_compile_definitions(${NAME} PRIVATE + ${STM32_DEFINES} + $<$:DEBUG_ENABLED> +) + +target_compile_options(${NAME} PRIVATE + ${COMPILER_OPTIONS} +) + +target_link_options(${NAME} PRIVATE + #-print-multi-lib + -T ${CMAKE_CURRENT_SOURCE_DIR}/memory.ld + -mcpu=cortex-m0 + -mthumb + -mfpu=auto + -mfloat-abi=soft + -specs=nosys.specs + -specs=nano.specs + -lc + -lm + -lnosys + -Wl,-Map=${PROJECT_NAME}.map,--cref + -Wl,--gc-sections + -Wl,--print-memory-usage + -Wstack-usage=128 + -Wno-register +) + +add_custom_command(TARGET ${NAME} + POST_BUILD + COMMAND arm-none-eabi-size ${NAME} +) +#convert to hex +add_custom_command(TARGET ${NAME} + POST_BUILD + COMMAND arm-none-eabi-objcopy -O ihex ${NAME} ${NAME}.hex + COMMAND arm-none-eabi-objcopy -O binary ${NAME} ${NAME}.bin +) + +get_target_property(BOOTLOADER_BIN_PATH orginal_fw BOOTLOADER_BIN_PATH) +add_custom_command(TARGET ${NAME} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo "generating full binary with bootloader to ${NAME}_with_bootloader.bin" + COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/fw_merger.py ${BOOTLOADER_BIN_PATH} ${NAME}.bin ${NAME}_with_bootloader.bin +) + +add_custom_target(${NAME}_flash + COMMAND openocd -f interface/cmsis-dap.cfg -f ${PROJECT_SOURCE_DIR}/openocd_scripts/dp32g030.cfg -c "write_image ${PROJECT_SOURCE_DIR}/build/src/rssi_printer/rssi_printer.bin 0x1000" -c "halt" -c "shutdown" + DEPENDS ${NAME} +) + +add_custom_target(${NAME}_encoded + COMMAND python ${PROJECT_SOURCE_DIR}/tools/fw_tools/python-utils/fw_pack.py ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.bin ${CMAKE_CURRENT_SOURCE_DIR}/../orginal_fw/k5_26_encrypted_18to1300MHz.ver.bin ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_encoded.bin + DEPENDS ${NAME} +) \ No newline at end of file diff --git a/src/am_tx/dp32g030.s b/src/am_tx/dp32g030.s new file mode 100644 index 0000000..8de265c --- /dev/null +++ b/src/am_tx/dp32g030.s @@ -0,0 +1,18 @@ + .syntax unified + .cpu cortex-m0 + .fpu softvfp + .thumb + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r0, =_estack + mov sp, r0 /* set stack pointer */ + + bl main + +LoopForever: + b LoopForever + +.size Reset_Handler, .-Reset_Handler diff --git a/src/am_tx/exec.hpp b/src/am_tx/exec.hpp new file mode 100644 index 0000000..184d46b --- /dev/null +++ b/src/am_tx/exec.hpp @@ -0,0 +1,17 @@ +#include "registers.hpp" + +class CExec final +{ + public: + CExec(){}; + + void InterruptCallback() + { + CheckButtons(); + } + + private: + void CheckButtons() const + { + } +}; \ No newline at end of file diff --git a/src/am_tx/fw_merger.py b/src/am_tx/fw_merger.py new file mode 100644 index 0000000..7a80c5c --- /dev/null +++ b/src/am_tx/fw_merger.py @@ -0,0 +1,16 @@ +import sys + +def merge_files(in1, in2, out): + f1 = open(in1, 'rb') + f2 = open(in2, 'rb') + fo = open(out, 'wb') + + fo.write(f1.read()) + fo.write(f2.read()) + fo.close() + f1.close() + f2.close() + +if __name__ == '__main__': + args = sys.argv + merge_files(args[1], args[2], args[3]) \ No newline at end of file diff --git a/src/am_tx/hardware/hardware.cpp b/src/am_tx/hardware/hardware.cpp new file mode 100644 index 0000000..32621a5 --- /dev/null +++ b/src/am_tx/hardware/hardware.cpp @@ -0,0 +1,50 @@ +#include "hardware.hpp" +#include "registers.hpp" + +using namespace Hardware; + +void TPower::EnableDbg() +{ + GPIOB->DIR &= ~(GPIO_PIN_11|GPIO_PIN_14); + // PB11 alternate fx to SWDIO + GPIO->PORTB_SEL1 &= ~(0b1111 << 12); + GPIO->PORTB_SEL1 |= (0b1 << 12); + + // PB14 alternate fx to SWDIO + GPIO->PORTB_SEL1 &= ~(0b1111 << 24); + GPIO->PORTB_SEL1 |= (0b1 << 24); +} + +void TSystem::Delay(unsigned int u32Ticks) +{ + for(volatile unsigned int i = 0; i < u32Ticks; i++) + { + __asm volatile ("dsb sy" : : : "memory"); + } +} + +void TFlashLight::On() +{ + GPIOC->DATA |= 1 << 3; +} + +void TFlashLight::Off() +{ + GPIOC->DATA &= ~(1 << 3); +} + +void TFlashLight::Toggle() +{ + GPIOC->DATA ^= 1 << 3; +} + +void TFlashLight::BlinkSync(unsigned char u8BlinksCnt) +{ + for(unsigned char i = 0; i < u8BlinksCnt*2; i++) + { + Toggle(); + System.Delay(200000); + } + + Off(); +} \ No newline at end of file diff --git a/src/am_tx/hardware/hardware.hpp b/src/am_tx/hardware/hardware.hpp new file mode 100644 index 0000000..e0a8120 --- /dev/null +++ b/src/am_tx/hardware/hardware.hpp @@ -0,0 +1,29 @@ +namespace Hardware +{ + struct TPower + { + void EnableDbg(); + }; + + struct TSystem + { + static void Delay(unsigned int u32Ticks); + }; + + struct TFlashLight + { + TFlashLight(TSystem& Sys) :System(Sys){}; + void On(); + void Off(); + void Toggle(); + void BlinkSync(unsigned char u8BlinksCnt); + TSystem& System; + }; + + struct THardware + { + TPower Power; + TSystem System; + TFlashLight FlashLight = {System}; + }; +} \ No newline at end of file diff --git a/src/am_tx/main.cpp b/src/am_tx/main.cpp new file mode 100644 index 0000000..30f62b3 --- /dev/null +++ b/src/am_tx/main.cpp @@ -0,0 +1,71 @@ +#include "system.hpp" +#include "uv_k5_display.hpp" +#include "messenger.hpp" +#include "radio.hpp" +#include "am_tx.hpp" +#include "rssi_sbar.hpp" +#include "manager.hpp" + +const System::TOrgFunctions &Fw = System::OrgFunc_01_26; +const System::TOrgData &FwData = System::OrgData_01_26; + +TUV_K5Display DisplayBuff(FwData.pDisplayBuffer); +const TUV_K5SmallNumbers FontSmallNr(FwData.pSmallDigs); +CDisplay Display(DisplayBuff); + +TUV_K5Display StatusBarBuff(FwData.pStatusBarData); +CDisplay DisplayStatusBar(StatusBarBuff); + +Radio::CBK4819 RadioDriver; + +// CRssiSbar< +// System::OrgFunc_01_26, +// System::OrgData_01_26, +// DisplayBuff, +// Display, +// DisplayStatusBar, +// FontSmallNr, +// RadioDriver> +// RssiSbar; + +CAmTx< + System::OrgFunc_01_26, + System::OrgData_01_26, + DisplayBuff, + Display, + DisplayStatusBar, + FontSmallNr, + RadioDriver> + AmTx; + +static IView * const Views[] = {&AmTx}; +CViewManager< + System::OrgFunc_01_26, + System::OrgData_01_26, + 8, 1, sizeof(Views) / sizeof(*Views)> + Manager(Views); + +int main() +{ + Fw.IRQ_RESET(); + return 0; +} + +extern "C" void Reset_Handler() +{ + Fw.IRQ_RESET(); +} + +extern "C" void SysTick_Handler() +{ + static bool bFirstInit = false; + if (!bFirstInit) + { + System::CopyDataSection(); + __libc_init_array(); + bFirstInit = true; + } + + Manager.Handle(); + Fw.IRQ_SYSTICK(); +} \ No newline at end of file diff --git a/src/am_tx/main_old.cpp b/src/am_tx/main_old.cpp new file mode 100644 index 0000000..f5ee502 --- /dev/null +++ b/src/am_tx/main_old.cpp @@ -0,0 +1,39 @@ +#include "system.hpp" +#include "hardware/hardware.hpp" +#include "registers.hpp" +#include "uv_k5_display.hpp" +#include "rssi_sbar.hpp" +#include + +Hardware::THardware Hw; +const System::TOrgFunctions& Fw = System::OrgFunc_01_26; +const System::TOrgData& FwData = System::OrgData_01_26; + +int main() +{ + Fw.IRQ_RESET(); + return 0; +} + +extern "C" void Reset_Handler() +{ + Fw.IRQ_RESET(); +} + +extern "C" void SysTick_Handler() +{ + static bool bFirstInit = false; + if(!bFirstInit) + { + System::CopyDataSection(); + __libc_init_array(); + bFirstInit = true; + } + + static unsigned int u32StupidCounter = 1; + if((!(u32StupidCounter++ % 10) && u32StupidCounter > 200)) // exit key + { + CRssiPrinter::Handle(Fw, FwData); + } + Fw.IRQ_SYSTICK(); +} \ No newline at end of file diff --git a/src/am_tx/memory.ld b/src/am_tx/memory.ld new file mode 100644 index 0000000..d6fedda --- /dev/null +++ b/src/am_tx/memory.ld @@ -0,0 +1,90 @@ +ENTRY(Reset_Handler) +EXTERN(VectorTable) + +MEMORY +{ + RAM (rwx) : ORIGIN = 0x2000138C, LENGTH = 256 + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 60K +} + +_estack = 0x20001388; + + +SECTIONS +{ + . = 0x0; + .isr_vectors : + { + . = ALIGN(4); + KEEP(*(.isr_vectors)) + . = ALIGN(4); + } >FLASH + + .org_fw_rest : + { + . = ALIGN(4); + KEEP(*(.org_fw_rest)) + } > FLASH + /* + .org_vectors : + { + . = ALIGN(4); + __org_vectors_start = .; + KEEP(*(.org_vectors)) + } > FLASH + */ + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.rodata) + *(.rodata*) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(4); + } >FLASH + + .preinit_array : + { + __preinit_array_start = .; + KEEP (*(.preinit_array*)) + __preinit_array_end = .; + } >FLASH + .init_array : + { + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + __init_array_end = .; + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + _flash_data_start = .; + } >FLASH + + _sidata = LOADADDR(.data); + .data : AT (_flash_data_start) + { + . = ALIGN(4); + _sdata = .; + *(.data) + *(.data*) + *(.ramsection) + _edata = .; + } >RAM + + .bss : + { + . = ALIGN(4); + _sbss = .; + *(.bss) + _ebss = .; + } >RAM + +} \ No newline at end of file