Porównaj commity

...

21 Commity

Autor SHA1 Wiadomość Data
Piotr Lewandowski 37b86a2d22 [skip ci] added _flash_uart targets to direct flash fw via k5prog 2023-08-23 18:34:35 +02:00
Piotr Lewandowski (SQ9P) 9150e39105
Merge pull request #70 from fagci/main
feat: 32KHz to track satellite doppler shift, better smaller steps, better sensitivity, better defaults, green led on rx only, use more fw functions, more precise numbers for freq&step
2023-08-14 09:01:11 +02:00
Mikhail Yudin d050bdcf19 feat: disable sound completely when "squelch" closed 2023-08-14 02:01:18 +07:00
Mikhail Yudin 28817c7d3b feat: reverted 100KHz mode, smaller scan delay step, more precise numbers 2023-08-13 16:02:55 +07:00
Mikhail Yudin 487b281779 feat: Strlen from fw, turn on green led on squelch open 2023-08-13 14:46:53 +07:00
Mikhail Yudin b56c2eb68a feat: 32kHz to track satellite doppler, set BK bandwidth by api 2023-08-13 13:36:18 +07:00
Mikhail Yudin a8bb4df507 feat: turn green led off 2023-08-13 12:52:13 +07:00
Mikhail Yudin 3b0508bee8 feat: better sensitivity, refactor 2023-08-13 11:52:02 +07:00
Mikhail f1396c3105
Merge branch 'piotr022:main' into main 2023-08-12 22:33:38 +07:00
Mikhail Yudin 1d65b2e798 refactor, feat: 100KHz to track satellite doppler shift, better smaller steps, better defaults 2023-08-12 22:30:43 +07:00
Piotr Lewandowski (SQ9P) aebb19b637
[skip ci] Merge pull request #68 from Tunas1337/main
Optimize 10MB GIF (!)
2023-08-10 22:35:33 +02:00
Andrej c470b8545e
Add files via upload 2023-08-09 10:19:47 +02:00
Andrej c669df83a2
Delete spectrum_fagci.gif 2023-08-09 10:19:30 +02:00
Piotr Lewandowski (SQ9P) 1e533bc6b8
Merge pull request #66 from fagci/main
merge
2023-08-09 01:13:25 +02:00
Mikhail Yudin 7dcfdd2360 feat: redesign, fixed dots for numbers 2023-08-08 01:29:41 +07:00
Mikhail Yudin 3d9171dc9e merge 2023-08-07 22:23:10 +07:00
Piotr Lewandowski 8d6d99de50 DualTachyon PR merge with origin, fixed formatting 2023-08-06 01:24:32 +02:00
Piotr Lewandowski 5a999abd10 am tx, adc 2023-08-01 21:44:52 +02:00
Dual Tachyon b4dad1ec2c Revamped linkage of the FW API
Added SRAM API functions
2023-08-01 16:54:30 +01:00
Piotr Lewandowski (SQ9P) 74da1c24ec
Merge pull request #57 from fagci/main
feat: squelch modes by 0, sticky (solid line) and non-sticky (dashed line)
2023-07-27 20:54:32 +02:00
Mikhail Yudin 00b4452cb2 feat: squelch modes by 0, sticky (solid line) and non-sticky (dashed line) 2023-07-28 00:12:32 +07:00
59 zmienionych plików z 1813 dodań i 1107 usunięć

3
.gitmodules vendored
Wyświetl plik

@ -1,3 +1,6 @@
[submodule "tools/fw_tools"]
path = tools/fw_tools
url = https://github.com/amnemonic/Quansheng_UV-K5_Firmware.git
[submodule "tools/k5prog"]
path = tools/k5prog
url = git@github.com:sq5bpf/k5prog.git

Wyświetl plik

@ -31,6 +31,7 @@ set(COMPILER_OPTIONS -mthumb -mcpu=cortex-m0 -mfpu=auto -mfloat-abi=soft -fno-ex
-O${OPTI_FLAG} -Wl,--gc-sections $<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>
)
add_subdirectory(tools)
add_subdirectory(libs)
add_subdirectory(src)

Wyświetl plik

@ -12,6 +12,44 @@ AFSK messenger with T9 typing support
* if message is cleared use **EXIT** to exit messenger view
* There is no timeout for the button. If you want to type letters located on the same button in a row, use an asterisk (*) to confirm the selected character
## src/spectrum_fagci ![auto release build](https://github.com/piotr022/UV_K5_playground/actions/workflows/c-cpp.yml/badge.svg)
Spectrum scanner by [@fagci](https://github.com/fagci)
![spectrum_fagci](./docs/spectrum_fagci.gif)
[more videos](https://youtube.com/playlist?list=PL67vBSofOrHMyXOEhonOzQz5gJzsZFiDq)
[download mod](https://github.com/piotr022/UV_K5_playground/releases/latest)
Features:
* no scan sound
* squelch by user input level
* 0.1 .. 3.2MHz frequency ranges
* ticks by frequency (100,500,1000KHz)
* catch signal peak frequency
* automatic frequency change step
* automatic scan step
* frequency blacklist to remove unwanted signals
* backlight control
How to start:
* set squelch level to 0 or go into monitor mode before enabling mod
* to enable spectum view press **flash light button**
How to operate:
* press **UP** / **DOWN** key to change frequency
* press **1** / **7** to control measurement time (increasing "sensitivity")
* press **2** / **8** to to set frequency change step
* press **9** / **3** for zoom in / zoom out
* press and hold **\*** / **F** to set squelch level
* press **5** to toggle backlight
* press **0** to remove frequency from sspectrum to scan
* press **EXIT** to disable spectrum view
## src/spectrum ![auto release build](https://github.com/piotr022/UV_K5_playground/actions/workflows/c-cpp.yml/badge.svg)
![spectrum](./docs/spectrum.gif)
**update**

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 4.0 MiB

Wyświetl plik

@ -12,6 +12,7 @@ target_include_directories(${NAME} PRIVATE
target_sources(${NAME} PRIVATE
system.cpp
vtable.s
api.s
)
target_link_libraries(${NAME}

Wyświetl plik

@ -0,0 +1,165 @@
.globl PrintTextOnScreen
PrintTextOnScreen = 0x874C + 1;
.globl DelayMs
DelayMs = 0xD0EC + 1;
.globl DelayUs
DelayUs = 0xD100 + 1;
.globl WriteSerialData
WriteSerialData = 0xBE44 + 1;
.globl BK4819Write
BK4819Write = 0xAF00 + 1;
.globl BK4819Read
BK4819Read = 0xA960 + 1;
.globl FlushFramebufferToScreen
FlushFramebufferToScreen = 0xB638 + 1;
.globl PollKeyboard
PollKeyboard = 0xb0b8 + 1;
.globl FormatString
FormatString = 0xC6E8 + 1;
.globl PrintSmallDigits
PrintSmallDigits = 0x870C + 1;
.globl PrintFrequency
PrintFrequency = 0x864C + 1;
.globl AirCopy72
AirCopy72 = 0xA67C + 1;
.globl AirCopyFskSetup
AirCopyFskSetup = 0xA518 + 1;
.globl BK4819Reset
BK4819Reset = 0xa7cc + 1;
.globl IntDivide
IntDivide = 0x128 + 1;
.globl Strlen
Strlen = 0x1c0 + 1;
.globl BK4819SetChannelBandwidth
BK4819SetChannelBandwidth = 0xaa48 + 1;
.globl BK4819WriteFrequency
BK4819WriteFrequency = 0xaabc + 1;
.globl BK4819SetPaGain
BK4819SetPaGain = 0xaad4 + 1;
.globl BK4819ConfigureAndStartTxFsk
BK4819ConfigureAndStartTxFsk = 0x1cd8 + 1;
.globl BK4819ConfigureAndStartRxFsk
BK4819ConfigureAndStartRxFsk = 0xa63c + 1;
.globl BK4819SetGpio
BK4819SetGpio = 0xa794 + 1;
.globl FlushStatusbarBufferToScreen
FlushStatusbarBufferToScreen = 0xb6b0 + 1;
.globl UpdateStatusBar
UpdateStatusBar = 0x9c10 + 1;
.globl AdcReadout
AdcReadout = 0x9d7c + 1;
.globl SomeAmStuff
SomeAmStuff = 0xc158 + 1;
.globl IRQ_RESET
IRQ_RESET = 0xd4 + 1;
.globl IRQ_SYSTICK
IRQ_SYSTICK = 0xc398 + 1;
.globl ConfigureTrimValuesFromNVR
ConfigureTrimValuesFromNVR = 0x20000230 + 1;
.globl FLASH_ReadNvrWord
FLASH_ReadNvrWord = 0x20000214 + 1;
.globl SystemReset
SystemReset = 0x200001f8 + 1;
.globl FLASH_SetProgramTime
FLASH_SetProgramTime = 0x200001d4 + 1;
.globl FLASH_SetMode
FLASH_SetMode = 0x200001b4 + 1;
.globl FLASH_WakeFromDeepSleep
FLASH_WakeFromDeepSleep = 0x20000194 + 1;
.globl FLASH_SetEraseTime
FLASH_SetEraseTime = 0x20000170 + 1;
.globl FLASH_SetReadMode
FLASH_SetReadMode = 0x20000148 + 1;
.globl FLASH_Set_NVR_SEL
FLASH_Set_NVR_SEL = 0x20000128 + 1;
.globl FLASH_ReadByAPB
FLASH_ReadByAPB = 0x200000e8 + 1;
.globl FLASH_ReadByAHB
FLASH_ReadByAHB = 0x200000dc + 1;
.globl FLASH_Unlock
FLASH_Unlock = 0x200000d0 + 1;
.globl FLASH_Lock
FLASH_Lock = 0x200000c4 + 1;
.globl FLASH_MaskUnlock
FLASH_MaskUnlock = 0x200000b0 + 1;
.globl FLASH_SetMaskSel
FLASH_SetMaskSel = 0x20000094 + 1;
.globl FLASH_MaskLock
FLASH_MaskLock = 0x20000080 + 1;
.globl FLASH_Init
FLASH_Init = 0x2000005c + 1;
.globl FLASH_Start
FLASH_Start = 0x20000044 + 1;
.globl FLASH_IsInitBusy
FLASH_IsInitBusy = 0x2000002c + 1;
.globl FLASH_IsBusy
FLASH_IsBusy = 0x20000014 + 1;
.globl FLASH_RebootToBootloader
FLASH_RebootToBootloader = 0x20000000 + 1;
.globl gDisplayBuffer
gDisplayBuffer = 0x20000704;
.globl gSmallDigs
gSmallDigs = 0xD620;
.globl gSmallLeters
gSmallLeters = 0xD348;
.globl gFlashLightStatus
gFlashLightStatus = 0x200003b3;
.globl gStatusBarData
gStatusBarData = 0x20000684;
.globl gVoltage
gVoltage = 0x20000406;

Wyświetl plik

@ -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;
}
};

Wyświetl plik

@ -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)

Wyświetl plik

@ -21,5 +21,5 @@ void System::CopyDataSection()
extern "C" unsigned int __wrap___udivsi3(unsigned int a, unsigned int b)
{
return OrgFunc_01_26.IntDivide(a, b);
}
return IntDivide(a, b);
}

Wyświetl plik

@ -1,4 +1,72 @@
#pragma once
extern "C" {
void PrintTextOnScreen(const char* U8Text,
unsigned int u32StartPixel,
unsigned int u32StopPixel,
unsigned int u32LineNumber,
unsigned int u32PxPerChar,
unsigned int u32Centered
);
void DelayMs(unsigned int u32Ms);
void DelayUs(unsigned int u32Us);
int WriteSerialData(unsigned char* p8Data, unsigned char u8Len);
void BK4819Write(unsigned int u32Address, unsigned int u32Data);
unsigned int BK4819Read(unsigned int u32Address);
void FlushFramebufferToScreen(void);
unsigned int PollKeyboard(void);
char* FormatString(char *, const char *, ...);
void PrintSmallDigits(unsigned int u32Len, const int* p32Number, int s32X, int s32Y);
void PrintFrequency(int frequency,int xpos,int ypos,int param_4,int param_5);
void AirCopy72(unsigned char*);
void AirCopyFskSetup();
void BK4819Reset();
int IntDivide(int s32Divident, int s32Divisor);
int Strlen(const char *string);
void BK4819SetChannelBandwidth(bool narrow);
void BK4819WriteFrequency(unsigned int u32Frequency);
void BK4819SetPaGain(unsigned short u16PaBias, unsigned int u32Frequency);
void BK4819ConfigureAndStartTxFsk();
void BK4819ConfigureAndStartRxFsk();
void BK4819SetGpio(unsigned int u32Pin, bool bState);
void FlushStatusbarBufferToScreen();
void UpdateStatusBar();
void AdcReadout(unsigned short* p16Data1, unsigned short* p16Data2);
void SomeAmStuff(unsigned int u32Param);
void IRQ_RESET(void);
void IRQ_SYSTICK(void);
// API available in the SRAM overlay installed by FW
void ConfigureTrimValuesFromNVR(void);
unsigned int FLASH_ReadNvrWord(unsigned int u32Offset);
void SystemReset(void);
void FLASH_SetProgramTime(void);
void FLASH_SetMode(unsigned int u32Mode);
void FLASH_WakeFromDeepSleep(void);
void FLASH_SetEraseTime(void);
void FLASH_SetReadMode(unsigned int u32Mode);
void FLASH_Set_NVR_SEL(unsigned int u32Sel);
unsigned int FLASH_ReadByAPB(unsigned int u32Offset);
unsigned int FLASH_ReadByAHB(unsigned int u32Offset);
void FLASH_Unlock(void);
void FLASH_Lock(void);
void FLASH_MaskUnlock(void);
void FLASH_SetMaskSel(unsigned int u32Mask);
void FLASH_MaskLock(void);
void FLASH_Init(unsigned int u32ReadMode);
void FLASH_Start(void);
int FLASH_IsInitBusy(void);
int FLASH_IsBusy(void);
int FLASH_RebootToBootloader(void);
};
extern unsigned char gDisplayBuffer[];
extern unsigned char gSmallDigs[];
extern unsigned char gSmallLeters[];
extern unsigned char gFlashLightStatus;
extern unsigned char gStatusBarData[];
extern unsigned short gVoltage;
namespace System
{
using VoidFxPointer = void(*)(void);
@ -32,94 +100,6 @@ namespace System
};
void CopyDataSection();
struct TOrgFunctions
{
void(*PrintTextOnScreen)(const char* U8Text,
unsigned int u32StartPixel,
unsigned int u32StopPixel,
unsigned int u32LineNumber,
unsigned int u32PxPerChar,
unsigned int u32Centered
);
void(*DelayMs)(unsigned int u32Ms);
void(*DelayUs)(unsigned int u32Us);
int(*WriteSerialData)(unsigned char* p8Data, unsigned char u8Len);
void(*BK4819Write)(unsigned int u32Address, unsigned int u32Data);
unsigned int(*BK4819Read)(unsigned int u32Address);
void(*FlushFramebufferToScreen)(void);
unsigned int(*PollKeyboard)(void);
char* (*FormatString)(char *, const char *, ...);
void(*PrintSmallDigits)(unsigned int u32Len, const int* p32Number, int s32X, int s32Y);
void(*PrintFrequency)(int frequency,int xpos,int ypos,int param_4,int param_5);
void(*AirCopy72)(unsigned char*);
void(*AirCopyFskSetup)();
void(*BK4819Reset)();
int(*IntDivide)(int s32Divident, int s32Divisor);
void(*BK4819WriteFrequency)(unsigned int u32Frequency);
void(*BK4819SetPaGain)(unsigned short u16PaBias, unsigned int u32Frequency);
void(*BK4819ConfigureAndStartTxFsk)();
void(*BK4819ConfigureAndStartRxFsk)();
void(*BK4819SetGpio)(unsigned int u32Pin, bool bState);
void(*FlushStatusbarBufferToScreen)();
void(*UpdateStatusBar)();
void(*AdcReadout)(unsigned short* p16Data1, unsigned short* p16Data2);
void(*SomeAmStuff)(unsigned int u32Param);
void (*IRQ_RESET)(void);
void (*IRQ_SYSTICK)(void);
};
struct TOrgData
{
unsigned char* pDisplayBuffer;
unsigned char* pSmallDigs;
unsigned char* pSmallLeters;
unsigned char* p8FlashLightStatus;
unsigned char* pStatusBarData;
unsigned short* p16Voltage;
};
inline const TOrgFunctions OrgFunc_01_26 =
{
.PrintTextOnScreen = (decltype(TOrgFunctions::PrintTextOnScreen))(0x874C + 1),
.DelayMs = (decltype(TOrgFunctions::DelayMs)) (0xD0EC + 1),
.DelayUs = (decltype(TOrgFunctions::DelayUs)) (0xD100 + 1),
.WriteSerialData = (int(*)(unsigned char*, unsigned char))(0xBE44 + 1),
.BK4819Write = (decltype(TOrgFunctions::BK4819Write) (0xAF00 + 1)),
.BK4819Read = (decltype(TOrgFunctions::BK4819Read) (0xA960 + 1)),
.FlushFramebufferToScreen = (decltype(TOrgFunctions::FlushFramebufferToScreen) (0xB638 + 1)),
.PollKeyboard = (decltype(TOrgFunctions::PollKeyboard) (0xb0b8 + 1)),
.FormatString = (decltype(TOrgFunctions::FormatString) (0xC6E8 + 1)),
.PrintSmallDigits = (decltype(TOrgFunctions::PrintSmallDigits) (0x870C + 1)),
.PrintFrequency = (decltype(TOrgFunctions::PrintFrequency) (0x864C + 1)),
.AirCopy72 = (decltype(TOrgFunctions::AirCopy72) (0xA67C + 1)),
.AirCopyFskSetup = (decltype(TOrgFunctions::AirCopyFskSetup) (0xA518 + 1)),
.BK4819Reset = (decltype(TOrgFunctions::BK4819Reset) (0xa7cc + 1)),
.IntDivide = (decltype(TOrgFunctions::IntDivide) (0x128 + 1)),
.BK4819WriteFrequency = (decltype(TOrgFunctions::BK4819WriteFrequency) (0xaabc + 1)),
.BK4819SetPaGain = (decltype(TOrgFunctions::BK4819SetPaGain) (0xaad4 + 1)),
.BK4819ConfigureAndStartTxFsk = (decltype(TOrgFunctions::BK4819ConfigureAndStartTxFsk) (0x1cd8 + 1)),
.BK4819ConfigureAndStartRxFsk = (decltype(TOrgFunctions::BK4819ConfigureAndStartRxFsk) (0xa63c + 1)),
.BK4819SetGpio = (decltype(TOrgFunctions::BK4819SetGpio) (0xa794 + 1)),
.FlushStatusbarBufferToScreen = (decltype(TOrgFunctions::FlushStatusbarBufferToScreen) (0xb6b0 + 1)),
.UpdateStatusBar = (decltype(TOrgFunctions::UpdateStatusBar) (0x9c10 + 1)),
.AdcReadout = (decltype(TOrgFunctions::AdcReadout) (0x9d7c + 1)),
.SomeAmStuff = (decltype(TOrgFunctions::SomeAmStuff) (0xc158 + 1)),
.IRQ_RESET = (decltype(TOrgFunctions::IRQ_RESET) (0xd4 + 1)),
.IRQ_SYSTICK = (decltype(TOrgFunctions::IRQ_SYSTICK) (0xc398 + 1))
};
inline const TOrgData OrgData_01_26 =
{
.pDisplayBuffer = (decltype(TOrgData::pDisplayBuffer)) 0x20000704,
.pSmallDigs = (decltype(TOrgData::pSmallDigs)) 0xD620,
.pSmallLeters = (decltype(TOrgData::pSmallLeters)) 0xD348,
.p8FlashLightStatus = (decltype(TOrgData::p8FlashLightStatus)) 0x200003b3,
.pStatusBarData = (decltype(TOrgData::pStatusBarData)) 0x20000684,
.p16Voltage = (decltype(TOrgData::p16Voltage)) 0x20000406,
};
}
extern "C" void __libc_init_array();
extern "C" void __libc_init_array();

