From a81caa0e6379bf3ea46b7227a2e7a85c24cf2935 Mon Sep 17 00:00:00 2001 From: Piotr Lewandowski Date: Wed, 12 Jul 2023 02:10:45 +0200 Subject: [PATCH] radio-lib-keyboard-t9-class --- libs/CMakeLists.txt | 3 +- libs/k5_uv_system/system.hpp | 4 +- libs/keyboard/CMakeLists.txt | 22 ++++ libs/keyboard/keyboard.hpp | 34 ++++++ libs/keyboard/t9.cpp | 2 + libs/keyboard/t9.hpp | 47 ++++++++ libs/radio/radio.hpp | 136 ++++++++++++++++----- src/CMakeLists.txt | 3 +- src/messenger/CMakeLists.txt | 80 +++++++++++++ src/messenger/dp32g030.s | 18 +++ src/messenger/exec.hpp | 17 +++ src/messenger/fw_merger.py | 16 +++ src/messenger/hardware/hardware.cpp | 50 ++++++++ src/messenger/hardware/hardware.hpp | 29 +++++ src/messenger/main.cpp | 42 +++++++ src/messenger/memory.ld | 88 ++++++++++++++ src/messenger/messenger.hpp | 175 ++++++++++++++++++++++++++++ src/most_useless_mod/main.cpp | 13 ++- src/most_useless_mod/memory.ld | 1 + src/most_useless_mod/spectrum.hpp | 116 ++++++++++++++---- src/spectrum/dp32g030.s | 1 + src/t9_texting/CMakeLists.txt | 1 + src/t9_texting/t9_texting.hpp | 4 + 23 files changed, 840 insertions(+), 62 deletions(-) create mode 100644 libs/keyboard/CMakeLists.txt create mode 100644 libs/keyboard/keyboard.hpp create mode 100644 libs/keyboard/t9.cpp create mode 100644 libs/keyboard/t9.hpp create mode 100644 src/messenger/CMakeLists.txt create mode 100644 src/messenger/dp32g030.s create mode 100644 src/messenger/exec.hpp create mode 100644 src/messenger/fw_merger.py create mode 100644 src/messenger/hardware/hardware.cpp create mode 100644 src/messenger/hardware/hardware.hpp create mode 100644 src/messenger/main.cpp create mode 100644 src/messenger/memory.ld create mode 100644 src/messenger/messenger.hpp diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index 70e1fc2..d518d86 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(k5_uv_system) add_subdirectory(lcd) -add_subdirectory(radio) \ No newline at end of file +add_subdirectory(radio) +add_subdirectory(keyboard) \ No newline at end of file diff --git a/libs/k5_uv_system/system.hpp b/libs/k5_uv_system/system.hpp index ca67d03..46a0e52 100644 --- a/libs/k5_uv_system/system.hpp +++ b/libs/k5_uv_system/system.hpp @@ -61,10 +61,11 @@ namespace System void(*AirCopy72)(unsigned char*); void(*AirCopyFskSetup)(); void(*BK4819Reset)(); - void(*IntDivide)(int s32Divident, int s32Divisor); + int(*IntDivide)(int s32Divident, int s32Divisor); void(*BK4819WriteFrequency)(unsigned int u32Frequency); void(*BK4819SetPaGain)(unsigned short u16PaBias, unsigned int u32Frequency); void(*BK4819ConfigureAndStartTxFsk)(); + void(*BK4819ConfigureAndStartRxFsk)(); }; @@ -100,6 +101,7 @@ namespace System .BK4819WriteFrequency = (decltype(TOrgFunctions::BK4819WriteFrequency) (0xaabc + 1)), .BK4819SetPaGain = (decltype(TOrgFunctions::BK4819SetPaGain) (0xaad4 + 1)), .BK4819ConfigureAndStartTxFsk = (decltype(TOrgFunctions::BK4819ConfigureAndStartTxFsk) (0x1cd8 + 1)), + .BK4819ConfigureAndStartRxFsk = (decltype(TOrgFunctions::BK4819ConfigureAndStartRxFsk) (0xa63c + 1)), }; inline const TOrgData OrgData_01_26 = diff --git a/libs/keyboard/CMakeLists.txt b/libs/keyboard/CMakeLists.txt new file mode 100644 index 0000000..0953461 --- /dev/null +++ b/libs/keyboard/CMakeLists.txt @@ -0,0 +1,22 @@ +set(NAME keyboard) + +add_library(${NAME} STATIC) + +target_include_directories(${NAME} INTERFACE + . +) + +target_include_directories(${NAME} PRIVATE + . +) + +target_sources(${NAME} PRIVATE + t9.cpp +) + +target_link_libraries(${NAME} + uv_k5_system +) + +target_compile_options(${NAME} PRIVATE ${COMPILER_OPTIONS}) + diff --git a/libs/keyboard/keyboard.hpp b/libs/keyboard/keyboard.hpp new file mode 100644 index 0000000..837c92f --- /dev/null +++ b/libs/keyboard/keyboard.hpp @@ -0,0 +1,34 @@ +#pragma once + +template +class CKeyboard +{ + static constexpr auto ReleasedRawState = 0xFF; + public: + CKeyboard(KeyboardUserType& _KeyboardUser): + KeyboardUser(_KeyboardUser), + u8LastKey(ReleasedRawState){}; + + void Handle(unsigned char u8RawButton) + { + if(u8RawButton == u8LastKey) + { + return; + } + + if(u8LastKey == ReleasedRawState) + { + KeyboardUser.HandlePressedButton(u8RawButton); + } + else + { + KeyboardUser.HandleReleasedButton(u8LastKey); + } + + u8LastKey = u8RawButton; + } + + private: + KeyboardUserType& KeyboardUser; + unsigned char u8LastKey; +}; \ No newline at end of file diff --git a/libs/keyboard/t9.cpp b/libs/keyboard/t9.cpp new file mode 100644 index 0000000..f9cb17f --- /dev/null +++ b/libs/keyboard/t9.cpp @@ -0,0 +1,2 @@ +#include "keyboard.hpp" +#include "t9.hpp" \ No newline at end of file diff --git a/libs/keyboard/t9.hpp b/libs/keyboard/t9.hpp new file mode 100644 index 0000000..7780a72 --- /dev/null +++ b/libs/keyboard/t9.hpp @@ -0,0 +1,47 @@ +#pragma once + +template +class CT9Decoder +{ +public: + CT9Decoder(char (&C8WorkingBuffRef)[u8BuffSize]) + : C8WorkingBuff(C8WorkingBuffRef) + { + } + + void ProcessButton(unsigned char key) + { + if (prev_key == key && key != 14) + { + c_index = (c_index > 0) ? c_index - 1 : 0; + C8WorkingBuff[c_index++] = T9_table[key][(++prev_letter) % numberOfLettersAssignedToKey[key]]; + } + else + { + prev_letter = 0; + C8WorkingBuff[c_index++] = T9_table[key][prev_letter]; + } + C8WorkingBuff[c_index] = '\0'; + prev_key = key; + } + + void ProcessStartKey() + { + prev_key = 14; + prev_letter = 0; + } + + void ProcessBackSpace() + { + c_index = (c_index > 0) ? c_index - 1 : 0; + C8WorkingBuff[c_index] = ' '; + } + +private: + char (&C8WorkingBuff)[u8BuffSize]; + char T9_table[10][4] = {{' ', '\0', '\0', '\0'}, {'\0', '\0', '\0', '\0'}, {'a', 'b', 'c', '\0'}, {'d', 'e', 'f', '\0'}, {'g', 'h', 'i', '\0'}, {'j', 'k', 'l', '\0'}, {'m', 'n', 'o', '\0'}, {'p', 'q', 'r', 's'}, {'t', 'u', 'v', '\0'}, {'w', 'x', 'y', 'z'}}; + unsigned char numberOfLettersAssignedToKey[10] = {1, 0, 3, 3, 3, 3, 3, 4, 3, 4}; + unsigned char prev_key = 0, prev_letter = 0; + unsigned char c_index = 0; + bool keyReleased = true; +}; \ No newline at end of file diff --git a/libs/radio/radio.hpp b/libs/radio/radio.hpp index 853c32d..598def0 100644 --- a/libs/radio/radio.hpp +++ b/libs/radio/radio.hpp @@ -5,6 +5,12 @@ namespace Radio { + enum eIrq : unsigned short + { + FifoAlmostFull = 1 << 12, + RxDone = 1 << 13, + }; + enum class eModulation : unsigned char { Ffsk, @@ -24,14 +30,14 @@ namespace Radio struct IRadioUser { - virtual void RxDoneHandler(){}; + virtual void RxDoneHandler(unsigned char u8DataLen, bool bCrcOk){}; }; template class CBK4819 { public: - CBK4819(){}; + CBK4819() : State(eState::Idle), u16RxDataLen(0){}; void SetFrequency(unsigned int u32FrequencyD10) { @@ -40,7 +46,7 @@ namespace Radio unsigned int GetFrequency() { - return 0; + return (Fw.BK4819Read(0x39) << 16) | Fw.BK4819Read(0x38); } void SendSyncAirCopyMode72(unsigned char *p8Data) @@ -50,7 +56,17 @@ namespace Radio Fw.AirCopy72(p8Data); } - void RecieveAsyncAirCopyMode(unsigned char *p8Data, unsigned char u8DataLen, IRadioUser* pUser) + 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, IRadioUser *pUser) { if (!p8Data || !u8DataLen) { @@ -60,22 +76,62 @@ namespace Radio pRadioUser = pUser; p8RxBuff = p8Data; u8RxBuffSize = u8DataLen; + u16RxDataLen = 0; Fw.AirCopyFskSetup(); - Fw.BK4819Write(0x59, 1 << 14); // clear rx fifo - Fw.BK4819Write(0x59, 0b0011'0000'0110'1000); // enable rx - Fw.BK4819Write(0x3f, 1 << 13); // enable rx done irq + // Fw.BK4819Write(0x2, 0); // clear irq + // Fw.BK4819Write(0x59, 1 << 14); // clear rx fifo + // Fw.BK4819Write(0x59, 0b0011'0000'0110'1000); // enable rx + // Fw.BK4819Write(0x3f, 1 << 13); // enable rx done irq - Fw.BK4819Write(0x30, 0); - Fw.BK4819Write(0x30, 0b1011'1101'1111'0001); + // Fw.BK4819Write(0x30, 0); + // Fw.BK4819Write(0x30, 0b1011'1101'1111'0001); + 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; + if (pRadioUser) + { + pRadioUser->RxDoneHandler(u16RxDataLen, CheckCrc()); + } + } + void InterruptHandler() { if (IsLockedByOrgFw()) @@ -83,36 +139,58 @@ namespace Radio return; } + if (State == eState::RxPending) { - auto const IrqReg = Fw.BK4819Read(0x02); - if (IrqReg & (1 << 13)) + FixIrqEnRegister(); + if (!(Fw.BK4819Read(0x0C) & 1)) // irq request indicator { - State = eState::Idle; - Fw.BK4819Write(0x2, 0); - unsigned char u8DataLen = Fw.BK4819Read(0x02); - u8DataLen = (u8DataLen >> 8) & 0xFF; - if (!p8RxBuff) - return; + return; + } - u8DataLen = u8RxBuffSize < u8DataLen ? u8RxBuffSize : u8DataLen; - for (unsigned char i = 0; i < u8DataLen; i++) - { - p8RxBuff[i] = Fw.BK4819Read(0x5F); - } - - if(pRadioUser) - { - pRadioUser->RxDoneHandler(); - } + auto const IrqReg = GetIrqReg(); + + if (IrqReg & eIrq::RxDone) + { + // HandleRxDone(); + } + + if (IrqReg & eIrq::FifoAlmostFull) + { + HandleFifoAlmostFull(); } } } + eState State; + unsigned short u16RxDataLen; + private: - IRadioUser* pRadioUser; + 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; + if (pRadioUser) + { + pRadioUser->RxDoneHandler(u8RxBuffSize, CheckCrc()); + } + } + } + + IRadioUser *pRadioUser; unsigned char *p8RxBuff; unsigned char u8RxBuffSize; - eState State; }; } \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2f6877c..48ec216 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,4 +4,5 @@ add_subdirectory(rssi_sbar) add_subdirectory(most_useless_mod) add_subdirectory(pong) add_subdirectory(spectrum) -add_subdirectory(t9_texting) \ No newline at end of file +add_subdirectory(t9_texting) +add_subdirectory(messenger) \ No newline at end of file diff --git a/src/messenger/CMakeLists.txt b/src/messenger/CMakeLists.txt new file mode 100644 index 0000000..bd3849a --- /dev/null +++ b/src/messenger/CMakeLists.txt @@ -0,0 +1,80 @@ +set(NAME messenger) +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 + keyboard +) + +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} + -flto +) + +target_link_options(${NAME} PRIVATE + #-print-multi-lib + -T ${CMAKE_CURRENT_SOURCE_DIR}/memory.ld + -flto + -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/messenger/dp32g030.s b/src/messenger/dp32g030.s new file mode 100644 index 0000000..8de265c --- /dev/null +++ b/src/messenger/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/messenger/exec.hpp b/src/messenger/exec.hpp new file mode 100644 index 0000000..184d46b --- /dev/null +++ b/src/messenger/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/messenger/fw_merger.py b/src/messenger/fw_merger.py new file mode 100644 index 0000000..7a80c5c --- /dev/null +++ b/src/messenger/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/messenger/hardware/hardware.cpp b/src/messenger/hardware/hardware.cpp new file mode 100644 index 0000000..32621a5 --- /dev/null +++ b/src/messenger/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/messenger/hardware/hardware.hpp b/src/messenger/hardware/hardware.hpp new file mode 100644 index 0000000..e0a8120 --- /dev/null +++ b/src/messenger/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/messenger/main.cpp b/src/messenger/main.cpp new file mode 100644 index 0000000..3e803de --- /dev/null +++ b/src/messenger/main.cpp @@ -0,0 +1,42 @@ +#include "system.hpp" +#include "hardware/hardware.hpp" +#include "registers.hpp" +#include "uv_k5_display.hpp" +#include "messenger.hpp" +#include + +Hardware::THardware Hw; +const System::TOrgFunctions& Fw = System::OrgFunc_01_26; +const System::TOrgData& FwData = System::OrgData_01_26; + +CMessenger Messenger; + +int main() +{ + System::JumpToOrginalFw(); + return 0; +} + +void MultiIrq_Handler(unsigned int u32IrqSource) +{ + unsigned int u32Dummy; + System::TCortexM0Stacking* pStackedRegs = + (System::TCortexM0Stacking*)(((unsigned int*)&u32Dummy) + 1); + + static bool bFirstInit = false; + if(!bFirstInit) + { + System::CopyDataSection(); + __libc_init_array(); + bFirstInit = true; + } + + bool bPreventWhileKeypadPolling = pStackedRegs->LR > (unsigned int)Fw.PollKeyboard && + pStackedRegs->PC < (unsigned int)Fw.PollKeyboard + 0x100; // i made a mistake and compared PC and LR, but this works fine xD + + static unsigned int u32StupidCounter = 1; + if(u32StupidCounter++ > 200 && !bPreventWhileKeypadPolling) + { + Messenger.Handle(); + } +} \ No newline at end of file diff --git a/src/messenger/memory.ld b/src/messenger/memory.ld new file mode 100644 index 0000000..2275d05 --- /dev/null +++ b/src/messenger/memory.ld @@ -0,0 +1,88 @@ +ENTRY(Reset_Handler) + +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 diff --git a/src/messenger/messenger.hpp b/src/messenger/messenger.hpp new file mode 100644 index 0000000..05c2452 --- /dev/null +++ b/src/messenger/messenger.hpp @@ -0,0 +1,175 @@ +#pragma once +#include "system.hpp" +#include "uv_k5_display.hpp" +#include "keyboard.hpp" + +template +class CMessenger +{ +public: + CMessenger() + : DisplayBuff(FwData.pDisplayBuffer), + Display(DisplayBuff), + Keyboard(*this), + bDisplayCleared(true), + bEnabled(0) + { + }; + + char T9_table[10][4] = {{' ', '\0', '\0', '\0'}, {'\0', '\0', '\0', '\0'}, {'a', 'b', 'c', '\0'}, {'d', 'e', 'f', '\0'}, {'g', 'h', 'i', '\0'}, {'j', 'k', 'l', '\0'}, {'m', 'n', 'o', '\0'}, {'p', 'q', 'r', 's'}, {'t', 'u', 'v', '\0'}, {'w', 'x', 'y', 'z'}}; + unsigned char numberOfLettersAssignedToKey[10] = {1, 0, 3, 3, 3, 3, 3, 4, 3, 4}; + unsigned char prev_key = 0, prev_letter = 0; + char cMessage[30]; + unsigned char c_index = 0; + bool keyReleased = true; + + void insert_char_to_cMessage(unsigned char key) + { + if (prev_key == key && key != 14) + { + c_index = (c_index > 0) ? c_index - 1 : 0; + cMessage[c_index++] = T9_table[key][(++prev_letter) % numberOfLettersAssignedToKey[key]]; + } + else + { + prev_letter = 0; + cMessage[c_index++] = T9_table[key][prev_letter]; + } + cMessage[c_index] = '\0'; + prev_key = key; + } + + void process_starkey() + { + prev_key = 14; + prev_letter = 0; + } + + void process_backspace() + { + c_index = (c_index > 0) ? c_index - 1 : 0; + cMessage[c_index] = ' '; + } + + void Handle() + { + if (!(GPIOC->DATA & 0b1)) + { + return; + } + + if (!FreeToDraw()) + { + if (!bDisplayCleared) + { + bDisplayCleared = true; + ClearDrawings(); + // Clear cMessage + memset(cMessage, 0, 30); + c_index = 0; + Fw.FlushFramebufferToScreen(); + } + + return; + } + + if (bDisplayCleared) + { + } + + bDisplayCleared = false; + + unsigned char key; + key = u8LastBtnPressed; + + if (key == 0xff) + { + keyReleased = true; + return; + } + else if (keyReleased) + { + keyReleased = false; + if (key == 0) + { // key 0 for space + prev_key = 0; + prev_letter = 0; + cMessage[c_index++] = ' '; + } + + else if (key == 13) + { + process_backspace(); + return; + } + + else if (key == 14) + { + process_starkey(); + return; + } + + else if (key == 10) + { + bEnabled = false; + return; + } + + else + { + insert_char_to_cMessage(key); + } + } + prev_key = key; + // Display.DrawRectangle(0,0, 7, 7, 0); + ClearDrawings(); + Fw.PrintTextOnScreen(cMessage, 0, 128, 0, 8, 0); + Fw.FlushFramebufferToScreen(); + } + +private: + bool + FreeToDraw() + { + bool bFlashlight = (GPIOC->DATA & GPIO_PIN_3); + if (bFlashlight) + { + bEnabled = true; + GPIOC->DATA &= ~GPIO_PIN_3; + *FwData.p8FlashLightStatus = 3; + } + + if (bEnabled) + { + u8LastBtnPressed = Fw.PollKeyboard(); + } + + // u8LastBtnPressed = Fw.PollKeyboard(); + // if (u8LastBtnPressed == EnableKey) + // { + // u8PressCnt++; + // } + + // if (u8PressCnt > (bEnabled ? 3 : PressDuration)) + // { + // u8PressCnt = 0; + // bEnabled = !bEnabled; + // } + + return bEnabled; + } + + void ClearDrawings() + { + memset(FwData.pDisplayBuffer, 0, (DisplayBuff.SizeX / 8) * DisplayBuff.SizeY); + } + + TUV_K5Display DisplayBuff; + CDisplay Display; + CKeyboard Keyboard; + + bool bDisplayCleared; + + unsigned char u8LastBtnPressed; + bool bEnabled; +}; \ No newline at end of file diff --git a/src/most_useless_mod/main.cpp b/src/most_useless_mod/main.cpp index f18e401..a6f0d6a 100644 --- a/src/most_useless_mod/main.cpp +++ b/src/most_useless_mod/main.cpp @@ -9,19 +9,20 @@ extern "C" void __libc_init_array(); Radio::CBK4819 RadioDriver; -CSpectrum Spectrum; +CSpectrum + Spectrum; int main() { System::JumpToOrginalFw(); return 0; -} +} void MultiIrq_Handler(unsigned int u32IrqSource) { static bool bFirstInit = false; - if(!bFirstInit) + if (!bFirstInit) { System::CopyDataSection(); __libc_init_array(); @@ -29,9 +30,9 @@ void MultiIrq_Handler(unsigned int u32IrqSource) } RadioDriver.InterruptHandler(); - + static unsigned int u32StupidCounter = 1; - if((!(u32StupidCounter++ % 64) && u32StupidCounter > 200)) + if ((!(u32StupidCounter++ % 15) && u32StupidCounter > 200)) { Spectrum.Handle(); } diff --git a/src/most_useless_mod/memory.ld b/src/most_useless_mod/memory.ld index 2275d05..498f9bf 100644 --- a/src/most_useless_mod/memory.ld +++ b/src/most_useless_mod/memory.ld @@ -1,4 +1,5 @@ ENTRY(Reset_Handler) +EXTERN(VectorTable) MEMORY { diff --git a/src/most_useless_mod/spectrum.hpp b/src/most_useless_mod/spectrum.hpp index 7ae23d1..1ec5cc6 100644 --- a/src/most_useless_mod/spectrum.hpp +++ b/src/most_useless_mod/spectrum.hpp @@ -4,8 +4,8 @@ #include "radio.hpp" template & RadioDriver> + const System::TOrgData &FwData, + Radio::CBK4819 &RadioDriver> class CSpectrum : public Radio::IRadioUser { public: @@ -23,7 +23,7 @@ public: }; CSpectrum() - : DisplayBuff(FwData.pDisplayBuffer), FontSmallNr(FwData.pSmallDigs), Display(DisplayBuff), State(eState::SendData), u8RxCnt(0){}; + : DisplayBuff(FwData.pDisplayBuffer), FontSmallNr(FwData.pSmallDigs), Display(DisplayBuff), State(eState::Init), u8RxCnt(0){}; void Handle() { @@ -32,38 +32,107 @@ public: return; } - switch(State) + switch (State) { - case eState::Init: - { - RadioDriver.RecieveAsyncAirCopyMode(U8RxBuff, sizeof(U8RxBuff), this); - State = eState::RxPending; - break; - } + case eState::Init: + { + - case eState::RxDone: + Fw.DelayMs(600); + //memset(U8Buff, 0, sizeof(U8Buff)); + RadioDriver.RecieveAsyncAirCopyMode(U8Buff, sizeof(U8Buff), this); + State = eState::RxPending; + // while(State == eState::RxPending) + // { + // RadioDriver.InterruptHandler(); + // // if(Fw.PollKeyboard() != 0xFF) + // // { + // // break; + // // } + // } + + break; + } + + case eState::RxDone: + { + char kupa[20]; + U8Buff[10] = 0; + DisplayBuff.ClearAll(); + Fw.FormatString(kupa, "RX DONE %u", u8RxCnt); + Fw.PrintTextOnScreen(kupa, 0, 127, 0, 8, 0); + Fw.FormatString(kupa, "LEN: %i", RadioDriver.u16RxDataLen); + Fw.PrintTextOnScreen(kupa, 0, 127, 2, 8, 0); + Fw.FormatString(kupa, "S: %s", U8Buff); + Fw.PrintTextOnScreen(kupa, 0, 127, 4, 8, 0); + Fw.FlushFramebufferToScreen(); + + static unsigned int u32Cnt = 1; + if(!(u32Cnt++%8)) { u8RxCnt++; - char kupa[20]; - Fw.FormatString(kupa, "test %u", u8RxCnt); - Fw.PrintTextOnScreen(kupa, 0, 127, 0, 8, 0); - Fw.FlushFramebufferToScreen(); State = eState::Init; - break; } - case eState::SendData: + // Fw.WriteSerialData((unsigned char *)"RX packet, hex: ", 17); + // for (unsigned int i = 0; i < sizeof(U8Buff); i++) + // { + // Fw.FormatString(kupa, "%02X", U8Buff[i]); + // Fw.WriteSerialData((unsigned char *)kupa, 1); + // } + // Fw.WriteSerialData((unsigned char *)"\n", 1); + break; + } + + case eState::RxPending: + { + + //Fw.AirCopyFskSetup(); + char kupa[20]; + DisplayBuff.ClearAll(); + Fw.FormatString(kupa, "Rx: %u kHz", Fw.IntDivide(RadioDriver.GetFrequency(), 100)); + Fw.PrintTextOnScreen(kupa, 0, 127, 0, 8, 0); + Fw.FormatString(kupa, "0x3F: 0x%04X", Fw.BK4819Read(0x3F)); + Fw.PrintTextOnScreen(kupa, 0, 127, 2, 8, 0); + Fw.FormatString(kupa, "len: %i", Fw.BK4819Read(0x5D) >> 8); + Fw.PrintTextOnScreen(kupa, 0, 127, 4, 8, 0); + Fw.FlushFramebufferToScreen(); + return; + } + + case eState::SendData: + { + + static char C8TxStr[20] __attribute__((aligned(4))); + char kupa[20]; + static unsigned char u8TxCnt = 0; + static unsigned int u32Cnt = 1; + if(!(u32Cnt++%8)) { - RadioDriver.SendSyncAirCopyMode72((unsigned char*)this); - return; + u8TxCnt++; + Fw.FormatString((char *)C8TxStr, "packet %i", u8TxCnt); + RadioDriver.SendSyncAirCopyMode72((unsigned char *)C8TxStr); } - default: - return; + DisplayBuff.ClearAll(); + Fw.FormatString(kupa, "TX: %u kHz", Fw.IntDivide(RadioDriver.GetFrequency(), 100)); + Fw.PrintTextOnScreen(kupa, 0, 127, 0, 8, 0); + Fw.FormatString(kupa, "Irq: 0x%04X", RadioDriver.GetIrqReg()); + Fw.PrintTextOnScreen(kupa, 0, 127, 2, 8, 0); + Fw.FormatString(kupa, "S: %s", C8TxStr); + Fw.PrintTextOnScreen(kupa, 0, 127, 4, 8, 0); + Fw.FlushFramebufferToScreen(); + + + return; + } + + default: + return; } } - void RxDoneHandler() override + void RxDoneHandler(unsigned char u8DataLen, bool bCrcOk) override { State = eState::RxDone; } @@ -73,7 +142,6 @@ private: const TUV_K5SmallNumbers FontSmallNr; CDisplay Display; eState State; - unsigned char U8RxBuff[72]; + unsigned char U8Buff[72]; unsigned char u8RxCnt; - }; \ No newline at end of file diff --git a/src/spectrum/dp32g030.s b/src/spectrum/dp32g030.s index 8de265c..54e6927 100644 --- a/src/spectrum/dp32g030.s +++ b/src/spectrum/dp32g030.s @@ -16,3 +16,4 @@ LoopForever: b LoopForever .size Reset_Handler, .-Reset_Handler + diff --git a/src/t9_texting/CMakeLists.txt b/src/t9_texting/CMakeLists.txt index 2790a46..24b48c6 100644 --- a/src/t9_texting/CMakeLists.txt +++ b/src/t9_texting/CMakeLists.txt @@ -11,6 +11,7 @@ target_link_libraries(${NAME} orginal_fw uv_k5_system lcd + keyboard ) target_include_directories(${NAME} PUBLIC diff --git a/src/t9_texting/t9_texting.hpp b/src/t9_texting/t9_texting.hpp index fe7e8f9..2943362 100644 --- a/src/t9_texting/t9_texting.hpp +++ b/src/t9_texting/t9_texting.hpp @@ -1,6 +1,7 @@ #pragma once #include "system.hpp" #include "uv_k5_display.hpp" +#include "keyboard.hpp" template class CT9Texting @@ -9,6 +10,7 @@ public: CT9Texting() : DisplayBuff(FwData.pDisplayBuffer), Display(DisplayBuff), + Keyboard(*this), bDisplayCleared(true), bEnabled(0) { @@ -164,6 +166,8 @@ private: TUV_K5Display DisplayBuff; CDisplay Display; + CKeyboard Keyboard; + bool bDisplayCleared; unsigned char u8LastBtnPressed;