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:
302
DOCUMENTATION.md
Normal file
302
DOCUMENTATION.md
Normal file
@@ -0,0 +1,302 @@
|
||||
# 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"
|
||||
```
|
||||
Reference in New Issue
Block a user