Wyświetl plik

@ -1,275 +1,280 @@
#pragma once
#include <type_traits>
#include <string.h>
#include <type_traits>
#include "system.hpp"
struct ILcd
{
virtual void UpdateScreen() = 0;
struct ILcd {
virtual void UpdateScreen() = 0;
};
template <unsigned short _SizeX, unsigned short _SizeY, unsigned char _LineHeight>
struct IBitmap
{
constexpr IBitmap(const unsigned char *_pBuffStart) : pBuffStart(_pBuffStart){};
static constexpr auto SizeX = _SizeX;
static constexpr auto SizeY = _SizeY;
static constexpr auto LineHeight = _LineHeight;
static constexpr auto Lines = _SizeX / _LineHeight;
static constexpr unsigned short GetCoursorPosition(unsigned char u8Line, unsigned char u8XPos)
{
return (u8Line * SizeX) + u8XPos;
}
template <unsigned short _SizeX, unsigned short _SizeY,
unsigned char _LineHeight>
struct IBitmap {
constexpr IBitmap(const unsigned char *_pBuffStart)
: pBuffStart(_pBuffStart){};
static constexpr auto SizeX = _SizeX;
static constexpr auto SizeY = _SizeY;
static constexpr auto LineHeight = _LineHeight;
static constexpr auto Lines = _SizeX / _LineHeight;
static constexpr unsigned short GetCoursorPosition(unsigned char u8Line,
unsigned char u8XPos) {
return (u8Line * SizeX) + u8XPos;
}
virtual bool GetPixel(unsigned char u8X, unsigned char u8Y) const = 0;
virtual void SetPixel(unsigned char u8X, unsigned char u8Y) const = 0;
virtual void *GetCoursorData(unsigned short u16CoursorPosition) const { return nullptr; }
virtual void ClearAll() = 0;
const unsigned char *pBuffStart;
virtual bool GetPixel(unsigned char u8X, unsigned char u8Y) const = 0;
virtual void SetPixel(unsigned char u8X, unsigned char u8Y) const = 0;
virtual void *GetCoursorData(unsigned short u16CoursorPosition) const {
return nullptr;
}
virtual void ClearAll() = 0;
const unsigned char *pBuffStart;
};
struct IFont
{
virtual bool GetPixel(char c8Character, unsigned char u8X, unsigned char u8Y) const = 0;
virtual unsigned char *GetRaw(char c8Character) const = 0;
virtual unsigned char GetSizeX(char c8Character) const = 0;
virtual unsigned char GetSizeY(char c8Character) const = 0;
struct IFont {
virtual bool GetPixel(char c8Character, unsigned char u8X,
unsigned char u8Y) const = 0;
virtual unsigned char *GetRaw(char c8Character) const = 0;
virtual unsigned char GetSizeX(char c8Character) const = 0;
virtual unsigned char GetSizeY(char c8Character) const = 0;
};
template <class BitmapType>
class CDisplay
{
template <class BitmapType> class CDisplay {
public:
constexpr CDisplay(BitmapType &_Bitmap)
: Bitmap(_Bitmap), pCurrentFont(nullptr), u16CoursorPosition(0)
{
}
constexpr CDisplay(BitmapType &_Bitmap)
: Bitmap(_Bitmap), pCurrentFont(nullptr), u16CoursorPosition(0) {}
void SetCoursor(unsigned char u8Line, unsigned char u8X) const
{
u16CoursorPosition = (u8Line * Bitmap.SizeX) + u8X;
}
void SetCoursor(unsigned char u8Line, unsigned char u8X) const {
u16CoursorPosition = (u8Line * Bitmap.SizeX) + u8X;
}
void SetCoursorXY(unsigned char x, unsigned char y) const
{
u16CoursorPosition = x + (y << 4);
}
void SetCoursorXY(unsigned char x, unsigned char y) const {
u16CoursorPosition = x + (y << 4);
}
void SetFont(const IFont *pFont) const
{
pCurrentFont = pFont;
}
void SetFont(const IFont *pFont) const { pCurrentFont = pFont; }
void DrawLine(int sx, int ex, int ny)
{
for (int i = sx; i <= ex; i++)
{
if (i < Bitmap.SizeX && ny < Bitmap.SizeY)
{
Bitmap.SetPixel(i, ny);
}
void DrawLine(int sx, int ex, int ny) {
for (int i = sx; i <= ex; i++) {
if (i < Bitmap.SizeX && ny < Bitmap.SizeY) {
Bitmap.SetPixel(i, ny);
}
}
}
}
void DrawHLine(int sy, int ey, int nx, bool bCropped = false)
{
for (int i = sy; i <= ey; i++)
{
if (i < Bitmap.SizeY && nx < Bitmap.SizeX && (!bCropped || i % 2))
{
Bitmap.SetPixel(nx, i);
}
void DrawHLine(int sy, int ey, int nx, bool bCropped = false) {
for (int i = sy; i <= ey; i++) {
if (i < Bitmap.SizeY && nx < Bitmap.SizeX && (!bCropped || i % 2)) {
Bitmap.SetPixel(nx, i);
}
}
}
}
void DrawCircle(unsigned char cx, unsigned char cy, unsigned int r, bool bFilled = false)
{
int x = 0;
int y = r;
int d = 3 - 2 * r;
if (!r)
return;
void DrawCircle(unsigned char cx, unsigned char cy, unsigned int r,
bool bFilled = false) {
int x = 0;
int y = r;
int d = 3 - 2 * r;
if (!r)
return;
while (y >= x)
{
// when bFilled is true, draw lines to fill the circle
if (bFilled)
{
DrawLine(cx - x, cx + x, cy - y);
DrawLine(cx - y, cx + y, cy - x);
DrawLine(cx - x, cx + x, cy + y);
DrawLine(cx - y, cx + y, cy + x);
}
else
{
if (cx + x < Bitmap.SizeX && cy + y < Bitmap.SizeY)
Bitmap.SetPixel(cx + x, cy - y); // 1st quarter
if (cx + y < Bitmap.SizeX && cy + x < Bitmap.SizeY)
Bitmap.SetPixel(cx + y, cy - x); // 2nd quarter
if (cx - x >= 0 && cy + y < Bitmap.SizeY)
Bitmap.SetPixel(cx - x, cy - y); // 3rd quarter
if (cx - y >= 0 && cy + x < Bitmap.SizeY)
Bitmap.SetPixel(cx - y, cy - x); // 4th quarter
if (cx + x < Bitmap.SizeX && cy + y < Bitmap.SizeY)
Bitmap.SetPixel(cx + x, cy + y); // 5th quarter
if (cx + y < Bitmap.SizeX && cy - x >= 0)
Bitmap.SetPixel(cx + y, cy + x); // 6th quarter
if (cx - x >= 0 && cy - y >= 0)
Bitmap.SetPixel(cx - x, cy + y); // 7th quarter
if (cx - y >= 0 && cy - x >= 0)
Bitmap.SetPixel(cx - y, cy + x); // 8th quarter
}
x++;
if (d < 0)
d += 4 * x + 6;
else
{
y--;
d += 4 * (x - y) + 10;
}
while (y >= x) {
// when bFilled is true, draw lines to fill the circle
if (bFilled) {
DrawLine(cx - x, cx + x, cy - y);
DrawLine(cx - y, cx + y, cy - x);
DrawLine(cx - x, cx + x, cy + y);
DrawLine(cx - y, cx + y, cy + x);
} else {
if (cx + x < Bitmap.SizeX && cy + y < Bitmap.SizeY)
Bitmap.SetPixel(cx + x, cy - y); // 1st quarter
if (cx + y < Bitmap.SizeX && cy + x < Bitmap.SizeY)
Bitmap.SetPixel(cx + y, cy - x); // 2nd quarter
if (cx - x >= 0 && cy + y < Bitmap.SizeY)
Bitmap.SetPixel(cx - x, cy - y); // 3rd quarter
if (cx - y >= 0 && cy + x < Bitmap.SizeY)
Bitmap.SetPixel(cx - y, cy - x); // 4th quarter
if (cx + x < Bitmap.SizeX && cy + y < Bitmap.SizeY)
Bitmap.SetPixel(cx + x, cy + y); // 5th quarter
if (cx + y < Bitmap.SizeX && cy - x >= 0)
Bitmap.SetPixel(cx + y, cy + x); // 6th quarter
if (cx - x >= 0 && cy - y >= 0)
Bitmap.SetPixel(cx - x, cy + y); // 7th quarter
if (cx - y >= 0 && cy - x >= 0)
Bitmap.SetPixel(cx - y, cy + x); // 8th quarter
}
}
void DrawRectangle(unsigned char sx, unsigned char sy, unsigned char width, unsigned char height, bool bFilled)
{
unsigned char maxX = (sx + width < Bitmap.SizeX) ? sx + width : Bitmap.SizeX;
unsigned char maxY = (sy + height < Bitmap.SizeY) ? sy + height : Bitmap.SizeY;
// Draw vertical lines
for (unsigned char y = sy; y < maxY; y++)
{
Bitmap.SetPixel(sx, y);
Bitmap.SetPixel(maxX - 1, y);
x++;
if (d < 0)
d += 4 * x + 6;
else {
y--;
d += 4 * (x - y) + 10;
}
}
}
// Draw horizontal lines
for (unsigned char x = sx; x < maxX; x++)
{
Bitmap.SetPixel(x, sy);
Bitmap.SetPixel(x, maxY - 1);
void DrawRectangle(unsigned char sx, unsigned char sy, unsigned char width,
unsigned char height, bool bFilled) {
unsigned char maxX =
(sx + width < Bitmap.SizeX) ? sx + width : Bitmap.SizeX;
unsigned char maxY =
(sy + height < Bitmap.SizeY) ? sy + height : Bitmap.SizeY;
// Draw vertical lines
for (unsigned char y = sy; y < maxY; y++) {
Bitmap.SetPixel(sx, y);
Bitmap.SetPixel(maxX - 1, y);
}
// Draw horizontal lines
for (unsigned char x = sx; x < maxX; x++) {
Bitmap.SetPixel(x, sy);
Bitmap.SetPixel(x, maxY - 1);
}
// If filled, draw horizontal lines within the rectangle
if (bFilled) {
for (unsigned char x = sx + 1; x < maxX - 1; x++) {
for (unsigned char y = sy + 1; y < maxY - 1; y++) {
Bitmap.SetPixel(x, y);
}
}
}
}
// If filled, draw horizontal lines within the rectangle
if (bFilled)
{
for (unsigned char x = sx + 1; x < maxX - 1; x++)
{
for (unsigned char y = sy + 1; y < maxY - 1; y++)
{
Bitmap.SetPixel(x, y);
}
}
}
}
unsigned char PrintCharacter(const char c8Character) const
{
if (!pCurrentFont)
{
return 0;
}
const auto *const pFontRawData = pCurrentFont->GetRaw(c8Character);
auto *pCoursorPosition = Bitmap.GetCoursorData(u16CoursorPosition);
auto const CopySize = pCurrentFont->GetSizeY(c8Character) * (BitmapType::LineHeight / 8);
if (pCoursorPosition && !(BitmapType::LineHeight % 8))
{
if (pFontRawData)
memcpy(pCoursorPosition, pFontRawData, CopySize);
else
memset(pCoursorPosition, 0, CopySize);
}
u16CoursorPosition += pCurrentFont->GetSizeY(c8Character);
unsigned char PrintCharacter(const char c8Character) const {
if (!pCurrentFont) {
return 0;
}
}
void Print(const char *C8String) const
{
for (unsigned char i = 0; i < strlen(C8String); i++)
{
PrintCharacter(C8String[i]);
const auto *const pFontRawData = pCurrentFont->GetRaw(c8Character);
auto *pCoursorPosition = Bitmap.GetCoursorData(u16CoursorPosition);
auto const CopySize =
pCurrentFont->GetSizeY(c8Character) * (BitmapType::LineHeight / 8);
if (pCoursorPosition && !(BitmapType::LineHeight % 8)) {
if (pFontRawData)
memcpy(pCoursorPosition, pFontRawData, CopySize);
else
memset(pCoursorPosition, 0, CopySize);
}
u16CoursorPosition += pCurrentFont->GetSizeY(c8Character);
return 0;
}
void Print(const char *C8String) const {
for (unsigned char i = 0; i < Strlen(C8String); i++) {
PrintCharacter(C8String[i]);
}
}
unsigned char PrintFixedDigtsNumer(int s32Number, unsigned char u8Digts) {
char U8NumBuff[32];
memset(U8NumBuff, 0, sizeof(U8NumBuff));
char *pString = U8NumBuff + u8Digts;
*pString = '\0';
if (s32Number < 0) {
U8NumBuff[0] = '-';
s32Number = -s32Number;
}
while (u8Digts--) {
*--pString = '0' + (s32Number % 10);
s32Number /= 10;
}
Print(U8NumBuff);
return u8Digts * pCurrentFont->GetSizeX('0');
}
static constexpr int powersOfTen[9] = {
1, // 10^0
10, // 10^1
100, // 10^2
1000, // 10^3
10000, // 10^4
100000, // 10^5
1000000, // 10^6
10000000, // 10^7
100000000 // 10^8
};
void PrintFixedDigitsNumber2(int s32Number, unsigned char u8DigsToCut = 2,
unsigned char u8FixedDigtsCnt = 0) {
char U8NumBuff[11] = {0}; // 9 digits, sign, and null terminator
int startIdx = 0;
bool isNegative = false;
if (s32Number < 0) {
PrintCharacter('-');
// U8NumBuff[0] = '-';
s32Number = -s32Number;
// isNegative = true;
}
for (int i = 8; i >= u8DigsToCut;
--i) // assuming powersOfTen is an array of powers of 10
{
int digit = 0;
while (s32Number >= powersOfTen[i]) {
s32Number -= powersOfTen[i];
++digit;
}
}
U8NumBuff[isNegative + (8 - i)] = '0' + digit;
unsigned char PrintFixedDigtsNumer(int s32Number, unsigned char u8Digts)
{
char U8NumBuff[32];
memset(U8NumBuff, 0, sizeof(U8NumBuff));
// We found the first non-zero digit
if (digit != 0 && startIdx == (isNegative ? 1 : 0))
startIdx = isNegative + (8 - i);
}
char *pString = U8NumBuff + u8Digts;
*pString = '\0';
// If the number was 0, we write a single 0.
if (startIdx == (isNegative ? 1 : 0))
U8NumBuff[isNegative] = '0';
if (s32Number < 0)
{
U8NumBuff[0] = '-';
s32Number = -s32Number;
// Print the string from the start index
if (u8FixedDigtsCnt) {
startIdx = 9 - u8DigsToCut - u8FixedDigtsCnt;
}
Print(U8NumBuff + startIdx);
}
void PrintFixedDigitsNumber3(int s32Number, unsigned char u8DigsToCut = 2,
unsigned char u8FixedDigtsCnt = 0,
unsigned char pointAt = 128) {
char U8NumBuff[11] = {0}; // 9 digits, sign, and null terminator
unsigned char startIdx = 0;
for (unsigned char i = 8; i >= u8DigsToCut; --i) {
int digit = 0;
while (s32Number >= powersOfTen[i]) {
s32Number -= powersOfTen[i];
++digit;
}
U8NumBuff[8 - i] = '0' + digit;
while (u8Digts--)
{
*--pString = '0' + (s32Number % 10);
s32Number /= 10;
// We found the first non-zero digit
if (digit != 0 && startIdx == 0)
startIdx = 8 - i;
}
// Print the string from the start index
startIdx = 9 - u8DigsToCut - u8FixedDigtsCnt;
const char *str = U8NumBuff + startIdx;
const char len = Strlen(str);
const char dot[1] = {64};
for (unsigned char i = 0; i < len; i++) {
if (pointAt == len - i) {
auto *pCoursorPosition = Bitmap.GetCoursorData(u16CoursorPosition + 1);
memcpy(pCoursorPosition, dot, 1);
u16CoursorPosition += 2;
}
Print(U8NumBuff);
return u8Digts * pCurrentFont->GetSizeX('0');
}
static constexpr int powersOfTen[9] = {
1, // 10^0
10, // 10^1
100, // 10^2
1000, // 10^3
10000, // 10^4
100000, // 10^5
1000000, // 10^6
10000000, // 10^7
100000000 // 10^8
};
void PrintFixedDigitsNumber2(int s32Number, unsigned char u8DigsToCut = 2, unsigned char u8FixedDigtsCnt = 0)
{
char U8NumBuff[11] = {0}; // 9 digits, sign, and null terminator
int startIdx = 0;
bool isNegative = false;
if (s32Number < 0)
{
PrintCharacter('-');
// U8NumBuff[0] = '-';
s32Number = -s32Number;
// isNegative = true;
}
for (int i = 8; i >= u8DigsToCut; --i) // assuming powersOfTen is an array of powers of 10
{
int digit = 0;
while (s32Number >= powersOfTen[i])
{
s32Number -= powersOfTen[i];
++digit;
}
U8NumBuff[isNegative + (8 - i)] = '0' + digit;
// We found the first non-zero digit
if (digit != 0 && startIdx == (isNegative ? 1 : 0))
startIdx = isNegative + (8 - i);
}
// If the number was 0, we write a single 0.
if (startIdx == (isNegative ? 1 : 0))
U8NumBuff[isNegative] = '0';
// Print the string from the start index
if (u8FixedDigtsCnt)
{
startIdx = 9 - u8DigsToCut - u8FixedDigtsCnt;
}
Print(U8NumBuff + startIdx);
}
PrintCharacter(str[i]);
}
}
private:
const BitmapType &Bitmap;
mutable const IFont *pCurrentFont;
mutable unsigned short u16CoursorPosition;
const BitmapType &Bitmap;
mutable const IFont *pCurrentFont;
mutable unsigned short u16CoursorPosition;
};

Wyświetl plik

@ -3,239 +3,286 @@
#include "registers.hpp"
#include "system.hpp"
#include <functional>
#include <cstring>
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,
};
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,
};
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;
};
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
};
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,
};
enum class eState : unsigned char
{
Idle,
RxPending,
};
using CallbackRxDoneType = CCallback<void, unsigned char, bool>;
template <const System::TOrgFunctions &Fw> class CBK4819 {
CallbackRxDoneType CallbackRxDone;
unsigned char *p8RxBuff;
unsigned char u8RxBuffSize;
using CallbackRxDoneType = CCallback<void, unsigned char, bool>;
class CBK4819
{
CallbackRxDoneType CallbackRxDone;
unsigned char *p8RxBuff;
unsigned char u8RxBuffSize;
public:
CBK4819() : State(eState::Idle), u16RxDataLen(0){};
public:
CBK4819() : State(eState::Idle), u16RxDataLen(0){};
// void SetFrequency(unsigned int u32FrequencyD10)
// {
// Fw.BK4819WriteFrequency(u32FrequencyD10);
// }
// void SetFrequency(unsigned int u32FrequencyD10)
// {
// 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);
}
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
static unsigned int GetFrequency()
{
return;
return (BK4819Read(0x39) << 16) | BK4819Read(0x38);
}
auto const IrqReg = GetIrqReg();
if (IrqReg & eIrq::RxDone) {
// HandleRxDone();
static signed short GetRssi()
{
short s16Rssi = ((BK4819Read(0x67) >> 1) & 0xFF);
return s16Rssi - 160;
}
if (IrqReg & eIrq::FifoAlmostFull) {
HandleFifoAlmostFull();
}
}
}
bool IsTx() { return BK4819Read(0x30) & 0b10; }
eState State;
unsigned short u16RxDataLen;
bool IsSqlOpen() { return BK4819Read(0x0C) & 0b10; }
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);
static void SetFrequency(unsigned int u32Freq)
{
BK4819Write(0x39, ((u32Freq >> 16) & 0xFFFF));
BK4819Write(0x38, (u32Freq & 0xFFFF));
auto OldReg = BK4819Read(0x30);
BK4819Write(0x30, 0);
BK4819Write(0x30, OldReg);
}
u16RxDataLen += 2;
}
void SetAgcTable(unsigned short *p16AgcTable)
{
for (unsigned char i = 0; i < 5; i++)
{
BK4819Write(0x10 + i, p16AgcTable[i]);
}
}
if (u16RxDataLen >= u8RxBuffSize) {
State = eState::Idle;
CallbackRxDone(u8RxBuffSize, CheckCrc());
}
}
};
void GetAgcTable(unsigned short *p16AgcTable)
{
for (unsigned char i = 0; i < 5; i++)
{
p16AgcTable[i] = BK4819Read(0x10 + i);
}
}
void SetDeviationPresent(unsigned char u8Present)
{
auto Reg40 = BK4819Read(0x40);
Reg40 &= ~(1 << 12);
Reg40 |= (u8Present << 12);
BK4819Write(0x40, Reg40);
}
void SetCalibration(unsigned char bOn)
{
auto Reg30 = BK4819Read(0x31);
Reg30 &= ~(1 << 3);
Reg30 |= (bOn << 3);
BK4819Write(0x31, Reg30);
}
unsigned char GetAFAmplitude() { return BK4819Read(0x6F) & 0b1111111; }
static void ToggleAFDAC(bool enabled)
{
auto Reg = BK4819Read(0x30);
Reg &= ~(1 << 9);
if (enabled)
Reg |= (1 << 9);
BK4819Write(0x30, Reg);
}
static void ToggleRXDSP(bool enabled)
{
auto Reg = BK4819Read(0x30);
Reg &= ~1;
if (enabled)
Reg |= 1;
BK4819Write(0x30, Reg);
}
void SendSyncAirCopyMode72(unsigned char *p8Data)
{
BK4819ConfigureAndStartTxFsk();
AirCopyFskSetup();
AirCopy72(p8Data);
BK4819SetGpio(1, false);
}
void DisablePa() { BK4819Write(0x30, BK4819Read(0x30) & ~0b1010); }
void SetFskMode(eFskMode Mode)
{
auto const &ModeParams = ModesBits[(int)Mode];
auto Reg58 = BK4819Read(0x58);
Reg58 &= ~((0b111 << 1) | (0b111 << 10) | (0b111 << 13));
Reg58 |= (ModeParams.u8RxBandWidthBits << 1) |
(ModeParams.u8RxModeBits << 10) | (ModeParams.u8TxModeBits << 13);
BK4819Write(0x58, 0);
BK4819Write(0x58, Reg58);
}
void FixIrqEnRegister() // original firmware overrides IRQ_EN reg, so we need
// to reenable it
{
auto const OldIrqEnReg = BK4819Read(0x3F);
if ((OldIrqEnReg & (eIrq::FifoAlmostFull | eIrq::RxDone)) !=
(eIrq::FifoAlmostFull | eIrq::RxDone))
{
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;
AirCopyFskSetup();
BK4819ConfigureAndStartRxFsk();
State = eState::RxPending;
}
void DisableFskModem()
{
auto const FskSettings = BK4819Read(0x58);
BK4819Write(0x58, FskSettings & ~1);
}
void ClearRxFifoBuff()
{
auto const Reg59 = BK4819Read(0x59);
BK4819Write(0x59, 1 << 14);
BK4819Write(0x59, Reg59);
}
unsigned short GetIrqReg()
{
BK4819Write(0x2, 0);
return BK4819Read(0x2);
}
bool CheckCrc() { return 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 (!(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 = 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

Wyświetl plik

@ -1,23 +1,24 @@
#pragma once
#include "manager.hpp"
#include "registers.hpp"
#include "hardware/adc.hpp"
template <
const System::TOrgFunctions &Fw,
const System::TOrgData &FwData,
TUV_K5Display &DisplayBuff,
CDisplay<TUV_K5Display> &Display,
CDisplay<TUV_K5Display> &DisplayStatusBar,
const TUV_K5SmallNumbers &FontSmallNr,
Radio::CBK4819<Fw> &RadioDriver>
Radio::CBK4819 &RadioDriver>
class CAmTx : public IView
{
static constexpr bool bAmpTests = true;
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 +30,22 @@ public:
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);
HandleTests();
u32StartFreq = RadioDriver.GetFrequency();
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;
@ -76,16 +62,17 @@ public:
// if (MicAmp < 0)
// MicAmp = 0;
unsigned short U16AdcData[2];
Fw.AdcReadout(U16AdcData, U16AdcData+1);
Fw.FormatString(S8DebugStr, "in 1: %05i ", U16AdcData[0]);
Fw.PrintTextOnScreen(S8DebugStr, 0, 127, 0, 8, 0);
Fw.FormatString(S8DebugStr, "in 2: %05i ", U16AdcData[1]);
Fw.PrintTextOnScreen(S8DebugStr, 0, 127, 2, 8, 0);
AdcReadout(U16AdcData, U16AdcData+1);
FormatString(S8DebugStr, "in 1: %05i ", U16AdcData[0]);
PrintTextOnScreen(S8DebugStr, 0, 127, 0, 8, 0);
FormatString(S8DebugStr, "in 2: %05i ", U16AdcData[1]);
PrintTextOnScreen(S8DebugStr, 0, 127, 2, 8, 0);
}
void HandleMicInput()
{
unsigned short u16ActualAmp = Fw.BK4819Read(0x64);
u16ActualAmp = BK4819Read(0x64);
// u16ActualAmp = BK4819Read(0x6F) & 0b1111111;
s32DeltaAmp = u16OldAmp - u16ActualAmp;
u16OldAmp = u16ActualAmp;
}
@ -98,7 +85,7 @@ public:
MicAmp = 0b111;
if (MicAmp < 0)
MicAmp = 0;
Fw.BK4819Write(0x36, ((MicAmp & 0b111) << 3) | (MicAmp & 0b111));
BK4819Write(0x36, ((MicAmp & 0b111) << 3) | (MicAmp & 0b111));
}
void HandleTxWfm()
@ -131,6 +118,7 @@ public:
return eScreenRefreshFlag::StatusBar;
}
bInit = true;
Context.ViewStack.Push(*this);
return eScreenRefreshFlag::StatusBar;
}
@ -145,7 +133,7 @@ public:
if (GPIOC->DATA & GPIO_PIN_3)
{
GPIOC->DATA &= ~GPIO_PIN_3;
*FwData.p8FlashLightStatus = 3;
gFlashLightStatus = 3;
return true;
}
@ -154,17 +142,17 @@ public:
void DrawAmIcon(bool bDraw)
{
memset(FwData.pStatusBarData, 0, 14);
memset(gStatusBarData, 0, 14);
if (!bDraw)
{
return;
}
memcpy(FwData.pStatusBarData, FwData.pSmallLeters + 223, 12);
unsigned char *pNegative = FwData.pStatusBarData;
memcpy(gStatusBarData, gSmallLeters + 223, 12);
unsigned char *pNegative = gStatusBarData;
for (unsigned char i = 0; i < 14; i++)
{
*pNegative++ ^= 0xFF;
}
}
};
};

Wyświetl plik

@ -4,7 +4,6 @@
#include "keyboard.hpp"
inline char S8Label[20];
template <const System::TOrgFunctions &Fw>
class CHeater : public IMenuElement
{
bool bEnabled = false;
@ -28,23 +27,22 @@ class CHeater : public IMenuElement
bEnabled = !bEnabled;
if(bEnabled)
{
Fw.BK4819SetGpio(1, true);
BK4819SetGpio(1, true);
}
else
{
Fw.BK4819SetGpio(1, false);
BK4819SetGpio(1, false);
}
}
};
template <const System::TOrgFunctions &Fw>
class CAmRx : public IMenuElement
{
unsigned char u8Mode = 0;
public:
const char *GetLabel() override
{
Fw.FormatString(S8Label, "AM RX %u", u8Mode);
FormatString(S8Label, "AM RX %u", u8Mode);
return S8Label;
}
@ -59,11 +57,11 @@ class CAmRx : public IMenuElement
if(u8Mode > 2)
u8Mode = 0;
// Fw.SomeAmStuff(u8Mode);
// SomeAmStuff(u8Mode);
}
};
template <const System::TOrgFunctions &Fw, Radio::CBK4819<Fw> &RadioDriver>
template <Radio::CBK4819 &RadioDriver>
class CMicVal : public IMenuElement
{
unsigned char u8Mode = 0;
@ -71,7 +69,7 @@ class CMicVal : public IMenuElement
public:
const char *GetLabel() override
{
Fw.FormatString(S8Label, "MIC in %u", Fw.BK4819Read(0x64));
FormatString(S8Label, "MIC in %u", BK4819Read(0x64));
return S8Label;
}
@ -80,7 +78,7 @@ class CMicVal : public IMenuElement
}
};
template <const System::TOrgFunctions &Fw, Radio::CBK4819<Fw> &RadioDriver>
template <Radio::CBK4819 &RadioDriver>
class CRssiVal : public IMenuElement
{
unsigned char u8Mode = 0;
@ -89,11 +87,11 @@ class CRssiVal : public IMenuElement
public:
const char *GetLabel() override
{
Fw.FormatString(S8Label, "RSSI %i", RadioDriver.GetRssi());
FormatString(S8Label, "RSSI %i", RadioDriver.GetRssi());
return S8Label;
}
void HandleUserAction(unsigned char u8Button) override
{
}
};
};

