kopia lustrzana https://github.com/piotr022/UV_K5_playground
radio-lib-keyboard-t9-class
rodzic
cf825bca79
commit
a81caa0e63
|
@ -1,3 +1,4 @@
|
|||
add_subdirectory(k5_uv_system)
|
||||
add_subdirectory(lcd)
|
||||
add_subdirectory(radio)
|
||||
add_subdirectory(radio)
|
||||
add_subdirectory(keyboard)
|
|
@ -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 =
|
||||
|
|
|
@ -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})
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
template<class KeyboardUserType>
|
||||
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;
|
||||
};
|
|
@ -0,0 +1,2 @@
|
|||
#include "keyboard.hpp"
|
||||
#include "t9.hpp"
|
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
template <unsigned char u8BuffSize>
|
||||
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;
|
||||
};
|
|
@ -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 <const System::TOrgFunctions &Fw>
|
||||
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;
|
||||
};
|
||||
}
|
|
@ -4,4 +4,5 @@ add_subdirectory(rssi_sbar)
|
|||
add_subdirectory(most_useless_mod)
|
||||
add_subdirectory(pong)
|
||||
add_subdirectory(spectrum)
|
||||
add_subdirectory(t9_texting)
|
||||
add_subdirectory(t9_texting)
|
||||
add_subdirectory(messenger)
|
|
@ -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}
|
||||
$<$<CONFIG:Debug>: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}
|
||||
)
|
|
@ -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
|
|
@ -0,0 +1,17 @@
|
|||
#include "registers.hpp"
|
||||
|
||||
class CExec final
|
||||
{
|
||||
public:
|
||||
CExec(){};
|
||||
|
||||
void InterruptCallback()
|
||||
{
|
||||
CheckButtons();
|
||||
}
|
||||
|
||||
private:
|
||||
void CheckButtons() const
|
||||
{
|
||||
}
|
||||
};
|
|
@ -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])
|
|
@ -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();
|
||||
}
|
|
@ -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};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
#include "system.hpp"
|
||||
#include "hardware/hardware.hpp"
|
||||
#include "registers.hpp"
|
||||
#include "uv_k5_display.hpp"
|
||||
#include "messenger.hpp"
|
||||
#include <string.h>
|
||||
|
||||
Hardware::THardware Hw;
|
||||
const System::TOrgFunctions& Fw = System::OrgFunc_01_26;
|
||||
const System::TOrgData& FwData = System::OrgData_01_26;
|
||||
|
||||
CMessenger<System::OrgFunc_01_26, System::OrgData_01_26> 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();
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
#pragma once
|
||||
#include "system.hpp"
|
||||
#include "uv_k5_display.hpp"
|
||||
#include "keyboard.hpp"
|
||||
|
||||
template <const System::TOrgFunctions &Fw, const System::TOrgData &FwData>
|
||||
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<const TUV_K5Display> Display;
|
||||
CKeyboard<CMessenger> Keyboard;
|
||||
|
||||
bool bDisplayCleared;
|
||||
|
||||
unsigned char u8LastBtnPressed;
|
||||
bool bEnabled;
|
||||
};
|
|
@ -9,19 +9,20 @@
|
|||
extern "C" void __libc_init_array();
|
||||
|
||||
Radio::CBK4819<System::OrgFunc_01_26> RadioDriver;
|
||||
CSpectrum<System::OrgFunc_01_26,
|
||||
System::OrgData_01_26, RadioDriver> Spectrum;
|
||||
CSpectrum<System::OrgFunc_01_26,
|
||||
System::OrgData_01_26, RadioDriver>
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
ENTRY(Reset_Handler)
|
||||
EXTERN(VectorTable)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#include "radio.hpp"
|
||||
|
||||
template <const System::TOrgFunctions &Fw,
|
||||
const System::TOrgData &FwData,
|
||||
Radio::CBK4819<Fw>& RadioDriver>
|
||||
const System::TOrgData &FwData,
|
||||
Radio::CBK4819<Fw> &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<const TUV_K5Display> Display;
|
||||
eState State;
|
||||
unsigned char U8RxBuff[72];
|
||||
unsigned char U8Buff[72];
|
||||
unsigned char u8RxCnt;
|
||||
|
||||
};
|
|
@ -16,3 +16,4 @@ LoopForever:
|
|||
b LoopForever
|
||||
|
||||
.size Reset_Handler, .-Reset_Handler
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ target_link_libraries(${NAME}
|
|||
orginal_fw
|
||||
uv_k5_system
|
||||
lcd
|
||||
keyboard
|
||||
)
|
||||
|
||||
target_include_directories(${NAME} PUBLIC
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "system.hpp"
|
||||
#include "uv_k5_display.hpp"
|
||||
#include "keyboard.hpp"
|
||||
|
||||
template <const System::TOrgFunctions &Fw, const System::TOrgData &FwData>
|
||||
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<const TUV_K5Display> Display;
|
||||
CKeyboard<CT9Texting> Keyboard;
|
||||
|
||||
bool bDisplayCleared;
|
||||
|
||||
unsigned char u8LastBtnPressed;
|
||||
|
|
Ładowanie…
Reference in New Issue