Files
uv-k5-ua1zbe-firmware/DOCUMENTATION.md
ua1zbe a1206d6fd4 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)
2026-04-12 00:44:05 +03:00

303 lines
8.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# UA1ZBE Custom Firmware — Полная документация
## 1. Обзор архитектуры
Прошивка заменяет стандартное меню и создаёт три режима: VFO, POCSAG, Spectrum + FM.
### Точка входа: `main.c`
```
Main()
├── SYSTICK_Init(), BOARD_Init()
├── BK4819_Init()
├── SETTINGS_InitEEPROM()
├── RADIO_ConfigureChannel()
├── BOOT_SplashShow() ← 2 сек заставка
├── RSSI_Init()
├── MODE_Init() ← VFO режим по умолчанию
└── while(1):
├── APP_Update()
├── if (gNextTimeslice):
│ ├── RSSI_Update()
│ └── MODE_TimeSlice10ms()
└── if (gNextTimeslice_500ms):
└── MODE_TimeSlice500ms()
```
### Диспетчер режимов: `app/mode.c`
```
MODE_TimeSlice10ms()
├── MODE_VFO:
│ └── APP_TimeSlice10ms() ← оригинальный VFO цикл
│ └── RSSI_Draw() ← overlay индикатор
├── MODE_POCSAG:
│ └── POCSAG_FeedSample() × 80 ← аудио сэмплинг
│ └── POCSAG_Process()
│ └── pocsag_draw()
├── MODE_SPECTRUM:
│ └── MODE_Switch(MODE_VFO) ← после возврата из spectrum
└── MODE_FM:
└── FM_Play()
```
---
## 2. Все ошибки при создании и их исправления
### Ошибка 1: `static_assert` не работает в C99
```
error: expected declaration specifiers or '...' before '(' token
static_assert(ARRAY_SIZE(ProcessKeysFunctions) == DISPLAY_N_ELEM);
```
**Причина:** `static_assert` — C11 feature. В `-std=c99` недоступен.
**Исправление:** Заменил `-std=c99` на `-std=gnu11` в Makefile.
---
### Ошибка 2: `[[fallthrough]]` не поддерживается GCC 9
```
error: expected expression before '[' token
[[fallthrough]];
```
**Причина:** Атрибут `[[fallthrough]]` — синтаксис C23. GCC 9.2.1 не понимает.
**Исправление:**
```bash
sed -i 's/\[\[fallthrough\]\]/__attribute__((fallthrough))/g' \
radio.c audio.c app/menu.c app/dtmf.c app/chFrScanner.c
```
---
### Ошибка 3: `SYSTICK_GetTickCounter()` не существует
**Причина:** В egzumer нет этой функции.
**Исправление:** В `pocsag.c` использован собственный статический счётчик `s_tick_counter`, инкрементируемый при каждом вызове `POCSAG_FeedSample()`.
---
### Ошибка 4: Сравнение `uint8_t >= 576` — всегда false
```
error: comparison is always false due to limited range of data type
if (s_preamble_alt_count >= POCSAG_PREAMBLE_MIN_BITS)
```
**Причина:** `s_preamble_alt_count` был `uint8_t` (макс 255), а `POCSAG_PREAMBLE_MIN_BITS` = 576.
**Исправление:**
```c
static uint16_t s_preamble_alt_count; // было uint8_t
```
---
### Ошибка 5: `dBmCorrTable` undeclared
```
error: 'dBmCorrTable' undeclared (first use in this function)
```
**Причина:** Таблица в `ui/main.c`, но нет extern в заголовке.
**Исправление:** Добавил в `display_rssi.c`:
```c
extern const int8_t dBmCorrTable[7];
```
---
### Ошибка 6: `display_rssi.h` не найден
```
fatal error: display_rssi.h: No such file or directory
```
**Исправление:** Заменил `#include "display_rssi.h"` на `#include "app/display_rssi.h"` везде.
---
### Ошибка 7: `sizeof` к неполному типу
```
error: invalid application of 'sizeof' to incomplete type 'char[]'
```
**Исправление:** Добавил `#include "app/dtmf.h"` в `main.c` — там полное объявление `extern char gDTMF_String[15]`.
---
### Ошибка 8: 40+ undefined reference
```
undefined reference to `gScreenToDisplay'
undefined reference to `GUI_SelectNextDisplay'
undefined reference to `GENERIC_Key_F', `ACTION_Scan'...
```
**Причина:** Исключил модули, но `app/app.c` и `app/main.c` их используют.
**Исправление:** Вернул в Makefile: `ui/ui.o`, `ui/inputbox.o`, `ui/menu.o`, `ui/welcome.o`, `ui/scanner.o`, `app/menu.o`, `app/generic.o`, `app/action.o`, `app/dtmf.o`
---
### Ошибка 9: `_sbrk` undefined
```
undefined reference to `_sbrk'
```
**Исправление:** Создал `syscalls.c`:
```c
caddr_t _sbrk(int incr) {
(void)incr;
return (caddr_t)0;
}
```
---
### Ошибка 10: `UI_DisplayReleaseKeys` / `UI_DisplayScanner`
**Исправление:** Добавил `ui/welcome.o` и `ui/scanner.o`.
---
## 3. Известные проблемы для доработки
### 3.1. POCSAG — недостаточно сэмплов
**Проблема:** `POCSAG_FeedSample()` вызывается ~1 раз/10мс. Для 1200 бод нужно ~1 раз/125мкс.
**Решение:**
```c
// В mode.c, case MODE_POCSAG:
for (int i = 0; i < 80; i++) {
uint16_t audio = BK4819_GetVoiceAmplitudeOut();
POCSAG_FeedSample(audio);
SYSTEM_DelayUs(125);
}
```
### 3.2. Нет отображения текста POCSAG сообщений
**Решение:** В `pocsag_draw()` добавить:
```c
static pocsag_msg_t last_msg;
if (POCSAG_GetMessage(&last_msg)) {
UI_PrintStringSmallNormal(last_msg.text, 0, 120, 28);
}
```
### 3.3. Дублирование APP_TimeSlice
`MODE_TimeSlice10ms()` вызывает `APP_TimeSlice10ms()`, что дублирует обработку.
**Решение:** Разделить — для VFO вызывать `APP_TimeSlice10ms()`, для POCSAG — только `CheckRadioInterrupts()`.
### 3.4. Flash на пределе (94.3%)
Осталось ~3.5 КБ. Для экономии можно отключить:
```makefile
ENABLE_FMRADIO = 0 # -2 КБ
ENABLE_SPECTRUM = 0 # -5 КБ
```
---
## 4. Инструкция по сборке
```bash
# Тулчейн
sudo apt-get install gcc-arm-none-eabi
# Сборка
cd uv-k5-firmware-custom
make clean && make
# Результат
arm-none-eabi-size firmware
# text data bss dec hex filename
# 57708 204 3364 61276 ef5c firmware
```
---
## 5. Инструкция по прошивке
### Вариант 1: SWD (J-Link)
```bash
# Установка OpenOCD
sudo apt-get install openocd
# Подключение:
# J-Link Pin 1 (VTref) — 3.3V
# J-Link Pin 2 (GND) — GND
# J-Link Pin 7 (SWDIO) — SWDIO на плате
# J-Link Pin 9 (SWCLK) — SWCLK на плате
make flash
# Или вручную:
openocd -f interface/jlink.cfg -f dp32g030.cfg \
-c "write_image firmware.bin 0; shutdown;"
```
### Вариант 2: UART
```bash
git clone https://github.com/piotr02/k5prog.git
cd k5prog && make && sudo cp k5prog /usr/local/bin/
# Включить рацию с зажатой SK2
k5prog -f firmware.bin -p /dev/ttyUSB0 -w
```
### Вариант 3: USB
```bash
# Выключить → зажать PTT+SK2 → включить
k5prog -f firmware.bin -w
```
---
## 6. Структура файлов
| Файл | Назначение |
|------|-----------|
| `Makefile` | Конфигурация сборки, флаги |
| `main.c` | Точка входа, инициализация, главный цикл |
| `syscalls.c` | Заглушка _sbrk для bare-metal |
| `app/boot_splash.c` | Заставка UA1ZBE / 2 сек |
| `app/display_rssi.c` | RSSI индикатор в dBm |
| `app/mode.c` | Диспетчер режимов |
| `app/pocsag/pocsag.c` | POCSAG декодер |
| `app/pocsag/bch31.c` | BCH(31,21) коррекция |
---
## 7. Отладочные команды
```bash
# Размер секций
arm-none-eabi-size -A firmware | sort -n -k2 | tail -20
# Символы
arm-none-eabi-nm --size-sort firmware | tail -30
# Дизассемблер
arm-none-eabi-objdump -d firmware | grep -A20 "<POCSAG_FeedSample>:"
# Проверка переполнения
SIZE=$(wc -c < firmware.bin)
[ $SIZE -gt 61440 ] && echo "OVERFLOW!" || echo "OK: $SIZE / 61440"
```