Wyświetl plik

@ -4,8 +4,7 @@
#include "keyboard.hpp"
#include "registers.hpp"
template <const System::TOrgFunctions &Fw,
const System::TOrgData &FwData,
template <
unsigned char BackgroundViewPrescaler,
unsigned char MainViewPrescaler,
unsigned char RegisteredViews>
@ -48,7 +47,7 @@ class CViewManager
% MainViewPrescaler))
{
if(!MainViewContext.OriginalFwStatus.b1RadioSpiCommInUse)
Keyboard.Handle(Fw.PollKeyboard());
Keyboard.Handle(PollKeyboard());
u8ScreenRefreshFlag |=
pViewStackTop->HandleMainView(MainViewContext);
@ -56,12 +55,12 @@ class CViewManager
if(u8ScreenRefreshFlag & eScreenRefreshFlag::MainScreen)
{
Fw.FlushFramebufferToScreen();
FlushFramebufferToScreen();
}
if(u8ScreenRefreshFlag & eScreenRefreshFlag::StatusBar)
{
Fw.FlushStatusbarBufferToScreen();
FlushStatusbarBufferToScreen();
}
}
@ -84,8 +83,8 @@ class CViewManager
inline void CheckOriginalFwStatus()
{
const auto *pMenuCheckData = (unsigned char *)(FwData.pDisplayBuffer + 2*128 + 6 * 8 + 1);
const auto *pFrequencyScanCheckData = (unsigned char *)(FwData.pDisplayBuffer + 6*128 + 3 * 8 + 2);
const auto *pMenuCheckData = (unsigned char *)(gDisplayBuffer + 2*128 + 6 * 8 + 1);
const auto *pFrequencyScanCheckData = (unsigned char *)(gDisplayBuffer + 6*128 + 3 * 8 + 2);
MainViewContext.OriginalFwStatus.b1MenuDrawed = *pMenuCheckData == 0xFF;
MainViewContext.OriginalFwStatus.b1FrequencyScan = *pFrequencyScanCheckData;
MainViewContext.OriginalFwStatus.b1RadioSpiCommInUse = !(GPIOC->DATA & 0b1);
@ -109,4 +108,4 @@ class CViewManager
pTop->HandleReleasedButton(MainViewContext, u8Key);
}
}
};
};

