UA1ZBE Custom Firmware v1.0

Features:
- VFO mode with direct frequency input
- POCSAG decoder (512/1200 baud) with BCH(31,21) correction
- Full-screen Spectrum analyzer
- FM Radio receiver
- RSSI signal indicator overlay
- Custom boot splash (UA1ZBE / POCSAG pager / build date)

Architecture:
- app/mode.c — mode dispatcher (VFO/POCSAG/Spectrum/FM)
- app/boot_splash.c — 2-second boot splash
- app/pocsag/ — POCSAG decoder + BCH correction
- app/display_rssi.c — RSSI indicator
- main.c — entry point with custom init
- syscalls.c — bare-metal _sbrk stub

Build: arm-none-eabi-gcc -Os -flto -Wall -Werror -Wextra
Size: 57.9KB Flash / 3.6KB RAM

Controls:
- 0-9: Direct frequency input (VFO)
- SK2: POCSAG mode
- SK1: Spectrum analyzer
- 0: FM Radio
- EXIT: Return to VFO
- F/*: Toggle 512/1200 baud (in POCSAG)
This commit is contained in:
2026-04-12 00:44:05 +03:00
parent 5c1229659b
commit a1206d6fd4
3435 changed files with 593221 additions and 2 deletions

120
dp32g030.cfg Normal file
View File

@@ -0,0 +1,120 @@
transport select swd
adapter speed 32000
reset_config srst_only srst_nogate connect_assert_srst
gdb_breakpoint_override hard
set _CHIP_NAME DP32G0xx
# Create a new dap, with name chip and role CPU, -enable let's OpenOCD to know to add it to the scan
swd newdap $_CHIP_NAME cpu -enable
# Create the DAP instance, this must be explicitly created according to the OpenOCD docs
dap create $_CHIP_NAME.dap -chain-position $_CHIP_NAME.cpu
# Set up the GDB target for the CPU, cortex_m is the CPU type,
target create $_CHIP_NAME.cpu cortex_m -dap $_CHIP_NAME.dap
set _SECTOR_SIZE 512
proc uv_clear_flash_sector {sector_number} {
echo [format "Erasing sector 0x%02x = offset 0x%04x" [expr {$sector_number}] [expr {$sector_number*256}] ]
write_memory 0x4006F000 32 {0x09} ;#set erasing mode
write_memory 0x4006F004 32 [expr {$sector_number << 6}]
write_memory 0x4006F01c 32 {0xAA} ;#unlock flash
write_memory 0x4006F010 32 {0x01} ;#set OPSTART=1
read_memory 0x4006F014 32 1 ;#check status for 0x02
uv_wait_busy
write_memory 0x4006F018 32 {0x55} ;#lock flash
}
proc uv_clear_whole_flash {} {
for {set i 0} {$i < 0x100} {incr i} {
uv_clear_flash_sector $i
}
}
proc uv_clear_sectors {sectors_count} {
for {set i 0} {$i < $sectors_count} {incr i} {
uv_clear_flash_sector $i
}
}
proc uv_flash_unlock {} {
write_memory 0x4006F01c 32 {0xAA} ;#unlock flash
uv_wait_busy
}
proc uv_flash_lock {} {
write_memory 0x4006F018 32 {0x55} ;#lock flash
uv_wait_busy
}
proc uv_flash_write {address value} {
write_memory 0x4006F000 32 {0x05} ;#set writing mode
write_memory 0x4006F004 32 [expr {($address>>2)+0xC000}] ;#set address in flash
write_memory 0x4006F008 32 $value ;#set data
write_memory 0x4006F010 32 {0x01} ;#set OPSTART=1
while {1} {
set status [read_memory 0x4006F014 32 1]
if {($status & 0x4) != 0} {
break
}
}
uv_wait_busy
}
proc uv_wait_busy {} {
while {1} {
set status [read_memory 0x4006F014 32 1]
if {($status & 0x2) == 0} {
break
}
}
}
proc write_image {filename address} {
global _SECTOR_SIZE
set fs [file size $filename]
set fd [open $filename "rb"]
echo "Checking mask"
set status [read_memory 0x4006F020 32 1]
if {$status != 6} {
echo "Changing mask"
write_memory 0x4006F020 32 0
uv_wait_busy
write_memory 0x4006F020 32 6
uv_wait_busy
set status [read_memory 0x4006F020 32 1]
if {$status != 6} {
echo [format "Cannot set flash mask %d!" $status]
close $fd
return
}
}
uv_clear_sectors [expr {(($fs+$_SECTOR_SIZE-1)&(0x10000000-$_SECTOR_SIZE))/($_SECTOR_SIZE/2)}]
uv_flash_unlock
set addr $address
while {![eof $fd]} {
set data [read $fd 4]
if {[string length $data] == 4} {
set b0 [scan [string index $data 0] %c]
set b1 [scan [string index $data 1] %c]
set b2 [scan [string index $data 2] %c]
set b3 [scan [string index $data 3] %c]
set i_data [expr {$b0 | $b1 << 8 | $b2 << 16 | $b3 << 24}]
echo [format "Writing 0x%04x to address 0x%04x (%02d %%)" $i_data $addr [expr {(100*($addr+4)/$fs)}]]
uv_flash_write $addr $i_data
incr addr 4
}
}
uv_flash_lock
close $fd
}
# dap init
init
halt
# reset halt