Wyświetl plik

@ -8,8 +8,6 @@ struct IMenuElement
virtual void HandleUserAction(unsigned char u8Button) = 0;
};
template <const System::TOrgFunctions &Fw,
const System::TOrgData &FwData>
class CMenu : public IView
{
static constexpr auto MenuLines = 3;
@ -73,18 +71,18 @@ public:
void DrawMenu()
{
memset(FwData.pDisplayBuffer, 0, 128*6);
memset(gDisplayBuffer, 0, 128*6);
for(unsigned char u8Line = 0; u8Line < MenuLines; u8Line++)
{
auto* Element = GetElement(u8Selected - 1 + u8Line);
if(!Element)
continue;
Fw.PrintTextOnScreen(Element->GetLabel(), 0, 127, u8Line << 1, 8, 0);
PrintTextOnScreen(Element->GetLabel(), 0, 127, u8Line << 1, 8, 0);
}
for(auto i = 0; i < 256; i++)
FwData.pDisplayBuffer[i + 2*128] ^= 0xFF;
gDisplayBuffer[i + 2*128] ^= 0xFF;
}
IMenuElement* GetElement(signed char s8Idx)
@ -102,10 +100,10 @@ public:
if (GPIOC->DATA & GPIO_PIN_3)
{
GPIOC->DATA &= ~GPIO_PIN_3;
*FwData.p8FlashLightStatus = 3;
gFlashLightStatus = 3;
return true;
}
return false;
}
};
};

Wyświetl plik

@ -8,9 +8,7 @@
template <
TUV_K5Display &DisplayBuff,
CDisplay<TUV_K5Display> &Display,
const System::TOrgFunctions &Fw,
const System::TOrgData &FwData,
Radio::CBK4819<Fw> &RadioDriver>
Radio::CBK4819 &RadioDriver>
class CMessenger : public IView
{
public:
@ -66,7 +64,7 @@ public:
if (u8RxDoneLabelCnt < 100)
{
u8RxDoneLabelCnt++;
Fw.PrintTextOnScreen("> RX <", 0, 128, 2, 8, 1);
PrintTextOnScreen("> RX <", 0, 128, 2, 8, 1);
}
switch (State)
@ -100,8 +98,8 @@ public:
void PrintTxData()
{
char C8PrintBuff[30];
Fw.FormatString(C8PrintBuff, ">%s", T9.C8WorkingBuff);
Fw.PrintTextOnScreen(C8PrintBuff, 0, 128, 0, 8, 0);
FormatString(C8PrintBuff, ">%s", T9.C8WorkingBuff);
PrintTextOnScreen(C8PrintBuff, 0, 128, 0, 8, 0);
}
void PrintRxData()
@ -109,9 +107,9 @@ public:
// char *tempRxBuff = S8RxBuff + MaxCharsInLine;
// char C8Temp = tempRxBuff[MaxCharsInLine];
// S8RxBuff[MaxCharsInLine] = '\0';
Fw.PrintTextOnScreen(S8RxBuff, 1, 128, 3, 8, 0);
PrintTextOnScreen(S8RxBuff, 1, 128, 3, 8, 0);
// S8RxBuff[MaxCharsInLine] = C8Temp;
// Fw.PrintTextOnScreen(tempRxBuff, 1, 128, 5, 8, 0);
// PrintTextOnScreen(tempRxBuff, 1, 128, 5, 8, 0);
}
void HandleInitTx()
@ -124,7 +122,7 @@ public:
State = eState::InitRx;
}
Fw.PrintTextOnScreen("> TX <", 0, 128, 2, 8, 1);
PrintTextOnScreen("> TX <", 0, 128, 2, 8, 1);
}
void RxDoneHandler(unsigned char u8DataLen, bool bCrcOk)
{
@ -142,12 +140,12 @@ private:
{
bEnabled = true;
GPIOC->DATA &= ~GPIO_PIN_3;
*FwData.p8FlashLightStatus = 3;
gFlashLightStatus = 3;
}
if (bEnabled)
{
// Keyboard.Handle(Fw.PollKeyboard());
// Keyboard.Handle(PollKeyboard());
}
return bEnabled;
@ -161,7 +159,7 @@ private:
void ClearDrawings()
{
memset(FwData.pDisplayBuffer, 0, (DisplayBuff.SizeX / 8) * DisplayBuff.SizeY);
memset(gDisplayBuffer, 0, (DisplayBuff.SizeX / 8) * DisplayBuff.SizeY);
}
void HandlePressedButton(unsigned char u8Button) override
@ -194,4 +192,4 @@ private:
bool bEnabled;
eState State;
unsigned char u8RxDoneLabelCnt;
};
};

Wyświetl plik

@ -4,8 +4,6 @@
#include "manager.hpp"
template <
System::TOrgFunctions &Fw,
System::TOrgData &FwData,
TUV_K5Display &DisplayBuff,
CDisplay<TUV_K5Display> &Display,
TUV_K5SmallNumbers &FontSmallNr>
@ -25,7 +23,7 @@ public:
return eScreenRefreshFlag::NoRefresh;
}
if (Fw.BK4819Read(0x0C) & 0b10)
if (BK4819Read(0x0C) & 0b10)
{
u8SqlDelayCnt = 0;
}
@ -55,7 +53,7 @@ public:
Display.SetFont(&FontSmallNr);
char C8RssiString[] = "g000";
unsigned char u8Rssi = ((Fw.BK4819Read(0x67) >> 1) & 0xFF);
unsigned char u8Rssi = ((BK4819Read(0x67) >> 1) & 0xFF);
if (!u8Rssi)
{
return eScreenRefreshFlag::NoRefresh;
@ -101,4 +99,4 @@ public:
u8ChartPosition++;
return eScreenRefreshFlag::MainScreen;
}
};
};

Wyświetl plik

@ -49,13 +49,11 @@ namespace Rssi
}
template <
const System::TOrgFunctions &Fw,
const System::TOrgData &FwData,
TUV_K5Display &DisplayBuff,
CDisplay<TUV_K5Display> &Display,
CDisplay<TUV_K5Display> &DisplayStatusBar,
const TUV_K5SmallNumbers &FontSmallNr,
Radio::CBK4819<Fw> &RadioDriver>
Radio::CBK4819 &RadioDriver>
class CRssiSbar : public IView, public IMenuElement
{
public:
@ -67,7 +65,7 @@ public:
static constexpr auto LinearBlocksCnt = 9;
static constexpr auto VoltageOffset = 77;
static constexpr auto MaxBarPoints = 13;
static inline unsigned char *const pDData = FwData.pDisplayBuffer + 128 * 3;
static inline unsigned char *const pDData = gDisplayBuffer + 128 * 3;
unsigned int u32DrawVoltagePsc = 0;
Rssi::TRssi RssiData;
@ -188,7 +186,7 @@ public:
{
if (bPtt) // print TX
{
memcpy(pDData + 5 * 7, FwData.pSmallLeters + 128 * 2 + 8 * 3 + 2, 15);
memcpy(pDData + 5 * 7, gSmallLeters + 128 * 2 + 8 * 3 + 2, 15);
unsigned char *pNegative = pDData + 5 * 7 - 2;
for (unsigned char i = 0; i < 19; i++)
{
@ -205,13 +203,13 @@ public:
}
else if (u8SValue > 9)
{
memcpy(pDData + 5 * 7, FwData.pSmallLeters + 109 - 3 * 8, 8);
memcpy(pDData + 5 * 7, gSmallLeters + 109 - 3 * 8, 8);
C8SignalString[1] = '0';
C8SignalString[0] = '0' + u8SValue - 9;
}
else
{
memcpy(pDData + 5 * 7, FwData.pSmallLeters + 109, 8);
memcpy(pDData + 5 * 7, gSmallLeters + 109, 8);
C8SignalString[0] = '0' + u8SValue;
C8SignalString[1] = ' ';
}
@ -234,20 +232,20 @@ public:
void PrintBatteryVoltage()
{
if(*(FwData.pStatusBarData + VoltageOffset + 4 * 6 + 1) ||
*(FwData.pStatusBarData + VoltageOffset + 4 * 6 - 6))
if(gStatusBarData[VoltageOffset + 4 * 6 + 1] ||
gStatusBarData[VoltageOffset + 4 * 6 - 6])
{ // disable printing when function or charging icon are printed
return;
}
unsigned short u16Voltage = *FwData.p16Voltage > 1000 ? 999 : *FwData.p16Voltage;
unsigned short u16Voltage = gVoltage > 1000 ? 999 : gVoltage;
memset(FwData.pStatusBarData + VoltageOffset, 0, 4 * 5);
memset(gStatusBarData + VoltageOffset, 0, 4 * 5);
DisplayStatusBar.SetCoursor(0, VoltageOffset);
DisplayStatusBar.PrintFixedDigitsNumber2(u16Voltage, 2, 1);
memset(FwData.pStatusBarData + VoltageOffset + 7 + 1, 0b1100000, 2); // dot
memset(gStatusBarData + VoltageOffset + 7 + 1, 0b1100000, 2); // dot
DisplayStatusBar.SetCoursor(0, VoltageOffset + 7 + 4);
DisplayStatusBar.PrintFixedDigitsNumber2(u16Voltage, 0, 2);
memcpy(FwData.pStatusBarData + VoltageOffset + 4 * 6 + 2, FwData.pSmallLeters + 128 * 2 + 102, 5); // V character
memcpy(gStatusBarData + VoltageOffset + 4 * 6 + 2, gSmallLeters + 128 * 2 + 102, 5); // V character
}
};
};

Wyświetl plik

@ -8,3 +8,4 @@ add_subdirectory(spectrum_fagci)
add_subdirectory(t9_texting)
add_subdirectory(messenger)
add_subdirectory(rssi_sbar_hot)
add_subdirectory(am_tx)

Wyświetl plik

@ -0,0 +1,84 @@
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}
$<$<CONFIG:Debug>: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}
)
add_custom_target(${NAME}_flash_uart
COMMAND ${CMAKE_BINARY_DIR}/tools/k5prog -F -p ${SERIAL_PORT} -b ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.bin -Y -Y -Y
DEPENDS ${NAME}_encoded
DEPENDS k5prog
)

Wyświetl plik

@ -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

17
src/am_tx/exec.hpp 100644
Wyświetl plik

@ -0,0 +1,17 @@
#include "registers.hpp"
class CExec final
{
public:
CExec(){};
void InterruptCallback()
{
CheckButtons();
}
private:
void CheckButtons() const
{
}
};

Wyświetl plik

@ -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])

Wyświetl plik

@ -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();
}

Wyświetl plik

@ -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};
};
}

64
src/am_tx/main.cpp 100644
Wyświetl plik

@ -0,0 +1,64 @@
#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"
TUV_K5Display DisplayBuff(gDisplayBuffer);
const TUV_K5SmallNumbers FontSmallNr(gSmallDigs);
CDisplay Display(DisplayBuff);
TUV_K5Display StatusBarBuff(gStatusBarData);
CDisplay DisplayStatusBar(StatusBarBuff);
Radio::CBK4819 RadioDriver;
// CRssiSbar<
// System::OrgFunc_01_26,
// System::OrgData_01_26,
// DisplayBuff,
// Display,
// DisplayStatusBar,
// FontSmallNr,
// RadioDriver>
// RssiSbar;
CAmTx<
DisplayBuff,
Display,
DisplayStatusBar,
FontSmallNr,
RadioDriver>
AmTx;
static IView * const Views[] = {&AmTx};
CViewManager<
8, 1, sizeof(Views) / sizeof(*Views)>
Manager(Views);
int main()
{
IRQ_RESET();
return 0;
}
extern "C" void Reset_Handler()
{
IRQ_RESET();
}
extern "C" void SysTick_Handler()
{
static bool bFirstInit = false;
if (!bFirstInit)
{
System::CopyDataSection();
__libc_init_array();
bFirstInit = true;
}
Manager.Handle();
IRQ_SYSTICK();
}

Wyświetl plik

@ -0,0 +1,39 @@
#include "system.hpp"
#include "hardware/hardware.hpp"
#include "registers.hpp"
#include "uv_k5_display.hpp"
#include "rssi_sbar.hpp"
#include <string.h>
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();
}

Wyświetl plik

@ -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
}

Wyświetl plik

@ -69,11 +69,21 @@ add_custom_command(TARGET ${NAME}
)
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"
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}
)
)
if(NOT DEFINED ${SERIAL_PORT})
set(SERIAL_PORT /dev/ttyUSB0)
endif()
add_custom_target(${NAME}_flash_uart
COMMAND ${CMAKE_BINARY_DIR}/tools/k5prog -F -p ${SERIAL_PORT} -b ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.bin -Y -Y -Y
DEPENDS ${NAME}_encoded
DEPENDS k5prog
)

Wyświetl plik

@ -3,26 +3,19 @@
#include "messenger.hpp"
#include "radio.hpp"
const System::TOrgFunctions &Fw = System::OrgFunc_01_26;
const System::TOrgData &FwData = System::OrgData_01_26;
Radio::CBK4819 RadioDriver;
Radio::CBK4819<System::OrgFunc_01_26> RadioDriver;
CMessenger<
System::OrgFunc_01_26,
System::OrgData_01_26,
RadioDriver>
Messenger;
CMessenger<RadioDriver> Messenger;
int main()
{
Fw.IRQ_RESET();
IRQ_RESET();
return 0;
}
extern "C" void Reset_Handler()
{
Fw.IRQ_RESET();
IRQ_RESET();
}
extern "C" void SysTick_Handler()
@ -37,5 +30,5 @@ extern "C" void SysTick_Handler()
RadioDriver.InterruptHandler();
Messenger.Handle();
Fw.IRQ_SYSTICK();
}
IRQ_SYSTICK();
}

Wyświetl plik

@ -5,25 +5,18 @@
#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);
TUV_K5Display DisplayBuff(gDisplayBuffer);
const TUV_K5SmallNumbers FontSmallNr(gSmallDigs);
CDisplay Display(DisplayBuff);
Radio::CBK4819<System::OrgFunc_01_26> RadioDriver;
Radio::CBK4819 RadioDriver;
CMessenger<
DisplayBuff,
Display,
System::OrgFunc_01_26,
System::OrgData_01_26,
RadioDriver>
Messenger;
CRssiSbar<
System::OrgFunc_01_26,
System::OrgData_01_26,
DisplayBuff,
Display,
FontSmallNr>
@ -31,8 +24,6 @@ CRssiSbar<
static IView * const Views[] = {&Messenger, &RssiSbar};
CViewManager<
System::OrgFunc_01_26,
System::OrgData_01_26,
16, 2, sizeof(Views) / sizeof(*Views)>
Manager(Views);
@ -60,4 +51,4 @@ extern "C" void SysTick_Handler()
RadioDriver.InterruptHandler();
Manager.Handle();
Fw.IRQ_SYSTICK();
}
}

Wyświetl plik

@ -4,9 +4,7 @@
#include "radio.hpp"
#include "t9.hpp"
template <const System::TOrgFunctions &Fw,
const System::TOrgData &FwData,
Radio::CBK4819<Fw> &RadioDriver>
template <Radio::CBK4819 &RadioDriver>
class CMessenger
{
public:
@ -23,7 +21,7 @@ public:
};
CMessenger()
: DisplayBuff(FwData.pDisplayBuffer),
: DisplayBuff(gDisplayBuffer),
Display(DisplayBuff),
Keyboard(*this),
T9(S8TxBuff),
@ -45,7 +43,7 @@ public:
{
bDisplayCleared = true;
ClearDrawings();
Fw.FlushFramebufferToScreen();
FlushFramebufferToScreen();
}
return;
@ -61,22 +59,22 @@ public:
Display.DrawHLine(3, 3 + 10, 1 * 8 + T9.GetIdx() * 8 + 2);
// print tx data
Fw.FormatString(C8PrintBuff, ">%s", T9.C8WorkingBuff);
Fw.PrintTextOnScreen(C8PrintBuff, 0, 128, 0, 8, 0);
FormatString(C8PrintBuff, ">%s", T9.C8WorkingBuff);
PrintTextOnScreen(C8PrintBuff, 0, 128, 0, 8, 0);
// print rx data
char C8Temp = S8RxBuff[MaxCharsInLine];
S8RxBuff[MaxCharsInLine] = '\0';
Fw.PrintTextOnScreen(S8RxBuff, 1, 128, 3, 8, 0);
PrintTextOnScreen(S8RxBuff, 1, 128, 3, 8, 0);
S8RxBuff[MaxCharsInLine] = C8Temp;
Fw.PrintTextOnScreen(S8RxBuff + MaxCharsInLine, 1, 128, 5, 8, 0);
PrintTextOnScreen(S8RxBuff + MaxCharsInLine, 1, 128, 5, 8, 0);
Display.DrawRectangle(0, (8 * 4) - 6, 127, 24 + 6, false);
if (u8RxDoneLabelCnt < 100)
{
u8RxDoneLabelCnt++;
Fw.PrintTextOnScreen(" >> RX << ", 0, 128, 2, 8, 1);
PrintTextOnScreen(" >> RX << ", 0, 128, 2, 8, 1);
}
switch (State)
@ -97,14 +95,14 @@ public:
State = eState::InitRx;
}
Fw.PrintTextOnScreen(" >> TX << ", 0, 128, 2, 8, 1);
PrintTextOnScreen(" >> TX << ", 0, 128, 2, 8, 1);
break;
}
default:
break;
}
Fw.FlushFramebufferToScreen();
FlushFramebufferToScreen();
}
void RxDoneHandler(unsigned char u8DataLen, bool bCrcOk)
@ -123,12 +121,12 @@ private:
{
bEnabled = true;
GPIOC->DATA &= ~GPIO_PIN_3;
*FwData.p8FlashLightStatus = 3;
gFlashLightStatus = 3;
}
if (bEnabled)
{
Keyboard.Handle(Fw.PollKeyboard());
Keyboard.Handle(PollKeyboard());
}
return bEnabled;
@ -142,7 +140,7 @@ private:
void ClearDrawings()
{
memset(FwData.pDisplayBuffer, 0, (DisplayBuff.SizeX / 8) * DisplayBuff.SizeY);
memset(gDisplayBuffer, 0, (DisplayBuff.SizeX / 8) * DisplayBuff.SizeY);
}
void HandlePressedButton(unsigned char u8Button)
@ -178,4 +176,4 @@ private:
bool bEnabled;
eState State;
unsigned char u8RxDoneLabelCnt;
};
};

Wyświetl plik

@ -75,4 +75,10 @@ add_custom_target(${NAME}_flash
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}
)
)
add_custom_target(${NAME}_flash_uart
COMMAND ${CMAKE_BINARY_DIR}/tools/k5prog -F -p ${SERIAL_PORT} -b ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.bin -Y -Y -Y
DEPENDS ${NAME}_encoded
DEPENDS k5prog
)

Wyświetl plik

@ -8,22 +8,18 @@
extern "C" void __libc_init_array();
const System::TOrgFunctions& Fw = System::OrgFunc_01_26;
Radio::CBK4819<System::OrgFunc_01_26> RadioDriver;
CSpectrum<System::OrgFunc_01_26,
System::OrgData_01_26, RadioDriver>
Spectrum;
Radio::CBK4819 RadioDriver;
CSpectrum<RadioDriver> Spectrum;
int main()
{
Fw.IRQ_RESET();
IRQ_RESET();
return 0;
}
extern "C" void Reset_Handler()
{
Fw.IRQ_RESET();
IRQ_RESET();
}
extern "C" void SysTick_Handler()
@ -41,5 +37,5 @@ extern "C" void SysTick_Handler()
{
Spectrum.Handle();
}
Fw.IRQ_SYSTICK();
}
IRQ_SYSTICK();
}

Wyświetl plik

@ -3,9 +3,7 @@
#include "uv_k5_display.hpp"
#include "radio.hpp"
template <const System::TOrgFunctions &Fw,
const System::TOrgData &FwData,
Radio::CBK4819<Fw> &RadioDriver>
template <Radio::CBK4819 &RadioDriver>
class CSpectrum
{
public:
@ -23,7 +21,7 @@ public:
};
CSpectrum()
: DisplayBuff(FwData.pDisplayBuffer), FontSmallNr(FwData.pSmallDigs), Display(DisplayBuff), State(eState::Init), u8RxCnt(0){};
: DisplayBuff(gDisplayBuffer), FontSmallNr(gSmallDigs), Display(DisplayBuff), State(eState::Init), u8RxCnt(0){};
void Handle()
{
@ -38,14 +36,14 @@ public:
{
Fw.DelayMs(600);
DelayMs(600);
//memset(U8Buff, 0, sizeof(U8Buff));
RadioDriver.RecieveAsyncAirCopyMode(U8Buff, sizeof(U8Buff), Radio::CallbackRxDoneType(this, &CSpectrum::RxDoneHandler));
State = eState::RxPending;
// while(State == eState::RxPending)
// {
// RadioDriver.InterruptHandler();
// // if(Fw.PollKeyboard() != 0xFF)
// // if(PollKeyboard() != 0xFF)
// // {
// // break;
// // }
@ -59,13 +57,13 @@ public:
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();
FormatString(kupa, "RX DONE %u", u8RxCnt);
PrintTextOnScreen(kupa, 0, 127, 0, 8, 0);
FormatString(kupa, "LEN: %i", RadioDriver.u16RxDataLen);
PrintTextOnScreen(kupa, 0, 127, 2, 8, 0);
FormatString(kupa, "S: %s", U8Buff);
PrintTextOnScreen(kupa, 0, 127, 4, 8, 0);
FlushFramebufferToScreen();
static unsigned int u32Cnt = 1;
if(!(u32Cnt++%8))
@ -74,29 +72,29 @@ public:
State = eState::Init;
}
// Fw.WriteSerialData((unsigned char *)"RX packet, hex: ", 17);
// 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);
// FormatString(kupa, "%02X", U8Buff[i]);
// WriteSerialData((unsigned char *)kupa, 1);
// }
// Fw.WriteSerialData((unsigned char *)"\n", 1);
// WriteSerialData((unsigned char *)"\n", 1);
break;
}
case eState::RxPending:
{
//Fw.AirCopyFskSetup();
//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();
FormatString(kupa, "Rx: %u kHz", IntDivide(RadioDriver.GetFrequency(), 100));
PrintTextOnScreen(kupa, 0, 127, 0, 8, 0);
FormatString(kupa, "0x3F: 0x%04X", BK4819Read(0x3F));
PrintTextOnScreen(kupa, 0, 127, 2, 8, 0);
FormatString(kupa, "len: %i", BK4819Read(0x5D) >> 8);
PrintTextOnScreen(kupa, 0, 127, 4, 8, 0);
FlushFramebufferToScreen();
return;
}
@ -110,18 +108,18 @@ public:
if(!(u32Cnt++%8))
{
u8TxCnt++;
Fw.FormatString((char *)C8TxStr, "packet %i", u8TxCnt);
FormatString((char *)C8TxStr, "packet %i", u8TxCnt);
RadioDriver.SendSyncAirCopyMode72((unsigned char *)C8TxStr);
}
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();
FormatString(kupa, "TX: %u kHz", IntDivide(RadioDriver.GetFrequency(), 100));
PrintTextOnScreen(kupa, 0, 127, 0, 8, 0);
FormatString(kupa, "Irq: 0x%04X", RadioDriver.GetIrqReg());
PrintTextOnScreen(kupa, 0, 127, 2, 8, 0);
FormatString(kupa, "S: %s", C8TxStr);
PrintTextOnScreen(kupa, 0, 127, 4, 8, 0);
FlushFramebufferToScreen();
return;
@ -144,4 +142,4 @@ private:
eState State;
unsigned char U8Buff[72];
unsigned char u8RxCnt;
};
};

Wyświetl plik

@ -74,4 +74,10 @@ add_custom_target(${NAME}_flash
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}
)
)
add_custom_target(${NAME}_flash_uart
COMMAND ${CMAKE_BINARY_DIR}/tools/k5prog -F -p ${SERIAL_PORT} -b ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.bin -Y -Y -Y
DEPENDS ${NAME}_encoded
DEPENDS k5prog
)

Wyświetl plik

@ -7,18 +7,17 @@
extern "C" void __libc_init_array();
const System::TOrgFunctions& Fw = System::OrgFunc_01_26;
CSPong<System::OrgFunc_01_26, System::OrgData_01_26> Pong;
CSPong Pong;
int main()
{
Fw.IRQ_RESET();
IRQ_RESET();
return 0;
}
extern "C" void Reset_Handler()
{
Fw.IRQ_RESET();
IRQ_RESET();
}
extern "C" void SysTick_Handler()
@ -36,5 +35,5 @@ extern "C" void SysTick_Handler()
{
Pong.Handle();
}
Fw.IRQ_SYSTICK();
}
IRQ_SYSTICK();
}

Wyświetl plik

@ -3,14 +3,13 @@
#include "uv_k5_display.hpp"
#include "gpt_pong.hpp"
template <const System::TOrgFunctions &Fw, const System::TOrgData &FwData>
class CSPong
{
public:
static constexpr auto StepSize = 0xFFFF / TUV_K5Display::SizeX;
static constexpr auto StepSizeFreq = 10'000;
CSPong()
: DisplayBuff(FwData.pDisplayBuffer), FontSmallNr(FwData.pSmallDigs), Display(DisplayBuff), x(DisplayBuff.SizeX / 2), y(DisplayBuff.SizeY / 2)
: DisplayBuff(gDisplayBuffer), FontSmallNr(gSmallDigs), Display(DisplayBuff), x(DisplayBuff.SizeX / 2), y(DisplayBuff.SizeY / 2)
,bEnabled(true){};
void Handle()
@ -23,7 +22,7 @@ public:
DisplayBuff.ClearAll();
char C8RssiString[] = "000";
unsigned int u32Key = Fw.PollKeyboard();
unsigned int u32Key = PollKeyboard();
if(u32Key == 13) // exit key
{
bEnabled = false;
@ -47,7 +46,7 @@ public:
u32Cnt++;
if((u32Cnt >> 8) % 2)
{
unsigned int* p32Buff = (unsigned int*)FwData.pDisplayBuffer;
unsigned int* p32Buff = (unsigned int*)gDisplayBuffer;
for(int i = 0; i < (DisplayBuff.SizeX * DisplayBuff.SizeY) / (8*4); i++)
{
*p32Buff = ~(*p32Buff);
@ -56,7 +55,7 @@ public:
}
Fw.FlushFramebufferToScreen();
FlushFramebufferToScreen();
}
private:
@ -67,4 +66,4 @@ private:
unsigned char x, y;
bool bEnabled;
};
};

Wyświetl plik

@ -74,4 +74,10 @@ add_custom_target(${NAME}_flash
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}
)
)
add_custom_target(${NAME}_flash_uart
COMMAND ${CMAKE_BINARY_DIR}/tools/k5prog -F -p ${SERIAL_PORT} -b ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.bin -Y -Y -Y
DEPENDS ${NAME}_encoded
DEPENDS k5prog
)

Wyświetl plik

@ -6,18 +6,16 @@
#include <string.h>
Hardware::THardware Hw;
const System::TOrgFunctions& Fw = System::OrgFunc_01_26;
const System::TOrgData& FwData = System::OrgData_01_26;
int main()
{
Fw.IRQ_RESET();
IRQ_RESET();
return 0;
}
extern "C" void Reset_Handler()
{
Fw.IRQ_RESET();
IRQ_RESET();
}
extern "C" void SysTick_Handler()
@ -33,7 +31,7 @@ extern "C" void SysTick_Handler()
static unsigned int u32StupidCounter = 1;
if((!(u32StupidCounter++ % 15) && u32StupidCounter > 200)) // exit key
{
CRssiPrinter::Handle(Fw, FwData);
CRssiPrinter::Handle();
}
Fw.IRQ_SYSTICK();
}
IRQ_SYSTICK();
}

Wyświetl plik

@ -6,14 +6,14 @@ class CRssiPrinter
{
public:
static constexpr auto ChartStartX = 4*7 + 4;
static void Handle(const System::TOrgFunctions& Fw, const System::TOrgData& FwData)
static void Handle(void)
{
static bool bIsCleared = true;
static unsigned char u8ChartPosition = 0;
static unsigned char u8SqlDelayCnt = 0xFF;
static unsigned char U8ScreenHistory[128 - ChartStartX] = {0};
TUV_K5Display DisplayBuff(FwData.pDisplayBuffer);
const TUV_K5SmallNumbers FontSmallNr(FwData.pSmallDigs);
TUV_K5Display DisplayBuff(gDisplayBuffer);
const TUV_K5SmallNumbers FontSmallNr(gSmallDigs);
CDisplay Display(DisplayBuff);
if(!(GPIOC->DATA & 0b1))
@ -22,7 +22,7 @@ class CRssiPrinter
}
auto* pMenuCheckData = (unsigned char*)DisplayBuff.GetCoursorData(DisplayBuff.GetCoursorPosition(2, 6*8 + 1));
if(Fw.BK4819Read(0x0C) & 0b10)
if(BK4819Read(0x0C) & 0b10)
{
u8SqlDelayCnt = 0;
}
@ -38,7 +38,7 @@ class CRssiPrinter
u8ChartPosition = 0;
if(*pMenuCheckData != 0xFF)
{
Fw.FlushFramebufferToScreen();
FlushFramebufferToScreen();
}
}
@ -52,7 +52,7 @@ class CRssiPrinter
Display.SetFont(&FontSmallNr);
char C8RssiString[] = "g000";
unsigned char u8Rssi = ((Fw.BK4819Read(0x67) >> 1) & 0xFF);
unsigned char u8Rssi = ((BK4819Read(0x67) >> 1) & 0xFF);
if(!u8Rssi)
{
return;
@ -96,6 +96,6 @@ class CRssiPrinter
memcpy(pDData, U8ScreenHistory, sizeof(U8ScreenHistory));
u8ChartPosition++;
Fw.FlushFramebufferToScreen();
FlushFramebufferToScreen();
}
};
};

Wyświetl plik

@ -75,4 +75,10 @@ add_custom_target(${NAME}_flash
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}
)
)
add_custom_target(${NAME}_flash_uart
COMMAND ${CMAKE_BINARY_DIR}/tools/k5prog -F -p ${SERIAL_PORT} -b ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.bin -Y -Y -Y
DEPENDS ${NAME}_encoded
DEPENDS k5prog
)

Wyświetl plik

@ -6,21 +6,16 @@
#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);
TUV_K5Display DisplayBuff(gDisplayBuffer);
const TUV_K5SmallNumbers FontSmallNr(gSmallDigs);
CDisplay Display(DisplayBuff);
TUV_K5Display StatusBarBuff(FwData.pStatusBarData);
TUV_K5Display StatusBarBuff(gStatusBarData);
CDisplay DisplayStatusBar(StatusBarBuff);
Radio::CBK4819<System::OrgFunc_01_26> RadioDriver;
Radio::CBK4819 RadioDriver;
CRssiSbar<
System::OrgFunc_01_26,
System::OrgData_01_26,
DisplayBuff,
Display,
DisplayStatusBar,
@ -30,8 +25,6 @@ CRssiSbar<
#ifdef AM_TX
CAmTx<
System::OrgFunc_01_26,
System::OrgData_01_26,
DisplayBuff,
Display,
DisplayStatusBar,
@ -49,20 +42,18 @@ static IView *const Views[] =
};
CViewManager<
System::OrgFunc_01_26,
System::OrgData_01_26,
8, 2, sizeof(Views) / sizeof(*Views)>
Manager(Views);
int main()
{
Fw.IRQ_RESET();
IRQ_RESET();
return 0;
}
extern "C" void Reset_Handler()
{
Fw.IRQ_RESET();
IRQ_RESET();
}
extern "C" void SysTick_Handler()
@ -77,5 +68,5 @@ extern "C" void SysTick_Handler()
RadioDriver.InterruptHandler();
Manager.Handle();
Fw.IRQ_SYSTICK();
}
IRQ_SYSTICK();
}

Wyświetl plik

@ -75,4 +75,10 @@ add_custom_target(${NAME}_flash
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}
)
)
add_custom_target(${NAME}_flash_uart
COMMAND ${CMAKE_BINARY_DIR}/tools/k5prog -F -p ${SERIAL_PORT} -b ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.bin -Y -Y -Y
DEPENDS ${NAME}_encoded
DEPENDS k5prog
)

Wyświetl plik

@ -7,21 +7,16 @@
#include "manager.hpp"
#include "heater.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);
TUV_K5Display DisplayBuff(gDisplayBuffer);
const TUV_K5SmallNumbers FontSmallNr(gSmallDigs);
CDisplay Display(DisplayBuff);
TUV_K5Display StatusBarBuff(FwData.pStatusBarData);
TUV_K5Display StatusBarBuff(gStatusBarData);
CDisplay DisplayStatusBar(StatusBarBuff);
Radio::CBK4819<System::OrgFunc_01_26> RadioDriver;
Radio::CBK4819 RadioDriver;
CRssiSbar<
System::OrgFunc_01_26,
System::OrgData_01_26,
DisplayBuff,
Display,
DisplayStatusBar,
@ -29,8 +24,6 @@ CRssiSbar<
RadioDriver>
RssiSbar;
// CAmTx<
// System::OrgFunc_01_26,
// System::OrgData_01_26,
// DisplayBuff,
// Display,
// DisplayStatusBar,
@ -38,32 +31,29 @@ CRssiSbar<
// RadioDriver>
// AmTx;
CHeater<System::OrgFunc_01_26> Heater;
CAmRx<System::OrgFunc_01_26> AmRx;
// CMicVal<System::OrgFunc_01_26, RadioDriver> MicVal;
// CRssiVal<System::OrgFunc_01_26, RadioDriver> RssiVal;
CHeater Heater;
CAmRx AmRx;
// CMicVal<RadioDriver> MicVal;
// CRssiVal<RadioDriver> RssiVal;
static IMenuElement * const MainMenuElements[] = {&Heater, &AmRx, &RssiSbar};
CMenu<System::OrgFunc_01_26,
System::OrgData_01_26> Menu(MainMenuElements);
CMenu Menu(MainMenuElements);
static IView * const Views[] = {&RssiSbar, &Menu};
CViewManager<
System::OrgFunc_01_26,
System::OrgData_01_26,
8, 1, sizeof(Views) / sizeof(*Views)>
Manager(Views);
int main()
{
Fw.IRQ_RESET();
IRQ_RESET();
return 0;
}
extern "C" void Reset_Handler()
{
Fw.IRQ_RESET();
IRQ_RESET();
}
extern "C" void SysTick_Handler()
@ -78,5 +68,5 @@ extern "C" void SysTick_Handler()
// RadioDriver.InterruptHandler();
Manager.Handle();
Fw.IRQ_SYSTICK();
}
IRQ_SYSTICK();
}

Wyświetl plik

@ -76,4 +76,10 @@ add_custom_target(${NAME}_flash
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}
)
)
add_custom_target(${NAME}_flash_uart
COMMAND ${CMAKE_BINARY_DIR}/tools/k5prog -F -p ${SERIAL_PORT} -b ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.bin -Y -Y -Y
DEPENDS ${NAME}_encoded
DEPENDS k5prog
)

Wyświetl plik

@ -6,21 +6,19 @@
#include <string.h>
Hardware::THardware Hw;
const System::TOrgFunctions& Fw = System::OrgFunc_01_26;
const System::TOrgData& FwData = System::OrgData_01_26;
CSpectrum<System::OrgFunc_01_26, System::OrgData_01_26> Spectrum;
CSpectrum Spectrum;
int main()
{
Fw.IRQ_RESET();
IRQ_RESET();
return 0;
}
extern "C" void Reset_Handler()
{
Fw.IRQ_RESET();
IRQ_RESET();
}
extern "C" void SysTick_Handler()
@ -37,8 +35,8 @@ extern "C" void SysTick_Handler()
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
bool bPreventWhileKeypadPolling = pStackedRegs->LR > (unsigned int)PollKeyboard &&
pStackedRegs->PC < (unsigned int)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)
@ -46,5 +44,5 @@ extern "C" void SysTick_Handler()
Spectrum.Handle();
}
Fw.IRQ_SYSTICK();
}
IRQ_SYSTICK();
}

Wyświetl plik

@ -19,7 +19,6 @@ static constexpr auto operator""_MHz(unsigned long long KiloHertz)
return KiloHertz * 1000_KHz;
}
template <const System::TOrgFunctions &Fw, const System::TOrgData &FwData>
class CSpectrum
{
public:
@ -33,8 +32,8 @@ public:
static constexpr auto PressDuration = 30;
static constexpr auto BWStep = 200_KHz;
CSpectrum()
: DisplayBuff(FwData.pDisplayBuffer),
FontSmallNr(FwData.pSmallDigs),
: DisplayBuff(gDisplayBuffer),
FontSmallNr(gSmallDigs),
Display(DisplayBuff),
bDisplayCleared(true),
u32ScanRange(1_MHz),
@ -58,9 +57,9 @@ public:
{
bDisplayCleared = true;
ClearDrawings();
Fw.FlushFramebufferToScreen();
FlushFramebufferToScreen();
SetFrequency(u32OldFreq);
Fw.BK4819Write(0x47, u16OldAfSettings); // set previous AF settings
BK4819Write(0x47, u16OldAfSettings); // set previous AF settings
}
return;
@ -69,8 +68,8 @@ public:
if (bDisplayCleared)
{
u32OldFreq = GetFrequency();
u16OldAfSettings = Fw.BK4819Read(0x47);
Fw.BK4819Write(0x47, 0); // mute AF during scan
u16OldAfSettings = BK4819Read(0x47);
BK4819Write(0x47, 0); // mute AF during scan
}
bDisplayCleared = false;
@ -118,7 +117,7 @@ public:
{
if (!(u8Pos % (DisplayBuff.SizeX / LabelsCnt)) || u8Pos == DisplayBuff.SizeX - 1)
{
*(FwData.pDisplayBuffer + 2 * DisplayBuff.SizeX + u8Pos) = 0xFF;
gDisplayBuffer[2 * DisplayBuff.SizeX + u8Pos] = 0xFF;
}
auto const FreqOffset = (u8Pos * u32ScanRange) >> 7;
@ -140,7 +139,7 @@ public:
}
}
// Display.DrawRectangle(0,0, 7, 7, 0);
memcpy(FwData.pDisplayBuffer + 8 * 2 + 10 * 6 + 2, FwData.pSmallLeters + 18 + 5, 7);
memcpy(gDisplayBuffer + 8 * 2 + 10 * 6 + 2, gSmallLeters + 18 + 5, 7);
Display.SetCoursor(0, 0);
Display.PrintFixedDigitsNumber2(u32OldFreq);
Display.SetCoursor(1, 0);
@ -152,31 +151,31 @@ public:
Display.SetCoursor(0, 8 * 2 + 10 * 7);
Display.PrintFixedDigitsNumber2(u32Peak);
memcpy(FwData.pDisplayBuffer + 128 * 2 + u8PeakPos - 3, FwData.pSmallLeters + 18 + 5, 7);
Fw.FlushFramebufferToScreen();
memcpy(gDisplayBuffer + 128 * 2 + u8PeakPos - 3, gSmallLeters + 18 + 5, 7);
FlushFramebufferToScreen();
}
private:
void SetFrequency(unsigned int u32Freq)
{
Fw.BK4819Write(0x39, ((u32Freq >> 16) & 0xFFFF));
Fw.BK4819Write(0x38, (u32Freq & 0xFFFF));
// Fw.BK4819Write(0x37,7951);
Fw.BK4819Write(0x30, 0);
Fw.BK4819Write(0x30, 0xbff1);
BK4819Write(0x39, ((u32Freq >> 16) & 0xFFFF));
BK4819Write(0x38, (u32Freq & 0xFFFF));
// BK4819Write(0x37,7951);
BK4819Write(0x30, 0);
BK4819Write(0x30, 0xbff1);
}
unsigned char GetRssi(unsigned int u32Freq)
{
SetFrequency(u32Freq);
Fw.DelayUs(800);
return ((Fw.BK4819Read(0x67) >> 1) & 0xFF);
DelayUs(800);
return ((BK4819Read(0x67) >> 1) & 0xFF);
}
unsigned int GetFrequency()
{
unsigned short u16f1 = Fw.BK4819Read(0x39);
unsigned short u16f2 = Fw.BK4819Read(0x38);
unsigned short u16f1 = BK4819Read(0x39);
unsigned short u16f2 = BK4819Read(0x38);
return ((u16f1 << 16) | u16f2);
}
@ -187,12 +186,12 @@ private:
{
bEnabled = true;
GPIOC->DATA &= ~GPIO_PIN_3;
*FwData.p8FlashLightStatus = 3;
gFlashLightStatus = 3;
}
if (bEnabled)
{
u8LastBtnPressed = Fw.PollKeyboard();
u8LastBtnPressed = PollKeyboard();
}
bool bPtt = !(GPIOC->DATA & GPIO_PIN_5);
@ -206,7 +205,7 @@ private:
void ClearDrawings()
{
memset(FwData.pDisplayBuffer, 0, (DisplayBuff.SizeX / 8) * DisplayBuff.SizeY);
memset(gDisplayBuffer, 0, (DisplayBuff.SizeX / 8) * DisplayBuff.SizeY);
}
TUV_K5Display DisplayBuff;
@ -223,4 +222,4 @@ private:
unsigned char u8ResolutionDiv;
bool bEnabled;
char C8Info[20];
};
};

Wyświetl plik

@ -78,3 +78,9 @@ 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}
)
add_custom_target(${NAME}_flash_uart
COMMAND ${CMAKE_BINARY_DIR}/tools/k5prog -F -p ${SERIAL_PORT} -b ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.bin -Y -Y -Y
DEPENDS ${NAME}_encoded
DEPENDS k5prog
)

Wyświetl plik

@ -0,0 +1,26 @@
enum Keys {
NUM0,
NUM1,
NUM2,
NUM3,
NUM4,
NUM5,
NUM6,
NUM7,
NUM8,
NUM9,
MENU, // 10
UP, // 11
DOWN, // 12
EXIT, // 13
ASTERISK, // 14
FUNCTION, // 15
_NA16,
_NA17,
_NA18,
_NA19,
_NA20,
_NA21,
FN2, // 22
FN1, // 23
};

Wyświetl plik

@ -1,24 +1,21 @@
#include "hardware/hardware.hpp"
#include "radio.hpp"
#include "registers.hpp"
#include "spectrum.hpp"
#include "system.hpp"
#include "radio.hpp"
#include "uv_k5_display.hpp"
#include <string.h>
Hardware::THardware Hw;
const System::TOrgFunctions &Fw = System::OrgFunc_01_26;
const System::TOrgData &FwData = System::OrgData_01_26;
Radio::CBK4819<System::OrgFunc_01_26> RadioDriver;
CSpectrum<System::OrgFunc_01_26, System::OrgData_01_26, RadioDriver> Spectrum;
Radio::CBK4819 RadioDriver;
CSpectrum<RadioDriver> Spectrum;
int main() {
Fw.IRQ_RESET();
IRQ_RESET();
return 0;
}
extern "C" void Reset_Handler() { Fw.IRQ_RESET(); }
extern "C" void Reset_Handler() { IRQ_RESET(); }
extern "C" void SysTick_Handler() {
static bool bFirstInit = false;
@ -30,5 +27,5 @@ extern "C" void SysTick_Handler() {
Spectrum.Handle();
Fw.IRQ_SYSTICK();
IRQ_SYSTICK();
}

Wyświetl plik

@ -1,372 +1,367 @@
#pragma once
#include "keys.hpp"
#include "radio.hpp"
#include "system.hpp"
#include "types.hpp"
#include "uv_k5_display.hpp"
typedef unsigned char u8;
typedef signed short i16;
typedef unsigned short u16;
typedef signed int i32;
typedef unsigned int u32;
typedef signed long long i64;
typedef unsigned long long u64;
template <const System::TOrgFunctions &Fw, const System::TOrgData &FwData,
Radio::CBK4819<Fw> &RadioDriver>
class CSpectrum {
template <Radio::CBK4819 &RadioDriver> class CSpectrum {
public:
static constexpr auto ExitKey = 13;
static constexpr auto DrawingEndY = 42;
static constexpr auto BarPos = 5 * 128;
u8 rssiHistory[64] = {};
u8 measurementsCount = 32;
static constexpr auto ModesCount = 7;
static constexpr auto LastLowBWModeIndex = 3;
static constexpr u32 modeHalfSpectrumBW[ModesCount] = {
16_KHz, 50_KHz, 100_KHz, 200_KHz, 400_KHz, 800_KHz, 1600_KHz};
static constexpr u16 modeScanStep[ModesCount] = {
1_KHz, 3125_Hz, 6250_Hz, 12500_Hz, 25_KHz, 25_KHz, 25_KHz};
static constexpr u8 modeXdiv[ModesCount] = {2, 2, 2, 2, 2, 1, 0};
u8 rssiHistory[128] = {};
u32 fMeasure;
u8 peakT = 0;
u8 peakRssi = 0;
u8 peakI = 0;
u32 peakF = 0;
u8 rssiMin = 255;
u8 highestPeakX = 0;
u8 highestPeakT = 0;
u8 highestPeakRssi = 0;
u32 highestPeakF = 0;
u32 FStart, fMeasure;
u8 btnCounter = 0;
CSpectrum()
: DisplayBuff(FwData.pDisplayBuffer), FontSmallNr(FwData.pSmallDigs),
Display(DisplayBuff), scanDelay(800), sampleZoom(2), scanStep(25_KHz),
frequencyChangeStep(100_KHz), rssiTriggerLevel(65) {
: DisplayBuff(gDisplayBuffer), Display(DisplayBuff),
FontSmallNr(gSmallDigs), scanDelay(800), mode(5), rssiTriggerLevel(50) {
Display.SetFont(&FontSmallNr);
frequencyChangeStep = modeHalfSpectrumBW[mode];
};
inline bool ListenPeak() {
if (highestPeakRssi < rssiTriggerLevel) {
return false;
}
if (fMeasure != highestPeakF) {
fMeasure = highestPeakF;
RadioDriver.SetFrequency(fMeasure);
Fw.BK4819Write(0x47, u16OldAfSettings);
RadioDriver.ToggleAFDAC(true);
}
// measure peak for this moment
highestPeakRssi = GetRssi(); // also sets freq for us
rssiHistory[highestPeakX >> sampleZoom] = highestPeakRssi;
if (highestPeakRssi >= rssiTriggerLevel) {
Listen(1000000);
return true;
}
return false;
}
inline void Scan() {
void Scan() {
u8 rssi = 0, rssiMax = 0;
u8 iPeak = 0;
u32 fPeak = currentFreq;
rssiMin = 255;
fMeasure = FStart;
RadioDriver.ToggleAFDAC(false);
Fw.BK4819Write(0x47, 0);
fMeasure = GetFStart();
for (u8 i = 0; i < measurementsCount; ++i, fMeasure += scanStep) {
rssi = rssiHistory[i] = GetRssi(fMeasure);
if (rssi < rssiMin) {
rssiMin = rssi;
// RadioDriver.ToggleAFDAC(false);
MuteAF();
u16 scanStep = GetScanStep();
u8 measurementsCount = GetMeasurementsCount();
for (u8 i = 0;
i < measurementsCount && (PollKeyboard() == 255 || resetBlacklist);
++i, fMeasure += scanStep) {
if (!resetBlacklist && rssiHistory[i] == 255) {
continue;
}
RadioDriver.SetFrequency(fMeasure);
rssi = rssiHistory[i] = GetRssi();
if (rssi > rssiMax) {
rssiMax = rssi;
fPeak = fMeasure;
iPeak = i;
}
if (rssi < rssiMin) {
rssiMin = rssi;
}
}
resetBlacklist = false;
++peakT;
++highestPeakT;
if (rssiMax > highestPeakRssi || highestPeakT >= (8 << sampleZoom)) {
highestPeakT = 0;
highestPeakRssi = rssiMax;
highestPeakX = iPeak << sampleZoom;
highestPeakF = fPeak;
if (rssiMax > peakRssi || peakT >= 16) {
peakT = 0;
peakRssi = rssiMax;
peakF = fPeak;
peakI = iPeak;
}
}
inline void DrawSpectrum() {
void DrawSpectrum() {
for (u8 x = 0; x < 128; ++x) {
Display.DrawHLine(Rssi2Y(rssiHistory[x >> sampleZoom]), DrawingEndY, x);
auto v = rssiHistory[x >> modeXdiv[mode]];
if (v != 255) {
Display.DrawHLine(Rssi2Y(v), DrawingEndY, x);
}
}
}
inline void DrawNums() {
void DrawNums() {
Display.SetCoursorXY(0, 0);
Display.PrintFixedDigitsNumber2(scanDelay, 0);
Display.PrintFixedDigitsNumber3(scanDelay, 2, 2, 1);
Display.SetCoursorXY(51, 0);
Display.PrintFixedDigitsNumber2(scanStep << (7 - sampleZoom));
Display.SetCoursorXY(105, 0);
Display.PrintFixedDigitsNumber3(GetBW(), 3, 3, 2);
Display.SetCoursorXY(58, 8);
Display.PrintFixedDigitsNumber2(scanStep);
Display.SetCoursorXY(42, 0);
Display.PrintFixedDigitsNumber3(peakF, 2, 6, 3);
Display.SetCoursorXY(107, 8);
Display.PrintFixedDigitsNumber2(highestPeakRssi, 0);
Display.SetCoursorXY(0, 48);
Display.PrintFixedDigitsNumber3(GetFStart(), 4, 4, 1);
Display.SetCoursorXY(86, 0);
Display.PrintFixedDigitsNumber2(highestPeakF);
Display.SetCoursorXY(98, 48);
Display.PrintFixedDigitsNumber3(GetFEnd(), 4, 4, 1);
Display.SetCoursorXY(44, 48);
Display.PrintFixedDigitsNumber2(currentFreq);
Display.SetCoursorXY(100, 48);
Display.PrintFixedDigitsNumber2(frequencyChangeStep);
Display.SetCoursorXY(0, 8);
Display.PrintFixedDigitsNumber2(rssiTriggerLevel, 0);
Display.SetCoursorXY(52, 48);
Display.PrintFixedDigitsNumber3(frequencyChangeStep, 3, 3, 2);
}
inline void DrawRssiTriggerLevel() {
Display.DrawLine(0, 127, Rssi2Y(rssiTriggerLevel));
}
inline void DrawTicks() {
u32 f = modulo(FStart, 1_MHz);
u32 step = scanStep >> sampleZoom;
for (u8 i = 0; i < 128; ++i, f += step) {
u8 barValue = 0b00001000;
modulo(f, 100_KHz) < step && (barValue |= 0b00010000);
modulo(f, 500_KHz) < step && (barValue |= 0b00100000);
modulo(f, 1_MHz) < step && (barValue |= 0b11000000);
*(FwData.pDisplayBuffer + BarPos + i) |= barValue;
void DrawRssiTriggerLevel() {
u8 y = Rssi2Y(rssiTriggerLevel);
for (u8 x = 0; x < 126; x += 4) {
Display.DrawLine(x, x + 2, y);
}
}
void DrawTicks() {
// center
*(FwData.pDisplayBuffer + BarPos + 64) |= 0b10101010;
gDisplayBuffer[BarPos + 64] = 0b00111000;
}
inline void DrawArrow(u8 x) {
u8 *peakPos = FwData.pDisplayBuffer + BarPos + x;
x > 1 && (*(peakPos - 2) |= 0b01000000);
x > 0 && (*(peakPos - 1) |= 0b01100000);
(*(peakPos) |= 0b01110000);
x < 127 && (*(peakPos + 1) |= 0b01100000);
x < 128 && (*(peakPos + 2) |= 0b01000000);
void DrawArrow(u8 x) {
for (signed i = -2; i <= 2; ++i) {
signed v = x + i;
if (!(v & 128)) {
gDisplayBuffer[BarPos + v] |= (0b01111000 << abs(i)) & 0b01111000;
}
}
}
void HandleUserInput() {
switch (lastButtonPressed) {
case 1:
UpdateScanDelay(200);
void OnKeyDown(u8 key) {
switch (key) {
case Keys::NUM1:
if (scanDelay < 8000) {
scanDelay += 100;
rssiMin = 255;
}
break;
case 7:
UpdateScanDelay(-200);
case Keys::NUM7:
if (scanDelay > 400) {
scanDelay -= 100;
rssiMin = 255;
}
break;
case 2:
UpdateSampleZoom(1);
case Keys::NUM3:
UpdateBWMul(1);
resetBlacklist = true;
break;
case 8:
UpdateSampleZoom(-1);
case Keys::NUM9:
UpdateBWMul(-1);
resetBlacklist = true;
break;
case 3:
UpdateRssiTriggerLevel(5);
break;
case 9:
UpdateRssiTriggerLevel(-5);
break;
case 4:
UpdateScanStep(-1);
UpdateSampleZoom(1);
break;
case 6:
UpdateScanStep(1);
UpdateSampleZoom(-1);
break;
case 11: // up
UpdateCurrentFreq(frequencyChangeStep);
break;
case 12: // down
UpdateCurrentFreq(-frequencyChangeStep);
break;
case 14:
case Keys::NUM2:
UpdateFreqChangeStep(100_KHz);
break;
case 15:
case Keys::NUM8:
UpdateFreqChangeStep(-100_KHz);
break;
case 5:
case Keys::UP:
UpdateCurrentFreq(frequencyChangeStep);
resetBlacklist = true;
break;
case Keys::DOWN:
UpdateCurrentFreq(-frequencyChangeStep);
resetBlacklist = true;
break;
case Keys::NUM5:
ToggleBacklight();
default:
isUserInput = false;
break;
case Keys::NUM0:
Blacklist();
break;
case Keys::ASTERISK:
UpdateRssiTriggerLevel(1);
DelayMs(90);
break;
case Keys::FUNCTION:
UpdateRssiTriggerLevel(-1);
DelayMs(90);
break;
}
ResetPeak();
}
bool HandleUserInput() {
btnPrev = btn;
btn = PollKeyboard();
if (btn == Keys::EXIT) {
DeInit();
return false;
}
if (btn != 255) {
if (btn == btnPrev && btnCounter < 255) {
btnCounter++;
}
if (btnPrev == 255 || btnCounter > 16) {
OnKeyDown(btn);
}
return true;
}
btnCounter = 0;
return true;
}
void Render() {
DisplayBuff.ClearAll();
DrawTicks();
DrawArrow(highestPeakX);
DrawArrow(peakI << modeXdiv[mode]);
DrawSpectrum();
DrawRssiTriggerLevel();
DrawNums();
Fw.FlushFramebufferToScreen();
FlushFramebufferToScreen();
}
void Update() {
if (bDisplayCleared) {
currentFreq = RadioDriver.GetFrequency();
OnUserInput();
u16OldAfSettings = Fw.BK4819Read(0x47);
Fw.BK4819Write(0x47, 0); // mute AF during scan
if (peakRssi >= rssiTriggerLevel) {
ToggleGreen(true);
GPIOC->DATA |= GPIO_PIN_4;
Listen();
}
bDisplayCleared = false;
HandleUserInput();
if (!ListenPeak())
if (peakRssi < rssiTriggerLevel) {
ToggleGreen(false);
GPIOC->DATA &= ~GPIO_PIN_4;
Scan();
}
}
void UpdateRssiTriggerLevel(i32 diff) {
rssiTriggerLevel = clamp(rssiTriggerLevel + diff, 10, 255);
OnUserInput();
}
void UpdateRssiTriggerLevel(i32 diff) { rssiTriggerLevel += diff; }
void UpdateScanDelay(i32 diff) {
scanDelay = clamp(scanDelay + diff, 800, 3200);
OnUserInput();
}
void UpdateSampleZoom(i32 diff) {
sampleZoom = clamp(sampleZoom - diff, 1, 5);
measurementsCount = 1 << (7 - sampleZoom);
OnUserInput();
void UpdateBWMul(i32 diff) {
if ((diff > 0 && mode < (ModesCount - 1)) || (diff < 0 && mode > 0)) {
mode += diff;
SetBW();
rssiMin = 255;
frequencyChangeStep = modeHalfSpectrumBW[mode];
}
}
void UpdateCurrentFreq(i64 diff) {
currentFreq = clamp(currentFreq + diff, 18_MHz, 1300_MHz);
OnUserInput();
}
void UpdateScanStep(i32 diff) {
if (diff > 0 && scanStep < 25_KHz) {
scanStep <<= 1;
if ((diff > 0 && currentFreq < 1300_MHz) ||
(diff < 0 && currentFreq > 18_MHz)) {
currentFreq += diff;
}
if (diff < 0 && scanStep > 6250_Hz) {
scanStep >>= 1;
}
OnUserInput();
}
void UpdateFreqChangeStep(i64 diff) {
frequencyChangeStep = clamp(frequencyChangeStep + diff, 100_KHz, 2_MHz);
OnUserInput();
}
inline void OnUserInput() {
isUserInput = true;
u32 halfOfScanRange = scanStep << (6 - sampleZoom);
FStart = currentFreq - halfOfScanRange;
// reset peak
highestPeakT = 0;
highestPeakRssi = 0;
highestPeakX = 64;
highestPeakF = currentFreq;
Fw.DelayUs(90000);
}
void Blacklist() { rssiHistory[peakI] = 255; }
void Handle() {
if (RadioDriver.IsLockedByOrgFw()) {
return;
}
if (!working) {
if (IsFlashLightOn()) {
working = true;
TurnOffFlashLight();
}
return;
if (!isInitialized && IsFlashLightOn()) {
TurnOffFlashLight();
Init();
}
lastButtonPressed = Fw.PollKeyboard();
if (lastButtonPressed == ExitKey) {
working = false;
RestoreParams();
return;
if (isInitialized && HandleUserInput()) {
Update();
Render();
}
Update();
Render();
}
private:
void RestoreParams() {
if (!bDisplayCleared) {
bDisplayCleared = true;
DisplayBuff.ClearAll();
Fw.FlushFramebufferToScreen();
RadioDriver.SetFrequency(currentFreq);
Fw.BK4819Write(0x47, u16OldAfSettings); // set previous AF settings
}
void Init() {
currentFreq = RadioDriver.GetFrequency();
oldAFSettings = BK4819Read(0x47);
oldBWSettings = BK4819Read(0x43);
MuteAF();
SetBW();
ResetPeak();
resetBlacklist = true;
ToggleGreen(false);
isInitialized = true;
}
inline void Listen(u32 duration) {
for (u8 i = 0; i < 16 && lastButtonPressed == 255; ++i) {
lastButtonPressed = Fw.PollKeyboard();
Fw.DelayUs(duration >> 4);
void DeInit() {
DisplayBuff.ClearAll();
FlushFramebufferToScreen();
RadioDriver.SetFrequency(currentFreq);
RestoreOldAFSettings();
BK4819Write(0x43, oldBWSettings);
ToggleGreen(true);
isInitialized = false;
}
void ResetPeak() { peakRssi = 0; }
void SetBW() { BK4819SetChannelBandwidth(mode <= LastLowBWModeIndex); }
void MuteAF() { BK4819Write(0x47, 0); }
void RestoreOldAFSettings() { BK4819Write(0x47, oldAFSettings); }
void Listen() {
if (fMeasure != peakF) {
fMeasure = peakF;
RadioDriver.SetFrequency(fMeasure);
RestoreOldAFSettings();
// RadioDriver.ToggleAFDAC(true);
}
for (u8 i = 0; i < 16 && PollKeyboard() == 255; ++i) {
DelayMs(64);
}
peakRssi = rssiHistory[peakI] = GetRssi();
}
u16 GetScanStep() { return modeScanStep[mode]; }
u32 GetBW() { return modeHalfSpectrumBW[mode] << 1; }
u32 GetFStart() { return currentFreq - modeHalfSpectrumBW[mode]; }
u32 GetFEnd() { return currentFreq + modeHalfSpectrumBW[mode]; }
u8 GetMeasurementsCount() { return 128 >> modeXdiv[mode]; }
void ResetRSSI() {
RadioDriver.ToggleRXDSP(false);
RadioDriver.ToggleRXDSP(true);
}
u8 GetRssi() {
Fw.BK4819Read(0x67); //reset RSSI =)
Fw.DelayUs(scanDelay);
return Fw.BK4819Read(0x67);
ResetRSSI();
DelayUs(scanDelay << (mode <= LastLowBWModeIndex));
auto v = BK4819Read(0x67) & 0x1FF;
return v < 255 ? v : 255;
}
u8 GetRssi(u32 f) {
RadioDriver.SetFrequency(f);
return GetRssi();
}
inline bool IsFlashLightOn() { return GPIOC->DATA & GPIO_PIN_3; }
inline void TurnOffFlashLight() {
bool IsFlashLightOn() { return GPIOC->DATA & GPIO_PIN_3; }
void TurnOffFlashLight() {
GPIOC->DATA &= ~GPIO_PIN_3;
*FwData.p8FlashLightStatus = 3;
gFlashLightStatus = 3;
}
inline void ToggleBacklight() { GPIOB->DATA ^= GPIO_PIN_6; }
void ToggleBacklight() { GPIOB->DATA ^= GPIO_PIN_6; }
inline u8 Rssi2Y(u8 rssi) {
return clamp(DrawingEndY - (rssi - rssiMin), 1, DrawingEndY);
void ToggleRed(bool flag) { BK4819SetGpio(5, flag); }
void ToggleGreen(bool flag) { BK4819SetGpio(6, flag); }
u8 Rssi2Y(u8 rssi) {
return DrawingEndY - clamp(rssi - rssiMin, 0, DrawingEndY);
}
inline i32 clamp(i32 v, i32 min, i32 max) {
if (v < min)
return min;
if (v > max)
return max;
return v;
}
inline u32 modulo(u32 num, u32 div) {
while (num >= div)
num -= div;
return num;
i32 clamp(i32 v, i32 min, i32 max) {
return v <= min ? min : (v >= max ? max : v);
}
TUV_K5Display DisplayBuff;
const TUV_K5SmallNumbers FontSmallNr;
CDisplay<const TUV_K5Display> Display;
u8 lastButtonPressed;
u32 currentFreq;
u16 u16OldAfSettings;
const TUV_K5SmallNumbers FontSmallNr;
u16 scanDelay;
u8 sampleZoom;
u32 scanStep;
u32 frequencyChangeStep;
u8 mode;
u8 rssiTriggerLevel;
bool working = false;
bool isUserInput = false;
bool bDisplayCleared = true;
u8 btn;
u8 btnPrev;
u32 currentFreq;
u16 oldAFSettings;
u16 oldBWSettings;
u32 frequencyChangeStep;
bool isInitialized;
bool resetBlacklist;
};

Wyświetl plik

@ -0,0 +1,10 @@
#pragma once
typedef unsigned char u8;
typedef signed short i16;
typedef unsigned short u16;
typedef signed int i32;
typedef unsigned int u32;
typedef signed long long i64;
typedef unsigned long long u64;

Wyświetl plik

@ -77,4 +77,10 @@ add_custom_target(${NAME}_flash
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}
)
)
add_custom_target(${NAME}_flash_uart
COMMAND ${CMAKE_BINARY_DIR}/tools/k5prog -F -p ${SERIAL_PORT} -b ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.bin -Y -Y -Y
DEPENDS ${NAME}_encoded
DEPENDS k5prog
)

Wyświetl plik

@ -6,20 +6,18 @@
#include <string.h>
Hardware::THardware Hw;
const System::TOrgFunctions& Fw = System::OrgFunc_01_26;
const System::TOrgData& FwData = System::OrgData_01_26;
CT9Texting<System::OrgFunc_01_26, System::OrgData_01_26> T9Texting;
CT9Texting T9Texting;
int main()
{
Fw.IRQ_RESET();
IRQ_RESET();
return 0;
}
extern "C" void Reset_Handler()
{
Fw.IRQ_RESET();
IRQ_RESET();
}
extern "C" void SysTick_Handler()
@ -36,13 +34,13 @@ extern "C" void SysTick_Handler()
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
bool bPreventWhileKeypadPolling = pStackedRegs->LR > (unsigned int)PollKeyboard &&
pStackedRegs->PC < (unsigned int)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)
{
T9Texting.Handle();
}
Fw.IRQ_SYSTICK();
}
IRQ_SYSTICK();
}

Wyświetl plik

@ -3,12 +3,11 @@
#include "uv_k5_display.hpp"
#include "keyboard.hpp"
template <const System::TOrgFunctions &Fw, const System::TOrgData &FwData>
class CT9Texting
{
public:
CT9Texting()
: DisplayBuff(FwData.pDisplayBuffer),
: DisplayBuff(gDisplayBuffer),
Display(DisplayBuff),
Keyboard(*this),
bDisplayCleared(true),
@ -67,7 +66,7 @@ public:
// Clear cMessage
memset(cMessage, 0, 30);
c_index = 0;
Fw.FlushFramebufferToScreen();
FlushFramebufferToScreen();
}
return;
@ -123,8 +122,8 @@ public:
prev_key = key;
// Display.DrawRectangle(0,0, 7, 7, 0);
ClearDrawings();
Fw.PrintTextOnScreen(cMessage, 0, 128, 0, 8, 0);
Fw.FlushFramebufferToScreen();
PrintTextOnScreen(cMessage, 0, 128, 0, 8, 0);
FlushFramebufferToScreen();
}
private:
@ -136,15 +135,15 @@ private:
{
bEnabled = true;
GPIOC->DATA &= ~GPIO_PIN_3;
*FwData.p8FlashLightStatus = 3;
gFlashLightStatus = 3;
}
if (bEnabled)
{
u8LastBtnPressed = Fw.PollKeyboard();
u8LastBtnPressed = PollKeyboard();
}
// u8LastBtnPressed = Fw.PollKeyboard();
// u8LastBtnPressed = PollKeyboard();
// if (u8LastBtnPressed == EnableKey)
// {
// u8PressCnt++;
@ -161,7 +160,7 @@ private:
void ClearDrawings()
{
memset(FwData.pDisplayBuffer, 0, (DisplayBuff.SizeX / 8) * DisplayBuff.SizeY);
memset(gDisplayBuffer, 0, (DisplayBuff.SizeX / 8) * DisplayBuff.SizeY);
}
TUV_K5Display DisplayBuff;

Wyświetl plik

@ -0,0 +1,8 @@
set(NAME k5prog)
set(k5prog_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/k5prog)
project(${NAME})
set(CMAKE_C_COMPILER "gcc")
add_executable(${NAME} ${k5prog_SRC_DIR}/k5prog.c)
target_include_directories(${NAME} PUBLIC ${k5prog_SRC_DIR})

1
tools/k5prog 160000

@ -0,0 +1 @@
Subproject commit 15e1dde73e70ec0f3e4c68e48d7e7ddc017cc250