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:
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
*.d
|
||||
*.o
|
||||
firmware
|
||||
/firmware.packed.bin
|
||||
/firmware.bin
|
||||
/compiled-firmware
|
||||
.cache
|
||||
compile_commands.json
|
||||
.vscode
|
||||
/docs
|
||||
k5_eeprom.raw
|
||||
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"
|
||||
```
|
||||
12
Dockerfile
Normal file
12
Dockerfile
Normal file
@@ -0,0 +1,12 @@
|
||||
FROM --platform=amd64 archlinux:latest
|
||||
RUN pacman -Syyu base-devel --noconfirm
|
||||
RUN pacman -Syyu arm-none-eabi-gcc --noconfirm
|
||||
RUN pacman -Syyu arm-none-eabi-newlib --noconfirm
|
||||
RUN pacman -Syyu git --noconfirm
|
||||
RUN pacman -Syyu python-pip --noconfirm
|
||||
RUN pacman -Syyu python-crcmod --noconfirm
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
|
||||
RUN git submodule update --init --recursive
|
||||
#RUN make && cp firmware* compiled-firmware/
|
||||
17
Doxyfile
Normal file
17
Doxyfile
Normal file
@@ -0,0 +1,17 @@
|
||||
OUTPUT_DIRECTORY = docs
|
||||
GENERATE_LATEX = NO
|
||||
GENERATE_RTF = NO
|
||||
GENERATE_MAN = NO
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
HAVE_DOT = YES
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_STATIC = YES
|
||||
CALL_GRAPH = YES
|
||||
CALLER_GRAPH = YES
|
||||
DISABLE_INDEX = YES
|
||||
GENERATE_TREEVIEW = YES
|
||||
RECURSIVE = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DOT_MULTI_TARGETS = YES
|
||||
201
LICENSE
Normal file
201
LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
425
Makefile
Normal file
425
Makefile
Normal file
@@ -0,0 +1,425 @@
|
||||
# =============================================================================
|
||||
# UA1ZBE Custom Firmware for Quansheng UV-K5/K6
|
||||
# Based on egzumer/uv-k5-firmware-custom
|
||||
# Three modes: VFO, POCSAG, Spectrum + FM Radio
|
||||
# =============================================================================
|
||||
|
||||
# ---- FEATURES ----
|
||||
ENABLE_UART ?= 0
|
||||
ENABLE_AIRCOPY ?= 0
|
||||
ENABLE_FMRADIO ?= 1
|
||||
ENABLE_NOAA ?= 0
|
||||
ENABLE_VOICE ?= 0
|
||||
ENABLE_VOX ?= 0
|
||||
ENABLE_ALARM ?= 0
|
||||
ENABLE_TX1750 ?= 0
|
||||
ENABLE_PWRON_PASSWORD ?= 0
|
||||
ENABLE_DTMF_CALLING ?= 0
|
||||
ENABLE_FLASHLIGHT ?= 0
|
||||
|
||||
# ---- CUSTOM MODS ----
|
||||
ENABLE_BIG_FREQ ?= 1
|
||||
ENABLE_SMALL_BOLD ?= 0
|
||||
ENABLE_CUSTOM_MENU_LAYOUT ?= 0
|
||||
ENABLE_KEEP_MEM_NAME ?= 0
|
||||
ENABLE_WIDE_RX ?= 1
|
||||
ENABLE_TX_WHEN_AM ?= 0
|
||||
ENABLE_F_CAL_MENU ?= 0
|
||||
ENABLE_CTCSS_TAIL_PHASE_SHIFT ?= 0
|
||||
ENABLE_BOOT_BEEPS ?= 0
|
||||
ENABLE_SHOW_CHARGE_LEVEL ?= 0
|
||||
ENABLE_REVERSE_BAT_SYMBOL ?= 0
|
||||
ENABLE_NO_CODE_SCAN_TIMEOUT ?= 0
|
||||
ENABLE_AM_FIX ?= 0
|
||||
ENABLE_SQUELCH_MORE_SENSITIVE ?= 0
|
||||
ENABLE_FASTER_CHANNEL_SCAN ?= 0
|
||||
ENABLE_RSSI_BAR ?= 1
|
||||
ENABLE_AUDIO_BAR ?= 0
|
||||
ENABLE_COPY_CHAN_TO_VFO ?= 0
|
||||
ENABLE_SPECTRUM ?= 1
|
||||
ENABLE_REDUCE_LOW_MID_TX_POWER?= 0
|
||||
ENABLE_BYP_RAW_DEMODULATORS ?= 0
|
||||
ENABLE_BLMIN_TMP_OFF ?= 0
|
||||
ENABLE_SCAN_RANGES ?= 0
|
||||
|
||||
# ---- DEBUGGING ----
|
||||
ENABLE_AM_FIX_SHOW_DATA ?= 0
|
||||
ENABLE_AGC_SHOW_DATA ?= 0
|
||||
ENABLE_UART_RW_BK_REGS ?= 0
|
||||
|
||||
# ---- COMPILER/LINKER OPTIONS ----
|
||||
ENABLE_CLANG ?= 0
|
||||
ENABLE_SWD ?= 0
|
||||
ENABLE_OVERLAY ?= 0
|
||||
ENABLE_LTO ?= 1
|
||||
|
||||
# ---- POCSAG DECODER ----
|
||||
ENABLE_POCSAG ?= 1
|
||||
|
||||
#############################################################
|
||||
|
||||
TARGET = firmware
|
||||
|
||||
ifeq ($(ENABLE_CLANG),1)
|
||||
ENABLE_LTO := 0
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_LTO),1)
|
||||
ENABLE_OVERLAY := 0
|
||||
endif
|
||||
|
||||
BSP_DEFINITIONS := $(wildcard hardware/*/*.def)
|
||||
BSP_HEADERS := $(patsubst hardware/%,bsp/%,$(BSP_DEFINITIONS))
|
||||
BSP_HEADERS := $(patsubst %.def,%.h,$(BSP_HEADERS))
|
||||
|
||||
OBJS =
|
||||
# Startup files
|
||||
OBJS += start.o
|
||||
OBJS += init.o
|
||||
ifeq ($(ENABLE_OVERLAY),1)
|
||||
OBJS += sram-overlay.o
|
||||
endif
|
||||
OBJS += external/printf/printf.o
|
||||
|
||||
# Drivers
|
||||
OBJS += driver/adc.o
|
||||
ifeq ($(ENABLE_UART),1)
|
||||
OBJS += driver/aes.o
|
||||
endif
|
||||
OBJS += driver/backlight.o
|
||||
ifeq ($(ENABLE_FMRADIO),1)
|
||||
OBJS += driver/bk1080.o
|
||||
endif
|
||||
OBJS += driver/bk4819.o
|
||||
ifeq ($(filter $(ENABLE_AIRCOPY) $(ENABLE_UART),1),1)
|
||||
OBJS += driver/crc.o
|
||||
endif
|
||||
OBJS += driver/eeprom.o
|
||||
ifeq ($(ENABLE_OVERLAY),1)
|
||||
OBJS += driver/flash.o
|
||||
endif
|
||||
OBJS += driver/gpio.o
|
||||
OBJS += driver/i2c.o
|
||||
OBJS += driver/keyboard.o
|
||||
OBJS += driver/spi.o
|
||||
OBJS += driver/st7565.o
|
||||
OBJS += driver/system.o
|
||||
OBJS += driver/systick.o
|
||||
ifeq ($(ENABLE_UART),1)
|
||||
OBJS += driver/uart.o
|
||||
endif
|
||||
|
||||
# App core
|
||||
OBJS += app/app.o
|
||||
OBJS += app/common.o
|
||||
OBJS += app/chFrScanner.o
|
||||
OBJS += app/scanner.o
|
||||
OBJS += app/main.o
|
||||
OBJS += app/mode.o
|
||||
|
||||
# POCSAG decoder
|
||||
ifeq ($(ENABLE_POCSAG),1)
|
||||
OBJS += app/pocsag/pocsag.o
|
||||
OBJS += app/pocsag/bch31.o
|
||||
endif
|
||||
|
||||
# FM Radio
|
||||
ifeq ($(ENABLE_FMRADIO),1)
|
||||
OBJS += app/fm.o
|
||||
OBJS += ui/fmradio.o
|
||||
endif
|
||||
|
||||
# Spectrum analyzer
|
||||
ifeq ($(ENABLE_SPECTRUM),1)
|
||||
OBJS += app/spectrum.o
|
||||
endif
|
||||
|
||||
# Reduced UI (no menu but needed for symbols)
|
||||
OBJS += app/boot_splash.o
|
||||
OBJS += app/display_rssi.o
|
||||
OBJS += ui/inputbox.o
|
||||
OBJS += ui/ui.o
|
||||
OBJS += ui/menu.o
|
||||
OBJS += app/menu.o
|
||||
OBJS += app/generic.o
|
||||
OBJS += app/action.o
|
||||
OBJS += app/dtmf.o
|
||||
|
||||
# UI modules
|
||||
OBJS += ui/main.o
|
||||
OBJS += ui/helper.o
|
||||
OBJS += ui/status.o
|
||||
OBJS += ui/battery.o
|
||||
OBJS += ui/welcome.o
|
||||
OBJS += ui/scanner.o
|
||||
|
||||
# Core modules
|
||||
OBJS += audio.o
|
||||
OBJS += bitmaps.o
|
||||
OBJS += board.o
|
||||
OBJS += dcs.o
|
||||
OBJS += font.o
|
||||
OBJS += frequencies.o
|
||||
OBJS += functions.o
|
||||
OBJS += radio.o
|
||||
OBJS += settings.o
|
||||
OBJS += misc.o
|
||||
OBJS += version.o
|
||||
OBJS += main.o
|
||||
OBJS += syscalls.o
|
||||
OBJS += helper/battery.o
|
||||
OBJS += helper/boot.o
|
||||
|
||||
ifeq ($(OS), Windows_NT)
|
||||
TOP := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
RM = del /Q
|
||||
FixPath = $(subst /,\,$1)
|
||||
WHERE = where
|
||||
NULL_OUTPUT = nul
|
||||
else
|
||||
TOP := $(shell pwd)
|
||||
RM = rm -f
|
||||
FixPath = $1
|
||||
WHERE = which
|
||||
NULL_OUTPUT = /dev/null
|
||||
endif
|
||||
|
||||
AS = arm-none-eabi-gcc
|
||||
LD = arm-none-eabi-gcc
|
||||
|
||||
ifeq ($(ENABLE_CLANG),0)
|
||||
CC = arm-none-eabi-gcc
|
||||
else
|
||||
CC = clang --sysroot=/usr/arm-none-eabi --target=arm-none-eabi
|
||||
endif
|
||||
|
||||
OBJCOPY = arm-none-eabi-objcopy
|
||||
SIZE = arm-none-eabi-size
|
||||
|
||||
AUTHOR_STRING ?= UA1ZBE
|
||||
ifneq (, $(shell $(WHERE) git))
|
||||
VERSION_STRING ?= $(shell git describe --tags --exact-match 2>$(NULL_OUTPUT))
|
||||
ifeq (, $(VERSION_STRING))
|
||||
VERSION_STRING := $(shell git rev-parse --short HEAD)
|
||||
endif
|
||||
endif
|
||||
ifeq (, $(VERSION_STRING))
|
||||
VERSION_STRING := NOGIT
|
||||
endif
|
||||
|
||||
ASFLAGS = -c -mcpu=cortex-m0
|
||||
ifeq ($(ENABLE_OVERLAY),1)
|
||||
ASFLAGS += -DENABLE_OVERLAY
|
||||
endif
|
||||
|
||||
CFLAGS =
|
||||
ifeq ($(ENABLE_CLANG),0)
|
||||
CFLAGS += -Os -Wall -Werror -Wextra -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=gnu11 -MMD
|
||||
else
|
||||
CFLAGS += -Oz -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=c99 -MMD
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_LTO),1)
|
||||
CFLAGS += -flto=auto
|
||||
else
|
||||
CFLAGS += -ffunction-sections -fdata-sections
|
||||
endif
|
||||
|
||||
CFLAGS += -DPRINTF_INCLUDE_CONFIG_H
|
||||
CFLAGS += -DAUTHOR_STRING=\"$(AUTHOR_STRING)\" -DVERSION_STRING=\"$(VERSION_STRING)\"
|
||||
CFLAGS += -DBUILD_DATE=\"$(shell date +%Y-%m-%d)\"
|
||||
|
||||
# Feature defines
|
||||
ifeq ($(ENABLE_SPECTRUM),1)
|
||||
CFLAGS += -DENABLE_SPECTRUM
|
||||
endif
|
||||
ifeq ($(ENABLE_SWD),1)
|
||||
CFLAGS += -DENABLE_SWD
|
||||
endif
|
||||
ifeq ($(ENABLE_OVERLAY),1)
|
||||
CFLAGS += -DENABLE_OVERLAY
|
||||
endif
|
||||
ifeq ($(ENABLE_AIRCOPY),1)
|
||||
CFLAGS += -DENABLE_AIRCOPY
|
||||
endif
|
||||
ifeq ($(ENABLE_FMRADIO),1)
|
||||
CFLAGS += -DENABLE_FMRADIO
|
||||
endif
|
||||
ifeq ($(ENABLE_UART),1)
|
||||
CFLAGS += -DENABLE_UART
|
||||
endif
|
||||
ifeq ($(ENABLE_BIG_FREQ),1)
|
||||
CFLAGS += -DENABLE_BIG_FREQ
|
||||
endif
|
||||
ifeq ($(ENABLE_SMALL_BOLD),1)
|
||||
CFLAGS += -DENABLE_SMALL_BOLD
|
||||
endif
|
||||
ifeq ($(ENABLE_NOAA),1)
|
||||
CFLAGS += -DENABLE_NOAA
|
||||
endif
|
||||
ifeq ($(ENABLE_VOICE),1)
|
||||
CFLAGS += -DENABLE_VOICE
|
||||
endif
|
||||
ifeq ($(ENABLE_VOX),1)
|
||||
CFLAGS += -DENABLE_VOX
|
||||
endif
|
||||
ifeq ($(ENABLE_ALARM),1)
|
||||
CFLAGS += -DENABLE_ALARM
|
||||
endif
|
||||
ifeq ($(ENABLE_TX1750),1)
|
||||
CFLAGS += -DENABLE_TX1750
|
||||
endif
|
||||
ifeq ($(ENABLE_PWRON_PASSWORD),1)
|
||||
CFLAGS += -DENABLE_PWRON_PASSWORD
|
||||
endif
|
||||
ifeq ($(ENABLE_KEEP_MEM_NAME),1)
|
||||
CFLAGS += -DENABLE_KEEP_MEM_NAME
|
||||
endif
|
||||
ifeq ($(ENABLE_WIDE_RX),1)
|
||||
CFLAGS += -DENABLE_WIDE_RX
|
||||
endif
|
||||
ifeq ($(ENABLE_TX_WHEN_AM),1)
|
||||
CFLAGS += -DENABLE_TX_WHEN_AM
|
||||
endif
|
||||
ifeq ($(ENABLE_F_CAL_MENU),1)
|
||||
CFLAGS += -DENABLE_F_CAL_MENU
|
||||
endif
|
||||
ifeq ($(ENABLE_CTCSS_TAIL_PHASE_SHIFT),1)
|
||||
CFLAGS += -DENABLE_CTCSS_TAIL_PHASE_SHIFT
|
||||
endif
|
||||
ifeq ($(ENABLE_BOOT_BEEPS),1)
|
||||
CFLAGS += -DENABLE_BOOT_BEEPS
|
||||
endif
|
||||
ifeq ($(ENABLE_SHOW_CHARGE_LEVEL),1)
|
||||
CFLAGS += -DENABLE_SHOW_CHARGE_LEVEL
|
||||
endif
|
||||
ifeq ($(ENABLE_REVERSE_BAT_SYMBOL),1)
|
||||
CFLAGS += -DENABLE_REVERSE_BAT_SYMBOL
|
||||
endif
|
||||
ifeq ($(ENABLE_NO_CODE_SCAN_TIMEOUT),1)
|
||||
CFLAGS += -DENABLE_NO_CODE_SCAN_TIMEOUT
|
||||
endif
|
||||
ifeq ($(ENABLE_AM_FIX),1)
|
||||
CFLAGS += -DENABLE_AM_FIX
|
||||
endif
|
||||
ifeq ($(ENABLE_AM_FIX_SHOW_DATA),1)
|
||||
CFLAGS += -DENABLE_AM_FIX_SHOW_DATA
|
||||
endif
|
||||
ifeq ($(ENABLE_SQUELCH_MORE_SENSITIVE),1)
|
||||
CFLAGS += -DENABLE_SQUELCH_MORE_SENSITIVE
|
||||
endif
|
||||
ifeq ($(ENABLE_FASTER_CHANNEL_SCAN),1)
|
||||
CFLAGS += -DENABLE_FASTER_CHANNEL_SCAN
|
||||
endif
|
||||
ifeq ($(ENABLE_RSSI_BAR),1)
|
||||
CFLAGS += -DENABLE_RSSI_BAR
|
||||
endif
|
||||
ifeq ($(ENABLE_AUDIO_BAR),1)
|
||||
CFLAGS += -DENABLE_AUDIO_BAR
|
||||
endif
|
||||
ifeq ($(ENABLE_COPY_CHAN_TO_VFO),1)
|
||||
CFLAGS += -DENABLE_COPY_CHAN_TO_VFO
|
||||
endif
|
||||
ifeq ($(ENABLE_SINGLE_VFO_CHAN),1)
|
||||
CFLAGS += -DENABLE_SINGLE_VFO_CHAN
|
||||
endif
|
||||
ifeq ($(ENABLE_BAND_SCOPE),1)
|
||||
CFLAGS += -DENABLE_BAND_SCOPE
|
||||
endif
|
||||
ifeq ($(ENABLE_REDUCE_LOW_MID_TX_POWER),1)
|
||||
CFLAGS += -DENABLE_REDUCE_LOW_MID_TX_POWER
|
||||
endif
|
||||
ifeq ($(ENABLE_BYP_RAW_DEMODULATORS),1)
|
||||
CFLAGS += -DENABLE_BYP_RAW_DEMODULATORS
|
||||
endif
|
||||
ifeq ($(ENABLE_BLMIN_TMP_OFF),1)
|
||||
CFLAGS += -DENABLE_BLMIN_TMP_OFF
|
||||
endif
|
||||
ifeq ($(ENABLE_SCAN_RANGES),1)
|
||||
CFLAGS += -DENABLE_SCAN_RANGES
|
||||
endif
|
||||
ifeq ($(ENABLE_DTMF_CALLING),1)
|
||||
CFLAGS += -DENABLE_DTMF_CALLING
|
||||
endif
|
||||
ifeq ($(ENABLE_AGC_SHOW_DATA),1)
|
||||
CFLAGS += -DENABLE_AGC_SHOW_DATA
|
||||
endif
|
||||
ifeq ($(ENABLE_FLASHLIGHT),1)
|
||||
CFLAGS += -DENABLE_FLASHLIGHT
|
||||
endif
|
||||
ifeq ($(ENABLE_UART_RW_BK_REGS),1)
|
||||
CFLAGS += -DENABLE_UART_RW_BK_REGS
|
||||
endif
|
||||
ifeq ($(ENABLE_CUSTOM_MENU_LAYOUT),1)
|
||||
CFLAGS += -DENABLE_CUSTOM_MENU_LAYOUT
|
||||
endif
|
||||
ifeq ($(ENABLE_POCSAG),1)
|
||||
CFLAGS += -DENABLE_POCSAG
|
||||
endif
|
||||
|
||||
LDFLAGS =
|
||||
LDFLAGS += -z noexecstack -mcpu=cortex-m0 -nostartfiles -Wl,-T,firmware.ld -Wl,--gc-sections
|
||||
LDFLAGS += --specs=nano.specs
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
ASFLAGS += -g
|
||||
CFLAGS += -g
|
||||
LDFLAGS += -g
|
||||
endif
|
||||
|
||||
INC =
|
||||
INC += -I $(TOP)
|
||||
INC += -I $(TOP)/external/CMSIS_5/CMSIS/Core/Include/
|
||||
INC += -I $(TOP)/external/CMSIS_5/Device/ARM/ARMCM0/Include
|
||||
|
||||
LIBS =
|
||||
|
||||
DEPS = $(OBJS:.o=.d)
|
||||
|
||||
ifneq (, $(shell $(WHERE) python))
|
||||
MY_PYTHON := python
|
||||
else ifneq (, $(shell $(WHERE) python3))
|
||||
MY_PYTHON := python3
|
||||
endif
|
||||
|
||||
ifdef MY_PYTHON
|
||||
HAS_CRCMOD := $(shell $(MY_PYTHON) -c "import crcmod" 2>&1)
|
||||
endif
|
||||
|
||||
all: $(TARGET)
|
||||
$(OBJCOPY) -O binary $< $<.bin
|
||||
|
||||
ifndef MY_PYTHON
|
||||
$(info )
|
||||
$(info !!!!!!!! PYTHON NOT FOUND, *.PACKED.BIN WON'T BE BUILT)
|
||||
$(info )
|
||||
else ifneq (,$(HAS_CRCMOD))
|
||||
$(info )
|
||||
$(info !!!!!!!! CRCMOD NOT INSTALLED, *.PACKED.BIN WON'T BE BUILT)
|
||||
$(info !!!!!!!! run: pip install crcmod)
|
||||
$(info )
|
||||
else
|
||||
-$(MY_PYTHON) fw-pack.py $<.bin $(AUTHOR_STRING) $(VERSION_STRING) $<.packed.bin
|
||||
endif
|
||||
|
||||
$(SIZE) $<
|
||||
|
||||
version.o: .FORCE
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(LD) $(LDFLAGS) $^ -o $@ $(LIBS)
|
||||
|
||||
bsp/dp32g030/%.h: hardware/dp32g030/%.def
|
||||
|
||||
%.o: %.c | $(BSP_HEADERS)
|
||||
$(CC) $(CFLAGS) $(INC) -c $< -o $@
|
||||
|
||||
%.o: %.S
|
||||
$(AS) $(ASFLAGS) $< -o $@
|
||||
|
||||
.FORCE:
|
||||
|
||||
-include $(DEPS)
|
||||
|
||||
clean:
|
||||
$(RM) $(call FixPath, $(TARGET).bin $(TARGET).packed.bin $(TARGET) $(OBJS) $(DEPS))
|
||||
43
README.md
43
README.md
@@ -1,3 +1,42 @@
|
||||
# uv-k5-ua1zbe-firmware
|
||||
# UA1ZBE Custom Firmware — Quansheng UV-K5/K6
|
||||
|
||||
UA1ZBE Custom Firmware for Quansheng UV-K5/K6 - POCSAG, Spectrum, FM, RSSI
|
||||
Кастомная прошивка на базе egzumer/uv-k5-firmware-custom.
|
||||
|
||||
## Возможности
|
||||
|
||||
| Функция | Описание |
|
||||
|---------|----------|
|
||||
| **VFO** | Основной режим — прямой ввод частоты с клавиатуры |
|
||||
| **POCSAG** | Декодирование пейджинговых сообщений (512/1200 бод) |
|
||||
| **Spectrum** | Полноэкранный спектр-анализатор |
|
||||
| **FM Radio** | Приём FM-радио |
|
||||
| **RSSI** | Индикатор уровня сигнала на дисплее |
|
||||
| **Boot Splash** | Кастомная заставка при старте |
|
||||
|
||||
## Управление
|
||||
|
||||
| Кнопка | Действие |
|
||||
|--------|----------|
|
||||
| `0-9` | Прямой ввод частоты в VFO |
|
||||
| `SK2` (нижняя боковая) | POCSAG режим |
|
||||
| `SK1` (средняя боковая) | Спектр-анализатор |
|
||||
| `0` (короткое) | FM-радио |
|
||||
| `EXIT` | Возврат в VFO |
|
||||
| `F` / `*` (в POCSAG) | Переключение 512 ↔ 1200 бод |
|
||||
|
||||
## Сборка
|
||||
|
||||
```bash
|
||||
sudo apt-get install gcc-arm-none-eabi
|
||||
make clean && make
|
||||
arm-none-eabi-size firmware
|
||||
```
|
||||
|
||||
## Размеры прошивки
|
||||
|
||||
```
|
||||
text data bss dec hex filename
|
||||
57708 204 3364 61276 ef5c firmware
|
||||
```
|
||||
|
||||
Flash: 57.9 КБ / 60 КБ | RAM: 3.6 КБ / 16 КБ
|
||||
|
||||
397
am_fix.c
Normal file
397
am_fix.c
Normal file
@@ -0,0 +1,397 @@
|
||||
|
||||
/* Copyright 2023 OneOfEleven
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// code to 'try' and reduce the AM demodulator saturation problem
|
||||
//
|
||||
// that is until someone works out how to properly configure the BK chip !
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "am_fix.h"
|
||||
#include "app/main.h"
|
||||
#include "board.h"
|
||||
#include "driver/bk4819.h"
|
||||
#include "external/printf/printf.h"
|
||||
#include "frequencies.h"
|
||||
#include "functions.h"
|
||||
#include "misc.h"
|
||||
#include "settings.h"
|
||||
#ifdef ENABLE_AGC_SHOW_DATA
|
||||
#include "ui/main.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_AM_FIX
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t reg_val;
|
||||
int8_t gain_dB;
|
||||
} __attribute__((packed)) t_gain_table;
|
||||
|
||||
// REG_10 AGC gain table
|
||||
//
|
||||
// <15:10> ???
|
||||
//
|
||||
// <9:8> = LNA Gain Short
|
||||
// 3 = 0dB < original value
|
||||
// 2 = -19dB // was -11
|
||||
// 1 = -24dB // was -16
|
||||
// 0 = -28dB // was -19
|
||||
//
|
||||
// <7:5> = LNA Gain
|
||||
// 7 = 0dB
|
||||
// 6 = -2dB
|
||||
// 5 = -4dB < original value
|
||||
// 4 = -6dB
|
||||
// 3 = -9dB
|
||||
// 2 = -14dB
|
||||
// 1 = -19dB
|
||||
// 0 = -24dB
|
||||
//
|
||||
// <4:3> = MIXER Gain
|
||||
// 3 = 0dB < original value
|
||||
// 2 = -3dB
|
||||
// 1 = -6dB
|
||||
// 0 = -8dB
|
||||
//
|
||||
// <2:0> = PGA Gain
|
||||
// 7 = 0dB
|
||||
// 6 = -3dB < original value
|
||||
// 5 = -6dB
|
||||
// 4 = -9dB
|
||||
// 3 = -15dB
|
||||
// 2 = -21dB
|
||||
// 1 = -27dB
|
||||
// 0 = -33dB
|
||||
|
||||
// front end register dB values
|
||||
//
|
||||
// these values need to be accurate for the code to properly/reliably switch
|
||||
// between table entries when adjusting the front end registers.
|
||||
//
|
||||
// these 4 tables need a measuring/calibration update
|
||||
//
|
||||
//// static const int16_t lna_short_dB[] = { -19, -16, -11, 0}; // was (but wrong)
|
||||
// static const int16_t lna_short_dB[] = { (-28), (-24), (-19), 0}; // corrected'ish
|
||||
// static const int16_t lna_dB[] = { (-24), (-19), (-14), ( -9), (-6), (-4), (-2), 0};
|
||||
// static const int16_t mixer_dB[] = { ( -8), ( -6), ( -3), 0};
|
||||
// static const int16_t pga_dB[] = { (-33), (-27), (-21), (-15), (-9), (-6), (-3), 0};
|
||||
|
||||
// lookup table is hugely easier than writing code to do the same
|
||||
//
|
||||
|
||||
#define LOOKUP_TABLE 1
|
||||
|
||||
#if LOOKUP_TABLE
|
||||
static const t_gain_table gain_table[] =
|
||||
{
|
||||
{0x03BE, -7}, // 0 .. 3 5 3 6 .. 0dB -4dB 0dB -3dB .. -7dB original
|
||||
|
||||
{0x0000,-93}, // 1 .. 0 0 0 0 .. -28dB -24dB -8dB -33dB .. -93dB
|
||||
{0x0008,-91}, // 2 .. 0 0 1 0 .. -28dB -24dB -6dB -33dB .. -91dB
|
||||
{0x0010,-88}, // 3 .. 0 0 2 0 .. -28dB -24dB -3dB -33dB .. -88dB
|
||||
{0x0001,-87}, // 4 .. 0 0 0 1 .. -28dB -24dB -8dB -27dB .. -87dB
|
||||
{0x0009,-85}, // 5 .. 0 0 1 1 .. -28dB -24dB -6dB -27dB .. -85dB
|
||||
{0x0011,-82}, // 6 .. 0 0 2 1 .. -28dB -24dB -3dB -27dB .. -82dB
|
||||
{0x0002,-81}, // 7 .. 0 0 0 2 .. -28dB -24dB -8dB -21dB .. -81dB
|
||||
{0x000A,-79}, // 8 .. 0 0 1 2 .. -28dB -24dB -6dB -21dB .. -79dB
|
||||
{0x0012,-76}, // 9 .. 0 0 2 2 .. -28dB -24dB -3dB -21dB .. -76dB
|
||||
{0x0003,-75}, // 10 .. 0 0 0 3 .. -28dB -24dB -8dB -15dB .. -75dB
|
||||
{0x000B,-73}, // 11 .. 0 0 1 3 .. -28dB -24dB -6dB -15dB .. -73dB
|
||||
{0x0013,-70}, // 12 .. 0 0 2 3 .. -28dB -24dB -3dB -15dB .. -70dB
|
||||
{0x0004,-69}, // 13 .. 0 0 0 4 .. -28dB -24dB -8dB -9dB .. -69dB
|
||||
{0x000C,-67}, // 14 .. 0 0 1 4 .. -28dB -24dB -6dB -9dB .. -67dB
|
||||
{0x000D,-64}, // 15 .. 0 0 1 5 .. -28dB -24dB -6dB -6dB .. -64dB
|
||||
{0x001C,-61}, // 16 .. 0 0 3 4 .. -28dB -24dB 0dB - 9dB .. -61dB
|
||||
{0x001D,-58}, // 17 .. 0 0 3 5 .. -28dB -24dB 0dB -6dB .. -58dB
|
||||
{0x001E,-55}, // 18 .. 0 0 3 6 .. -28dB -24dB 0dB -3dB .. -55dB
|
||||
{0x001F,-52}, // 19 .. 0 0 3 7 .. -28dB -24dB 0dB 0dB .. -52dB
|
||||
{0x003E,-50}, // 20 .. 0 1 3 6 .. -28dB -19dB 0dB -3dB .. -50dB
|
||||
{0x003F,-47}, // 21 .. 0 1 3 7 .. -28dB -19dB 0dB 0dB .. -47dB
|
||||
{0x005E,-45}, // 22 .. 0 2 3 6 .. -28dB -14dB 0dB -3dB .. -45dB
|
||||
{0x005F,-42}, // 23 .. 0 2 3 7 .. -28dB -14dB 0dB 0dB .. -42dB
|
||||
{0x007E,-40}, // 24 .. 0 3 3 6 .. -28dB -9dB 0dB -3dB .. -40dB
|
||||
{0x007F,-37}, // 25 .. 0 3 3 7 .. -28dB -9dB 0dB 0dB .. -37dB
|
||||
{0x009F,-34}, // 26 .. 0 4 3 7 .. -28dB -6dB 0dB 0dB .. -34dB
|
||||
{0x00BF,-32}, // 27 .. 0 5 3 7 .. -28dB -4dB 0dB 0dB .. -32dB
|
||||
{0x00DF,-30}, // 28 .. 0 6 3 7 .. -28dB -2dB 0dB 0dB .. -30dB
|
||||
{0x00FF,-28}, // 29 .. 0 7 3 7 .. -28dB 0dB 0dB 0dB .. -28dB
|
||||
{0x01DF,-26}, // 30 .. 1 6 3 7 .. -24dB -2dB 0dB 0dB .. -26dB
|
||||
{0x01FF,-24}, // 31 .. 1 7 3 7 .. -24dB 0dB 0dB 0dB .. -24dB
|
||||
{0x02BF,-23}, // 32 .. 2 5 3 7 .. -19dB -4dB 0dB 0dB .. -23dB
|
||||
{0x02DF,-21}, // 33 .. 2 6 3 7 .. -19dB -2dB 0dB -0dB .. -21dB
|
||||
{0x02FF,-19}, // 34 .. 2 7 3 7 .. -19dB 0dB 0dB 0dB .. -19dB
|
||||
{0x035E,-17}, // 35 .. 3 2 3 6 .. 0dB -14dB 0dB -3dB .. -17dB
|
||||
{0x035F,-14}, // 36 .. 3 2 3 7 .. 0dB -14dB 0dB 0dB .. -14dB
|
||||
{0x037E,-12}, // 37 .. 3 3 3 6 .. 0dB -9dB 0dB -3dB .. -12dB
|
||||
{0x037F,-9}, // 38 .. 3 3 3 7 .. 0dB -9dB 0dB 0dB .. -9dB
|
||||
{0x038F,-6}, // 39 .. 3 4 3 7 .. 0dB - 6dB 0dB 0dB .. -6dB
|
||||
{0x03BF,-4}, // 40 .. 3 5 3 7 .. 0dB -4dB 0dB 0dB .. -4dB
|
||||
{0x03DF,-2}, // 41 .. 3 6 3 7 .. 0dB - 2dB 0dB 0dB .. -2dB
|
||||
{0x03FF,0} // 42 .. 3 7 3 7 .. 0dB 0dB 0dB 0dB .. 0dB
|
||||
};
|
||||
|
||||
const uint8_t gain_table_size = ARRAY_SIZE(gain_table);
|
||||
#else
|
||||
|
||||
t_gain_table gain_table[100] = {{0x03BE, -7}}; //original
|
||||
uint8_t gain_table_size = 0;
|
||||
|
||||
void CreateTable()
|
||||
{
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t pgaIdx:3;
|
||||
uint8_t mixerIdx:2;
|
||||
uint8_t lnaIdx:3;
|
||||
uint8_t lnaSIdx:2;
|
||||
};
|
||||
uint16_t __raw;
|
||||
} GainData;
|
||||
|
||||
static const int8_t lna_short_dB[] = {-28, -24, -19, 0}; // corrected'ish
|
||||
static const int8_t lna_dB[] = {-24, -19, -14, -9, -6, -4, -2, 0};
|
||||
static const int8_t mixer_dB[] = { -8, -6, -3, 0};
|
||||
static const int8_t pga_dB[] = {-33, -27, -21, -15, -9, -6, -3, 0};
|
||||
|
||||
unsigned i;
|
||||
for (uint8_t lnaSIdx = 0; lnaSIdx < ARRAY_SIZE(lna_short_dB); lnaSIdx++) {
|
||||
for (uint8_t lnaIdx = 0; lnaIdx < ARRAY_SIZE(lna_dB); lnaIdx++) {
|
||||
for (uint8_t mixerIdx = 0; mixerIdx < ARRAY_SIZE(mixer_dB); mixerIdx++) {
|
||||
for (uint8_t pgaIdx = 0; pgaIdx < ARRAY_SIZE(pga_dB); pgaIdx++) {
|
||||
int16_t db = lna_short_dB[lnaSIdx] + lna_dB[lnaIdx] + mixer_dB[mixerIdx] + pga_dB[pgaIdx];
|
||||
GainData gainData = {{
|
||||
pgaIdx,
|
||||
mixerIdx,
|
||||
lnaIdx,
|
||||
lnaSIdx,
|
||||
}};
|
||||
|
||||
for (i = 1; i < ARRAY_SIZE(gain_table); i++) {
|
||||
t_gain_table * gain = &gain_table[i];
|
||||
if (db == gain->gain_dB)
|
||||
break;
|
||||
if (db > gain->gain_dB)
|
||||
continue;
|
||||
if (db < gain->gain_dB) {
|
||||
if(gain->gain_dB)
|
||||
memmove(gain + 1, gain, 100 - i);
|
||||
gain->gain_dB = db;
|
||||
gain->reg_val = gainData.__raw;
|
||||
break;
|
||||
}
|
||||
gain->gain_dB = db;
|
||||
gain->reg_val = gainData.__raw;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gain_table_size = i+1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ENABLE_AM_FIX_SHOW_DATA
|
||||
// display update rate
|
||||
static const unsigned int display_update_rate = 250 / 10; // max 250ms display update rate
|
||||
unsigned int counter = 0;
|
||||
#endif
|
||||
|
||||
unsigned int gain_table_index[2] = {0, 0};
|
||||
// used simply to detect a changed gain setting
|
||||
unsigned int gain_table_index_prev[2] = {0, 0};
|
||||
// holds the previous RSSI level .. we do an average of old + new RSSI reading
|
||||
int16_t prev_rssi[2] = {0, 0};
|
||||
// to help reduce gain hunting, peak hold count down tick
|
||||
unsigned int hold_counter[2] = {0, 0};
|
||||
// -89dBm, any higher and the AM demodulator starts to saturate/clip/distort
|
||||
const int16_t desired_rssi = (-89 + 160) * 2;
|
||||
|
||||
int8_t currentGainDiff;
|
||||
bool enabled = true;
|
||||
|
||||
void AM_fix_init(void)
|
||||
{ // called at boot-up
|
||||
for (int i = 0; i < 2; i++) {
|
||||
gain_table_index[i] = 0; // re-start with original QS setting
|
||||
}
|
||||
#if !LOOKUP_TABLE
|
||||
CreateTable();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AM_fix_reset(const unsigned vfo)
|
||||
{ // reset the AM fixer upper
|
||||
if (vfo > 1)
|
||||
return;
|
||||
|
||||
#ifdef ENABLE_AM_FIX_SHOW_DATA
|
||||
counter = 0;
|
||||
#endif
|
||||
|
||||
prev_rssi[vfo] = 0;
|
||||
hold_counter[vfo] = 0;
|
||||
gain_table_index_prev[vfo] = 0;
|
||||
}
|
||||
|
||||
// adjust the RX gain to try and prevent the AM demodulator from
|
||||
// saturating/overloading/clipping (distorted AM audio)
|
||||
//
|
||||
// we're actually doing the BK4819's job for it here, but as the chip
|
||||
// won't/don't do it for itself, we're left to bodging it ourself by
|
||||
// playing with the RF front end gain setting
|
||||
//
|
||||
void AM_fix_10ms(const unsigned vfo)
|
||||
{
|
||||
if(!gSetting_AM_fix || !enabled || vfo > 1 )
|
||||
return;
|
||||
|
||||
if (gCurrentFunction != FUNCTION_FOREGROUND && !FUNCTION_IsRx()) {
|
||||
#ifdef ENABLE_AM_FIX_SHOW_DATA
|
||||
counter = display_update_rate; // queue up a display update as soon as we switch to RX mode
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_AM_FIX_SHOW_DATA
|
||||
if (counter > 0) {
|
||||
if (++counter >= display_update_rate) { // trigger a display update
|
||||
counter = 0;
|
||||
gUpdateDisplay = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t lastFreq[2];
|
||||
if(gEeprom.VfoInfo[vfo].pRX->Frequency != lastFreq[vfo]) {
|
||||
lastFreq[vfo] = gEeprom.VfoInfo[vfo].pRX->Frequency;
|
||||
AM_fix_reset(vfo);
|
||||
}
|
||||
|
||||
int16_t rssi;
|
||||
{ // sample the current RSSI level
|
||||
// average it with the previous rssi (a bit of noise/spike immunity)
|
||||
const int16_t new_rssi = BK4819_GetRSSI();
|
||||
rssi = (prev_rssi[vfo] > 0) ? (prev_rssi[vfo] + new_rssi) / 2 : new_rssi;
|
||||
prev_rssi[vfo] = new_rssi;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_AM_FIX_SHOW_DATA
|
||||
{
|
||||
static int16_t lastRssi;
|
||||
|
||||
if (lastRssi != rssi) { // rssi changed
|
||||
lastRssi = rssi;
|
||||
|
||||
if (counter == 0) {
|
||||
counter = 1;
|
||||
gUpdateDisplay = true; // trigger a display update
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// automatically adjust the RF RX gain
|
||||
|
||||
// update the gain hold counter
|
||||
if (hold_counter[vfo] > 0)
|
||||
hold_counter[vfo]--;
|
||||
|
||||
// dB difference between actual and desired RSSI level
|
||||
int16_t diff_dB = (rssi - desired_rssi) / 2;
|
||||
|
||||
if (diff_dB > 0) { // decrease gain
|
||||
unsigned int index = gain_table_index[vfo]; // current position we're at
|
||||
|
||||
if (diff_dB >= 10) { // jump immediately to a new gain setting
|
||||
// this greatly speeds up initial gain reduction (but reduces noise/spike immunity)
|
||||
|
||||
const int16_t desired_gain_dB = (int16_t)gain_table[index].gain_dB - diff_dB + 8; // get no closer than 8dB (bit of noise/spike immunity)
|
||||
|
||||
// scan the table to see what index to jump straight too
|
||||
while (index > 1)
|
||||
if (gain_table[--index].gain_dB <= desired_gain_dB)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{ // incrementally reduce the gain .. taking it slow improves noise/spike immunity
|
||||
if (index > 1)
|
||||
index--; // slow step-by-step gain reduction
|
||||
}
|
||||
|
||||
index = MAX(1u, index);
|
||||
|
||||
if (gain_table_index[vfo] != index)
|
||||
{
|
||||
gain_table_index[vfo] = index;
|
||||
hold_counter[vfo] = 30; // 300ms hold
|
||||
}
|
||||
}
|
||||
|
||||
if (diff_dB >= -6) // 6dB hysterisis (help reduce gain hunting)
|
||||
hold_counter[vfo] = 30; // 300ms hold
|
||||
|
||||
if (hold_counter[vfo] == 0)
|
||||
{ // hold has been released, we're free to increase gain
|
||||
const unsigned int index = gain_table_index[vfo] + 1; // move up to next gain index
|
||||
gain_table_index[vfo] = MIN(index, gain_table_size - 1u);
|
||||
}
|
||||
|
||||
|
||||
{ // apply the new settings to the front end registers
|
||||
const unsigned int index = gain_table_index[vfo];
|
||||
|
||||
// remember the new table index
|
||||
gain_table_index_prev[vfo] = index;
|
||||
currentGainDiff = gain_table[0].gain_dB - gain_table[index].gain_dB;
|
||||
BK4819_WriteRegister(BK4819_REG_13, gain_table[index].reg_val);
|
||||
#ifdef ENABLE_AGC_SHOW_DATA
|
||||
UI_MAIN_PrintAGC(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ENABLE_AM_FIX_SHOW_DATA
|
||||
if (counter == 0) {
|
||||
counter = 1;
|
||||
gUpdateDisplay = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ENABLE_AM_FIX_SHOW_DATA
|
||||
void AM_fix_print_data(const unsigned vfo, char *s) {
|
||||
if (s != NULL && vfo < ARRAY_SIZE(gain_table_index)) {
|
||||
const unsigned int index = gain_table_index[vfo];
|
||||
sprintf(s, "%2u %4ddB %3u", index, gain_table[index].gain_dB, prev_rssi[vfo]);
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int8_t AM_fix_get_gain_diff()
|
||||
{
|
||||
return currentGainDiff;
|
||||
}
|
||||
|
||||
void AM_fix_enable(bool on)
|
||||
{
|
||||
enabled = on;
|
||||
}
|
||||
#endif
|
||||
35
am_fix.h
Normal file
35
am_fix.h
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
/* Copyright 2023 OneOfEleven
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AM_FIXH
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef ENABLE_AM_FIX
|
||||
void AM_fix_init(void);
|
||||
void AM_fix_reset(const unsigned vfo);
|
||||
void AM_fix_10ms(const unsigned vfo);
|
||||
#ifdef ENABLE_AM_FIX_SHOW_DATA
|
||||
void AM_fix_print_data(const unsigned vfo, char *s);
|
||||
#endif
|
||||
int8_t AM_fix_get_gain_diff();
|
||||
void AM_fix_enable(bool on);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
453
app/action.c
Normal file
453
app/action.c
Normal file
@@ -0,0 +1,453 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "app/action.h"
|
||||
#include "app/app.h"
|
||||
#include "app/chFrScanner.h"
|
||||
#include "app/common.h"
|
||||
#include "app/dtmf.h"
|
||||
#ifdef ENABLE_FLASHLIGHT
|
||||
#include "app/flashlight.h"
|
||||
#endif
|
||||
#ifdef ENABLE_FMRADIO
|
||||
#include "app/fm.h"
|
||||
#endif
|
||||
#include "app/scanner.h"
|
||||
#include "audio.h"
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#ifdef ENABLE_FMRADIO
|
||||
#include "driver/bk1080.h"
|
||||
#endif
|
||||
#include "driver/bk4819.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/backlight.h"
|
||||
#include "functions.h"
|
||||
#include "misc.h"
|
||||
#include "settings.h"
|
||||
#include "ui/inputbox.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
#if defined(ENABLE_FMRADIO)
|
||||
static void ACTION_Scan_FM(bool bRestart);
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
|
||||
static void ACTION_AlarmOr1750(bool b1750);
|
||||
inline static void ACTION_Alarm() { ACTION_AlarmOr1750(false); }
|
||||
inline static void ACTION_1750() { ACTION_AlarmOr1750(true); };
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SPECTRUM
|
||||
#include "app/spectrum.h"
|
||||
#endif
|
||||
|
||||
inline static void ACTION_ScanRestart() { ACTION_Scan(true); };
|
||||
|
||||
void (*action_opt_table[])(void) = {
|
||||
[ACTION_OPT_NONE] = &FUNCTION_NOP,
|
||||
[ACTION_OPT_POWER] = &ACTION_Power,
|
||||
[ACTION_OPT_MONITOR] = &ACTION_Monitor,
|
||||
[ACTION_OPT_SCAN] = &ACTION_ScanRestart,
|
||||
[ACTION_OPT_KEYLOCK] = &COMMON_KeypadLockToggle,
|
||||
[ACTION_OPT_A_B] = &COMMON_SwitchVFOs,
|
||||
[ACTION_OPT_VFO_MR] = &COMMON_SwitchVFOMode,
|
||||
[ACTION_OPT_SWITCH_DEMODUL] = &ACTION_SwitchDemodul,
|
||||
|
||||
#ifdef ENABLE_FLASHLIGHT
|
||||
[ACTION_OPT_FLASHLIGHT] = &ACTION_FlashLight,
|
||||
#else
|
||||
[ACTION_OPT_FLASHLIGHT] = &FUNCTION_NOP,
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_VOX
|
||||
[ACTION_OPT_VOX] = &ACTION_Vox,
|
||||
#else
|
||||
[ACTION_OPT_VOX] = &FUNCTION_NOP,
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
[ACTION_OPT_FM] = &ACTION_FM,
|
||||
#else
|
||||
[ACTION_OPT_FM] = &FUNCTION_NOP,
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_ALARM
|
||||
[ACTION_OPT_ALARM] = &ACTION_Alarm,
|
||||
#else
|
||||
[ACTION_OPT_ALARM] = &FUNCTION_NOP,
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_TX1750
|
||||
[ACTION_OPT_1750] = &ACTION_1750,
|
||||
#else
|
||||
[ACTION_OPT_1750] = &FUNCTION_NOP,
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_BLMIN_TMP_OFF
|
||||
[ACTION_OPT_BLMIN_TMP_OFF] = &ACTION_BlminTmpOff,
|
||||
#else
|
||||
[ACTION_OPT_BLMIN_TMP_OFF] = &FUNCTION_NOP,
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SPECTRUM
|
||||
[ACTION_OPT_SPECTRUM] = &APP_RunSpectrum,
|
||||
#else
|
||||
[ACTION_OPT_SPECTRUM] = &FUNCTION_NOP,
|
||||
#endif
|
||||
};
|
||||
|
||||
static_assert(ARRAY_SIZE(action_opt_table) == ACTION_OPT_LEN);
|
||||
|
||||
void ACTION_Power(void)
|
||||
{
|
||||
if (++gTxVfo->OUTPUT_POWER > OUTPUT_POWER_HIGH)
|
||||
gTxVfo->OUTPUT_POWER = OUTPUT_POWER_LOW;
|
||||
|
||||
gRequestSaveChannel = 1;
|
||||
|
||||
gRequestDisplayScreen = gScreenToDisplay;
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_POWER;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void ACTION_Monitor(void)
|
||||
{
|
||||
if (gCurrentFunction != FUNCTION_MONITOR) { // enable the monitor
|
||||
RADIO_SelectVfos();
|
||||
#ifdef ENABLE_NOAA
|
||||
if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gIsNoaaMode)
|
||||
gNoaaChannel = gRxVfo->CHANNEL_SAVE - NOAA_CHANNEL_FIRST;
|
||||
#endif
|
||||
RADIO_SetupRegisters(true);
|
||||
APP_StartListening(FUNCTION_MONITOR);
|
||||
return;
|
||||
}
|
||||
|
||||
gMonitor = false;
|
||||
|
||||
if (gScanStateDir != SCAN_OFF) {
|
||||
gScanPauseDelayIn_10ms = scan_pause_delay_in_1_10ms;
|
||||
gScheduleScanListen = false;
|
||||
gScanPauseMode = true;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_NOAA
|
||||
if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF && gIsNoaaMode) {
|
||||
gNOAA_Countdown_10ms = NOAA_countdown_10ms;
|
||||
gScheduleNOAA = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
RADIO_SetupRegisters(true);
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (gFmRadioMode) {
|
||||
FM_Start();
|
||||
gRequestDisplayScreen = DISPLAY_FM;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
gRequestDisplayScreen = gScreenToDisplay;
|
||||
}
|
||||
|
||||
void ACTION_Scan(bool bRestart)
|
||||
{
|
||||
(void)bRestart;
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (gFmRadioMode) {
|
||||
ACTION_Scan_FM(bRestart);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SCANNER_IsScanning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// not scanning
|
||||
gMonitor = false;
|
||||
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
DTMF_clear_RX();
|
||||
#endif
|
||||
gDTMF_RX_live_timeout = 0;
|
||||
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
|
||||
|
||||
RADIO_SelectVfos();
|
||||
|
||||
#ifdef ENABLE_NOAA
|
||||
if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE)) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
GUI_SelectNextDisplay(DISPLAY_MAIN);
|
||||
|
||||
if (gScanStateDir != SCAN_OFF) {
|
||||
// already scanning
|
||||
|
||||
if (!IS_MR_CHANNEL(gNextMrChannel)) {
|
||||
CHFRSCANNER_Stop();
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// channel mode. Keep scanning but toggle between scan lists
|
||||
gEeprom.SCAN_LIST_DEFAULT = (gEeprom.SCAN_LIST_DEFAULT + 1) % 3;
|
||||
|
||||
// jump to the next channel
|
||||
CHFRSCANNER_Start(false, gScanStateDir);
|
||||
gScanPauseDelayIn_10ms = 1;
|
||||
gScheduleScanListen = false;
|
||||
} else {
|
||||
// start scanning
|
||||
CHFRSCANNER_Start(true, SCAN_FWD);
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
AUDIO_SetVoiceID(0, VOICE_ID_SCANNING_BEGIN);
|
||||
AUDIO_PlaySingleVoice(true);
|
||||
#endif
|
||||
|
||||
// clear the other vfo's rssi level (to hide the antenna symbol)
|
||||
gVFO_RSSI_bar_level[(gEeprom.RX_VFO + 1) & 1U] = 0;
|
||||
|
||||
// let the user see DW is not active
|
||||
gDualWatchActive = false;
|
||||
}
|
||||
|
||||
gUpdateStatus = true;
|
||||
}
|
||||
|
||||
|
||||
void ACTION_SwitchDemodul(void)
|
||||
{
|
||||
gRequestSaveChannel = 1;
|
||||
|
||||
gTxVfo->Modulation++;
|
||||
|
||||
if(gTxVfo->Modulation == MODULATION_UKNOWN)
|
||||
gTxVfo->Modulation = MODULATION_FM;
|
||||
}
|
||||
|
||||
|
||||
void ACTION_Handle(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
if (gScreenToDisplay == DISPLAY_MAIN && gDTMF_InputMode){
|
||||
// entering DTMF code
|
||||
|
||||
gPttWasReleased = true;
|
||||
|
||||
if (Key != KEY_SIDE1 || bKeyHeld || !bKeyPressed){
|
||||
return;
|
||||
}
|
||||
|
||||
// side1 btn pressed
|
||||
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
|
||||
if (gDTMF_InputBox_Index <= 0) {
|
||||
// turn off DTMF input box if no codes left
|
||||
gDTMF_InputMode = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// DTMF codes are in the input box
|
||||
gDTMF_InputBox[--gDTMF_InputBox_Index] = '-'; // delete one code
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_CANCEL;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
enum ACTION_OPT_t funcShort = ACTION_OPT_NONE;
|
||||
enum ACTION_OPT_t funcLong = ACTION_OPT_NONE;
|
||||
switch(Key) {
|
||||
case KEY_SIDE1:
|
||||
funcShort = gEeprom.KEY_1_SHORT_PRESS_ACTION;
|
||||
funcLong = gEeprom.KEY_1_LONG_PRESS_ACTION;
|
||||
break;
|
||||
case KEY_SIDE2:
|
||||
funcShort = gEeprom.KEY_2_SHORT_PRESS_ACTION;
|
||||
funcLong = gEeprom.KEY_2_LONG_PRESS_ACTION;
|
||||
break;
|
||||
case KEY_MENU:
|
||||
funcLong = gEeprom.KEY_M_LONG_PRESS_ACTION;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!bKeyHeld && bKeyPressed) // button pushed
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// held or released beyond this point
|
||||
|
||||
if(!(bKeyHeld && !bKeyPressed)) // don't beep on released after hold
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
|
||||
if (bKeyHeld || bKeyPressed) // held
|
||||
{
|
||||
funcShort = funcLong;
|
||||
|
||||
if (!bKeyPressed) //ignore release if held
|
||||
return;
|
||||
}
|
||||
|
||||
// held or released after short press beyond this point
|
||||
|
||||
action_opt_table[funcShort]();
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
void ACTION_FM(void)
|
||||
{
|
||||
if (gCurrentFunction != FUNCTION_TRANSMIT && gCurrentFunction != FUNCTION_MONITOR)
|
||||
{
|
||||
gInputBoxIndex = 0;
|
||||
|
||||
if (gFmRadioMode) {
|
||||
FM_TurnOff();
|
||||
gFlagReconfigureVfos = true;
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
|
||||
#ifdef ENABLE_VOX
|
||||
gVoxResumeCountdown = 80;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
gMonitor = false;
|
||||
|
||||
RADIO_SelectVfos();
|
||||
RADIO_SetupRegisters(true);
|
||||
|
||||
FM_Start();
|
||||
|
||||
gRequestDisplayScreen = DISPLAY_FM;
|
||||
}
|
||||
}
|
||||
|
||||
static void ACTION_Scan_FM(bool bRestart)
|
||||
{
|
||||
if (FUNCTION_IsRx())
|
||||
return;
|
||||
|
||||
GUI_SelectNextDisplay(DISPLAY_FM);
|
||||
|
||||
gMonitor = false;
|
||||
|
||||
if (gFM_ScanState != FM_SCAN_OFF) {
|
||||
FM_PlayAndUpdate();
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t freq;
|
||||
|
||||
if (bRestart) {
|
||||
gFM_AutoScan = true;
|
||||
gFM_ChannelPosition = 0;
|
||||
FM_EraseChannels();
|
||||
freq = BK1080_GetFreqLoLimit(gEeprom.FM_Band);
|
||||
} else {
|
||||
gFM_AutoScan = false;
|
||||
gFM_ChannelPosition = 0;
|
||||
freq = gEeprom.FM_FrequencyPlaying;
|
||||
}
|
||||
|
||||
BK1080_GetFrequencyDeviation(freq);
|
||||
FM_Tune(freq, 1, bRestart);
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_SCANNING_BEGIN;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
|
||||
static void ACTION_AlarmOr1750(const bool b1750)
|
||||
{
|
||||
|
||||
#if defined(ENABLE_ALARM)
|
||||
const AlarmState_t alarm_mode = (gEeprom.ALARM_MODE == ALARM_MODE_TONE) ? ALARM_STATE_TXALARM : ALARM_STATE_SITE_ALARM;
|
||||
gAlarmRunningCounter = 0;
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_ALARM) && defined(ENABLE_TX1750)
|
||||
gAlarmState = b1750 ? ALARM_STATE_TX1750 : alarm_mode;
|
||||
#elif defined(ENABLE_ALARM)
|
||||
gAlarmState = alarm_mode;
|
||||
#else
|
||||
gAlarmState = ALARM_STATE_TX1750;
|
||||
#endif
|
||||
|
||||
(void)b1750;
|
||||
gInputBoxIndex = 0;
|
||||
|
||||
gFlagPrepareTX = gAlarmState != ALARM_STATE_OFF;
|
||||
|
||||
if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_VOX
|
||||
void ACTION_Vox(void)
|
||||
{
|
||||
gEeprom.VOX_SWITCH = !gEeprom.VOX_SWITCH;
|
||||
gRequestSaveSettings = true;
|
||||
gFlagReconfigureVfos = true;
|
||||
gUpdateStatus = true;
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_VOX;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_BLMIN_TMP_OFF
|
||||
void ACTION_BlminTmpOff(void)
|
||||
{
|
||||
if(++gEeprom.BACKLIGHT_MIN_STAT == BLMIN_STAT_UNKNOWN) {
|
||||
gEeprom.BACKLIGHT_MIN_STAT = BLMIN_STAT_ON;
|
||||
BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MIN);
|
||||
} else {
|
||||
BACKLIGHT_SetBrightness(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
40
app/action.h
Normal file
40
app/action.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APP_ACTION_H
|
||||
#define APP_ACTION_H
|
||||
|
||||
#include "driver/keyboard.h"
|
||||
|
||||
void ACTION_Power(void);
|
||||
void ACTION_Monitor(void);
|
||||
void ACTION_Scan(bool bRestart);
|
||||
#ifdef ENABLE_VOX
|
||||
void ACTION_Vox(void);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
void ACTION_FM(void);
|
||||
#endif
|
||||
void ACTION_SwitchDemodul(void);
|
||||
|
||||
#ifdef ENABLE_BLMIN_TMP_OFF
|
||||
void ACTION_BlminTmpOff(void);
|
||||
#endif
|
||||
|
||||
void ACTION_Handle(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);
|
||||
|
||||
#endif
|
||||
242
app/aircopy.c
Normal file
242
app/aircopy.c
Normal file
@@ -0,0 +1,242 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_AIRCOPY
|
||||
|
||||
#include "app/aircopy.h"
|
||||
#include "audio.h"
|
||||
#include "driver/bk4819.h"
|
||||
#include "driver/crc.h"
|
||||
#include "driver/eeprom.h"
|
||||
#include "frequencies.h"
|
||||
#include "misc.h"
|
||||
#include "radio.h"
|
||||
#include "ui/helper.h"
|
||||
#include "ui/inputbox.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
static const uint16_t Obfuscation[8] = { 0x6C16, 0xE614, 0x912E, 0x400D, 0x3521, 0x40D5, 0x0313, 0x80E9 };
|
||||
|
||||
AIRCOPY_State_t gAircopyState;
|
||||
uint16_t gAirCopyBlockNumber;
|
||||
uint16_t gErrorsDuringAirCopy;
|
||||
uint8_t gAirCopyIsSendMode;
|
||||
|
||||
uint16_t g_FSK_Buffer[36];
|
||||
|
||||
bool AIRCOPY_SendMessage(void)
|
||||
{
|
||||
static uint8_t gAircopySendCountdown = 1;
|
||||
|
||||
if (gAircopyState != AIRCOPY_TRANSFER) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (--gAircopySendCountdown) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_FSK_Buffer[1] = (gAirCopyBlockNumber & 0x3FF) << 6;
|
||||
|
||||
EEPROM_ReadBuffer(g_FSK_Buffer[1], &g_FSK_Buffer[2], 64);
|
||||
|
||||
g_FSK_Buffer[34] = CRC_Calculate(&g_FSK_Buffer[1], 2 + 64);
|
||||
|
||||
for (unsigned int i = 0; i < 34; i++) {
|
||||
g_FSK_Buffer[i + 1] ^= Obfuscation[i % 8];
|
||||
}
|
||||
|
||||
if (++gAirCopyBlockNumber >= 0x78) {
|
||||
gAircopyState = AIRCOPY_COMPLETE;
|
||||
}
|
||||
|
||||
RADIO_SetTxParameters();
|
||||
|
||||
BK4819_SendFSKData(g_FSK_Buffer);
|
||||
BK4819_SetupPowerAmplifier(0, 0);
|
||||
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_PA_ENABLE, false);
|
||||
|
||||
gAircopySendCountdown = 30;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AIRCOPY_StorePacket(void)
|
||||
{
|
||||
if (gFSKWriteIndex < 36) {
|
||||
return;
|
||||
}
|
||||
|
||||
gFSKWriteIndex = 0;
|
||||
gUpdateDisplay = true;
|
||||
uint16_t Status = BK4819_ReadRegister(BK4819_REG_0B);
|
||||
BK4819_PrepareFSKReceive();
|
||||
|
||||
// Doc says bit 4 should be 1 = CRC OK, 0 = CRC FAIL, but original firmware checks for FAIL.
|
||||
|
||||
if ((Status & 0x0010U) != 0 || g_FSK_Buffer[0] != 0xABCD || g_FSK_Buffer[35] != 0xDCBA) {
|
||||
gErrorsDuringAirCopy++;
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < 34; i++) {
|
||||
g_FSK_Buffer[i + 1] ^= Obfuscation[i % 8];
|
||||
}
|
||||
|
||||
uint16_t CRC = CRC_Calculate(&g_FSK_Buffer[1], 2 + 64);
|
||||
if (g_FSK_Buffer[34] != CRC) {
|
||||
gErrorsDuringAirCopy++;
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t Offset = g_FSK_Buffer[1];
|
||||
|
||||
if (Offset >= 0x1E00) {
|
||||
gErrorsDuringAirCopy++;
|
||||
return;
|
||||
}
|
||||
|
||||
const uint16_t *pData = &g_FSK_Buffer[2];
|
||||
for (unsigned int i = 0; i < 8; i++) {
|
||||
EEPROM_WriteBuffer(Offset, pData);
|
||||
pData += 4;
|
||||
Offset += 8;
|
||||
}
|
||||
|
||||
if (Offset == 0x1E00) {
|
||||
gAircopyState = AIRCOPY_COMPLETE;
|
||||
}
|
||||
|
||||
gAirCopyBlockNumber++;
|
||||
}
|
||||
|
||||
static void AIRCOPY_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
if (bKeyHeld || !bKeyPressed) {
|
||||
return;
|
||||
}
|
||||
|
||||
INPUTBOX_Append(Key);
|
||||
|
||||
gRequestDisplayScreen = DISPLAY_AIRCOPY;
|
||||
|
||||
if (gInputBoxIndex < 6) {
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
gInputBoxIndex = 0;
|
||||
uint32_t Frequency = StrToUL(INPUTBOX_GetAscii()) * 100;
|
||||
|
||||
for (unsigned int i = 0; i < BAND_N_ELEM; i++) {
|
||||
if (Frequency < frequencyBandTable[i].lower || Frequency >= frequencyBandTable[i].upper) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TX_freq_check(Frequency)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||||
#endif
|
||||
|
||||
Frequency = FREQUENCY_RoundToStep(Frequency, gRxVfo->StepFrequency);
|
||||
gRxVfo->Band = i;
|
||||
gRxVfo->freq_config_RX.Frequency = Frequency;
|
||||
gRxVfo->freq_config_TX.Frequency = Frequency;
|
||||
RADIO_ConfigureSquelchAndOutputPower(gRxVfo);
|
||||
gCurrentVfo = gRxVfo;
|
||||
RADIO_SetupRegisters(true);
|
||||
BK4819_SetupAircopy();
|
||||
BK4819_ResetFSK();
|
||||
return;
|
||||
}
|
||||
|
||||
gRequestDisplayScreen = DISPLAY_AIRCOPY;
|
||||
}
|
||||
|
||||
static void AIRCOPY_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
if (bKeyHeld || !bKeyPressed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gInputBoxIndex == 0) {
|
||||
gFSKWriteIndex = 0;
|
||||
gAirCopyBlockNumber = 0;
|
||||
gInputBoxIndex = 0;
|
||||
gErrorsDuringAirCopy = 0;
|
||||
gAirCopyIsSendMode = 0;
|
||||
|
||||
BK4819_PrepareFSKReceive();
|
||||
|
||||
gAircopyState = AIRCOPY_TRANSFER;
|
||||
} else {
|
||||
gInputBox[--gInputBoxIndex] = 10;
|
||||
}
|
||||
|
||||
gRequestDisplayScreen = DISPLAY_AIRCOPY;
|
||||
}
|
||||
|
||||
static void AIRCOPY_Key_MENU(bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
if (bKeyHeld || !bKeyPressed) {
|
||||
return;
|
||||
}
|
||||
|
||||
gFSKWriteIndex = 0;
|
||||
gAirCopyBlockNumber = 0;
|
||||
gInputBoxIndex = 0;
|
||||
gAirCopyIsSendMode = 1;
|
||||
g_FSK_Buffer[0] = 0xABCD;
|
||||
g_FSK_Buffer[1] = 0;
|
||||
g_FSK_Buffer[35] = 0xDCBA;
|
||||
|
||||
GUI_DisplayScreen();
|
||||
|
||||
gAircopyState = AIRCOPY_TRANSFER;
|
||||
}
|
||||
|
||||
void AIRCOPY_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
switch (Key) {
|
||||
case KEY_0:
|
||||
case KEY_1:
|
||||
case KEY_2:
|
||||
case KEY_3:
|
||||
case KEY_4:
|
||||
case KEY_5:
|
||||
case KEY_6:
|
||||
case KEY_7:
|
||||
case KEY_8:
|
||||
case KEY_9:
|
||||
AIRCOPY_Key_DIGITS(Key, bKeyPressed, bKeyHeld);
|
||||
break;
|
||||
case KEY_MENU:
|
||||
AIRCOPY_Key_MENU(bKeyPressed, bKeyHeld);
|
||||
break;
|
||||
case KEY_EXIT:
|
||||
AIRCOPY_Key_EXIT(bKeyPressed, bKeyHeld);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
46
app/aircopy.h
Normal file
46
app/aircopy.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APP_AIRCOPY_H
|
||||
#define APP_AIRCOPY_H
|
||||
|
||||
#ifdef ENABLE_AIRCOPY
|
||||
|
||||
#include "driver/keyboard.h"
|
||||
|
||||
enum AIRCOPY_State_t
|
||||
{
|
||||
AIRCOPY_READY = 0,
|
||||
AIRCOPY_TRANSFER,
|
||||
AIRCOPY_COMPLETE
|
||||
};
|
||||
|
||||
typedef enum AIRCOPY_State_t AIRCOPY_State_t;
|
||||
|
||||
extern AIRCOPY_State_t gAircopyState;
|
||||
extern uint16_t gAirCopyBlockNumber;
|
||||
extern uint16_t gErrorsDuringAirCopy;
|
||||
extern uint8_t gAirCopyIsSendMode;
|
||||
|
||||
extern uint16_t g_FSK_Buffer[36];
|
||||
|
||||
bool AIRCOPY_SendMessage(void);
|
||||
void AIRCOPY_StorePacket(void);
|
||||
void AIRCOPY_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
35
app/app.h
Normal file
35
app/app.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APP_APP_H
|
||||
#define APP_APP_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "functions.h"
|
||||
#include "frequencies.h"
|
||||
#include "radio.h"
|
||||
|
||||
void APP_EndTransmission(void);
|
||||
void APP_StartListening(FUNCTION_Type_t function);
|
||||
uint32_t APP_SetFreqByStepAndLimits(VFO_Info_t *pInfo, int8_t direction, uint32_t lower, uint32_t upper);
|
||||
uint32_t APP_SetFrequencyByStep(VFO_Info_t *pInfo, int8_t direction);
|
||||
void APP_Update(void);
|
||||
void APP_TimeSlice10ms(void);
|
||||
void APP_TimeSlice500ms(void);
|
||||
|
||||
#endif
|
||||
|
||||
53
app/boot_splash.c
Normal file
53
app/boot_splash.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/* UA1ZBE Custom Firmware - Boot Splash Screen
|
||||
* Displays:
|
||||
* Line 1 (top, large): UA1ZBE
|
||||
* Line 2 (center): POCSAG pager
|
||||
* Line 3 (bottom): YYYY-MM-DD (build date)
|
||||
* Then fades to VFO mode after 2 seconds.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "driver/st7565.h"
|
||||
#include "driver/system.h"
|
||||
#include "ui/helper.h"
|
||||
#include "font.h"
|
||||
|
||||
#ifndef BUILD_DATE
|
||||
#define BUILD_DATE "unknown"
|
||||
#endif
|
||||
|
||||
void BOOT_SplashShow(void)
|
||||
{
|
||||
/* Clear screen */
|
||||
ST7565_FillScreen(0x00);
|
||||
memset(gStatusLine, 0, sizeof(gStatusLine));
|
||||
for (int line = 0; line < FRAME_LINES; line++)
|
||||
memset(gFrameBuffer[line], 0, LCD_WIDTH);
|
||||
|
||||
/* Line 1: UA1ZBE — large font, centered, top */
|
||||
UI_PrintString("UA1ZBE", 0, LCD_WIDTH, 0, 12);
|
||||
|
||||
/* Line 2: "POCSAG pager" — small font, centered */
|
||||
/* Small font is 6 pixels tall, at y-offset line 3 (~24px) */
|
||||
const char *line2 = "POCSAG pager";
|
||||
int len2 = 0;
|
||||
while (line2[len2]) len2++;
|
||||
int x2 = (LCD_WIDTH - len2 * 6) / 2;
|
||||
if (x2 < 0) x2 = 0;
|
||||
UI_PrintStringSmallNormal(line2, x2, LCD_WIDTH, 24);
|
||||
|
||||
/* Line 3: BUILD_DATE — small font, centered, bottom */
|
||||
const char *date_str = BUILD_DATE;
|
||||
int len3 = 0;
|
||||
while (date_str[len3]) len3++;
|
||||
int x3 = (LCD_WIDTH - len3 * 6) / 2;
|
||||
if (x3 < 0) x3 = 0;
|
||||
UI_PrintStringSmallNormal(date_str, x3, LCD_WIDTH, 48);
|
||||
|
||||
/* Blit to screen */
|
||||
ST7565_BlitStatusLine();
|
||||
ST7565_BlitFullScreen();
|
||||
|
||||
/* Hold for 2 seconds */
|
||||
SYSTEM_DelayMs(2000);
|
||||
}
|
||||
7
app/boot_splash.h
Normal file
7
app/boot_splash.h
Normal file
@@ -0,0 +1,7 @@
|
||||
/* UA1ZBE Custom Firmware - Boot Splash Screen */
|
||||
#ifndef APP_BOOT_SPLASH_H
|
||||
#define APP_BOOT_SPLASH_H
|
||||
|
||||
void BOOT_SplashShow(void);
|
||||
|
||||
#endif
|
||||
273
app/chFrScanner.c
Normal file
273
app/chFrScanner.c
Normal file
@@ -0,0 +1,273 @@
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/chFrScanner.h"
|
||||
#include "functions.h"
|
||||
#include "misc.h"
|
||||
#include "settings.h"
|
||||
|
||||
int8_t gScanStateDir;
|
||||
bool gScanKeepResult;
|
||||
bool gScanPauseMode;
|
||||
|
||||
#ifdef ENABLE_SCAN_RANGES
|
||||
uint32_t gScanRangeStart;
|
||||
uint32_t gScanRangeStop;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
SCAN_NEXT_CHAN_SCANLIST1 = 0,
|
||||
SCAN_NEXT_CHAN_SCANLIST2,
|
||||
SCAN_NEXT_CHAN_DUAL_WATCH,
|
||||
SCAN_NEXT_CHAN_MR,
|
||||
SCAN_NEXT_NUM
|
||||
} scan_next_chan_t;
|
||||
|
||||
scan_next_chan_t currentScanList;
|
||||
uint32_t initialFrqOrChan;
|
||||
uint8_t initialCROSS_BAND_RX_TX;
|
||||
uint32_t lastFoundFrqOrChan;
|
||||
|
||||
static void NextFreqChannel(void);
|
||||
static void NextMemChannel(void);
|
||||
|
||||
void CHFRSCANNER_Start(const bool storeBackupSettings, const int8_t scan_direction)
|
||||
{
|
||||
if (storeBackupSettings) {
|
||||
initialCROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX;
|
||||
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
|
||||
gScanKeepResult = false;
|
||||
}
|
||||
|
||||
RADIO_SelectVfos();
|
||||
|
||||
gNextMrChannel = gRxVfo->CHANNEL_SAVE;
|
||||
currentScanList = SCAN_NEXT_CHAN_SCANLIST1;
|
||||
gScanStateDir = scan_direction;
|
||||
|
||||
if (IS_MR_CHANNEL(gNextMrChannel))
|
||||
{ // channel mode
|
||||
if (storeBackupSettings) {
|
||||
initialFrqOrChan = gRxVfo->CHANNEL_SAVE;
|
||||
lastFoundFrqOrChan = initialFrqOrChan;
|
||||
}
|
||||
NextMemChannel();
|
||||
}
|
||||
else
|
||||
{ // frequency mode
|
||||
if (storeBackupSettings) {
|
||||
initialFrqOrChan = gRxVfo->freq_config_RX.Frequency;
|
||||
lastFoundFrqOrChan = initialFrqOrChan;
|
||||
}
|
||||
NextFreqChannel();
|
||||
}
|
||||
|
||||
gScanPauseDelayIn_10ms = scan_pause_delay_in_2_10ms;
|
||||
gScheduleScanListen = false;
|
||||
gRxReceptionMode = RX_MODE_NONE;
|
||||
gScanPauseMode = false;
|
||||
}
|
||||
|
||||
void CHFRSCANNER_ContinueScanning(void)
|
||||
{
|
||||
if (IS_FREQ_CHANNEL(gNextMrChannel))
|
||||
{
|
||||
if (gCurrentFunction == FUNCTION_INCOMING)
|
||||
APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE);
|
||||
else
|
||||
NextFreqChannel(); // switch to next frequency
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gCurrentCodeType == CODE_TYPE_OFF && gCurrentFunction == FUNCTION_INCOMING)
|
||||
APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE);
|
||||
else
|
||||
NextMemChannel(); // switch to next channel
|
||||
}
|
||||
|
||||
gScanPauseMode = false;
|
||||
gRxReceptionMode = RX_MODE_NONE;
|
||||
gScheduleScanListen = false;
|
||||
}
|
||||
|
||||
void CHFRSCANNER_Found(void)
|
||||
{
|
||||
switch (gEeprom.SCAN_RESUME_MODE)
|
||||
{
|
||||
case SCAN_RESUME_TO:
|
||||
if (!gScanPauseMode)
|
||||
{
|
||||
gScanPauseDelayIn_10ms = scan_pause_delay_in_1_10ms;
|
||||
gScheduleScanListen = false;
|
||||
gScanPauseMode = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCAN_RESUME_CO:
|
||||
case SCAN_RESUME_SE:
|
||||
gScanPauseDelayIn_10ms = 0;
|
||||
gScheduleScanListen = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_MR_CHANNEL(gRxVfo->CHANNEL_SAVE)) { //memory scan
|
||||
lastFoundFrqOrChan = gRxVfo->CHANNEL_SAVE;
|
||||
}
|
||||
else { // frequency scan
|
||||
lastFoundFrqOrChan = gRxVfo->freq_config_RX.Frequency;
|
||||
}
|
||||
|
||||
|
||||
gScanKeepResult = true;
|
||||
}
|
||||
|
||||
void CHFRSCANNER_Stop(void)
|
||||
{
|
||||
if(initialCROSS_BAND_RX_TX != CROSS_BAND_OFF) {
|
||||
gEeprom.CROSS_BAND_RX_TX = initialCROSS_BAND_RX_TX;
|
||||
initialCROSS_BAND_RX_TX = CROSS_BAND_OFF;
|
||||
}
|
||||
|
||||
gScanStateDir = SCAN_OFF;
|
||||
|
||||
const uint32_t chFr = gScanKeepResult ? lastFoundFrqOrChan : initialFrqOrChan;
|
||||
const bool channelChanged = chFr != initialFrqOrChan;
|
||||
if (IS_MR_CHANNEL(gNextMrChannel)) {
|
||||
gEeprom.MrChannel[gEeprom.RX_VFO] = chFr;
|
||||
gEeprom.ScreenChannel[gEeprom.RX_VFO] = chFr;
|
||||
RADIO_ConfigureChannel(gEeprom.RX_VFO, VFO_CONFIGURE_RELOAD);
|
||||
|
||||
if(channelChanged) {
|
||||
SETTINGS_SaveVfoIndices();
|
||||
gUpdateStatus = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
gRxVfo->freq_config_RX.Frequency = chFr;
|
||||
RADIO_ApplyOffset(gRxVfo);
|
||||
RADIO_ConfigureSquelchAndOutputPower(gRxVfo);
|
||||
if(channelChanged) {
|
||||
SETTINGS_SaveChannel(gRxVfo->CHANNEL_SAVE, gEeprom.RX_VFO, gRxVfo, 1);
|
||||
}
|
||||
}
|
||||
|
||||
RADIO_SetupRegisters(true);
|
||||
gUpdateDisplay = true;
|
||||
}
|
||||
|
||||
static void NextFreqChannel(void)
|
||||
{
|
||||
#ifdef ENABLE_SCAN_RANGES
|
||||
if(gScanRangeStart) {
|
||||
gRxVfo->freq_config_RX.Frequency = APP_SetFreqByStepAndLimits(gRxVfo, gScanStateDir, gScanRangeStart, gScanRangeStop);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
gRxVfo->freq_config_RX.Frequency = APP_SetFrequencyByStep(gRxVfo, gScanStateDir);
|
||||
|
||||
RADIO_ApplyOffset(gRxVfo);
|
||||
RADIO_ConfigureSquelchAndOutputPower(gRxVfo);
|
||||
RADIO_SetupRegisters(true);
|
||||
|
||||
#ifdef ENABLE_FASTER_CHANNEL_SCAN
|
||||
gScanPauseDelayIn_10ms = 9; // 90ms
|
||||
#else
|
||||
gScanPauseDelayIn_10ms = scan_pause_delay_in_6_10ms;
|
||||
#endif
|
||||
|
||||
gUpdateDisplay = true;
|
||||
}
|
||||
|
||||
static void NextMemChannel(void)
|
||||
{
|
||||
static unsigned int prev_mr_chan = 0;
|
||||
const bool enabled = (gEeprom.SCAN_LIST_DEFAULT < 2) ? gEeprom.SCAN_LIST_ENABLED[gEeprom.SCAN_LIST_DEFAULT] : true;
|
||||
const int chan1 = (gEeprom.SCAN_LIST_DEFAULT < 2) ? gEeprom.SCANLIST_PRIORITY_CH1[gEeprom.SCAN_LIST_DEFAULT] : -1;
|
||||
const int chan2 = (gEeprom.SCAN_LIST_DEFAULT < 2) ? gEeprom.SCANLIST_PRIORITY_CH2[gEeprom.SCAN_LIST_DEFAULT] : -1;
|
||||
const unsigned int prev_chan = gNextMrChannel;
|
||||
unsigned int chan = 0;
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
switch (currentScanList)
|
||||
{
|
||||
case SCAN_NEXT_CHAN_SCANLIST1:
|
||||
prev_mr_chan = gNextMrChannel;
|
||||
|
||||
if (chan1 >= 0)
|
||||
{
|
||||
if (RADIO_CheckValidChannel(chan1, false, 0))
|
||||
{
|
||||
currentScanList = SCAN_NEXT_CHAN_SCANLIST1;
|
||||
gNextMrChannel = chan1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
__attribute__((fallthrough));
|
||||
case SCAN_NEXT_CHAN_SCANLIST2:
|
||||
if (chan2 >= 0)
|
||||
{
|
||||
if (RADIO_CheckValidChannel(chan2, false, 0))
|
||||
{
|
||||
currentScanList = SCAN_NEXT_CHAN_SCANLIST2;
|
||||
gNextMrChannel = chan2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
__attribute__((fallthrough));
|
||||
|
||||
// this bit doesn't yet work if the other VFO is a frequency
|
||||
case SCAN_NEXT_CHAN_DUAL_WATCH:
|
||||
// dual watch is enabled - include the other VFO in the scan
|
||||
// if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF)
|
||||
// {
|
||||
// chan = (gEeprom.RX_VFO + 1) & 1u;
|
||||
// chan = gEeprom.ScreenChannel[chan];
|
||||
// if (IS_MR_CHANNEL(chan))
|
||||
// {
|
||||
// currentScanList = SCAN_NEXT_CHAN_DUAL_WATCH;
|
||||
// gNextMrChannel = chan;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
default:
|
||||
case SCAN_NEXT_CHAN_MR:
|
||||
currentScanList = SCAN_NEXT_CHAN_MR;
|
||||
gNextMrChannel = prev_mr_chan;
|
||||
chan = 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!enabled || chan == 0xff)
|
||||
{
|
||||
chan = RADIO_FindNextChannel(gNextMrChannel + gScanStateDir, gScanStateDir, (gEeprom.SCAN_LIST_DEFAULT < 2) ? true : false, gEeprom.SCAN_LIST_DEFAULT);
|
||||
if (chan == 0xFF)
|
||||
{ // no valid channel found
|
||||
chan = MR_CHANNEL_FIRST;
|
||||
}
|
||||
|
||||
gNextMrChannel = chan;
|
||||
}
|
||||
|
||||
if (gNextMrChannel != prev_chan)
|
||||
{
|
||||
gEeprom.MrChannel[ gEeprom.RX_VFO] = gNextMrChannel;
|
||||
gEeprom.ScreenChannel[gEeprom.RX_VFO] = gNextMrChannel;
|
||||
|
||||
RADIO_ConfigureChannel(gEeprom.RX_VFO, VFO_CONFIGURE_RELOAD);
|
||||
RADIO_SetupRegisters(true);
|
||||
|
||||
gUpdateDisplay = true;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_FASTER_CHANNEL_SCAN
|
||||
gScanPauseDelayIn_10ms = 9; // 90ms .. <= ~60ms it misses signals (squelch response and/or PLL lock time) ?
|
||||
#else
|
||||
gScanPauseDelayIn_10ms = scan_pause_delay_in_3_10ms;
|
||||
#endif
|
||||
|
||||
if (enabled)
|
||||
if (++currentScanList >= SCAN_NEXT_NUM)
|
||||
currentScanList = SCAN_NEXT_CHAN_SCANLIST1; // back round we go
|
||||
}
|
||||
23
app/chFrScanner.h
Normal file
23
app/chFrScanner.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef APP_CHFRSCANNER_H
|
||||
#define APP_CHFRSCANNER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// scan direction, if not equal SCAN_OFF indicates
|
||||
// that we are in a process of scanning channels/frequencies
|
||||
extern int8_t gScanStateDir;
|
||||
extern bool gScanKeepResult;
|
||||
extern bool gScanPauseMode;
|
||||
|
||||
#ifdef ENABLE_SCAN_RANGES
|
||||
extern uint32_t gScanRangeStart;
|
||||
extern uint32_t gScanRangeStop;
|
||||
#endif
|
||||
|
||||
void CHFRSCANNER_Found(void);
|
||||
void CHFRSCANNER_Stop(void);
|
||||
void CHFRSCANNER_Start(const bool storeBackupSettings, const int8_t scan_direction);
|
||||
void CHFRSCANNER_ContinueScanning(void);
|
||||
|
||||
#endif
|
||||
77
app/common.c
Normal file
77
app/common.c
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "app/chFrScanner.h"
|
||||
#include "audio.h"
|
||||
#include "functions.h"
|
||||
#include "misc.h"
|
||||
#include "settings.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
void COMMON_KeypadLockToggle()
|
||||
{
|
||||
|
||||
if (gScreenToDisplay != DISPLAY_MENU &&
|
||||
gCurrentFunction != FUNCTION_TRANSMIT)
|
||||
{ // toggle the keyboad lock
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = gEeprom.KEY_LOCK ? VOICE_ID_UNLOCK : VOICE_ID_LOCK;
|
||||
#endif
|
||||
|
||||
gEeprom.KEY_LOCK = !gEeprom.KEY_LOCK;
|
||||
|
||||
gRequestSaveSettings = true;
|
||||
}
|
||||
}
|
||||
|
||||
void COMMON_SwitchVFOs()
|
||||
{
|
||||
#ifdef ENABLE_SCAN_RANGES
|
||||
gScanRangeStart = 0;
|
||||
#endif
|
||||
gEeprom.TX_VFO ^= 1;
|
||||
|
||||
if (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF)
|
||||
gEeprom.CROSS_BAND_RX_TX = gEeprom.TX_VFO + 1;
|
||||
if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF)
|
||||
gEeprom.DUAL_WATCH = gEeprom.TX_VFO + 1;
|
||||
|
||||
gRequestSaveSettings = 1;
|
||||
gFlagReconfigureVfos = true;
|
||||
gScheduleDualWatch = true;
|
||||
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
}
|
||||
|
||||
void COMMON_SwitchVFOMode()
|
||||
{
|
||||
#ifdef ENABLE_NOAA
|
||||
if (gEeprom.VFO_OPEN && !IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE))
|
||||
#else
|
||||
if (gEeprom.VFO_OPEN)
|
||||
#endif
|
||||
{
|
||||
if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE))
|
||||
{ // swap to frequency mode
|
||||
gEeprom.ScreenChannel[gEeprom.TX_VFO] = gEeprom.FreqChannel[gEeprom.TX_VFO];
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_FREQUENCY_MODE;
|
||||
#endif
|
||||
gRequestSaveVFO = true;
|
||||
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t Channel = RADIO_FindNextChannel(gEeprom.MrChannel[gEeprom.TX_VFO], 1, false, 0);
|
||||
if (Channel != 0xFF)
|
||||
{ // swap to channel mode
|
||||
gEeprom.ScreenChannel[gEeprom.TX_VFO] = Channel;
|
||||
#ifdef ENABLE_VOICE
|
||||
AUDIO_SetVoiceID(0, VOICE_ID_CHANNEL_MODE);
|
||||
AUDIO_SetDigitVoice(1, Channel + 1);
|
||||
gAnotherVoiceID = (VOICE_ID_t)0xFE;
|
||||
#endif
|
||||
gRequestSaveVFO = true;
|
||||
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
13
app/common.h
Normal file
13
app/common.h
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
#ifndef APP_COMMON_H
|
||||
#define APP_COMMON_H
|
||||
|
||||
#include "functions.h"
|
||||
#include "settings.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
void COMMON_KeypadLockToggle();
|
||||
void COMMON_SwitchVFOs();
|
||||
void COMMON_SwitchVFOMode();
|
||||
|
||||
#endif
|
||||
128
app/display_rssi.c
Normal file
128
app/display_rssi.c
Normal file
@@ -0,0 +1,128 @@
|
||||
/* UA1ZBE Custom Firmware - RSSI Display Implementation
|
||||
*
|
||||
* Reads RSSI from BK4819 REG_67 (9-bit value).
|
||||
* Conversion: dBm = (raw / 2) - 160 + band_correction
|
||||
*
|
||||
* Displays as "S:XX" format with optional mini bar.
|
||||
* Updates every ~150ms via internal counter.
|
||||
*/
|
||||
|
||||
#include "display_rssi.h"
|
||||
#include "driver/bk4819.h"
|
||||
#include "driver/st7565.h"
|
||||
#include "ui/helper.h"
|
||||
#include "ui/main.h"
|
||||
#include "misc.h"
|
||||
#include "radio.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* dBm correction table — defined in ui/main.c */
|
||||
extern const int8_t dBmCorrTable[7];
|
||||
|
||||
/* === Internal state === */
|
||||
|
||||
static int16_t s_rssi_dbm;
|
||||
static uint16_t s_rssi_raw;
|
||||
static uint8_t s_s_level;
|
||||
static uint16_t s_update_counter;
|
||||
|
||||
/* Update interval: ~15 (150ms at 10ms tick) */
|
||||
#define RSSI_UPDATE_INTERVAL 15
|
||||
|
||||
/* S-meter thresholds (dBm) — simplified from U8RssiMap */
|
||||
static const int8_t s_thresholds[] = {
|
||||
-121, -115, -109, -103, -97, -91, -85, -79, -73, -63
|
||||
};
|
||||
|
||||
void RSSI_Init(void)
|
||||
{
|
||||
s_rssi_dbm = -160;
|
||||
s_rssi_raw = 0;
|
||||
s_s_level = 0;
|
||||
s_update_counter = 0;
|
||||
}
|
||||
|
||||
void RSSI_Update(void)
|
||||
{
|
||||
s_update_counter++;
|
||||
if (s_update_counter < RSSI_UPDATE_INTERVAL)
|
||||
return;
|
||||
s_update_counter = 0;
|
||||
|
||||
/* Read raw RSSI from BK4819 */
|
||||
s_rssi_raw = BK4819_GetRSSI();
|
||||
|
||||
/* Convert to dBm: (raw / 2) - 160 + band_correction
|
||||
* Avoid division: raw >> 1 */
|
||||
int8_t band_corr = dBmCorrTable[gRxVfo->Band];
|
||||
s_rssi_dbm = (int16_t)(s_rssi_raw >> 1) - 160 + band_corr;
|
||||
|
||||
/* Calculate S-level */
|
||||
s_s_level = 0;
|
||||
for (uint8_t i = 0; i < ARRAY_SIZE(s_thresholds); i++) {
|
||||
if (s_rssi_dbm >= s_thresholds[i]) {
|
||||
s_s_level = i + 1;
|
||||
}
|
||||
}
|
||||
if (s_s_level > 9)
|
||||
s_s_level = 9;
|
||||
}
|
||||
|
||||
int16_t RSSI_GetdBm(void)
|
||||
{
|
||||
return s_rssi_dbm;
|
||||
}
|
||||
|
||||
uint16_t RSSI_GetRaw(void)
|
||||
{
|
||||
return s_rssi_raw;
|
||||
}
|
||||
|
||||
uint8_t RSSI_GetSLevel(void)
|
||||
{
|
||||
return s_s_level;
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw RSSI indicator.
|
||||
* Format: "S:42" or raw dBm with mini bar.
|
||||
* Uses small font to fit in upper-right corner.
|
||||
*/
|
||||
void RSSI_Draw(int x, int y, bool with_bar)
|
||||
{
|
||||
static char buf[16];
|
||||
|
||||
/* Draw dBm value: "-87dBm" */
|
||||
sprintf(buf, "%ddBm", s_rssi_dbm);
|
||||
UI_PrintStringSmallNormal(buf, x, LCD_WIDTH, y);
|
||||
|
||||
if (with_bar) {
|
||||
/* Draw mini signal bar below the text
|
||||
* 5 bars, each 2px wide, 1px gap */
|
||||
int bar_x = x;
|
||||
int bar_y = y + 8;
|
||||
uint8_t bars = (s_s_level + 1) / 2; /* 0-5 bars from S0-S9 */
|
||||
if (bars > 5) bars = 5;
|
||||
|
||||
for (uint8_t i = 0; i < 5; i++) {
|
||||
uint8_t h = 2 + i * 2; /* Bar heights: 2,4,6,8,10 */
|
||||
if (i < bars) {
|
||||
/* Draw filled bar */
|
||||
for (uint8_t py = 0; py < h; py++) {
|
||||
for (uint8_t px = 0; px < 2; px++) {
|
||||
UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3 + px, bar_y + (10 - h) + py, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Draw outline only */
|
||||
UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3, bar_y + (10 - h), false);
|
||||
UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3 + 1, bar_y + (10 - h), false);
|
||||
UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3, bar_y + 9, false);
|
||||
UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3 + 1, bar_y + 9, false);
|
||||
UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3, bar_y + (10 - h) + 1, false);
|
||||
UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3 + 1, bar_y + (10 - h) + 1, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
36
app/display_rssi.h
Normal file
36
app/display_rssi.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* UA1ZBE Custom Firmware - RSSI Display Module
|
||||
*
|
||||
* Reads RSSI from BK4819 every 100-200ms, converts to dBm,
|
||||
* and draws an indicator on the display.
|
||||
*
|
||||
* Format: "S:42" or "-87dBm" with mini bar
|
||||
* Shown in upper-right corner of screen.
|
||||
*/
|
||||
|
||||
#ifndef APP_DISPLAY_RSSI_H
|
||||
#define APP_DISPLAY_RSSI_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Initialize RSSI display module */
|
||||
void RSSI_Init(void);
|
||||
|
||||
/* Call from 10ms timeslice to update RSSI reading */
|
||||
void RSSI_Update(void);
|
||||
|
||||
/* Draw RSSI indicator on the screen
|
||||
* x, y: position on screen
|
||||
* with_bar: if true, draw a mini signal bar next to the value */
|
||||
void RSSI_Draw(int x, int y, bool with_bar);
|
||||
|
||||
/* Get current RSSI value in dBm */
|
||||
int16_t RSSI_GetdBm(void);
|
||||
|
||||
/* Get raw RSSI value (0-511 from BK4819 REG_67) */
|
||||
uint16_t RSSI_GetRaw(void);
|
||||
|
||||
/* Get S-meter level (0-9) */
|
||||
uint8_t RSSI_GetSLevel(void);
|
||||
|
||||
#endif
|
||||
504
app/dtmf.c
Normal file
504
app/dtmf.c
Normal file
@@ -0,0 +1,504 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h> // NULL
|
||||
|
||||
#include "app/chFrScanner.h"
|
||||
#ifdef ENABLE_FMRADIO
|
||||
#include "app/fm.h"
|
||||
#endif
|
||||
#include "app/scanner.h"
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "audio.h"
|
||||
#include "driver/bk4819.h"
|
||||
#include "driver/eeprom.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/system.h"
|
||||
#include "dtmf.h"
|
||||
#include "external/printf/printf.h"
|
||||
#include "misc.h"
|
||||
#include "settings.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
char gDTMF_String[15];
|
||||
|
||||
char gDTMF_InputBox[15];
|
||||
uint8_t gDTMF_InputBox_Index = 0;
|
||||
bool gDTMF_InputMode = false;
|
||||
uint8_t gDTMF_PreviousIndex = 0;
|
||||
|
||||
char gDTMF_RX_live[20];
|
||||
uint8_t gDTMF_RX_live_timeout = 0;
|
||||
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
char gDTMF_RX[17];
|
||||
uint8_t gDTMF_RX_index = 0;
|
||||
uint8_t gDTMF_RX_timeout = 0;
|
||||
bool gDTMF_RX_pending = false;
|
||||
|
||||
bool gIsDtmfContactValid;
|
||||
char gDTMF_ID[4];
|
||||
char gDTMF_Caller[4];
|
||||
char gDTMF_Callee[4];
|
||||
DTMF_State_t gDTMF_State;
|
||||
uint8_t gDTMF_DecodeRingCountdown_500ms;
|
||||
uint8_t gDTMF_chosen_contact;
|
||||
uint8_t gDTMF_auto_reset_time_500ms;
|
||||
DTMF_CallState_t gDTMF_CallState;
|
||||
DTMF_CallMode_t gDTMF_CallMode;
|
||||
|
||||
bool gDTMF_IsTx;
|
||||
|
||||
uint8_t gDTMF_TxStopCountdown_500ms;
|
||||
bool gDTMF_IsGroupCall;
|
||||
#endif
|
||||
DTMF_ReplyState_t gDTMF_ReplyState;
|
||||
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
void DTMF_clear_RX(void)
|
||||
{
|
||||
gDTMF_RX_timeout = 0;
|
||||
gDTMF_RX_index = 0;
|
||||
gDTMF_RX_pending = false;
|
||||
memset(gDTMF_RX, 0, sizeof(gDTMF_RX));
|
||||
}
|
||||
#endif
|
||||
|
||||
void DTMF_SendEndOfTransmission(void)
|
||||
{
|
||||
if (gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO)
|
||||
BK4819_PlaySingleTone(2475, 250, 28, gEeprom.DTMF_SIDE_TONE);
|
||||
else if ((gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_TX_DOWN || gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_BOTH)
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
&& gDTMF_CallState == DTMF_CALL_STATE_NONE
|
||||
#endif
|
||||
) { // end-of-tx
|
||||
if (gEeprom.DTMF_SIDE_TONE) {
|
||||
AUDIO_AudioPathOn();
|
||||
gEnableSpeaker = true;
|
||||
SYSTEM_DelayMs(60);
|
||||
}
|
||||
|
||||
BK4819_EnterDTMF_TX(gEeprom.DTMF_SIDE_TONE);
|
||||
|
||||
BK4819_PlayDTMFString(
|
||||
gEeprom.DTMF_DOWN_CODE,
|
||||
0,
|
||||
gEeprom.DTMF_FIRST_CODE_PERSIST_TIME,
|
||||
gEeprom.DTMF_HASH_CODE_PERSIST_TIME,
|
||||
gEeprom.DTMF_CODE_PERSIST_TIME,
|
||||
gEeprom.DTMF_CODE_INTERVAL_TIME);
|
||||
|
||||
AUDIO_AudioPathOff();
|
||||
gEnableSpeaker = false;
|
||||
}
|
||||
|
||||
BK4819_ExitDTMF_TX(true);
|
||||
}
|
||||
|
||||
bool DTMF_ValidateCodes(char *pCode, const unsigned int size)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (pCode[0] == 0xFF || pCode[0] == 0)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (pCode[i] == 0xFF || pCode[i] == 0)
|
||||
{
|
||||
pCode[i] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((pCode[i] < '0' || pCode[i] > '9') && (pCode[i] < 'A' || pCode[i] > 'D') && pCode[i] != '*' && pCode[i] != '#')
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
bool DTMF_GetContact(const int Index, char *pContact)
|
||||
{
|
||||
if (Index < 0 || Index >= MAX_DTMF_CONTACTS || pContact == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EEPROM_ReadBuffer(0x1C00 + (Index * 16), pContact, 16);
|
||||
|
||||
// check whether the first character is printable or not
|
||||
return (pContact[0] >= ' ' && pContact[0] < 127);
|
||||
}
|
||||
|
||||
bool DTMF_FindContact(const char *pContact, char *pResult)
|
||||
{
|
||||
pResult[0] = 0;
|
||||
|
||||
for (unsigned int i = 0; i < MAX_DTMF_CONTACTS; i++) {
|
||||
char Contact[16];
|
||||
if (!DTMF_GetContact(i, Contact)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(pContact, Contact + 8, 3) == 0) {
|
||||
memcpy(pResult, Contact, 8);
|
||||
pResult[8] = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
char DTMF_GetCharacter(const unsigned int code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case KEY_0: return '0';
|
||||
case KEY_1: return '1';
|
||||
case KEY_2: return '2';
|
||||
case KEY_3: return '3';
|
||||
case KEY_4: return '4';
|
||||
case KEY_5: return '5';
|
||||
case KEY_6: return '6';
|
||||
case KEY_7: return '7';
|
||||
case KEY_8: return '8';
|
||||
case KEY_9: return '9';
|
||||
case KEY_MENU: return 'A';
|
||||
case KEY_UP: return 'B';
|
||||
case KEY_DOWN: return 'C';
|
||||
case KEY_EXIT: return 'D';
|
||||
case KEY_STAR: return '*';
|
||||
case KEY_F: return '#';
|
||||
default: return 0xff;
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
static bool CompareMessage(const char *pMsg, const char *pTemplate, const unsigned int size, const bool bCheckGroup)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (pMsg[i] != pTemplate[i])
|
||||
{
|
||||
if (!bCheckGroup || pMsg[i] != gEeprom.DTMF_GROUP_CALL_CODE)
|
||||
return false;
|
||||
gDTMF_IsGroupCall = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DTMF_CallMode_t DTMF_CheckGroupCall(const char *pMsg, const unsigned int size)
|
||||
{
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
if (pMsg[i] == gEeprom.DTMF_GROUP_CALL_CODE) {
|
||||
return DTMF_CALL_MODE_GROUP;
|
||||
}
|
||||
|
||||
return DTMF_CALL_MODE_NOT_GROUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
void DTMF_clear_input_box(void)
|
||||
{
|
||||
memset(gDTMF_InputBox, 0, sizeof(gDTMF_InputBox));
|
||||
gDTMF_InputBox_Index = 0;
|
||||
gDTMF_InputMode = false;
|
||||
}
|
||||
|
||||
void DTMF_Append(const char code)
|
||||
{
|
||||
if (gDTMF_InputBox_Index == 0)
|
||||
{
|
||||
memset(gDTMF_InputBox, '-', sizeof(gDTMF_InputBox) - 1);
|
||||
gDTMF_InputBox[sizeof(gDTMF_InputBox) - 1] = 0;
|
||||
}
|
||||
|
||||
if (gDTMF_InputBox_Index < (sizeof(gDTMF_InputBox) - 1))
|
||||
gDTMF_InputBox[gDTMF_InputBox_Index++] = code;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
void DTMF_HandleRequest(void)
|
||||
{ // proccess the RX'ed DTMF characters
|
||||
|
||||
char String[21];
|
||||
unsigned int Offset;
|
||||
|
||||
if (!gDTMF_RX_pending)
|
||||
return; // nothing new received
|
||||
|
||||
if (gScanStateDir != SCAN_OFF || gCssBackgroundScan)
|
||||
{ // we're busy scanning
|
||||
DTMF_clear_RX();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gRxVfo->DTMF_DECODING_ENABLE && !gSetting_KILLED)
|
||||
{ // D-DCD is disabled or we're alive
|
||||
DTMF_clear_RX();
|
||||
return;
|
||||
}
|
||||
|
||||
gDTMF_RX_pending = false;
|
||||
|
||||
if (gDTMF_RX_index >= 9)
|
||||
{ // look for the KILL code
|
||||
|
||||
sprintf(String, "%s%c%s", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE, gEeprom.KILL_CODE);
|
||||
|
||||
Offset = gDTMF_RX_index - strlen(String);
|
||||
|
||||
if (CompareMessage(gDTMF_RX + Offset, String, strlen(String), true))
|
||||
{ // bugger
|
||||
|
||||
if (gEeprom.PERMIT_REMOTE_KILL)
|
||||
{
|
||||
gSetting_KILLED = true; // oooerr !
|
||||
|
||||
DTMF_clear_RX();
|
||||
|
||||
SETTINGS_SaveSettings();
|
||||
|
||||
gDTMF_ReplyState = DTMF_REPLY_AB;
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (gFmRadioMode)
|
||||
{
|
||||
FM_TurnOff();
|
||||
GUI_SelectNextDisplay(DISPLAY_MAIN);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
gDTMF_ReplyState = DTMF_REPLY_NONE;
|
||||
}
|
||||
|
||||
gDTMF_CallState = DTMF_CALL_STATE_NONE;
|
||||
|
||||
gUpdateDisplay = true;
|
||||
gUpdateStatus = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (gDTMF_RX_index >= 9)
|
||||
{ // look for the REVIVE code
|
||||
|
||||
sprintf(String, "%s%c%s", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE, gEeprom.REVIVE_CODE);
|
||||
|
||||
Offset = gDTMF_RX_index - strlen(String);
|
||||
|
||||
if (CompareMessage(gDTMF_RX + Offset, String, strlen(String), true))
|
||||
{ // shit, we're back !
|
||||
|
||||
gSetting_KILLED = false;
|
||||
|
||||
DTMF_clear_RX();
|
||||
|
||||
SETTINGS_SaveSettings();
|
||||
|
||||
gDTMF_ReplyState = DTMF_REPLY_AB;
|
||||
gDTMF_CallState = DTMF_CALL_STATE_NONE;
|
||||
|
||||
gUpdateDisplay = true;
|
||||
gUpdateStatus = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (gDTMF_RX_index >= 2)
|
||||
{ // look for ACK reply
|
||||
char *pPrintStr = "AB";
|
||||
|
||||
Offset = gDTMF_RX_index - strlen(pPrintStr);
|
||||
|
||||
if (CompareMessage(gDTMF_RX + Offset, pPrintStr, strlen(pPrintStr), true)) {
|
||||
// ends with "AB"
|
||||
|
||||
if (gDTMF_ReplyState != DTMF_REPLY_NONE) // 1of11
|
||||
// if (gDTMF_CallState != DTMF_CALL_STATE_NONE) // 1of11
|
||||
// if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT) // 1of11
|
||||
{
|
||||
gDTMF_State = DTMF_STATE_TX_SUCC;
|
||||
DTMF_clear_RX();
|
||||
gUpdateDisplay = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT &&
|
||||
gDTMF_CallMode == DTMF_CALL_MODE_NOT_GROUP &&
|
||||
gDTMF_RX_index >= 9)
|
||||
{ // waiting for a reply
|
||||
|
||||
sprintf(String, "%s%c%s", gDTMF_String, gEeprom.DTMF_SEPARATE_CODE, "AAAAA");
|
||||
|
||||
Offset = gDTMF_RX_index - strlen(String);
|
||||
|
||||
if (CompareMessage(gDTMF_RX + Offset, String, strlen(String), false))
|
||||
{ // we got a response
|
||||
gDTMF_State = DTMF_STATE_CALL_OUT_RSP;
|
||||
DTMF_clear_RX();
|
||||
gUpdateDisplay = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (gSetting_KILLED || gDTMF_CallState != DTMF_CALL_STATE_NONE)
|
||||
{ // we've been killed or expecting a reply
|
||||
return;
|
||||
}
|
||||
|
||||
if (gDTMF_RX_index >= 7)
|
||||
{ // see if we're being called
|
||||
|
||||
gDTMF_IsGroupCall = false;
|
||||
|
||||
sprintf(String, "%s%c", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE);
|
||||
|
||||
Offset = gDTMF_RX_index - strlen(String) - 3;
|
||||
|
||||
if (CompareMessage(gDTMF_RX + Offset, String, strlen(String), true))
|
||||
{ // it's for us !
|
||||
|
||||
gDTMF_CallState = DTMF_CALL_STATE_RECEIVED;
|
||||
|
||||
memset(gDTMF_Callee, 0, sizeof(gDTMF_Callee));
|
||||
memset(gDTMF_Caller, 0, sizeof(gDTMF_Caller));
|
||||
memcpy(gDTMF_Callee, gDTMF_RX + Offset + 0, 3);
|
||||
memcpy(gDTMF_Caller, gDTMF_RX + Offset + 4, 3);
|
||||
|
||||
DTMF_clear_RX();
|
||||
|
||||
gUpdateDisplay = true;
|
||||
|
||||
switch (gEeprom.DTMF_DECODE_RESPONSE)
|
||||
{
|
||||
case DTMF_DEC_RESPONSE_BOTH:
|
||||
gDTMF_DecodeRingCountdown_500ms = DTMF_decode_ring_countdown_500ms;
|
||||
__attribute__((fallthrough));
|
||||
case DTMF_DEC_RESPONSE_REPLY:
|
||||
gDTMF_ReplyState = DTMF_REPLY_AAAAA;
|
||||
break;
|
||||
case DTMF_DEC_RESPONSE_RING:
|
||||
gDTMF_DecodeRingCountdown_500ms = DTMF_decode_ring_countdown_500ms;
|
||||
break;
|
||||
default:
|
||||
case DTMF_DEC_RESPONSE_NONE:
|
||||
gDTMF_DecodeRingCountdown_500ms = 0;
|
||||
gDTMF_ReplyState = DTMF_REPLY_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (gDTMF_IsGroupCall)
|
||||
gDTMF_ReplyState = DTMF_REPLY_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void DTMF_Reply(void)
|
||||
{
|
||||
uint16_t Delay;
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
char String[23];
|
||||
#endif
|
||||
const char *pString = NULL;
|
||||
|
||||
switch (gDTMF_ReplyState)
|
||||
{
|
||||
case DTMF_REPLY_ANI:
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
if (gDTMF_CallMode != DTMF_CALL_MODE_DTMF)
|
||||
{ // append our ID code onto the end of the DTMF code to send
|
||||
sprintf(String, "%s%c%s", gDTMF_String, gEeprom.DTMF_SEPARATE_CODE, gEeprom.ANI_DTMF_ID);
|
||||
pString = String;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
pString = gDTMF_String;
|
||||
}
|
||||
|
||||
break;
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
case DTMF_REPLY_AB:
|
||||
pString = "AB";
|
||||
break;
|
||||
|
||||
case DTMF_REPLY_AAAAA:
|
||||
sprintf(String, "%s%c%s", gEeprom.ANI_DTMF_ID, gEeprom.DTMF_SEPARATE_CODE, "AAAAA");
|
||||
pString = String;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
case DTMF_REPLY_NONE:
|
||||
if (
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
gDTMF_CallState != DTMF_CALL_STATE_NONE ||
|
||||
#endif
|
||||
gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO ||
|
||||
gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_OFF ||
|
||||
gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_TX_DOWN)
|
||||
{
|
||||
gDTMF_ReplyState = DTMF_REPLY_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
// send TX-UP DTMF
|
||||
pString = gEeprom.DTMF_UP_CODE;
|
||||
break;
|
||||
}
|
||||
|
||||
gDTMF_ReplyState = DTMF_REPLY_NONE;
|
||||
|
||||
if (pString == NULL)
|
||||
return;
|
||||
|
||||
Delay = (gEeprom.DTMF_PRELOAD_TIME < 200) ? 200 : gEeprom.DTMF_PRELOAD_TIME;
|
||||
|
||||
if (gEeprom.DTMF_SIDE_TONE)
|
||||
{ // the user will also hear the transmitted tones
|
||||
AUDIO_AudioPathOn();
|
||||
gEnableSpeaker = true;
|
||||
}
|
||||
|
||||
SYSTEM_DelayMs(Delay);
|
||||
|
||||
BK4819_EnterDTMF_TX(gEeprom.DTMF_SIDE_TONE);
|
||||
|
||||
BK4819_PlayDTMFString(
|
||||
pString,
|
||||
1,
|
||||
gEeprom.DTMF_FIRST_CODE_PERSIST_TIME,
|
||||
gEeprom.DTMF_HASH_CODE_PERSIST_TIME,
|
||||
gEeprom.DTMF_CODE_PERSIST_TIME,
|
||||
gEeprom.DTMF_CODE_INTERVAL_TIME);
|
||||
|
||||
AUDIO_AudioPathOff();
|
||||
|
||||
gEnableSpeaker = false;
|
||||
|
||||
BK4819_ExitDTMF_TX(false);
|
||||
}
|
||||
119
app/dtmf.h
Normal file
119
app/dtmf.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DTMF_H
|
||||
#define DTMF_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAX_DTMF_CONTACTS 16
|
||||
|
||||
enum DTMF_State_t {
|
||||
DTMF_STATE_0 = 0,
|
||||
DTMF_STATE_TX_SUCC,
|
||||
DTMF_STATE_CALL_OUT_RSP
|
||||
};
|
||||
|
||||
typedef enum DTMF_State_t DTMF_State_t;
|
||||
|
||||
enum DTMF_CallState_t {
|
||||
DTMF_CALL_STATE_NONE = 0,
|
||||
DTMF_CALL_STATE_CALL_OUT,
|
||||
DTMF_CALL_STATE_RECEIVED,
|
||||
DTMF_CALL_STATE_RECEIVED_STAY
|
||||
};
|
||||
|
||||
enum DTMF_DecodeResponse_t {
|
||||
DTMF_DEC_RESPONSE_NONE = 0,
|
||||
DTMF_DEC_RESPONSE_RING,
|
||||
DTMF_DEC_RESPONSE_REPLY,
|
||||
DTMF_DEC_RESPONSE_BOTH
|
||||
};
|
||||
|
||||
typedef enum DTMF_CallState_t DTMF_CallState_t;
|
||||
|
||||
enum DTMF_ReplyState_t {
|
||||
DTMF_REPLY_NONE = 0,
|
||||
DTMF_REPLY_ANI,
|
||||
DTMF_REPLY_AB,
|
||||
DTMF_REPLY_AAAAA
|
||||
};
|
||||
|
||||
typedef enum DTMF_ReplyState_t DTMF_ReplyState_t;
|
||||
|
||||
enum DTMF_CallMode_t {
|
||||
DTMF_CALL_MODE_NOT_GROUP = 0,
|
||||
DTMF_CALL_MODE_GROUP,
|
||||
DTMF_CALL_MODE_DTMF
|
||||
};
|
||||
|
||||
enum { // seconds
|
||||
DTMF_HOLD_MIN = 5,
|
||||
DTMF_HOLD_MAX = 60
|
||||
};
|
||||
|
||||
typedef enum DTMF_CallMode_t DTMF_CallMode_t;
|
||||
|
||||
extern char gDTMF_String[15];
|
||||
|
||||
extern char gDTMF_InputBox[15];
|
||||
extern uint8_t gDTMF_InputBox_Index;
|
||||
extern bool gDTMF_InputMode;
|
||||
extern uint8_t gDTMF_PreviousIndex;
|
||||
|
||||
extern char gDTMF_RX_live[20];
|
||||
extern uint8_t gDTMF_RX_live_timeout;
|
||||
|
||||
extern DTMF_ReplyState_t gDTMF_ReplyState;
|
||||
|
||||
bool DTMF_ValidateCodes(char *pCode, const unsigned int size);
|
||||
char DTMF_GetCharacter(const unsigned int code);
|
||||
void DTMF_clear_input_box(void);
|
||||
void DTMF_Append(const char code);
|
||||
void DTMF_Reply(void);
|
||||
void DTMF_SendEndOfTransmission(void);
|
||||
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
|
||||
extern char gDTMF_RX[17];
|
||||
extern uint8_t gDTMF_RX_index;
|
||||
extern uint8_t gDTMF_RX_timeout;
|
||||
extern bool gDTMF_RX_pending;
|
||||
|
||||
extern bool gIsDtmfContactValid;
|
||||
extern char gDTMF_ID[4];
|
||||
extern char gDTMF_Caller[4];
|
||||
extern char gDTMF_Callee[4];
|
||||
extern DTMF_State_t gDTMF_State;
|
||||
extern uint8_t gDTMF_DecodeRingCountdown_500ms;
|
||||
extern uint8_t gDTMF_chosen_contact;
|
||||
extern uint8_t gDTMF_auto_reset_time_500ms;
|
||||
extern DTMF_CallState_t gDTMF_CallState;
|
||||
|
||||
extern DTMF_CallMode_t gDTMF_CallMode;
|
||||
extern bool gDTMF_IsTx;
|
||||
extern uint8_t gDTMF_TxStopCountdown_500ms;
|
||||
|
||||
void DTMF_clear_RX(void);
|
||||
DTMF_CallMode_t DTMF_CheckGroupCall(const char *pDTMF, const unsigned int size);
|
||||
bool DTMF_GetContact(const int Index, char *pContact);
|
||||
bool DTMF_FindContact(const char *pContact, char *pResult);
|
||||
void DTMF_HandleRequest(void);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
66
app/flashlight.c
Normal file
66
app/flashlight.c
Normal file
@@ -0,0 +1,66 @@
|
||||
#ifdef ENABLE_FLASHLIGHT
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
|
||||
#include "flashlight.h"
|
||||
|
||||
enum FlashlightMode_t gFlashLightState;
|
||||
|
||||
void FlashlightTimeSlice()
|
||||
{
|
||||
if (gFlashLightState == FLASHLIGHT_BLINK && (gFlashLightBlinkCounter & 15u) == 0) {
|
||||
GPIO_FlipBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gFlashLightState == FLASHLIGHT_SOS) {
|
||||
const uint16_t u = 15;
|
||||
static uint8_t c;
|
||||
static uint16_t next;
|
||||
|
||||
if (gFlashLightBlinkCounter - next > 7 * u) {
|
||||
c = 0;
|
||||
next = gFlashLightBlinkCounter + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gFlashLightBlinkCounter == next) {
|
||||
if (c==0) {
|
||||
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT);
|
||||
} else {
|
||||
GPIO_FlipBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT);
|
||||
}
|
||||
|
||||
if (c >= 18) {
|
||||
next = gFlashLightBlinkCounter + 7 * u;
|
||||
c = 0;
|
||||
} else if(c==7 || c==9 || c==11) {
|
||||
next = gFlashLightBlinkCounter + 3 * u;
|
||||
} else {
|
||||
next = gFlashLightBlinkCounter + u;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ACTION_FlashLight(void)
|
||||
{
|
||||
switch (gFlashLightState) {
|
||||
case FLASHLIGHT_OFF:
|
||||
gFlashLightState++;
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT);
|
||||
break;
|
||||
case FLASHLIGHT_ON:
|
||||
case FLASHLIGHT_BLINK:
|
||||
gFlashLightState++;
|
||||
break;
|
||||
case FLASHLIGHT_SOS:
|
||||
default:
|
||||
gFlashLightState = 0;
|
||||
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
23
app/flashlight.h
Normal file
23
app/flashlight.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef APP_FLASHLIGHT_H
|
||||
#define APP_FLASHLIGHT_H
|
||||
|
||||
#ifdef ENABLE_FLASHLIGHT
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum FlashlightMode_t {
|
||||
FLASHLIGHT_OFF = 0,
|
||||
FLASHLIGHT_ON,
|
||||
FLASHLIGHT_BLINK,
|
||||
FLASHLIGHT_SOS
|
||||
};
|
||||
|
||||
extern enum FlashlightMode_t gFlashLightState;
|
||||
extern volatile uint16_t gFlashLightBlinkCounter;
|
||||
|
||||
void FlashlightTimeSlice(void);
|
||||
void ACTION_FlashLight(void);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
605
app/fm.c
Normal file
605
app/fm.c
Normal file
@@ -0,0 +1,605 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "app/action.h"
|
||||
#include "app/fm.h"
|
||||
#include "app/generic.h"
|
||||
#include "audio.h"
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "driver/bk1080.h"
|
||||
#include "driver/eeprom.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "functions.h"
|
||||
#include "misc.h"
|
||||
#include "settings.h"
|
||||
#include "ui/inputbox.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||||
#endif
|
||||
|
||||
uint16_t gFM_Channels[20];
|
||||
bool gFmRadioMode;
|
||||
uint8_t gFmRadioCountdown_500ms;
|
||||
volatile uint16_t gFmPlayCountdown_10ms;
|
||||
volatile int8_t gFM_ScanState;
|
||||
bool gFM_AutoScan;
|
||||
uint8_t gFM_ChannelPosition;
|
||||
bool gFM_FoundFrequency;
|
||||
bool gFM_AutoScan;
|
||||
uint16_t gFM_RestoreCountdown_10ms;
|
||||
|
||||
|
||||
|
||||
const uint8_t BUTTON_STATE_PRESSED = 1 << 0;
|
||||
const uint8_t BUTTON_STATE_HELD = 1 << 1;
|
||||
|
||||
const uint8_t BUTTON_EVENT_PRESSED = BUTTON_STATE_PRESSED;
|
||||
const uint8_t BUTTON_EVENT_HELD = BUTTON_STATE_PRESSED | BUTTON_STATE_HELD;
|
||||
const uint8_t BUTTON_EVENT_SHORT = 0;
|
||||
const uint8_t BUTTON_EVENT_LONG = BUTTON_STATE_HELD;
|
||||
|
||||
|
||||
static void Key_FUNC(KEY_Code_t Key, uint8_t state);
|
||||
|
||||
bool FM_CheckValidChannel(uint8_t Channel)
|
||||
{
|
||||
return Channel < ARRAY_SIZE(gFM_Channels) &&
|
||||
gFM_Channels[Channel] >= BK1080_GetFreqLoLimit(gEeprom.FM_Band) &&
|
||||
gFM_Channels[Channel] < BK1080_GetFreqHiLimit(gEeprom.FM_Band);
|
||||
}
|
||||
|
||||
uint8_t FM_FindNextChannel(uint8_t Channel, uint8_t Direction)
|
||||
{
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(gFM_Channels); i++) {
|
||||
if (Channel == 0xFF)
|
||||
Channel = ARRAY_SIZE(gFM_Channels) - 1;
|
||||
else if (Channel >= ARRAY_SIZE(gFM_Channels))
|
||||
Channel = 0;
|
||||
if (FM_CheckValidChannel(Channel))
|
||||
return Channel;
|
||||
Channel += Direction;
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
int FM_ConfigureChannelState(void)
|
||||
{
|
||||
gEeprom.FM_FrequencyPlaying = gEeprom.FM_SelectedFrequency;
|
||||
|
||||
if (gEeprom.FM_IsMrMode) {
|
||||
const uint8_t Channel = FM_FindNextChannel(gEeprom.FM_SelectedChannel, FM_CHANNEL_UP);
|
||||
if (Channel == 0xFF) {
|
||||
gEeprom.FM_IsMrMode = false;
|
||||
return -1;
|
||||
}
|
||||
gEeprom.FM_SelectedChannel = Channel;
|
||||
gEeprom.FM_FrequencyPlaying = gFM_Channels[Channel];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FM_TurnOff(void)
|
||||
{
|
||||
gFmRadioMode = false;
|
||||
gFM_ScanState = FM_SCAN_OFF;
|
||||
gFM_RestoreCountdown_10ms = 0;
|
||||
|
||||
AUDIO_AudioPathOff();
|
||||
gEnableSpeaker = false;
|
||||
|
||||
BK1080_Init0();
|
||||
|
||||
gUpdateStatus = true;
|
||||
}
|
||||
|
||||
void FM_EraseChannels(void)
|
||||
{
|
||||
uint8_t Template[8];
|
||||
memset(Template, 0xFF, sizeof(Template));
|
||||
|
||||
for (unsigned i = 0; i < 5; i++)
|
||||
EEPROM_WriteBuffer(0x0E40 + (i * 8), Template);
|
||||
|
||||
memset(gFM_Channels, 0xFF, sizeof(gFM_Channels));
|
||||
}
|
||||
|
||||
void FM_Tune(uint16_t Frequency, int8_t Step, bool bFlag)
|
||||
{
|
||||
AUDIO_AudioPathOff();
|
||||
|
||||
gEnableSpeaker = false;
|
||||
|
||||
gFmPlayCountdown_10ms = (gFM_ScanState == FM_SCAN_OFF) ? fm_play_countdown_noscan_10ms : fm_play_countdown_scan_10ms;
|
||||
|
||||
gScheduleFM = false;
|
||||
gFM_FoundFrequency = false;
|
||||
gAskToSave = false;
|
||||
gAskToDelete = false;
|
||||
gEeprom.FM_FrequencyPlaying = Frequency;
|
||||
|
||||
if (!bFlag) {
|
||||
Frequency += Step;
|
||||
if (Frequency < BK1080_GetFreqLoLimit(gEeprom.FM_Band))
|
||||
Frequency = BK1080_GetFreqHiLimit(gEeprom.FM_Band);
|
||||
else if (Frequency > BK1080_GetFreqHiLimit(gEeprom.FM_Band))
|
||||
Frequency = BK1080_GetFreqLoLimit(gEeprom.FM_Band);
|
||||
|
||||
gEeprom.FM_FrequencyPlaying = Frequency;
|
||||
}
|
||||
|
||||
gFM_ScanState = Step;
|
||||
|
||||
BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||||
}
|
||||
|
||||
void FM_PlayAndUpdate(void)
|
||||
{
|
||||
gFM_ScanState = FM_SCAN_OFF;
|
||||
|
||||
if (gFM_AutoScan) {
|
||||
gEeprom.FM_IsMrMode = true;
|
||||
gEeprom.FM_SelectedChannel = 0;
|
||||
}
|
||||
|
||||
FM_ConfigureChannelState();
|
||||
BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||||
SETTINGS_SaveFM();
|
||||
|
||||
gFmPlayCountdown_10ms = 0;
|
||||
gScheduleFM = false;
|
||||
gAskToSave = false;
|
||||
|
||||
AUDIO_AudioPathOn();
|
||||
|
||||
gEnableSpeaker = true;
|
||||
}
|
||||
|
||||
int FM_CheckFrequencyLock(uint16_t Frequency, uint16_t LowerLimit)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
const uint16_t Test2 = BK1080_ReadRegister(BK1080_REG_07);
|
||||
|
||||
// This is supposed to be a signed value, but above function is unsigned
|
||||
const uint16_t Deviation = BK1080_REG_07_GET_FREQD(Test2);
|
||||
|
||||
if (BK1080_REG_07_GET_SNR(Test2) <= 2) {
|
||||
goto Bail;
|
||||
}
|
||||
|
||||
const uint16_t Status = BK1080_ReadRegister(BK1080_REG_10);
|
||||
|
||||
if ((Status & BK1080_REG_10_MASK_AFCRL) != BK1080_REG_10_AFCRL_NOT_RAILED || BK1080_REG_10_GET_RSSI(Status) < 10) {
|
||||
goto Bail;
|
||||
}
|
||||
|
||||
//if (Deviation > -281 && Deviation < 280)
|
||||
if (Deviation >= 280 && Deviation <= 3815) {
|
||||
goto Bail;
|
||||
}
|
||||
|
||||
// not BLE(less than or equal)
|
||||
if (Frequency > LowerLimit && (Frequency - BK1080_BaseFrequency) == 1) {
|
||||
if (BK1080_FrequencyDeviation & 0x800 || (BK1080_FrequencyDeviation < 20))
|
||||
goto Bail;
|
||||
}
|
||||
|
||||
// not BLT(less than)
|
||||
|
||||
if (Frequency >= LowerLimit && (BK1080_BaseFrequency - Frequency) == 1) {
|
||||
if ((BK1080_FrequencyDeviation & 0x800) == 0 || (BK1080_FrequencyDeviation > 4075))
|
||||
goto Bail;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
Bail:
|
||||
BK1080_FrequencyDeviation = Deviation;
|
||||
BK1080_BaseFrequency = Frequency;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void Key_DIGITS(KEY_Code_t Key, uint8_t state)
|
||||
{
|
||||
enum { STATE_FREQ_MODE, STATE_MR_MODE, STATE_SAVE };
|
||||
|
||||
if (state == BUTTON_EVENT_SHORT && !gWasFKeyPressed) {
|
||||
uint8_t State;
|
||||
|
||||
if (gAskToDelete) {
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gAskToSave) {
|
||||
State = STATE_SAVE;
|
||||
}
|
||||
else {
|
||||
if (gFM_ScanState != FM_SCAN_OFF) {
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
State = gEeprom.FM_IsMrMode ? STATE_MR_MODE : STATE_FREQ_MODE;
|
||||
}
|
||||
|
||||
INPUTBOX_Append(Key);
|
||||
|
||||
gRequestDisplayScreen = DISPLAY_FM;
|
||||
|
||||
if (State == STATE_FREQ_MODE) {
|
||||
if (gInputBoxIndex == 1) {
|
||||
if (gInputBox[0] > 1) {
|
||||
gInputBox[1] = gInputBox[0];
|
||||
gInputBox[0] = 0;
|
||||
gInputBoxIndex = 2;
|
||||
}
|
||||
}
|
||||
else if (gInputBoxIndex > 3) {
|
||||
uint32_t Frequency;
|
||||
|
||||
gInputBoxIndex = 0;
|
||||
Frequency = StrToUL(INPUTBOX_GetAscii());
|
||||
|
||||
if (Frequency < BK1080_GetFreqLoLimit(gEeprom.FM_Band) || BK1080_GetFreqHiLimit(gEeprom.FM_Band) < Frequency) {
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
gRequestDisplayScreen = DISPLAY_FM;
|
||||
return;
|
||||
}
|
||||
|
||||
gEeprom.FM_SelectedFrequency = (uint16_t)Frequency;
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||||
#endif
|
||||
gEeprom.FM_FrequencyPlaying = gEeprom.FM_SelectedFrequency;
|
||||
BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||||
gRequestSaveFM = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (gInputBoxIndex == 2) {
|
||||
uint8_t Channel;
|
||||
|
||||
gInputBoxIndex = 0;
|
||||
Channel = ((gInputBox[0] * 10) + gInputBox[1]) - 1;
|
||||
|
||||
if (State == STATE_MR_MODE) {
|
||||
if (FM_CheckValidChannel(Channel)) {
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||||
#endif
|
||||
gEeprom.FM_SelectedChannel = Channel;
|
||||
gEeprom.FM_FrequencyPlaying = gFM_Channels[Channel];
|
||||
BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||||
gRequestSaveFM = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (Channel < 20) {
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||||
#endif
|
||||
gRequestDisplayScreen = DISPLAY_FM;
|
||||
gInputBoxIndex = 0;
|
||||
gFM_ChannelPosition = Channel;
|
||||
return;
|
||||
}
|
||||
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
Key_FUNC(Key, state);
|
||||
}
|
||||
|
||||
static void Key_FUNC(KEY_Code_t Key, uint8_t state)
|
||||
{
|
||||
if (state == BUTTON_EVENT_SHORT || state == BUTTON_EVENT_HELD) {
|
||||
bool autoScan = gWasFKeyPressed || (state == BUTTON_EVENT_HELD);
|
||||
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
gWasFKeyPressed = false;
|
||||
gUpdateStatus = true;
|
||||
gRequestDisplayScreen = DISPLAY_FM;
|
||||
|
||||
switch (Key) {
|
||||
case KEY_0:
|
||||
ACTION_FM();
|
||||
break;
|
||||
|
||||
case KEY_1:
|
||||
gEeprom.FM_Band++;
|
||||
gRequestSaveFM = true;
|
||||
break;
|
||||
|
||||
// case KEY_2:
|
||||
// gEeprom.FM_Space = (gEeprom.FM_Space + 1) % 3;
|
||||
// gRequestSaveFM = true;
|
||||
// break;
|
||||
|
||||
case KEY_3:
|
||||
gEeprom.FM_IsMrMode = !gEeprom.FM_IsMrMode;
|
||||
|
||||
if (!FM_ConfigureChannelState()) {
|
||||
BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||||
gRequestSaveFM = true;
|
||||
}
|
||||
else
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
break;
|
||||
|
||||
case KEY_STAR:
|
||||
ACTION_Scan(autoScan);
|
||||
break;
|
||||
|
||||
default:
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Key_EXIT(uint8_t state)
|
||||
{
|
||||
if (state != BUTTON_EVENT_SHORT)
|
||||
return;
|
||||
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
|
||||
if (gFM_ScanState == FM_SCAN_OFF) {
|
||||
if (gInputBoxIndex == 0) {
|
||||
if (!gAskToSave && !gAskToDelete) {
|
||||
ACTION_FM();
|
||||
return;
|
||||
}
|
||||
|
||||
gAskToSave = false;
|
||||
gAskToDelete = false;
|
||||
}
|
||||
else {
|
||||
gInputBox[--gInputBoxIndex] = 10;
|
||||
|
||||
if (gInputBoxIndex) {
|
||||
if (gInputBoxIndex != 1) {
|
||||
gRequestDisplayScreen = DISPLAY_FM;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gInputBox[0] != 0) {
|
||||
gRequestDisplayScreen = DISPLAY_FM;
|
||||
return;
|
||||
}
|
||||
}
|
||||
gInputBoxIndex = 0;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_CANCEL;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
FM_PlayAndUpdate();
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
|
||||
#endif
|
||||
}
|
||||
|
||||
gRequestDisplayScreen = DISPLAY_FM;
|
||||
}
|
||||
|
||||
static void Key_MENU(uint8_t state)
|
||||
{
|
||||
if (state != BUTTON_EVENT_SHORT)
|
||||
return;
|
||||
|
||||
|
||||
gRequestDisplayScreen = DISPLAY_FM;
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
|
||||
if (gFM_ScanState == FM_SCAN_OFF) {
|
||||
if (!gEeprom.FM_IsMrMode) {
|
||||
if (gAskToSave) {
|
||||
gFM_Channels[gFM_ChannelPosition] = gEeprom.FM_FrequencyPlaying;
|
||||
gRequestSaveFM = true;
|
||||
}
|
||||
gAskToSave = !gAskToSave;
|
||||
}
|
||||
else {
|
||||
if (gAskToDelete) {
|
||||
gFM_Channels[gEeprom.FM_SelectedChannel] = 0xFFFF;
|
||||
|
||||
FM_ConfigureChannelState();
|
||||
BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||||
|
||||
gRequestSaveFM = true;
|
||||
}
|
||||
gAskToDelete = !gAskToDelete;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (gFM_AutoScan || !gFM_FoundFrequency) {
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
gInputBoxIndex = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gAskToSave) {
|
||||
gFM_Channels[gFM_ChannelPosition] = gEeprom.FM_FrequencyPlaying;
|
||||
gRequestSaveFM = true;
|
||||
}
|
||||
gAskToSave = !gAskToSave;
|
||||
}
|
||||
}
|
||||
|
||||
static void Key_UP_DOWN(uint8_t state, int8_t Step)
|
||||
{
|
||||
if (state == BUTTON_EVENT_PRESSED) {
|
||||
if (gInputBoxIndex) {
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
} else if (gInputBoxIndex || state!=BUTTON_EVENT_HELD) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gAskToSave) {
|
||||
gRequestDisplayScreen = DISPLAY_FM;
|
||||
gFM_ChannelPosition = NUMBER_AddWithWraparound(gFM_ChannelPosition, Step, 0, 19);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gFM_ScanState != FM_SCAN_OFF) {
|
||||
if (gFM_AutoScan) {
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
FM_Tune(gEeprom.FM_FrequencyPlaying, Step, false);
|
||||
gRequestDisplayScreen = DISPLAY_FM;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gEeprom.FM_IsMrMode) {
|
||||
const uint8_t Channel = FM_FindNextChannel(gEeprom.FM_SelectedChannel + Step, Step);
|
||||
if (Channel == 0xFF || gEeprom.FM_SelectedChannel == Channel)
|
||||
goto Bail;
|
||||
|
||||
gEeprom.FM_SelectedChannel = Channel;
|
||||
gEeprom.FM_FrequencyPlaying = gFM_Channels[Channel];
|
||||
}
|
||||
else {
|
||||
uint16_t Frequency = gEeprom.FM_SelectedFrequency + Step;
|
||||
|
||||
if (Frequency < BK1080_GetFreqLoLimit(gEeprom.FM_Band))
|
||||
Frequency = BK1080_GetFreqHiLimit(gEeprom.FM_Band);
|
||||
else if (Frequency > BK1080_GetFreqHiLimit(gEeprom.FM_Band))
|
||||
Frequency = BK1080_GetFreqLoLimit(gEeprom.FM_Band);
|
||||
|
||||
gEeprom.FM_FrequencyPlaying = Frequency;
|
||||
gEeprom.FM_SelectedFrequency = gEeprom.FM_FrequencyPlaying;
|
||||
}
|
||||
|
||||
gRequestSaveFM = true;
|
||||
|
||||
Bail:
|
||||
BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||||
|
||||
gRequestDisplayScreen = DISPLAY_FM;
|
||||
}
|
||||
|
||||
void FM_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
uint8_t state = bKeyPressed + 2 * bKeyHeld;
|
||||
|
||||
switch (Key) {
|
||||
case KEY_0...KEY_9:
|
||||
Key_DIGITS(Key, state);
|
||||
break;
|
||||
case KEY_STAR:
|
||||
Key_FUNC(Key, state);
|
||||
break;
|
||||
case KEY_MENU:
|
||||
Key_MENU(state);
|
||||
break;
|
||||
case KEY_UP:
|
||||
Key_UP_DOWN(state, 1);
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
Key_UP_DOWN(state, -1);
|
||||
break;;
|
||||
case KEY_EXIT:
|
||||
Key_EXIT(state);
|
||||
break;
|
||||
case KEY_F:
|
||||
GENERIC_Key_F(bKeyPressed, bKeyHeld);
|
||||
break;
|
||||
case KEY_PTT:
|
||||
GENERIC_Key_PTT(bKeyPressed);
|
||||
break;
|
||||
default:
|
||||
if (!bKeyHeld && bKeyPressed)
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FM_Play(void)
|
||||
{
|
||||
if (!FM_CheckFrequencyLock(gEeprom.FM_FrequencyPlaying, BK1080_GetFreqLoLimit(gEeprom.FM_Band))) {
|
||||
if (!gFM_AutoScan) {
|
||||
gFmPlayCountdown_10ms = 0;
|
||||
gFM_FoundFrequency = true;
|
||||
|
||||
if (!gEeprom.FM_IsMrMode)
|
||||
gEeprom.FM_SelectedFrequency = gEeprom.FM_FrequencyPlaying;
|
||||
|
||||
AUDIO_AudioPathOn();
|
||||
gEnableSpeaker = true;
|
||||
|
||||
GUI_SelectNextDisplay(DISPLAY_FM);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gFM_ChannelPosition < 20)
|
||||
gFM_Channels[gFM_ChannelPosition++] = gEeprom.FM_FrequencyPlaying;
|
||||
|
||||
if (gFM_ChannelPosition >= 20) {
|
||||
FM_PlayAndUpdate();
|
||||
GUI_SelectNextDisplay(DISPLAY_FM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (gFM_AutoScan && gEeprom.FM_FrequencyPlaying >= BK1080_GetFreqHiLimit(1))
|
||||
FM_PlayAndUpdate();
|
||||
else
|
||||
FM_Tune(gEeprom.FM_FrequencyPlaying, gFM_ScanState, false);
|
||||
|
||||
GUI_SelectNextDisplay(DISPLAY_FM);
|
||||
}
|
||||
|
||||
void FM_Start(void)
|
||||
{
|
||||
gDualWatchActive = false;
|
||||
gFmRadioMode = true;
|
||||
gFM_ScanState = FM_SCAN_OFF;
|
||||
gFM_RestoreCountdown_10ms = 0;
|
||||
|
||||
BK1080_Init(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
|
||||
|
||||
AUDIO_AudioPathOn();
|
||||
|
||||
gEnableSpeaker = true;
|
||||
gUpdateStatus = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
61
app/fm.h
Normal file
61
app/fm.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APP_FM_H
|
||||
#define APP_FM_H
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
|
||||
#include "driver/keyboard.h"
|
||||
|
||||
#define FM_CHANNEL_UP 0x01
|
||||
#define FM_CHANNEL_DOWN 0xFF
|
||||
|
||||
enum {
|
||||
FM_SCAN_OFF = 0U,
|
||||
};
|
||||
|
||||
extern uint16_t gFM_Channels[20];
|
||||
extern bool gFmRadioMode;
|
||||
extern uint8_t gFmRadioCountdown_500ms;
|
||||
extern volatile uint16_t gFmPlayCountdown_10ms;
|
||||
extern volatile int8_t gFM_ScanState;
|
||||
extern bool gFM_AutoScan;
|
||||
extern uint8_t gFM_ChannelPosition;
|
||||
// Doubts about whether this should be signed or not
|
||||
extern uint16_t gFM_FrequencyDeviation;
|
||||
extern bool gFM_FoundFrequency;
|
||||
extern uint16_t gFM_RestoreCountdown_10ms;
|
||||
|
||||
bool FM_CheckValidChannel(uint8_t Channel);
|
||||
// returns first valid channel starting at Channel
|
||||
uint8_t FM_FindNextChannel(uint8_t Channel, uint8_t Direction);
|
||||
int FM_ConfigureChannelState(void);
|
||||
void FM_TurnOff(void);
|
||||
void FM_EraseChannels(void);
|
||||
|
||||
void FM_Tune(uint16_t Frequency, int8_t Step, bool bFlag);
|
||||
void FM_PlayAndUpdate(void);
|
||||
int FM_CheckFrequencyLock(uint16_t Frequency, uint16_t LowerLimit);
|
||||
|
||||
void FM_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);
|
||||
|
||||
void FM_Play(void);
|
||||
void FM_Start(void);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
225
app/generic.c
Normal file
225
app/generic.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/chFrScanner.h"
|
||||
#include "app/common.h"
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
#include "app/fm.h"
|
||||
#endif
|
||||
|
||||
#include "app/generic.h"
|
||||
#include "app/menu.h"
|
||||
#include "app/scanner.h"
|
||||
#include "audio.h"
|
||||
#include "driver/keyboard.h"
|
||||
#include "dtmf.h"
|
||||
#include "external/printf/printf.h"
|
||||
#include "functions.h"
|
||||
#include "misc.h"
|
||||
#include "settings.h"
|
||||
#include "ui/inputbox.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
void GENERIC_Key_F(bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
if (gInputBoxIndex > 0) {
|
||||
if (!bKeyHeld && bKeyPressed) // short pressed
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (bKeyHeld || !bKeyPressed) { // held or released
|
||||
if (bKeyHeld || bKeyPressed) { // held or pressed (cannot be held and not pressed I guess, so it checks only if HELD?)
|
||||
if (!bKeyHeld) // won't ever pass
|
||||
return;
|
||||
|
||||
if (!bKeyPressed) // won't ever pass
|
||||
return;
|
||||
|
||||
COMMON_KeypadLockToggle();
|
||||
}
|
||||
else { // released
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if ((gFmRadioMode || gScreenToDisplay != DISPLAY_MAIN) && gScreenToDisplay != DISPLAY_FM)
|
||||
return;
|
||||
#else
|
||||
if (gScreenToDisplay != DISPLAY_MAIN)
|
||||
return;
|
||||
#endif
|
||||
|
||||
gWasFKeyPressed = !gWasFKeyPressed; // toggle F function
|
||||
|
||||
if (gWasFKeyPressed)
|
||||
gKeyInputCountdown = key_input_timeout_500ms;
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
if (!gWasFKeyPressed)
|
||||
gAnotherVoiceID = VOICE_ID_CANCEL;
|
||||
#endif
|
||||
gUpdateStatus = true;
|
||||
}
|
||||
}
|
||||
else { // short pressed
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (gScreenToDisplay != DISPLAY_FM)
|
||||
#endif
|
||||
{
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (gFM_ScanState == FM_SCAN_OFF) { // not scanning
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
gBeepToPlay = BEEP_440HZ_500MS;
|
||||
gPttWasReleased = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GENERIC_Key_PTT(bool bKeyPressed)
|
||||
{
|
||||
gInputBoxIndex = 0;
|
||||
|
||||
if (!bKeyPressed || SerialConfigInProgress())
|
||||
{ // PTT released
|
||||
if (gCurrentFunction == FUNCTION_TRANSMIT) {
|
||||
// we are transmitting .. stop
|
||||
if (gFlagEndTransmission) {
|
||||
FUNCTION_Select(FUNCTION_FOREGROUND);
|
||||
}
|
||||
else {
|
||||
APP_EndTransmission();
|
||||
|
||||
if (gEeprom.REPEATER_TAIL_TONE_ELIMINATION == 0)
|
||||
FUNCTION_Select(FUNCTION_FOREGROUND);
|
||||
else
|
||||
gRTTECountdown_10ms = gEeprom.REPEATER_TAIL_TONE_ELIMINATION * 10;
|
||||
}
|
||||
|
||||
gFlagEndTransmission = false;
|
||||
#ifdef ENABLE_VOX
|
||||
gVOX_NoiseDetected = false;
|
||||
#endif
|
||||
RADIO_SetVfoState(VFO_STATE_NORMAL);
|
||||
|
||||
if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// PTT pressed
|
||||
|
||||
|
||||
if (SCANNER_IsScanning()) {
|
||||
SCANNER_Stop(); // CTCSS/CDCSS scanning .. stop
|
||||
goto cancel_tx;
|
||||
}
|
||||
|
||||
if (gScanStateDir != SCAN_OFF) {
|
||||
CHFRSCANNER_Stop(); // frequency/channel scanning . .stop
|
||||
goto cancel_tx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (gFM_ScanState != FM_SCAN_OFF) { // FM radio is scanning .. stop
|
||||
FM_PlayAndUpdate();
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
|
||||
#endif
|
||||
gRequestDisplayScreen = DISPLAY_FM;
|
||||
goto cancel_tx;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (gScreenToDisplay == DISPLAY_FM)
|
||||
goto start_tx; // listening to the FM radio .. start TX'ing
|
||||
#endif
|
||||
|
||||
if (gCurrentFunction == FUNCTION_TRANSMIT && gRTTECountdown_10ms == 0) {// already transmitting
|
||||
gInputBoxIndex = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
|
||||
|
||||
if (!gDTMF_InputMode && gDTMF_InputBox_Index == 0)
|
||||
goto start_tx; // wasn't entering a DTMF code .. start TX'ing (maybe)
|
||||
|
||||
// was entering a DTMF string
|
||||
|
||||
if (gDTMF_InputBox_Index > 0 || gDTMF_PreviousIndex > 0) { // going to transmit a DTMF string
|
||||
if (gDTMF_InputBox_Index == 0 && gDTMF_PreviousIndex > 0)
|
||||
gDTMF_InputBox_Index = gDTMF_PreviousIndex; // use the previous DTMF string
|
||||
|
||||
if (gDTMF_InputBox_Index < sizeof(gDTMF_InputBox))
|
||||
gDTMF_InputBox[gDTMF_InputBox_Index] = 0; // NULL term the string
|
||||
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
// append our DTMF ID to the inputted DTMF code -
|
||||
// IF the user inputted code is exactly 3 digits long and D-DCD is enabled
|
||||
if (gDTMF_InputBox_Index == 3 && gTxVfo->DTMF_DECODING_ENABLE > 0)
|
||||
gDTMF_CallMode = DTMF_CheckGroupCall(gDTMF_InputBox, 3);
|
||||
else
|
||||
gDTMF_CallMode = DTMF_CALL_MODE_DTMF;
|
||||
|
||||
gDTMF_State = DTMF_STATE_0;
|
||||
#endif
|
||||
// remember the DTMF string
|
||||
gDTMF_PreviousIndex = gDTMF_InputBox_Index;
|
||||
strcpy(gDTMF_String, gDTMF_InputBox);
|
||||
gDTMF_ReplyState = DTMF_REPLY_ANI;
|
||||
}
|
||||
|
||||
DTMF_clear_input_box();
|
||||
|
||||
start_tx:
|
||||
// request start TX
|
||||
gFlagPrepareTX = true;
|
||||
goto done;
|
||||
|
||||
cancel_tx:
|
||||
if (gPttIsPressed) {
|
||||
gPttWasPressed = true;
|
||||
}
|
||||
|
||||
done:
|
||||
gPttDebounceCounter = 0;
|
||||
if (gScreenToDisplay != DISPLAY_MENU
|
||||
#ifdef ENABLE_FMRADIO
|
||||
&& gRequestDisplayScreen != DISPLAY_FM
|
||||
#endif
|
||||
) {
|
||||
// 1of11 .. don't close the menu
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
}
|
||||
|
||||
gUpdateStatus = true;
|
||||
gUpdateDisplay = true;
|
||||
}
|
||||
26
app/generic.h
Normal file
26
app/generic.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APP_GENERIC_H
|
||||
#define APP_GENERIC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
void GENERIC_Key_F(bool bKeyPressed, bool bKeyHeld);
|
||||
void GENERIC_Key_PTT(bool bKeyPressed);
|
||||
|
||||
#endif
|
||||
|
||||
743
app/main.c
Normal file
743
app/main.c
Normal file
@@ -0,0 +1,743 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "app/action.h"
|
||||
#include "app/app.h"
|
||||
#include "app/chFrScanner.h"
|
||||
#include "app/common.h"
|
||||
#ifdef ENABLE_FMRADIO
|
||||
#include "app/fm.h"
|
||||
#endif
|
||||
#include "app/generic.h"
|
||||
#include "app/main.h"
|
||||
#include "app/scanner.h"
|
||||
|
||||
#ifdef ENABLE_SPECTRUM
|
||||
#include "app/spectrum.h"
|
||||
#endif
|
||||
|
||||
#include "audio.h"
|
||||
#include "board.h"
|
||||
#include "driver/bk4819.h"
|
||||
#include "dtmf.h"
|
||||
#include "frequencies.h"
|
||||
#include "misc.h"
|
||||
#include "radio.h"
|
||||
#include "settings.h"
|
||||
#include "ui/inputbox.h"
|
||||
#include "ui/ui.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void toggle_chan_scanlist(void)
|
||||
{ // toggle the selected channels scanlist setting
|
||||
|
||||
if (SCANNER_IsScanning())
|
||||
return;
|
||||
|
||||
if(!IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) {
|
||||
#ifdef ENABLE_SCAN_RANGES
|
||||
gScanRangeStart = gScanRangeStart ? 0 : gTxVfo->pRX->Frequency;
|
||||
gScanRangeStop = gEeprom.VfoInfo[!gEeprom.TX_VFO].freq_config_RX.Frequency;
|
||||
if(gScanRangeStart > gScanRangeStop)
|
||||
SWAP(gScanRangeStart, gScanRangeStop);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (gTxVfo->SCANLIST1_PARTICIPATION ^ gTxVfo->SCANLIST2_PARTICIPATION){
|
||||
gTxVfo->SCANLIST2_PARTICIPATION = gTxVfo->SCANLIST1_PARTICIPATION;
|
||||
} else {
|
||||
gTxVfo->SCANLIST1_PARTICIPATION = !gTxVfo->SCANLIST1_PARTICIPATION;
|
||||
}
|
||||
|
||||
SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true);
|
||||
|
||||
gVfoConfigureMode = VFO_CONFIGURE;
|
||||
gFlagResetVfos = true;
|
||||
}
|
||||
|
||||
static void processFKeyFunction(const KEY_Code_t Key, const bool beep)
|
||||
{
|
||||
uint8_t Vfo = gEeprom.TX_VFO;
|
||||
|
||||
if (gScreenToDisplay == DISPLAY_MENU) {
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
|
||||
switch (Key) {
|
||||
case KEY_0:
|
||||
#ifdef ENABLE_FMRADIO
|
||||
ACTION_FM();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case KEY_1:
|
||||
if (!IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE)) {
|
||||
gWasFKeyPressed = false;
|
||||
gUpdateStatus = true;
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
|
||||
#ifdef ENABLE_COPY_CHAN_TO_VFO
|
||||
if (!gEeprom.VFO_OPEN || gCssBackgroundScan) {
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gScanStateDir != SCAN_OFF) {
|
||||
if (gCurrentFunction != FUNCTION_INCOMING ||
|
||||
gRxReceptionMode == RX_MODE_NONE ||
|
||||
gScanPauseDelayIn_10ms == 0)
|
||||
{ // scan is running (not paused)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t vfo = gEeprom.TX_VFO;
|
||||
|
||||
if (IS_MR_CHANNEL(gEeprom.ScreenChannel[vfo]))
|
||||
{ // copy channel to VFO, then swap to the VFO
|
||||
|
||||
gEeprom.ScreenChannel[vfo] = FREQ_CHANNEL_FIRST + gEeprom.VfoInfo[vfo].Band;
|
||||
gEeprom.VfoInfo[vfo].CHANNEL_SAVE = gEeprom.ScreenChannel[vfo];
|
||||
|
||||
RADIO_SelectVfos();
|
||||
RADIO_ApplyOffset(gRxVfo);
|
||||
RADIO_ConfigureSquelchAndOutputPower(gRxVfo);
|
||||
RADIO_SetupRegisters(true);
|
||||
|
||||
//SETTINGS_SaveChannel(channel, gEeprom.RX_VFO, gRxVfo, 1);
|
||||
|
||||
gUpdateDisplay = true;
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WIDE_RX
|
||||
if(gTxVfo->Band == BAND7_470MHz && gTxVfo->pRX->Frequency < _1GHz_in_KHz) {
|
||||
gTxVfo->pRX->Frequency = _1GHz_in_KHz;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
gTxVfo->Band += 1;
|
||||
|
||||
if (gTxVfo->Band == BAND5_350MHz && !gSetting_350EN) {
|
||||
// skip if not enabled
|
||||
gTxVfo->Band += 1;
|
||||
} else if (gTxVfo->Band >= BAND_N_ELEM){
|
||||
// go arround if overflowed
|
||||
gTxVfo->Band = BAND1_50MHz;
|
||||
}
|
||||
|
||||
gEeprom.ScreenChannel[Vfo] = FREQ_CHANNEL_FIRST + gTxVfo->Band;
|
||||
gEeprom.FreqChannel[Vfo] = FREQ_CHANNEL_FIRST + gTxVfo->Band;
|
||||
|
||||
gRequestSaveVFO = true;
|
||||
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
|
||||
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
|
||||
if (beep)
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
|
||||
break;
|
||||
|
||||
case KEY_2:
|
||||
COMMON_SwitchVFOs();
|
||||
|
||||
if (beep)
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
break;
|
||||
|
||||
case KEY_3:
|
||||
COMMON_SwitchVFOMode();
|
||||
|
||||
if (beep)
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
|
||||
break;
|
||||
|
||||
case KEY_4:
|
||||
gWasFKeyPressed = false;
|
||||
|
||||
gBackup_CROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX;
|
||||
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
|
||||
gUpdateStatus = true;
|
||||
if (beep)
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
|
||||
SCANNER_Start(false);
|
||||
gRequestDisplayScreen = DISPLAY_SCANNER;
|
||||
break;
|
||||
|
||||
case KEY_5:
|
||||
if(beep) {
|
||||
#ifdef ENABLE_NOAA
|
||||
if (!IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE)) {
|
||||
gEeprom.ScreenChannel[Vfo] = gEeprom.NoaaChannel[gEeprom.TX_VFO];
|
||||
}
|
||||
else {
|
||||
gEeprom.ScreenChannel[Vfo] = gEeprom.FreqChannel[gEeprom.TX_VFO];
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_FREQUENCY_MODE;
|
||||
#endif
|
||||
}
|
||||
gRequestSaveVFO = true;
|
||||
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
|
||||
#elif defined(ENABLE_SPECTRUM)
|
||||
APP_RunSpectrum();
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#ifdef ENABLE_VOX
|
||||
toggle_chan_scanlist();
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case KEY_6:
|
||||
ACTION_Power();
|
||||
break;
|
||||
|
||||
case KEY_7:
|
||||
#ifdef ENABLE_VOX
|
||||
ACTION_Vox();
|
||||
#else
|
||||
toggle_chan_scanlist();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case KEY_8:
|
||||
gTxVfo->FrequencyReverse = gTxVfo->FrequencyReverse == false;
|
||||
gRequestSaveChannel = 1;
|
||||
break;
|
||||
|
||||
case KEY_9:
|
||||
if (RADIO_CheckValidChannel(gEeprom.CHAN_1_CALL, false, 0)) {
|
||||
gEeprom.MrChannel[Vfo] = gEeprom.CHAN_1_CALL;
|
||||
gEeprom.ScreenChannel[Vfo] = gEeprom.CHAN_1_CALL;
|
||||
#ifdef ENABLE_VOICE
|
||||
AUDIO_SetVoiceID(0, VOICE_ID_CHANNEL_MODE);
|
||||
AUDIO_SetDigitVoice(1, gEeprom.CHAN_1_CALL + 1);
|
||||
gAnotherVoiceID = (VOICE_ID_t)0xFE;
|
||||
#endif
|
||||
gRequestSaveVFO = true;
|
||||
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
|
||||
break;
|
||||
}
|
||||
|
||||
if (beep)
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
gUpdateStatus = true;
|
||||
gWasFKeyPressed = false;
|
||||
|
||||
if (beep)
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void MAIN_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
if (bKeyHeld) { // key held down
|
||||
if (bKeyPressed) {
|
||||
if (gScreenToDisplay == DISPLAY_MAIN) {
|
||||
if (gInputBoxIndex > 0) { // delete any inputted chars
|
||||
gInputBoxIndex = 0;
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
}
|
||||
|
||||
gWasFKeyPressed = false;
|
||||
gUpdateStatus = true;
|
||||
|
||||
processFKeyFunction(Key, false);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (bKeyPressed)
|
||||
{ // key is pressed
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; // beep when key is pressed
|
||||
return; // don't use the key till it's released
|
||||
}
|
||||
|
||||
if (!gWasFKeyPressed) { // F-key wasn't pressed
|
||||
const uint8_t Vfo = gEeprom.TX_VFO;
|
||||
gKeyInputCountdown = key_input_timeout_500ms;
|
||||
INPUTBOX_Append(Key);
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
|
||||
if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) { // user is entering channel number
|
||||
|
||||
if (gInputBoxIndex != 3) {
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||||
#endif
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
return;
|
||||
}
|
||||
|
||||
gInputBoxIndex = 0;
|
||||
|
||||
const uint16_t Channel = ((gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]) - 1;
|
||||
|
||||
if (!RADIO_CheckValidChannel(Channel, false, 0)) {
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||||
#endif
|
||||
|
||||
gEeprom.MrChannel[Vfo] = (uint8_t)Channel;
|
||||
gEeprom.ScreenChannel[Vfo] = (uint8_t)Channel;
|
||||
gRequestSaveVFO = true;
|
||||
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// #ifdef ENABLE_NOAA
|
||||
// if (!IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE))
|
||||
// #endif
|
||||
if (IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE))
|
||||
{ // user is entering a frequency
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||||
#endif
|
||||
bool isGigaF = gTxVfo->pRX->Frequency >= _1GHz_in_KHz;
|
||||
if (gInputBoxIndex < 6 + isGigaF) {
|
||||
return;
|
||||
}
|
||||
|
||||
gInputBoxIndex = 0;
|
||||
uint32_t Frequency = StrToUL(INPUTBOX_GetAscii()) * 100;
|
||||
|
||||
// clamp the frequency entered to some valid value
|
||||
if (Frequency < frequencyBandTable[0].lower) {
|
||||
Frequency = frequencyBandTable[0].lower;
|
||||
}
|
||||
else if (Frequency >= BX4819_band1.upper && Frequency < BX4819_band2.lower) {
|
||||
const uint32_t center = (BX4819_band1.upper + BX4819_band2.lower) / 2;
|
||||
Frequency = (Frequency < center) ? BX4819_band1.upper : BX4819_band2.lower;
|
||||
}
|
||||
else if (Frequency > frequencyBandTable[BAND_N_ELEM - 1].upper) {
|
||||
Frequency = frequencyBandTable[BAND_N_ELEM - 1].upper;
|
||||
}
|
||||
|
||||
const FREQUENCY_Band_t band = FREQUENCY_GetBand(Frequency);
|
||||
|
||||
if (gTxVfo->Band != band) {
|
||||
gTxVfo->Band = band;
|
||||
gEeprom.ScreenChannel[Vfo] = band + FREQ_CHANNEL_FIRST;
|
||||
gEeprom.FreqChannel[Vfo] = band + FREQ_CHANNEL_FIRST;
|
||||
|
||||
SETTINGS_SaveVfoIndices();
|
||||
|
||||
RADIO_ConfigureChannel(Vfo, VFO_CONFIGURE_RELOAD);
|
||||
}
|
||||
|
||||
Frequency = FREQUENCY_RoundToStep(Frequency, gTxVfo->StepFrequency);
|
||||
|
||||
if (Frequency >= BX4819_band1.upper && Frequency < BX4819_band2.lower)
|
||||
{ // clamp the frequency to the limit
|
||||
const uint32_t center = (BX4819_band1.upper + BX4819_band2.lower) / 2;
|
||||
Frequency = (Frequency < center) ? BX4819_band1.upper - gTxVfo->StepFrequency : BX4819_band2.lower;
|
||||
}
|
||||
|
||||
gTxVfo->freq_config_RX.Frequency = Frequency;
|
||||
|
||||
gRequestSaveChannel = 1;
|
||||
return;
|
||||
|
||||
}
|
||||
#ifdef ENABLE_NOAA
|
||||
else
|
||||
if (IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE))
|
||||
{ // user is entering NOAA channel
|
||||
if (gInputBoxIndex != 2) {
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||||
#endif
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
return;
|
||||
}
|
||||
|
||||
gInputBoxIndex = 0;
|
||||
|
||||
uint8_t Channel = (gInputBox[0] * 10) + gInputBox[1];
|
||||
if (Channel >= 1 && Channel <= ARRAY_SIZE(NoaaFrequencyTable)) {
|
||||
Channel += NOAA_CHANNEL_FIRST;
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||||
#endif
|
||||
gEeprom.NoaaChannel[Vfo] = Channel;
|
||||
gEeprom.ScreenChannel[Vfo] = Channel;
|
||||
gRequestSaveVFO = true;
|
||||
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
gWasFKeyPressed = false;
|
||||
gUpdateStatus = true;
|
||||
|
||||
processFKeyFunction(Key, true);
|
||||
}
|
||||
|
||||
static void MAIN_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
if (!bKeyHeld && bKeyPressed) { // exit key pressed
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
if (gDTMF_CallState != DTMF_CALL_STATE_NONE && gCurrentFunction != FUNCTION_TRANSMIT)
|
||||
{ // clear CALL mode being displayed
|
||||
gDTMF_CallState = DTMF_CALL_STATE_NONE;
|
||||
gUpdateDisplay = true;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (!gFmRadioMode)
|
||||
#endif
|
||||
{
|
||||
if (gScanStateDir == SCAN_OFF) {
|
||||
if (gInputBoxIndex == 0)
|
||||
return;
|
||||
gInputBox[--gInputBoxIndex] = 10;
|
||||
|
||||
gKeyInputCountdown = key_input_timeout_500ms;
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
if (gInputBoxIndex == 0)
|
||||
gAnotherVoiceID = VOICE_ID_CANCEL;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
gScanKeepResult = false;
|
||||
CHFRSCANNER_Stop();
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
|
||||
#endif
|
||||
}
|
||||
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
ACTION_FM();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (bKeyHeld && bKeyPressed) { // exit key held down
|
||||
if (gInputBoxIndex > 0 || gDTMF_InputBox_Index > 0 || gDTMF_InputMode)
|
||||
{ // cancel key input mode (channel/frequency entry)
|
||||
gDTMF_InputMode = false;
|
||||
gDTMF_InputBox_Index = 0;
|
||||
memset(gDTMF_String, 0, sizeof(gDTMF_String));
|
||||
gInputBoxIndex = 0;
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MAIN_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
|
||||
{
|
||||
if (bKeyPressed && !bKeyHeld) // menu key pressed
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
|
||||
if (bKeyHeld) { // menu key held down (long press)
|
||||
if (bKeyPressed) { // long press MENU key
|
||||
|
||||
gWasFKeyPressed = false;
|
||||
|
||||
if (gScreenToDisplay == DISPLAY_MAIN) {
|
||||
if (gInputBoxIndex > 0) { // delete any inputted chars
|
||||
gInputBoxIndex = 0;
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
}
|
||||
|
||||
gWasFKeyPressed = false;
|
||||
gUpdateStatus = true;
|
||||
|
||||
ACTION_Handle(KEY_MENU, bKeyPressed, bKeyHeld);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bKeyPressed && !gDTMF_InputMode) { // menu key released
|
||||
const bool bFlag = !gInputBoxIndex;
|
||||
gInputBoxIndex = 0;
|
||||
|
||||
if (bFlag) {
|
||||
if (gScanStateDir != SCAN_OFF) {
|
||||
CHFRSCANNER_Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
gFlagRefreshSetting = true;
|
||||
gRequestDisplayScreen = DISPLAY_MENU;
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_MENU;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MAIN_Key_STAR(bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
if (gCurrentFunction == FUNCTION_TRANSMIT)
|
||||
return;
|
||||
|
||||
if (gInputBoxIndex) {
|
||||
if (!bKeyHeld && bKeyPressed)
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (bKeyHeld && !gWasFKeyPressed){ // long press
|
||||
if (!bKeyPressed) // released
|
||||
return;
|
||||
|
||||
ACTION_Scan(false);// toggle scanning
|
||||
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (bKeyPressed) { // just pressed
|
||||
return;
|
||||
}
|
||||
|
||||
// just released
|
||||
|
||||
if (!gWasFKeyPressed) // pressed without the F-key
|
||||
{
|
||||
if (gScanStateDir == SCAN_OFF
|
||||
#ifdef ENABLE_NOAA
|
||||
&& !IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE)
|
||||
#endif
|
||||
#ifdef ENABLE_SCAN_RANGES
|
||||
&& gScanRangeStart == 0
|
||||
#endif
|
||||
)
|
||||
{ // start entering a DTMF string
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
memcpy(gDTMF_InputBox, gDTMF_String, MIN(sizeof(gDTMF_InputBox), sizeof(gDTMF_String) - 1));
|
||||
gDTMF_InputBox_Index = 0;
|
||||
gDTMF_InputMode = true;
|
||||
|
||||
gKeyInputCountdown = key_input_timeout_500ms;
|
||||
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
}
|
||||
else
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
}
|
||||
else
|
||||
{ // with the F-key
|
||||
gWasFKeyPressed = false;
|
||||
|
||||
#ifdef ENABLE_NOAA
|
||||
if (IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE)) {
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// scan the CTCSS/DCS code
|
||||
gBackup_CROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX;
|
||||
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
|
||||
SCANNER_Start(true);
|
||||
gRequestDisplayScreen = DISPLAY_SCANNER;
|
||||
}
|
||||
|
||||
gPttWasReleased = true;
|
||||
gUpdateStatus = true;
|
||||
}
|
||||
|
||||
static void MAIN_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
|
||||
{
|
||||
uint8_t Channel = gEeprom.ScreenChannel[gEeprom.TX_VFO];
|
||||
|
||||
if (bKeyHeld || !bKeyPressed) { // key held or released
|
||||
if (gInputBoxIndex > 0)
|
||||
return; // leave if input box active
|
||||
|
||||
if (!bKeyPressed) {
|
||||
if (!bKeyHeld || IS_FREQ_CHANNEL(Channel))
|
||||
return;
|
||||
// if released long button press and not in freq mode
|
||||
#ifdef ENABLE_VOICE
|
||||
AUDIO_SetDigitVoice(0, gTxVfo->CHANNEL_SAVE + 1); // say channel number
|
||||
gAnotherVoiceID = (VOICE_ID_t)0xFE;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
else { // short pressed
|
||||
if (gInputBoxIndex > 0) {
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
}
|
||||
|
||||
if (gScanStateDir == SCAN_OFF) {
|
||||
#ifdef ENABLE_NOAA
|
||||
if (!IS_NOAA_CHANNEL(Channel))
|
||||
#endif
|
||||
{
|
||||
uint8_t Next;
|
||||
if (IS_FREQ_CHANNEL(Channel)) { // step/down in frequency
|
||||
const uint32_t frequency = APP_SetFrequencyByStep(gTxVfo, Direction);
|
||||
|
||||
if (RX_freq_check(frequency) < 0) { // frequency not allowed
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
gTxVfo->freq_config_RX.Frequency = frequency;
|
||||
BK4819_SetFrequency(frequency);
|
||||
BK4819_RX_TurnOn();
|
||||
gRequestSaveChannel = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
Next = RADIO_FindNextChannel(Channel + Direction, Direction, false, 0);
|
||||
if (Next == 0xFF)
|
||||
return;
|
||||
if (Channel == Next)
|
||||
return;
|
||||
gEeprom.MrChannel[gEeprom.TX_VFO] = Next;
|
||||
gEeprom.ScreenChannel[gEeprom.TX_VFO] = Next;
|
||||
|
||||
if (!bKeyHeld) {
|
||||
#ifdef ENABLE_VOICE
|
||||
AUDIO_SetDigitVoice(0, Next + 1);
|
||||
gAnotherVoiceID = (VOICE_ID_t)0xFE;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_NOAA
|
||||
else {
|
||||
Channel = NOAA_CHANNEL_FIRST + NUMBER_AddWithWraparound(gEeprom.ScreenChannel[gEeprom.TX_VFO] - NOAA_CHANNEL_FIRST, Direction, 0, 9);
|
||||
gEeprom.NoaaChannel[gEeprom.TX_VFO] = Channel;
|
||||
gEeprom.ScreenChannel[gEeprom.TX_VFO] = Channel;
|
||||
}
|
||||
#endif
|
||||
|
||||
gRequestSaveVFO = true;
|
||||
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
|
||||
return;
|
||||
}
|
||||
|
||||
// jump to the next channel
|
||||
CHFRSCANNER_Start(false, Direction);
|
||||
gScanPauseDelayIn_10ms = 1;
|
||||
gScheduleScanListen = false;
|
||||
|
||||
gPttWasReleased = true;
|
||||
}
|
||||
|
||||
void MAIN_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (gFmRadioMode && Key != KEY_PTT && Key != KEY_EXIT) {
|
||||
if (!bKeyHeld && bKeyPressed)
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (gDTMF_InputMode && bKeyPressed && !bKeyHeld) {
|
||||
const char Character = DTMF_GetCharacter(Key);
|
||||
if (Character != 0xFF)
|
||||
{ // add key to DTMF string
|
||||
DTMF_Append(Character);
|
||||
gKeyInputCountdown = key_input_timeout_500ms;
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
gPttWasReleased = true;
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: ???
|
||||
// if (Key > KEY_PTT)
|
||||
// {
|
||||
// Key = KEY_SIDE2; // what's this doing ???
|
||||
// }
|
||||
|
||||
switch (Key) {
|
||||
case KEY_0...KEY_9:
|
||||
MAIN_Key_DIGITS(Key, bKeyPressed, bKeyHeld);
|
||||
break;
|
||||
case KEY_MENU:
|
||||
MAIN_Key_MENU(bKeyPressed, bKeyHeld);
|
||||
break;
|
||||
case KEY_UP:
|
||||
MAIN_Key_UP_DOWN(bKeyPressed, bKeyHeld, 1);
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
MAIN_Key_UP_DOWN(bKeyPressed, bKeyHeld, -1);
|
||||
break;
|
||||
case KEY_EXIT:
|
||||
MAIN_Key_EXIT(bKeyPressed, bKeyHeld);
|
||||
break;
|
||||
case KEY_STAR:
|
||||
MAIN_Key_STAR(bKeyPressed, bKeyHeld);
|
||||
break;
|
||||
case KEY_F:
|
||||
GENERIC_Key_F(bKeyPressed, bKeyHeld);
|
||||
break;
|
||||
case KEY_PTT:
|
||||
GENERIC_Key_PTT(bKeyPressed);
|
||||
break;
|
||||
default:
|
||||
if (!bKeyHeld && bKeyPressed)
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
25
app/main.h
Normal file
25
app/main.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APP_MAIN_H
|
||||
#define APP_MAIN_H
|
||||
|
||||
#include "driver/keyboard.h"
|
||||
|
||||
void MAIN_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);
|
||||
|
||||
#endif
|
||||
|
||||
1739
app/menu.c
Normal file
1739
app/menu.c
Normal file
File diff suppressed because it is too large
Load Diff
38
app/menu.h
Normal file
38
app/menu.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APP_MENU_H
|
||||
#define APP_MENU_H
|
||||
|
||||
#include "driver/keyboard.h"
|
||||
|
||||
#ifdef ENABLE_F_CAL_MENU
|
||||
void writeXtalFreqCal(const int32_t value, const bool update_eeprom);
|
||||
#endif
|
||||
|
||||
extern uint8_t gUnlockAllTxConfCnt;
|
||||
|
||||
int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax);
|
||||
void MENU_AcceptSetting(void);
|
||||
void MENU_ShowCurrentSetting(void);
|
||||
void MENU_StartCssScan(void);
|
||||
void MENU_CssScanFound(void);
|
||||
void MENU_StopCssScan(void);
|
||||
|
||||
void MENU_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);
|
||||
|
||||
#endif
|
||||
|
||||
333
app/mode.c
Normal file
333
app/mode.c
Normal file
@@ -0,0 +1,333 @@
|
||||
/* UA1ZBE Custom Firmware - Mode Dispatcher Implementation
|
||||
*
|
||||
* Central dispatcher for VFO, POCSAG, Spectrum, and FM modes.
|
||||
*
|
||||
* Architecture:
|
||||
* - VFO mode: use full APP_TimeSlice infrastructure
|
||||
* - POCSAG mode: use APP_TimeSlice for interrupts but intercept keys
|
||||
* - Spectrum: blocking loop, returns to VFO
|
||||
* - FM: uses FM radio subsystem
|
||||
*/
|
||||
|
||||
#include "mode.h"
|
||||
#include "app/app.h"
|
||||
#include "app/common.h"
|
||||
#include "app/display_rssi.h"
|
||||
#include "driver/bk4819.h"
|
||||
#include "driver/keyboard.h"
|
||||
#include "driver/st7565.h"
|
||||
#include "driver/system.h"
|
||||
#include "ui/helper.h"
|
||||
#include "ui/main.h"
|
||||
#include "misc.h"
|
||||
#include "radio.h"
|
||||
#include "settings.h"
|
||||
#include "functions.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef ENABLE_POCSAG
|
||||
#include "pocsag/pocsag.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SPECTRUM
|
||||
#include "app/spectrum.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
#include "app/fm.h"
|
||||
#endif
|
||||
|
||||
/* === State === */
|
||||
|
||||
static op_mode_t s_current_mode = MODE_VFO;
|
||||
static GUI_DisplayType_t s_saved_display_type;
|
||||
|
||||
/* === Mode entry/exit === */
|
||||
|
||||
static void mode_enter_vfo(void)
|
||||
{
|
||||
RADIO_SetupRegisters(true);
|
||||
gScreenToDisplay = s_saved_display_type;
|
||||
gUpdateDisplay = true;
|
||||
}
|
||||
|
||||
static void mode_enter_pocsag(void)
|
||||
{
|
||||
#ifdef ENABLE_POCSAG
|
||||
POCSAG_ConfigureRadio(gRxVfo->freq_config_RX.Frequency);
|
||||
POCSAG_Init(POCSAG_BAUD_1200);
|
||||
|
||||
/* Save current display type and set to INVALID to skip standard key handling */
|
||||
s_saved_display_type = gScreenToDisplay;
|
||||
gScreenToDisplay = DISPLAY_INVALID;
|
||||
|
||||
ST7565_FillScreen(0x00);
|
||||
for (int line = 0; line < FRAME_LINES; line++)
|
||||
memset(gFrameBuffer[line], 0, LCD_WIDTH);
|
||||
memset(gStatusLine, 0, sizeof(gStatusLine));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mode_enter_fm(void)
|
||||
{
|
||||
#ifdef ENABLE_FMRADIO
|
||||
s_saved_display_type = gScreenToDisplay;
|
||||
gFmRadioMode = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mode_exit_current(void)
|
||||
{
|
||||
switch (s_current_mode) {
|
||||
case MODE_POCSAG:
|
||||
#ifdef ENABLE_POCSAG
|
||||
POCSAG_Stop();
|
||||
gScreenToDisplay = s_saved_display_type;
|
||||
#endif
|
||||
break;
|
||||
case MODE_FM:
|
||||
#ifdef ENABLE_FMRADIO
|
||||
FM_TurnOff();
|
||||
gFmRadioMode = false;
|
||||
gScreenToDisplay = s_saved_display_type;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* === Mode switching === */
|
||||
|
||||
void MODE_Switch(op_mode_t mode)
|
||||
{
|
||||
if (mode == s_current_mode || mode >= MODE_COUNT)
|
||||
return;
|
||||
|
||||
mode_exit_current();
|
||||
s_current_mode = mode;
|
||||
|
||||
switch (mode) {
|
||||
case MODE_VFO: mode_enter_vfo(); break;
|
||||
case MODE_POCSAG: mode_enter_pocsag(); break;
|
||||
case MODE_SPECTRUM: /* Spectrum is blocking */ break;
|
||||
case MODE_FM: mode_enter_fm(); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
gUpdateDisplay = true;
|
||||
}
|
||||
|
||||
op_mode_t MODE_GetCurrent(void)
|
||||
{
|
||||
return s_current_mode;
|
||||
}
|
||||
|
||||
void MODE_Init(void)
|
||||
{
|
||||
s_current_mode = MODE_VFO;
|
||||
s_saved_display_type = DISPLAY_MAIN;
|
||||
mode_enter_vfo();
|
||||
}
|
||||
|
||||
/* === POCSAG display === */
|
||||
|
||||
static void pocsag_draw(void)
|
||||
{
|
||||
#ifdef ENABLE_POCSAG
|
||||
ST7565_FillScreen(0x00);
|
||||
for (int line = 0; line < FRAME_LINES; line++)
|
||||
memset(gFrameBuffer[line], 0, LCD_WIDTH);
|
||||
memset(gStatusLine, 0, sizeof(gStatusLine));
|
||||
|
||||
char buf[32];
|
||||
|
||||
/* Header */
|
||||
uint32_t baud = POCSAG_GetBaud();
|
||||
sprintf(buf, "POCSAG %lu", baud);
|
||||
UI_PrintString(buf, 0, LCD_WIDTH, 0, 10);
|
||||
|
||||
/* Status */
|
||||
const char *state_str = POCSAG_StateString(POCSAG_GetState());
|
||||
UI_PrintStringSmallNormal(state_str, 0, LCD_WIDTH, 16);
|
||||
|
||||
if (POCSAG_SignalDetected())
|
||||
UI_PrintStringSmallNormal("SIG", 100, LCD_WIDTH, 16);
|
||||
|
||||
/* Message count and stats */
|
||||
sprintf(buf, "Msgs:%d W:%lu", gPocsag.msg_count, gPocsag.total_words);
|
||||
UI_PrintStringSmallNormal(buf, 0, LCD_WIDTH, 28);
|
||||
|
||||
sprintf(buf, "Corr:%lu", gPocsag.corrected_errors);
|
||||
UI_PrintStringSmallNormal(buf, 0, LCD_WIDTH, 38);
|
||||
|
||||
/* RSSI */
|
||||
sprintf(buf, "%ddBm", RSSI_GetdBm());
|
||||
UI_PrintStringSmallNormal(buf, 0, LCD_WIDTH, 48);
|
||||
|
||||
/* Help */
|
||||
UI_PrintStringSmallNormal("F=512/1200 X=VFO", 0, LCD_WIDTH, 56);
|
||||
|
||||
ST7565_BlitStatusLine();
|
||||
ST7565_BlitFullScreen();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* === Key debounce for POCSAG === */
|
||||
|
||||
static KEY_Code_t s_last_key = KEY_INVALID;
|
||||
static uint16_t s_key_debounce = 0;
|
||||
|
||||
static KEY_Code_t read_key_debounced(void)
|
||||
{
|
||||
KEY_Code_t key = KEYBOARD_Poll();
|
||||
|
||||
if (key == s_last_key) {
|
||||
if (s_key_debounce < 3) {
|
||||
s_key_debounce++;
|
||||
return KEY_INVALID;
|
||||
}
|
||||
} else {
|
||||
s_last_key = key;
|
||||
s_key_debounce = 0;
|
||||
return KEY_INVALID;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/* === Timeslice handlers === */
|
||||
|
||||
void MODE_TimeSlice10ms(void)
|
||||
{
|
||||
/* Always call standard app processing for interrupts, etc. */
|
||||
APP_TimeSlice10ms();
|
||||
|
||||
/* Mode-specific processing */
|
||||
switch (s_current_mode) {
|
||||
case MODE_VFO:
|
||||
/* VFO display already handled by APP_TimeSlice10ms.
|
||||
* Add RSSI overlay on top. */
|
||||
if (gScreenToDisplay == DISPLAY_MAIN) {
|
||||
RSSI_Draw(95, 0, false);
|
||||
ST7565_BlitFullScreen();
|
||||
}
|
||||
break;
|
||||
|
||||
case MODE_POCSAG:
|
||||
#ifdef ENABLE_POCSAG
|
||||
/* Feed audio samples to POCSAG decoder */
|
||||
{
|
||||
uint16_t audio = BK4819_GetVoiceAmplitudeOut();
|
||||
POCSAG_FeedSample(audio);
|
||||
}
|
||||
POCSAG_Process();
|
||||
|
||||
/* Check for messages */
|
||||
if (POCSAG_MessageAvailable()) {
|
||||
pocsag_msg_t msg;
|
||||
if (POCSAG_GetMessage(&msg)) {
|
||||
/* New message received */
|
||||
}
|
||||
}
|
||||
|
||||
/* Process POCSAG-specific keys (gScreenToDisplay is INVALID) */
|
||||
{
|
||||
KEY_Code_t Key = read_key_debounced();
|
||||
if (Key != KEY_INVALID) {
|
||||
if (Key == KEY_EXIT) {
|
||||
MODE_Switch(MODE_VFO);
|
||||
} else if (Key == KEY_F || Key == KEY_STAR) {
|
||||
uint32_t cur = POCSAG_GetBaud();
|
||||
POCSAG_SwitchBaud(cur == POCSAG_BAUD_1200
|
||||
? POCSAG_BAUD_512
|
||||
: POCSAG_BAUD_1200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Redraw POCSAG display periodically */
|
||||
{
|
||||
static uint16_t rc = 0;
|
||||
if (++rc >= 5) {
|
||||
rc = 0;
|
||||
pocsag_draw();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MODE_SPECTRUM:
|
||||
/* Spectrum has returned — go back to VFO */
|
||||
MODE_Switch(MODE_VFO);
|
||||
break;
|
||||
|
||||
case MODE_FM:
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (!gFmRadioMode)
|
||||
MODE_Switch(MODE_VFO);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MODE_TimeSlice500ms(void)
|
||||
{
|
||||
switch (s_current_mode) {
|
||||
case MODE_VFO:
|
||||
APP_TimeSlice500ms();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* === External key processing hook === */
|
||||
|
||||
bool MODE_ProcessKey(int key, bool pressed, bool held)
|
||||
{
|
||||
KEY_Code_t k = (KEY_Code_t)key;
|
||||
|
||||
if (k == KEY_EXIT && pressed && !held) {
|
||||
if (s_current_mode != MODE_VFO) {
|
||||
MODE_Switch(MODE_VFO);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pressed && !held) {
|
||||
switch (s_current_mode) {
|
||||
case MODE_VFO:
|
||||
if (k == KEY_SIDE2) {
|
||||
#ifdef ENABLE_POCSAG
|
||||
MODE_Switch(MODE_POCSAG);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
if (k == KEY_SIDE1) {
|
||||
#ifdef ENABLE_SPECTRUM
|
||||
MODE_Switch(MODE_SPECTRUM);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
if (k == KEY_0) {
|
||||
#ifdef ENABLE_FMRADIO
|
||||
MODE_Switch(MODE_FM);
|
||||
FM_Start();
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
50
app/mode.h
Normal file
50
app/mode.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* UA1ZBE Custom Firmware - Mode Dispatcher
|
||||
*
|
||||
* Manages switching between operating modes:
|
||||
* MODE_VFO — Main VFO mode (default)
|
||||
* MODE_POCSAG — POCSAG decoder
|
||||
* MODE_SPECTRUM — Spectrum analyzer
|
||||
* MODE_FM — FM radio receiver
|
||||
*
|
||||
* Key mappings:
|
||||
* KEY_SIDE2 (SK2) → POCSAG mode
|
||||
* KEY_SIDE1 (SK1) → Spectrum mode
|
||||
* KEY_EXIT → Return to VFO
|
||||
* KEY_0 (short) → FM mode
|
||||
*/
|
||||
|
||||
#ifndef APP_MODE_H
|
||||
#define APP_MODE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Operating modes */
|
||||
typedef enum {
|
||||
MODE_VFO = 0,
|
||||
MODE_POCSAG,
|
||||
MODE_SPECTRUM,
|
||||
MODE_FM,
|
||||
MODE_COUNT
|
||||
} op_mode_t;
|
||||
|
||||
/* Get current mode */
|
||||
op_mode_t MODE_GetCurrent(void);
|
||||
|
||||
/* Switch to a mode */
|
||||
void MODE_Switch(op_mode_t mode);
|
||||
|
||||
/* Initialize mode dispatcher (call once at boot) */
|
||||
void MODE_Init(void);
|
||||
|
||||
/* Call from 10ms timeslice */
|
||||
void MODE_TimeSlice10ms(void);
|
||||
|
||||
/* Call from 500ms timeslice */
|
||||
void MODE_TimeSlice500ms(void);
|
||||
|
||||
/* Process key press for mode switching.
|
||||
* Returns true if the key was consumed by mode switch. */
|
||||
bool MODE_ProcessKey(int key, bool pressed, bool held);
|
||||
|
||||
#endif
|
||||
228
app/pocsag/bch31.c
Normal file
228
app/pocsag/bch31.c
Normal file
@@ -0,0 +1,228 @@
|
||||
/* UA1ZBE Custom Firmware - BCH(31,21) Decoder for POCSAG
|
||||
*
|
||||
* POCSAG uses a shortened BCH(31,21) code:
|
||||
* - 31-bit codeword (n=31)
|
||||
* - 21 data bits (k=21)
|
||||
* - 10 parity/check bits (n-k=10)
|
||||
* - Can correct up to 2 bit errors per codeword
|
||||
*
|
||||
* Generator polynomial: g(x) = x^10 + x^9 + x^8 + x^6 + x^5 + x^3 + 1
|
||||
* = 0x72D (binary: 111 0010 1101)
|
||||
*
|
||||
* The full 32-bit word includes:
|
||||
* - Bit 31: even parity bit (bit 0 of the word after inversion)
|
||||
* - Bits 30-0: 31-bit BCH codeword
|
||||
*
|
||||
* This implementation avoids hardware division (Cortex-M0 has no DIV unit).
|
||||
* All operations use shifts and XOR (GF(2) arithmetic).
|
||||
*/
|
||||
|
||||
#include "pocsag.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Generator polynomial for BCH(31,21): x^10 + x^9 + x^8 + x^6 + x^5 + x^3 + 1 */
|
||||
#define BCH31_GEN_POLY 0x72DU /* 11100101101 binary */
|
||||
|
||||
/* POCSAG sync word (32-bit) */
|
||||
#define POCSAG_SYNC_WORD 0x7CD21538U
|
||||
|
||||
/* POCSAG idle word */
|
||||
#define POCSAG_IDLE_WORD 0x7A89C197U
|
||||
|
||||
/* Parity check mask for even parity */
|
||||
#define BCH31_PARITY_MASK 0x80000000U
|
||||
|
||||
/*
|
||||
* Calculate syndrome of a 31-bit BCH codeword.
|
||||
* The syndrome is the remainder of dividing the received word by g(x).
|
||||
* If syndrome == 0, the word is valid (no errors or undetectable errors).
|
||||
*
|
||||
* word: 31-bit codeword (bits 30:0, parity bit excluded)
|
||||
* Returns: 10-bit syndrome value
|
||||
*/
|
||||
static uint16_t bch31_syndrome(uint32_t word)
|
||||
{
|
||||
uint32_t reg = word & 0x7FFFFFFFU; /* Mask to 31 bits */
|
||||
int i;
|
||||
|
||||
/* Polynomial division in GF(2) using shift-and-XOR */
|
||||
/* We process from MSB to LSB, XORing with generator when MSB is 1 */
|
||||
for (i = 30; i >= 10; i--) {
|
||||
if (reg & ((uint32_t)1 << i)) {
|
||||
reg ^= (BCH31_GEN_POLY << (i - 10));
|
||||
}
|
||||
}
|
||||
|
||||
/* The remainder is in the lower 10 bits */
|
||||
return (uint16_t)(reg & 0x03FFU);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check even parity of a 32-bit word.
|
||||
* Returns true if parity is correct (even number of 1-bits).
|
||||
*/
|
||||
static bool bch31_check_parity(uint32_t word)
|
||||
{
|
||||
/* Count set bits using a lookup-free method (no division needed) */
|
||||
uint32_t v = word;
|
||||
v = v - ((v >> 1) & 0x55555555U);
|
||||
v = (v & 0x33333333U) + ((v >> 2) & 0x33333333U);
|
||||
v = (v + (v >> 4)) & 0x0F0F0F0FU;
|
||||
v = (v * 0x01010101U) >> 24; /* Sum of all bytes */
|
||||
|
||||
return (v & 1U) == 0; /* Even parity = even number of 1-bits */
|
||||
}
|
||||
|
||||
/*
|
||||
* Find error position from syndrome.
|
||||
* For single-bit errors, the syndrome directly maps to the error position.
|
||||
* For double-bit errors, we need more complex correction.
|
||||
*
|
||||
* syndrome: 10-bit syndrome value
|
||||
* Returns: bit position (0-30) if single error, 0 if no error,
|
||||
* or a special value for double errors.
|
||||
*/
|
||||
static int bch31_find_single_error(uint16_t syndrome)
|
||||
{
|
||||
if (syndrome == 0)
|
||||
return -1; /* No error */
|
||||
|
||||
/* For single-bit errors, syndrome = x^i mod g(x) for error at position i.
|
||||
* We try each position by computing the expected syndrome.
|
||||
* This avoids division — just shift and XOR. */
|
||||
uint32_t test_syn = 1; /* Start with x^0 mod g(x) = 1 */
|
||||
|
||||
for (int i = 0; i < 31; i++) {
|
||||
if (test_syn == syndrome)
|
||||
return i; /* Error at position i */
|
||||
|
||||
/* Multiply by x in GF(2^10 / g(x)):
|
||||
* Shift left; if bit 10 is set, XOR with generator */
|
||||
test_syn <<= 1;
|
||||
if (test_syn & 0x0400U) { /* Bit 10 set */
|
||||
test_syn ^= BCH31_GEN_POLY;
|
||||
}
|
||||
test_syn &= 0x03FFU; /* Keep 10 bits */
|
||||
}
|
||||
|
||||
return -2; /* Not a single-bit error */
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to correct double-bit errors using syndrome decoding.
|
||||
* For a (31,21) BCH code with d_min=5, we can correct up to 2 errors.
|
||||
*
|
||||
* This uses a simplified approach: try all pairs of error positions.
|
||||
* For performance on Cortex-M0, we use a precomputed approach.
|
||||
*
|
||||
* word: pointer to the 32-bit word (will be modified in place if corrected)
|
||||
* Returns: 0 = no error, 1 = single error corrected,
|
||||
* 2 = double error corrected, -1 = uncorrectable
|
||||
*/
|
||||
int bch31_correct(uint32_t *word)
|
||||
{
|
||||
uint32_t data = *word;
|
||||
|
||||
/* Step 1: Check parity */
|
||||
bool parity_ok = bch31_check_parity(data);
|
||||
|
||||
/* Extract 31-bit codeword (strip parity bit 31) */
|
||||
uint32_t codeword = data & 0x7FFFFFFFU;
|
||||
|
||||
/* Step 2: Calculate syndrome */
|
||||
uint16_t syn = bch31_syndrome(codeword);
|
||||
|
||||
if (syn == 0 && parity_ok) {
|
||||
/* No errors detected */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Step 3: Try single-bit error correction */
|
||||
int err_pos = bch31_find_single_error(syn);
|
||||
if (err_pos >= 0) {
|
||||
/* Single-bit error at position err_pos */
|
||||
codeword ^= ((uint32_t)1 << err_pos);
|
||||
/* Fix parity bit too */
|
||||
*word = codeword | ((uint32_t)bch31_check_parity(codeword) << 31);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Step 4: Try double-bit error correction
|
||||
*
|
||||
* For double errors at positions i and j:
|
||||
* syndrome S = x^i + x^j (mod g(x))
|
||||
*
|
||||
* We use a brute-force search over all pairs (i, j) where i > j.
|
||||
* For 31 bits, this is 31*30/2 = 465 pairs — acceptable.
|
||||
*/
|
||||
if (err_pos == -2) {
|
||||
/* Precompute all single-error syndromes */
|
||||
uint16_t single_syn[31];
|
||||
uint32_t test = 1;
|
||||
for (int i = 0; i < 31; i++) {
|
||||
single_syn[i] = (uint16_t)test;
|
||||
test <<= 1;
|
||||
if (test & 0x0400U)
|
||||
test ^= BCH31_GEN_POLY;
|
||||
test &= 0x03FFU;
|
||||
}
|
||||
|
||||
/* Search for pair (i, j) where syn_i XOR syn_j == syn */
|
||||
for (int i = 1; i < 31; i++) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
if ((single_syn[i] ^ single_syn[j]) == syn) {
|
||||
/* Found double error at positions i and j */
|
||||
codeword ^= ((uint32_t)1 << i);
|
||||
codeword ^= ((uint32_t)1 << j);
|
||||
*word = codeword | ((uint32_t)bch31_check_parity(codeword) << 31);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 5: If syndrome != 0 but we couldn't find error positions,
|
||||
* check if it might still be valid (parity might catch it).
|
||||
* POCSAG spec says words with uncorrectable errors should be discarded.
|
||||
*/
|
||||
return -1; /* Uncorrectable */
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract 21 data bits from a corrected 32-bit POCSAG word.
|
||||
* Returns the 21-bit data value.
|
||||
*/
|
||||
uint32_t bch31_get_data(uint32_t word)
|
||||
{
|
||||
/* Data bits are in positions 30:10 of the 31-bit codeword
|
||||
* (bit 31 is parity, bits 9:0 are check bits)
|
||||
* So data = bits [30:10] = (word >> 10) & 0x1FFFFF */
|
||||
return (word >> 10) & 0x001FFFFFU;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get function bits from a POCSAG address word.
|
||||
* Address words have function code in bits 11:10 of the data portion.
|
||||
*/
|
||||
uint8_t bch31_get_func(uint32_t word)
|
||||
{
|
||||
/* Function bits are data bits [11:10] = bits [21:20] of full word */
|
||||
return (uint8_t)((word >> 20) & 0x03U);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if a word is a sync word.
|
||||
*/
|
||||
bool bch31_is_sync(uint32_t word)
|
||||
{
|
||||
return word == POCSAG_SYNC_WORD;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if a word is an idle word.
|
||||
*/
|
||||
bool bch31_is_idle(uint32_t word)
|
||||
{
|
||||
return word == POCSAG_IDLE_WORD;
|
||||
}
|
||||
25
app/pocsag/bch31.h
Normal file
25
app/pocsag/bch31.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* UA1ZBE Custom Firmware - BCH(31,21) header */
|
||||
#ifndef APP_POCSAG_BCH31_H
|
||||
#define APP_POCSAG_BCH31_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Correct errors in a POCSAG 32-bit word in place.
|
||||
* Returns: 0 = no error, 1 = single corrected,
|
||||
* 2 = double corrected, -1 = uncorrectable */
|
||||
int bch31_correct(uint32_t *word);
|
||||
|
||||
/* Extract 21 data bits from corrected word */
|
||||
uint32_t bch31_get_data(uint32_t word);
|
||||
|
||||
/* Get 2-bit function code */
|
||||
uint8_t bch31_get_func(uint32_t word);
|
||||
|
||||
/* Check if word is sync word */
|
||||
bool bch31_is_sync(uint32_t word);
|
||||
|
||||
/* Check if word is idle word */
|
||||
bool bch31_is_idle(uint32_t word);
|
||||
|
||||
#endif
|
||||
542
app/pocsag/pocsag.c
Normal file
542
app/pocsag/pocsag.c
Normal file
@@ -0,0 +1,542 @@
|
||||
/* UA1ZBE Custom Firmware - POCSAG Decoder Implementation
|
||||
*
|
||||
* Implements POCSAG decoding from FM discriminator audio samples.
|
||||
* Uses zero-crossing detection for bit slicing.
|
||||
*
|
||||
* Signal chain:
|
||||
* BK4819 FM demod -> AF output -> ADC sampling
|
||||
* -> zero-crossing detection -> bit stream -> POCSAG decode
|
||||
*
|
||||
* Cortex-M0 optimized: no hardware division in hot path.
|
||||
* All memory statically allocated.
|
||||
*/
|
||||
|
||||
#include "pocsag.h"
|
||||
#include "bch31.h"
|
||||
#include "driver/bk4819.h"
|
||||
#include "driver/system.h"
|
||||
#include "driver/st7565.h"
|
||||
#include "misc.h"
|
||||
#include "radio.h"
|
||||
#include <string.h>
|
||||
|
||||
/* === Configuration === */
|
||||
|
||||
/* Sampling rate for audio (Hz) — must be much higher than max baud rate */
|
||||
#define POCSAG_SAMPLE_RATE 8000 /* 8 kHz — sufficient for 1200 baud */
|
||||
|
||||
/* Threshold for zero-crossing detection (ADC counts) */
|
||||
#define POCSAG_ZERO_THRESHOLD 2048 /* Midpoint of 12-bit ADC range (0-4095) */
|
||||
|
||||
/* Minimum preamble bits to detect (POCSAG spec: 576 bits of 0x55 + 1) */
|
||||
#define POCSAG_PREAMBLE_MIN_BITS 576
|
||||
|
||||
/* BPSK bit extraction: compare sample against threshold */
|
||||
#define IS_BIT_ONE(sample) ((sample) > POCSAG_ZERO_THRESHOLD)
|
||||
|
||||
/* === Global decoder instance === */
|
||||
pocsag_decoder_t gPocsag;
|
||||
|
||||
/* === Internal state for bit slicing === */
|
||||
|
||||
/* Samples since last bit decision */
|
||||
static uint16_t s_sample_counter;
|
||||
|
||||
/* Samples per bit for current baud rate */
|
||||
static uint16_t s_samples_per_bit;
|
||||
|
||||
/* Accumulated samples for current bit decision */
|
||||
static uint32_t s_bit_accumulator;
|
||||
static uint8_t s_bit_sample_count;
|
||||
|
||||
/* Preamble detection: count alternating bits */
|
||||
static uint16_t s_preamble_alt_count;
|
||||
static uint8_t s_last_bit;
|
||||
|
||||
/* Sync detection shift register (holds last 32 bits) */
|
||||
static uint32_t s_sync_reg;
|
||||
|
||||
/* Bit buffer for assembling 32-bit words */
|
||||
static uint32_t s_word_reg;
|
||||
static uint8_t s_word_bits;
|
||||
|
||||
/* Batch tracking */
|
||||
static uint8_t s_batch_words;
|
||||
|
||||
/* Address/message assembly */
|
||||
static uint32_t s_msg_address;
|
||||
static uint8_t s_msg_func;
|
||||
static uint8_t s_msg_buf[POCSAG_MSG_MAX_LEN];
|
||||
static uint8_t s_msg_len;
|
||||
static bool s_msg_is_alpha;
|
||||
|
||||
/* Alpha decoder state */
|
||||
static uint32_t s_alpha_bits;
|
||||
static uint8_t s_alpha_bit_count;
|
||||
|
||||
/* State */
|
||||
static pocsag_state_t s_state;
|
||||
|
||||
/* Previous save state for restoration */
|
||||
static uint16_t s_saved_reg_30;
|
||||
static uint16_t s_saved_reg_47;
|
||||
static uint16_t s_saved_reg_33;
|
||||
|
||||
/* Timing counter — increments each time FeedSample is called (every ~10ms) */
|
||||
static uint32_t s_tick_counter;
|
||||
|
||||
/* Last sync timestamp */
|
||||
static uint32_t s_last_sync_tick;
|
||||
|
||||
/* === Baud rate lookup === */
|
||||
|
||||
/* Samples per bit for supported baud rates at 8kHz sample rate */
|
||||
static uint16_t get_samples_per_bit(uint32_t baud)
|
||||
{
|
||||
/* Avoid division: use precomputed values
|
||||
* 8000 / 512 = 15.625 -> 16
|
||||
* 8000 / 1200 = 6.667 -> 7 */
|
||||
if (baud == POCSAG_BAUD_512)
|
||||
return 16;
|
||||
if (baud == POCSAG_BAUD_1200)
|
||||
return 7;
|
||||
return 7; /* Default to 1200 */
|
||||
}
|
||||
|
||||
/* === Message ring buffer === */
|
||||
|
||||
static void msg_push(const pocsag_msg_t *msg)
|
||||
{
|
||||
if (gPocsag.msg_count >= POCSAG_MSG_POOL_SIZE) {
|
||||
/* Buffer full — drop oldest */
|
||||
gPocsag.msg_read_idx = (gPocsag.msg_read_idx + 1) % POCSAG_MSG_POOL_SIZE;
|
||||
gPocsag.msg_count--;
|
||||
}
|
||||
|
||||
gPocsag.messages[gPocsag.msg_write_idx] = *msg;
|
||||
gPocsag.msg_write_idx = (gPocsag.msg_write_idx + 1) % POCSAG_MSG_POOL_SIZE;
|
||||
gPocsag.msg_count++;
|
||||
gPocsag.msg_available = true;
|
||||
}
|
||||
|
||||
/* === POCSAG word processing === */
|
||||
|
||||
static void process_pocsag_word(uint32_t word)
|
||||
{
|
||||
/* Check parity first — quick reject using bit count */
|
||||
uint32_t v = word;
|
||||
v = v - ((v >> 1) & 0x55555555U);
|
||||
v = (v & 0x33333333U) + ((v >> 2) & 0x33333333U);
|
||||
v = (v + (v >> 4)) & 0x0F0F0F0FU;
|
||||
v = (v * 0x01010101U) >> 24;
|
||||
bool parity_ok = (v & 1U) == 0;
|
||||
|
||||
/* Try BCH correction */
|
||||
int corr = bch31_correct(&word);
|
||||
|
||||
if (corr < 0 && !parity_ok) {
|
||||
/* Uncorrectable — discard */
|
||||
gPocsag.uncorrectable_errors++;
|
||||
if (s_state == POCSAG_STATE_DATA) {
|
||||
s_state = POCSAG_STATE_SYNC;
|
||||
s_batch_words = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (corr > 0)
|
||||
gPocsag.corrected_errors++;
|
||||
|
||||
gPocsag.total_words++;
|
||||
|
||||
/* Check for sync word */
|
||||
if (bch31_is_sync(word)) {
|
||||
s_batch_words = 0;
|
||||
s_last_sync_tick = s_tick_counter;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for idle word */
|
||||
if (bch31_is_idle(word)) {
|
||||
return; /* Skip idle words */
|
||||
}
|
||||
|
||||
/* In DATA state, process the word */
|
||||
if (s_state != POCSAG_STATE_DATA) {
|
||||
s_state = POCSAG_STATE_DATA;
|
||||
s_batch_words = 0;
|
||||
}
|
||||
|
||||
/* Even/odd position in batch determines address vs data */
|
||||
if (s_batch_words % 2 == 0) {
|
||||
/* Address word */
|
||||
s_msg_address = bch31_get_data(word);
|
||||
s_msg_func = bch31_get_func(word);
|
||||
s_msg_len = 0;
|
||||
s_msg_is_alpha = false;
|
||||
s_msg_buf[0] = '\0';
|
||||
/* Reset alpha decoder state */
|
||||
s_alpha_bits = 0;
|
||||
s_alpha_bit_count = 0;
|
||||
} else {
|
||||
/* Data word */
|
||||
uint32_t data = bch31_get_data(word);
|
||||
|
||||
if (s_msg_func == 0) {
|
||||
/* Numeric pager — data is BCD digits */
|
||||
uint32_t num = data & 0x000FFFFFU;
|
||||
char digits[12];
|
||||
int idx = 0;
|
||||
|
||||
if (num == 0) {
|
||||
digits[idx++] = '0';
|
||||
} else {
|
||||
/* Extract digits using precomputed powers of 10 (no division) */
|
||||
static const uint32_t powers[] = {
|
||||
1000000000U, 100000000U, 10000000U, 1000000U,
|
||||
100000U, 10000U, 1000U, 100U, 10U, 1U
|
||||
};
|
||||
bool started = false;
|
||||
for (int p = 0; p < 10; p++) {
|
||||
uint32_t pwr = powers[p];
|
||||
uint8_t digit = 0;
|
||||
while (num >= pwr) {
|
||||
num -= pwr;
|
||||
digit++;
|
||||
}
|
||||
if (digit > 0 || started || p == 9) {
|
||||
digits[idx++] = '0' + digit;
|
||||
started = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
digits[idx] = '\0';
|
||||
|
||||
/* Push message */
|
||||
if (s_msg_len == 0) {
|
||||
pocsag_msg_t msg;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.address = s_msg_address;
|
||||
msg.func = s_msg_func;
|
||||
msg.is_alpha = false;
|
||||
msg.timestamp = s_tick_counter;
|
||||
|
||||
int copy_len = idx;
|
||||
if (copy_len > POCSAG_MSG_MAX_LEN - 1)
|
||||
copy_len = POCSAG_MSG_MAX_LEN - 1;
|
||||
memcpy(msg.text, digits, copy_len);
|
||||
msg.text[copy_len] = '\0';
|
||||
msg.text_len = copy_len;
|
||||
|
||||
msg_push(&msg);
|
||||
}
|
||||
} else if (s_msg_func == 2) {
|
||||
/* Alpha pager — 7-bit ASCII, 20 bits per word */
|
||||
uint32_t bits20 = data & 0x000FFFFFU;
|
||||
|
||||
s_alpha_bits = (s_alpha_bits << 20) | bits20;
|
||||
s_alpha_bit_count += 20;
|
||||
|
||||
while (s_alpha_bit_count >= 7 && s_msg_len < POCSAG_MSG_MAX_LEN - 1) {
|
||||
s_alpha_bit_count -= 7;
|
||||
uint8_t ch = (s_alpha_bits >> s_alpha_bit_count) & 0x7F;
|
||||
|
||||
if (ch == 0x03) {
|
||||
/* ETX — end of message */
|
||||
s_msg_buf[s_msg_len] = '\0';
|
||||
pocsag_msg_t msg;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.address = s_msg_address;
|
||||
msg.func = s_msg_func;
|
||||
msg.is_alpha = true;
|
||||
msg.timestamp = s_tick_counter;
|
||||
memcpy(msg.text, s_msg_buf, s_msg_len);
|
||||
msg.text[s_msg_len] = '\0';
|
||||
msg.text_len = s_msg_len;
|
||||
msg_push(&msg);
|
||||
|
||||
s_msg_len = 0;
|
||||
s_alpha_bits = 0;
|
||||
s_alpha_bit_count = 0;
|
||||
break;
|
||||
}
|
||||
s_msg_buf[s_msg_len++] = ch;
|
||||
}
|
||||
s_msg_is_alpha = true;
|
||||
}
|
||||
}
|
||||
|
||||
s_batch_words++;
|
||||
|
||||
/* After 32 words, expect new sync */
|
||||
if (s_batch_words >= 32) {
|
||||
s_state = POCSAG_STATE_SYNC;
|
||||
s_batch_words = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* === Bit processing === */
|
||||
|
||||
static void process_bit(bool bit)
|
||||
{
|
||||
gPocsag.total_bits++;
|
||||
|
||||
switch (s_state) {
|
||||
case POCSAG_STATE_IDLE:
|
||||
case POCSAG_STATE_PREAMBLE:
|
||||
s_state = POCSAG_STATE_PREAMBLE;
|
||||
|
||||
/* Look for alternating pattern: 01010101... (0x55) ending with 1 (0xAB) */
|
||||
if (s_preamble_alt_count == 0) {
|
||||
s_last_bit = bit ? 1 : 0;
|
||||
s_preamble_alt_count = 1;
|
||||
} else if ((bit ? 1 : 0) != s_last_bit) {
|
||||
s_preamble_alt_count++;
|
||||
s_last_bit = bit ? 1 : 0;
|
||||
} else {
|
||||
s_preamble_alt_count = 1;
|
||||
s_last_bit = bit ? 1 : 0;
|
||||
}
|
||||
|
||||
if (s_preamble_alt_count >= POCSAG_PREAMBLE_MIN_BITS) {
|
||||
/* Preamble detected — look for sync word */
|
||||
s_state = POCSAG_STATE_SYNC;
|
||||
s_sync_reg = 0;
|
||||
s_word_bits = 0;
|
||||
s_preamble_alt_count = 0;
|
||||
s_last_sync_tick = s_tick_counter;
|
||||
}
|
||||
break;
|
||||
|
||||
case POCSAG_STATE_SYNC:
|
||||
/* Collect bits into 32-bit sync register */
|
||||
s_sync_reg = (s_sync_reg << 1) | (bit ? 1 : 0);
|
||||
|
||||
if (s_sync_reg == 0x7CD21538U) {
|
||||
/* Sync word found! */
|
||||
s_state = POCSAG_STATE_DATA;
|
||||
s_word_reg = 0;
|
||||
s_word_bits = 0;
|
||||
s_batch_words = 0;
|
||||
gPocsag.signal_detected = true;
|
||||
s_last_sync_tick = s_tick_counter;
|
||||
}
|
||||
|
||||
/* Timeout: ~1000 bits at 1200 baud ≈ 833ms ≈ 83 calls */
|
||||
if ((s_tick_counter - s_last_sync_tick) > 100) {
|
||||
s_state = POCSAG_STATE_IDLE;
|
||||
s_preamble_alt_count = 0;
|
||||
gPocsag.signal_detected = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case POCSAG_STATE_DATA:
|
||||
/* Collect 32-bit words */
|
||||
s_word_reg = (s_word_reg << 1) | (bit ? 1 : 0);
|
||||
s_word_bits++;
|
||||
|
||||
if (s_word_bits >= 32) {
|
||||
process_pocsag_word(s_word_reg);
|
||||
s_word_reg = 0;
|
||||
s_word_bits = 0;
|
||||
}
|
||||
|
||||
/* Sync loss check */
|
||||
if ((s_tick_counter - s_last_sync_tick) > 300) {
|
||||
s_state = POCSAG_STATE_SYNC;
|
||||
s_sync_reg = 0;
|
||||
gPocsag.signal_detected = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* === Sample processing (hot path) === */
|
||||
|
||||
bool POCSAG_FeedSample(uint16_t audio_sample)
|
||||
{
|
||||
s_tick_counter++;
|
||||
s_sample_counter++;
|
||||
|
||||
/* Accumulate samples for bit decision */
|
||||
s_bit_accumulator += audio_sample;
|
||||
s_bit_sample_count++;
|
||||
|
||||
if (s_bit_sample_count >= s_samples_per_bit) {
|
||||
/* Make bit decision from averaged sample.
|
||||
* Avoid division: compare accumulated value against threshold * count.
|
||||
*
|
||||
* For 1200 baud (7 samples): threshold * 7 = 2048 * 7 = 14336
|
||||
* For 512 baud (16 samples): threshold * 16 = 2048 * 16 = 32768 */
|
||||
uint32_t thresh;
|
||||
if (gPocsag.baud_rate == POCSAG_BAUD_512)
|
||||
thresh = 32768;
|
||||
else
|
||||
thresh = 14336;
|
||||
|
||||
bool bit = (s_bit_accumulator >= thresh);
|
||||
|
||||
s_bit_accumulator = 0;
|
||||
s_bit_sample_count = 0;
|
||||
|
||||
/* Process the bit */
|
||||
process_bit(bit);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void POCSAG_FeedBit(bool bit)
|
||||
{
|
||||
process_bit(bit);
|
||||
}
|
||||
|
||||
/* === Public API === */
|
||||
|
||||
void POCSAG_Init(uint32_t baud_rate)
|
||||
{
|
||||
memset(&gPocsag, 0, sizeof(gPocsag));
|
||||
gPocsag.baud_rate = baud_rate;
|
||||
gPocsag.state = POCSAG_STATE_IDLE;
|
||||
gPocsag.msg_read_idx = 0;
|
||||
gPocsag.msg_write_idx = 0;
|
||||
gPocsag.msg_count = 0;
|
||||
gPocsag.msg_available = false;
|
||||
|
||||
s_sample_counter = 0;
|
||||
s_samples_per_bit = get_samples_per_bit(baud_rate);
|
||||
s_bit_accumulator = 0;
|
||||
s_bit_sample_count = 0;
|
||||
s_preamble_alt_count = 0;
|
||||
s_last_bit = 0;
|
||||
s_sync_reg = 0;
|
||||
s_word_reg = 0;
|
||||
s_word_bits = 0;
|
||||
s_batch_words = 0;
|
||||
s_msg_address = 0;
|
||||
s_msg_func = 0;
|
||||
s_msg_len = 0;
|
||||
s_msg_is_alpha = false;
|
||||
s_alpha_bits = 0;
|
||||
s_alpha_bit_count = 0;
|
||||
s_state = POCSAG_STATE_IDLE;
|
||||
s_tick_counter = 0;
|
||||
s_last_sync_tick = 0;
|
||||
}
|
||||
|
||||
void POCSAG_SwitchBaud(uint32_t baud_rate)
|
||||
{
|
||||
gPocsag.baud_rate = baud_rate;
|
||||
s_samples_per_bit = get_samples_per_bit(baud_rate);
|
||||
s_state = POCSAG_STATE_IDLE;
|
||||
s_preamble_alt_count = 0;
|
||||
s_sync_reg = 0;
|
||||
s_word_reg = 0;
|
||||
s_word_bits = 0;
|
||||
s_batch_words = 0;
|
||||
gPocsag.signal_detected = false;
|
||||
}
|
||||
|
||||
uint32_t POCSAG_GetBaud(void)
|
||||
{
|
||||
return gPocsag.baud_rate;
|
||||
}
|
||||
|
||||
bool POCSAG_MessageAvailable(void)
|
||||
{
|
||||
return gPocsag.msg_count > 0;
|
||||
}
|
||||
|
||||
bool POCSAG_GetMessage(pocsag_msg_t *msg)
|
||||
{
|
||||
if (gPocsag.msg_count == 0)
|
||||
return false;
|
||||
|
||||
*msg = gPocsag.messages[gPocsag.msg_read_idx];
|
||||
gPocsag.msg_read_idx = (gPocsag.msg_read_idx + 1) % POCSAG_MSG_POOL_SIZE;
|
||||
gPocsag.msg_count--;
|
||||
|
||||
if (gPocsag.msg_count == 0)
|
||||
gPocsag.msg_available = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
pocsag_state_t POCSAG_GetState(void)
|
||||
{
|
||||
return s_state;
|
||||
}
|
||||
|
||||
bool POCSAG_SignalDetected(void)
|
||||
{
|
||||
return gPocsag.signal_detected;
|
||||
}
|
||||
|
||||
void POCSAG_Reset(void)
|
||||
{
|
||||
uint32_t baud = gPocsag.baud_rate;
|
||||
POCSAG_Init(baud);
|
||||
}
|
||||
|
||||
void POCSAG_Process(void)
|
||||
{
|
||||
gPocsag.state = s_state;
|
||||
}
|
||||
|
||||
/* === Radio configuration === */
|
||||
|
||||
void POCSAG_ConfigureRadio(uint32_t frequency_hz)
|
||||
{
|
||||
/* Save current radio state */
|
||||
s_saved_reg_30 = BK4819_ReadRegister(BK4819_REG_30);
|
||||
s_saved_reg_47 = BK4819_ReadRegister(BK4819_REG_47);
|
||||
s_saved_reg_33 = BK4819_ReadRegister(BK4819_REG_33);
|
||||
|
||||
/* Set frequency */
|
||||
BK4819_SetFrequency(frequency_hz);
|
||||
BK4819_PickRXFilterPathBasedOnFrequency(frequency_hz);
|
||||
|
||||
/* Configure for narrow FM (POCSAG is typically narrow FM) */
|
||||
BK4819_SetFilterBandwidth(BK4819_FILTER_BW_NARROW, true);
|
||||
|
||||
/* Turn on RX */
|
||||
BK4819_RX_TurnOn();
|
||||
|
||||
/* Set AF output to FM (demodulated audio) for sampling */
|
||||
BK4819_SetAF(BK4819_AF_FM);
|
||||
|
||||
/* Disable squelch for continuous audio monitoring */
|
||||
BK4819_SetupSquelch(0, 0, 0, 0, 255, 0);
|
||||
|
||||
/* Enable RX link, AF DAC, disc mode */
|
||||
BK4819_WriteRegister(BK4819_REG_30,
|
||||
BK4819_REG_30_ENABLE_VCO_CALIB |
|
||||
BK4819_REG_30_ENABLE_RX_LINK |
|
||||
BK4819_REG_30_ENABLE_AF_DAC |
|
||||
BK4819_REG_30_ENABLE_DISC_MODE |
|
||||
BK4819_REG_30_ENABLE_PLL_VCO |
|
||||
BK4819_REG_30_ENABLE_RX_DSP);
|
||||
|
||||
/* Enable green LED */
|
||||
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, true);
|
||||
}
|
||||
|
||||
void POCSAG_Stop(void)
|
||||
{
|
||||
BK4819_WriteRegister(BK4819_REG_30, s_saved_reg_30);
|
||||
BK4819_WriteRegister(BK4819_REG_47, s_saved_reg_47);
|
||||
BK4819_WriteRegister(BK4819_REG_33, s_saved_reg_33);
|
||||
|
||||
gPocsag.signal_detected = false;
|
||||
s_state = POCSAG_STATE_IDLE;
|
||||
}
|
||||
|
||||
/* === State description strings === */
|
||||
|
||||
const char *POCSAG_StateString(pocsag_state_t state)
|
||||
{
|
||||
static const char *const strs[] = { "IDLE", "SEARCH", "SYNC", "DATA" };
|
||||
if ((unsigned int)state > 3u) return "???";
|
||||
return strs[(unsigned int)state];
|
||||
}
|
||||
150
app/pocsag/pocsag.h
Normal file
150
app/pocsag/pocsag.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/* UA1ZBE Custom Firmware - POCSAG Decoder
|
||||
*
|
||||
* Decodes POCSAG paging signals from FM discriminator output.
|
||||
* Supports 512 and 1200 baud rates with dynamic switching.
|
||||
*
|
||||
* POCSAG Protocol:
|
||||
* - Preamble: 0xAAAAAAAB (at least 576 bits of alternating 1010... ending with 1)
|
||||
* - Sync word: 0x7CD21538
|
||||
* - Data words: 32-bit (21 data + 10 BCH + 1 parity)
|
||||
* - BCH(31,21) code, corrects up to 2 errors per word
|
||||
*
|
||||
* Architecture:
|
||||
* - Samples audio from BK4819 discriminator (REG_69 AF output or FSK FIFO)
|
||||
* - Zero-crossing detection for bit slicing
|
||||
* - State machine: IDLE -> PREAMBLE -> SYNC -> DATA
|
||||
* - Ring buffer for decoded messages
|
||||
* - Zero malloc — all static allocation
|
||||
*/
|
||||
|
||||
#ifndef APP_POCSAG_POCSAG_H
|
||||
#define APP_POCSAG_POCSAG_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* POCSAG baud rates */
|
||||
#define POCSAG_BAUD_512 512
|
||||
#define POCSAG_BAUD_1200 1200
|
||||
|
||||
/* Maximum message length in bytes (arbitrary, fits in static buffer) */
|
||||
#define POCSAG_MSG_MAX_LEN 64
|
||||
|
||||
/* Maximum messages in ring buffer */
|
||||
#define POCSAG_MSG_POOL_SIZE 8
|
||||
|
||||
/* Decoded message structure */
|
||||
typedef struct {
|
||||
uint32_t address; /* Address (21-bit frame address) */
|
||||
uint8_t func; /* Function code (2 bits) */
|
||||
char text[POCSAG_MSG_MAX_LEN]; /* Decoded text (alpha pager) */
|
||||
uint8_t text_len; /* Length of decoded text */
|
||||
bool is_alpha; /* true = alpha pager, false = numeric */
|
||||
uint32_t timestamp; /* System tick when received */
|
||||
} pocsag_msg_t;
|
||||
|
||||
/* Decoder state machine states */
|
||||
typedef enum {
|
||||
POCSAG_STATE_IDLE = 0,
|
||||
POCSAG_STATE_PREAMBLE,
|
||||
POCSAG_STATE_SYNC,
|
||||
POCSAG_STATE_DATA
|
||||
} pocsag_state_t;
|
||||
|
||||
/* Decoder context — all static, no malloc */
|
||||
typedef struct {
|
||||
/* Configuration */
|
||||
uint32_t baud_rate; /* Current baud rate: 512 or 1200 */
|
||||
|
||||
/* State machine */
|
||||
pocsag_state_t state;
|
||||
|
||||
/* Bit accumulation */
|
||||
uint32_t shift_reg; /* Shift register for incoming bits */
|
||||
uint8_t bit_count; /* Number of bits collected in shift_reg */
|
||||
uint8_t preamble_count; /* Consecutive alternating bits in preamble */
|
||||
|
||||
/* Sync detection */
|
||||
uint8_t sync_word_count; /* Number of sync words found in a row */
|
||||
|
||||
/* Word collection */
|
||||
uint8_t batch_count; /* Words in current batch (0-16) */
|
||||
uint8_t word_in_batch; /* Current word position in batch */
|
||||
|
||||
/* Message assembly */
|
||||
uint32_t current_address;
|
||||
uint8_t current_func;
|
||||
uint8_t msg_data[POCSAG_MSG_MAX_LEN];
|
||||
uint8_t msg_len;
|
||||
bool msg_is_alpha;
|
||||
|
||||
/* Ring buffer of decoded messages */
|
||||
pocsag_msg_t messages[POCSAG_MSG_POOL_SIZE];
|
||||
volatile uint8_t msg_read_idx;
|
||||
volatile uint8_t msg_write_idx;
|
||||
volatile uint8_t msg_count;
|
||||
|
||||
/* Statistics */
|
||||
uint32_t total_bits;
|
||||
uint32_t total_words;
|
||||
uint32_t corrected_errors;
|
||||
uint32_t uncorrectable_errors;
|
||||
|
||||
/* Flag for new message available */
|
||||
volatile bool msg_available;
|
||||
|
||||
/* Signal active flag */
|
||||
bool signal_detected;
|
||||
|
||||
} pocsag_decoder_t;
|
||||
|
||||
/* Global decoder instance */
|
||||
extern pocsag_decoder_t gPocsag;
|
||||
|
||||
/* === API === */
|
||||
|
||||
/* Initialize decoder, set baud rate */
|
||||
void POCSAG_Init(uint32_t baud_rate);
|
||||
|
||||
/* Switch baud rate dynamically (512 <-> 1200) */
|
||||
void POCSAG_SwitchBaud(uint32_t baud_rate);
|
||||
|
||||
/* Get current baud rate */
|
||||
uint32_t POCSAG_GetBaud(void);
|
||||
|
||||
/* Feed audio sample (12-bit ADC value from discriminator)
|
||||
* Call this from the 10ms timeslice or a dedicated sampling timer.
|
||||
* Returns true if a bit was detected. */
|
||||
bool POCSAG_FeedSample(uint16_t audio_sample);
|
||||
|
||||
/* Feed a single bit (after external bit-slicing) */
|
||||
void POCSAG_FeedBit(bool bit);
|
||||
|
||||
/* Check if a decoded message is available (non-blocking) */
|
||||
bool POCSAG_MessageAvailable(void);
|
||||
|
||||
/* Pop the next decoded message from the ring buffer */
|
||||
bool POCSAG_GetMessage(pocsag_msg_t *msg);
|
||||
|
||||
/* Get decoder state (for display) */
|
||||
pocsag_state_t POCSAG_GetState(void);
|
||||
|
||||
/* Get signal detection status */
|
||||
bool POCSAG_SignalDetected(void);
|
||||
|
||||
/* Reset decoder to idle state */
|
||||
void POCSAG_Reset(void);
|
||||
|
||||
/* Process decoder state machine (call from main loop) */
|
||||
void POCSAG_Process(void);
|
||||
|
||||
/* Configure BK4819 for POCSAG reception on given frequency */
|
||||
void POCSAG_ConfigureRadio(uint32_t frequency_hz);
|
||||
|
||||
/* Stop POCSAG reception, restore normal RX */
|
||||
void POCSAG_Stop(void);
|
||||
|
||||
/* Get state description string */
|
||||
const char *POCSAG_StateString(pocsag_state_t state);
|
||||
|
||||
#endif /* APP_POCSAG_POCSAG_H */
|
||||
528
app/scanner.c
Normal file
528
app/scanner.c
Normal file
@@ -0,0 +1,528 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/dtmf.h"
|
||||
#include "app/generic.h"
|
||||
#include "app/menu.h"
|
||||
#include "app/scanner.h"
|
||||
#include "audio.h"
|
||||
#include "driver/bk4819.h"
|
||||
#include "frequencies.h"
|
||||
#include "misc.h"
|
||||
#include "radio.h"
|
||||
#include "settings.h"
|
||||
#include "ui/inputbox.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
DCS_CodeType_t gScanCssResultType;
|
||||
uint8_t gScanCssResultCode;
|
||||
bool gScanSingleFrequency; // scan CTCSS/DCS codes for current frequency
|
||||
SCAN_SaveState_t gScannerSaveState;
|
||||
uint8_t gScanChannel;
|
||||
uint32_t gScanFrequency;
|
||||
SCAN_CssState_t gScanCssState;
|
||||
uint8_t gScanProgressIndicator;
|
||||
bool gScanUseCssResult;
|
||||
|
||||
STEP_Setting_t stepSetting;
|
||||
uint8_t scanHitCount;
|
||||
|
||||
|
||||
static void SCANNER_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
if (!bKeyHeld && bKeyPressed)
|
||||
{
|
||||
if (gScannerSaveState == SCAN_SAVE_CHAN_SEL) {
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
|
||||
INPUTBOX_Append(Key);
|
||||
|
||||
gRequestDisplayScreen = DISPLAY_SCANNER;
|
||||
|
||||
if (gInputBoxIndex < 3) {
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
gInputBoxIndex = 0;
|
||||
|
||||
uint16_t chan = ((gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]) - 1;
|
||||
if (IS_MR_CHANNEL(chan)) {
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = (VOICE_ID_t)Key;
|
||||
#endif
|
||||
gShowChPrefix = RADIO_CheckValidChannel(chan, false, 0);
|
||||
gScanChannel = (uint8_t)chan;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
}
|
||||
}
|
||||
|
||||
static void SCANNER_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
if (!bKeyHeld && bKeyPressed) { // short pressed
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
|
||||
switch (gScannerSaveState) {
|
||||
case SCAN_SAVE_NO_PROMPT:
|
||||
SCANNER_Stop();
|
||||
gRequestDisplayScreen = DISPLAY_MAIN;
|
||||
break;
|
||||
|
||||
case SCAN_SAVE_CHAN_SEL:
|
||||
if (gInputBoxIndex > 0) {
|
||||
gInputBox[--gInputBoxIndex] = 10;
|
||||
gRequestDisplayScreen = DISPLAY_SCANNER;
|
||||
break;
|
||||
}
|
||||
|
||||
// Fallthrough
|
||||
|
||||
case SCAN_SAVE_CHANNEL:
|
||||
gScannerSaveState = SCAN_SAVE_NO_PROMPT;
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_CANCEL;
|
||||
#endif
|
||||
gRequestDisplayScreen = DISPLAY_SCANNER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SCANNER_Key_MENU(bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
if (bKeyHeld || !bKeyPressed) // ignore long press or release button events
|
||||
return;
|
||||
|
||||
if (gScanCssState == SCAN_CSS_STATE_OFF && !gScanSingleFrequency) {
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gScanCssState == SCAN_CSS_STATE_SCANNING && gScanSingleFrequency) {
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gScanCssState == SCAN_CSS_STATE_FAILED) {
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
return;
|
||||
}
|
||||
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
|
||||
switch (gScannerSaveState) {
|
||||
case SCAN_SAVE_NO_PROMPT:
|
||||
if (!gScanSingleFrequency)
|
||||
{
|
||||
uint32_t freq250 = FREQUENCY_RoundToStep(gScanFrequency, 250);
|
||||
uint32_t freq625 = FREQUENCY_RoundToStep(gScanFrequency, 625);
|
||||
|
||||
uint32_t diff250 = gScanFrequency > freq250 ? gScanFrequency - freq250 : freq250 - gScanFrequency;
|
||||
uint32_t diff625 = gScanFrequency > freq625 ? gScanFrequency - freq625 : freq625 - gScanFrequency;
|
||||
|
||||
if(diff250 > diff625) {
|
||||
stepSetting = STEP_6_25kHz;
|
||||
gScanFrequency = freq625;
|
||||
}
|
||||
else {
|
||||
stepSetting = STEP_2_5kHz;
|
||||
gScanFrequency = freq250;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) {
|
||||
gScannerSaveState = SCAN_SAVE_CHAN_SEL;
|
||||
gScanChannel = gTxVfo->CHANNEL_SAVE;
|
||||
gShowChPrefix = RADIO_CheckValidChannel(gTxVfo->CHANNEL_SAVE, false, 0);
|
||||
}
|
||||
else {
|
||||
gScannerSaveState = SCAN_SAVE_CHANNEL;
|
||||
}
|
||||
|
||||
gScanCssState = SCAN_CSS_STATE_FOUND;
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_MEMORY_CHANNEL;
|
||||
#endif
|
||||
gRequestDisplayScreen = DISPLAY_SCANNER;
|
||||
|
||||
gUpdateStatus = true;
|
||||
break;
|
||||
|
||||
case SCAN_SAVE_CHAN_SEL:
|
||||
if (gInputBoxIndex == 0) {
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
gRequestDisplayScreen = DISPLAY_SCANNER;
|
||||
gScannerSaveState = SCAN_SAVE_CHANNEL;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCAN_SAVE_CHANNEL:
|
||||
if (!gScanSingleFrequency) {
|
||||
RADIO_InitInfo(gTxVfo, gTxVfo->CHANNEL_SAVE, gScanFrequency);
|
||||
|
||||
if (gScanUseCssResult) {
|
||||
gTxVfo->freq_config_RX.CodeType = gScanCssResultType;
|
||||
gTxVfo->freq_config_RX.Code = gScanCssResultCode;
|
||||
}
|
||||
|
||||
gTxVfo->freq_config_TX = gTxVfo->freq_config_RX;
|
||||
gTxVfo->STEP_SETTING = stepSetting;
|
||||
}
|
||||
else {
|
||||
RADIO_ConfigureChannel(0, VFO_CONFIGURE_RELOAD);
|
||||
RADIO_ConfigureChannel(1, VFO_CONFIGURE_RELOAD);
|
||||
|
||||
gTxVfo->freq_config_RX.CodeType = gScanCssResultType;
|
||||
gTxVfo->freq_config_RX.Code = gScanCssResultCode;
|
||||
gTxVfo->freq_config_TX.CodeType = gScanCssResultType;
|
||||
gTxVfo->freq_config_TX.Code = gScanCssResultCode;
|
||||
}
|
||||
|
||||
uint8_t chan;
|
||||
if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) {
|
||||
chan = gScanChannel;
|
||||
gEeprom.MrChannel[gEeprom.TX_VFO] = chan;
|
||||
}
|
||||
else {
|
||||
chan = gTxVfo->Band + FREQ_CHANNEL_FIRST;
|
||||
gEeprom.FreqChannel[gEeprom.TX_VFO] = chan;
|
||||
}
|
||||
|
||||
gTxVfo->CHANNEL_SAVE = chan;
|
||||
gEeprom.ScreenChannel[gEeprom.TX_VFO] = chan;
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_CONFIRM;
|
||||
#endif
|
||||
gRequestDisplayScreen = DISPLAY_SCANNER;
|
||||
gRequestSaveChannel = 2;
|
||||
gScannerSaveState = SCAN_SAVE_NO_PROMPT;
|
||||
break;
|
||||
|
||||
default:
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void SCANNER_Key_STAR(bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
if (!bKeyHeld && bKeyPressed) {
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
SCANNER_Start(gScanSingleFrequency);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void SCANNER_Key_UP_DOWN(bool bKeyPressed, bool pKeyHeld, int8_t Direction)
|
||||
{
|
||||
if (pKeyHeld) {
|
||||
if (!bKeyPressed)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (!bKeyPressed)
|
||||
return;
|
||||
|
||||
gInputBoxIndex = 0;
|
||||
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
|
||||
}
|
||||
|
||||
if (gScannerSaveState == SCAN_SAVE_CHAN_SEL) {
|
||||
gScanChannel = NUMBER_AddWithWraparound(gScanChannel, Direction, 0, MR_CHANNEL_LAST);
|
||||
gShowChPrefix = RADIO_CheckValidChannel(gScanChannel, false, 0);
|
||||
gRequestDisplayScreen = DISPLAY_SCANNER;
|
||||
}
|
||||
else
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
}
|
||||
|
||||
void SCANNER_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
switch (Key) {
|
||||
case KEY_0:
|
||||
case KEY_1:
|
||||
case KEY_2:
|
||||
case KEY_3:
|
||||
case KEY_4:
|
||||
case KEY_5:
|
||||
case KEY_6:
|
||||
case KEY_7:
|
||||
case KEY_8:
|
||||
case KEY_9:
|
||||
SCANNER_Key_DIGITS(Key, bKeyPressed, bKeyHeld);
|
||||
break;
|
||||
case KEY_MENU:
|
||||
SCANNER_Key_MENU(bKeyPressed, bKeyHeld);
|
||||
break;
|
||||
case KEY_UP:
|
||||
SCANNER_Key_UP_DOWN(bKeyPressed, bKeyHeld, 1);
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
SCANNER_Key_UP_DOWN(bKeyPressed, bKeyHeld, -1);
|
||||
break;
|
||||
case KEY_EXIT:
|
||||
SCANNER_Key_EXIT(bKeyPressed, bKeyHeld);
|
||||
break;
|
||||
case KEY_STAR:
|
||||
SCANNER_Key_STAR(bKeyPressed, bKeyHeld);
|
||||
break;
|
||||
case KEY_PTT:
|
||||
GENERIC_Key_PTT(bKeyPressed);
|
||||
break;
|
||||
default:
|
||||
if (!bKeyHeld && bKeyPressed)
|
||||
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SCANNER_Start(bool singleFreq)
|
||||
{
|
||||
gScanSingleFrequency = singleFreq;
|
||||
gMonitor = false;
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_SCANNING_BEGIN;
|
||||
#endif
|
||||
|
||||
BK4819_StopScan();
|
||||
RADIO_SelectVfos();
|
||||
|
||||
#ifdef ENABLE_NOAA
|
||||
if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE))
|
||||
gRxVfo->CHANNEL_SAVE = FREQ_CHANNEL_FIRST + BAND6_400MHz;
|
||||
#endif
|
||||
|
||||
uint8_t backupStep = gRxVfo->STEP_SETTING;
|
||||
uint16_t backupFrequency = gRxVfo->StepFrequency;
|
||||
|
||||
RADIO_InitInfo(gRxVfo, gRxVfo->CHANNEL_SAVE, gRxVfo->pRX->Frequency);
|
||||
|
||||
gRxVfo->STEP_SETTING = backupStep;
|
||||
gRxVfo->StepFrequency = backupFrequency;
|
||||
|
||||
RADIO_SetupRegisters(true);
|
||||
|
||||
#ifdef ENABLE_NOAA
|
||||
gIsNoaaMode = false;
|
||||
#endif
|
||||
|
||||
if (gScanSingleFrequency) {
|
||||
gScanCssState = SCAN_CSS_STATE_SCANNING;
|
||||
gScanFrequency = gRxVfo->pRX->Frequency;
|
||||
stepSetting = gRxVfo->STEP_SETTING;
|
||||
|
||||
BK4819_PickRXFilterPathBasedOnFrequency(gScanFrequency);
|
||||
BK4819_SetScanFrequency(gScanFrequency);
|
||||
|
||||
gUpdateStatus = true;
|
||||
}
|
||||
else {
|
||||
gScanCssState = SCAN_CSS_STATE_OFF;
|
||||
gScanFrequency = 0xFFFFFFFF;
|
||||
|
||||
BK4819_PickRXFilterPathBasedOnFrequency(gScanFrequency);
|
||||
BK4819_EnableFrequencyScan();
|
||||
|
||||
gUpdateStatus = true;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
DTMF_clear_RX();
|
||||
#endif
|
||||
|
||||
gScanDelay_10ms = scan_delay_10ms;
|
||||
gScanCssResultCode = 0xFF;
|
||||
gScanCssResultType = 0xFF;
|
||||
scanHitCount = 0;
|
||||
gScanUseCssResult = false;
|
||||
g_CxCSS_TAIL_Found = false;
|
||||
g_CDCSS_Lost = false;
|
||||
gCDCSSCodeType = 0;
|
||||
g_CTCSS_Lost = false;
|
||||
#ifdef ENABLE_VOX
|
||||
g_VOX_Lost = false;
|
||||
#endif
|
||||
g_SquelchLost = false;
|
||||
gScannerSaveState = SCAN_SAVE_NO_PROMPT;
|
||||
gScanProgressIndicator = 0;
|
||||
}
|
||||
|
||||
void SCANNER_Stop(void)
|
||||
{
|
||||
if(SCANNER_IsScanning()) {
|
||||
gEeprom.CROSS_BAND_RX_TX = gBackup_CROSS_BAND_RX_TX;
|
||||
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
|
||||
gFlagResetVfos = true;
|
||||
gUpdateStatus = true;
|
||||
gCssBackgroundScan = false;
|
||||
gScanUseCssResult = false;
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_CANCEL;
|
||||
#endif
|
||||
BK4819_StopScan();
|
||||
}
|
||||
}
|
||||
|
||||
void SCANNER_TimeSlice10ms(void)
|
||||
{
|
||||
if (!SCANNER_IsScanning())
|
||||
return;
|
||||
|
||||
if (gScanDelay_10ms > 0) {
|
||||
gScanDelay_10ms--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gScannerSaveState != SCAN_SAVE_NO_PROMPT) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (gScanCssState) {
|
||||
case SCAN_CSS_STATE_OFF: {
|
||||
// must be RF frequency scanning if we're here ?
|
||||
uint32_t result;
|
||||
if (!BK4819_GetFrequencyScanResult(&result))
|
||||
break;
|
||||
|
||||
int32_t delta = result - gScanFrequency;
|
||||
gScanFrequency = result;
|
||||
|
||||
if (delta < 0)
|
||||
delta = -delta;
|
||||
if (delta < 100)
|
||||
scanHitCount++;
|
||||
else
|
||||
scanHitCount = 0;
|
||||
|
||||
BK4819_DisableFrequencyScan();
|
||||
|
||||
if (scanHitCount < 3) {
|
||||
BK4819_EnableFrequencyScan();
|
||||
}
|
||||
else {
|
||||
BK4819_SetScanFrequency(gScanFrequency);
|
||||
gScanCssResultCode = 0xFF;
|
||||
gScanCssResultType = 0xFF;
|
||||
scanHitCount = 0;
|
||||
gScanUseCssResult = false;
|
||||
gScanProgressIndicator = 0;
|
||||
gScanCssState = SCAN_CSS_STATE_SCANNING;
|
||||
|
||||
if(!gCssBackgroundScan)
|
||||
GUI_SelectNextDisplay(DISPLAY_SCANNER);
|
||||
|
||||
gUpdateStatus = true;
|
||||
}
|
||||
|
||||
gScanDelay_10ms = scan_delay_10ms;
|
||||
//gScanDelay_10ms = 1; // 10ms
|
||||
break;
|
||||
}
|
||||
case SCAN_CSS_STATE_SCANNING: {
|
||||
uint32_t cdcssFreq;
|
||||
uint16_t ctcssFreq;
|
||||
BK4819_CssScanResult_t scanResult = BK4819_GetCxCSSScanResult(&cdcssFreq, &ctcssFreq);
|
||||
if (scanResult == BK4819_CSS_RESULT_NOT_FOUND)
|
||||
break;
|
||||
|
||||
BK4819_Disable();
|
||||
|
||||
if (scanResult == BK4819_CSS_RESULT_CDCSS) {
|
||||
const uint8_t Code = DCS_GetCdcssCode(cdcssFreq);
|
||||
if (Code != 0xFF)
|
||||
{
|
||||
gScanCssResultCode = Code;
|
||||
gScanCssResultType = CODE_TYPE_DIGITAL;
|
||||
gScanCssState = SCAN_CSS_STATE_FOUND;
|
||||
gScanUseCssResult = true;
|
||||
gUpdateStatus = true;
|
||||
}
|
||||
}
|
||||
else if (scanResult == BK4819_CSS_RESULT_CTCSS) {
|
||||
const uint8_t Code = DCS_GetCtcssCode(ctcssFreq);
|
||||
if (Code != 0xFF) {
|
||||
if (Code == gScanCssResultCode && gScanCssResultType == CODE_TYPE_CONTINUOUS_TONE) {
|
||||
if (++scanHitCount >= 2) {
|
||||
gScanCssState = SCAN_CSS_STATE_FOUND;
|
||||
gScanUseCssResult = true;
|
||||
gUpdateStatus = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
scanHitCount = 0;
|
||||
|
||||
gScanCssResultType = CODE_TYPE_CONTINUOUS_TONE;
|
||||
gScanCssResultCode = Code;
|
||||
}
|
||||
}
|
||||
|
||||
if (gScanCssState < SCAN_CSS_STATE_FOUND) { // scanning or off
|
||||
BK4819_SetScanFrequency(gScanFrequency);
|
||||
gScanDelay_10ms = scan_delay_10ms;
|
||||
break;
|
||||
}
|
||||
|
||||
if(gCssBackgroundScan) {
|
||||
gCssBackgroundScan = false;
|
||||
if(gScanUseCssResult)
|
||||
MENU_CssScanFound();
|
||||
}
|
||||
else
|
||||
GUI_SelectNextDisplay(DISPLAY_SCANNER);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
gCssBackgroundScan = false;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SCANNER_TimeSlice500ms(void)
|
||||
{
|
||||
if (SCANNER_IsScanning() && gScannerSaveState == SCAN_SAVE_NO_PROMPT && gScanCssState < SCAN_CSS_STATE_FOUND) {
|
||||
gScanProgressIndicator++;
|
||||
#ifndef ENABLE_NO_CODE_SCAN_TIMEOUT
|
||||
if (gScanProgressIndicator > 32) {
|
||||
if (gScanCssState == SCAN_CSS_STATE_SCANNING && !gScanSingleFrequency)
|
||||
gScanCssState = SCAN_CSS_STATE_FOUND;
|
||||
else
|
||||
gScanCssState = SCAN_CSS_STATE_FAILED;
|
||||
|
||||
gUpdateStatus = true;
|
||||
}
|
||||
#endif
|
||||
gUpdateDisplay = true;
|
||||
}
|
||||
else if(gCssBackgroundScan) {
|
||||
gUpdateDisplay = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool SCANNER_IsScanning(void)
|
||||
{
|
||||
return gCssBackgroundScan || (gScreenToDisplay == DISPLAY_SCANNER);
|
||||
}
|
||||
57
app/scanner.h
Normal file
57
app/scanner.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APP_SCANNER_H
|
||||
#define APP_SCANNER_H
|
||||
|
||||
#include "dcs.h"
|
||||
#include "driver/keyboard.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SCAN_CSS_STATE_OFF,
|
||||
SCAN_CSS_STATE_SCANNING,
|
||||
SCAN_CSS_STATE_FOUND,
|
||||
SCAN_CSS_STATE_FAILED
|
||||
} SCAN_CssState_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SCAN_SAVE_NO_PROMPT, // saving process not initiated
|
||||
SCAN_SAVE_CHAN_SEL, // "SAVE: ", channel select prompt, actives only in channel mode
|
||||
SCAN_SAVE_CHANNEL, // "SAVE?" prompt, waits for confirmation to save settings to channel, or current VFO
|
||||
} SCAN_SaveState_t;
|
||||
|
||||
|
||||
extern DCS_CodeType_t gScanCssResultType;
|
||||
extern uint8_t gScanCssResultCode;
|
||||
extern bool gScanSingleFrequency;
|
||||
extern SCAN_SaveState_t gScannerSaveState;
|
||||
extern uint8_t gScanChannel;
|
||||
extern uint32_t gScanFrequency;
|
||||
extern SCAN_CssState_t gScanCssState;
|
||||
extern uint8_t gScanProgressIndicator;
|
||||
extern bool gScanUseCssResult;
|
||||
|
||||
void SCANNER_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);
|
||||
void SCANNER_Start(bool singleFreq);
|
||||
void SCANNER_Stop(void);
|
||||
void SCANNER_TimeSlice10ms(void);
|
||||
void SCANNER_TimeSlice500ms(void);
|
||||
bool SCANNER_IsScanning(void);
|
||||
|
||||
#endif
|
||||
|
||||
1310
app/spectrum.c
Normal file
1310
app/spectrum.c
Normal file
File diff suppressed because it is too large
Load Diff
158
app/spectrum.h
Normal file
158
app/spectrum.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/* Copyright 2023 fagci
|
||||
* https://github.com/fagci
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SPECTRUM_H
|
||||
#define SPECTRUM_H
|
||||
|
||||
#include "../bitmaps.h"
|
||||
#include "../board.h"
|
||||
#include "../bsp/dp32g030/gpio.h"
|
||||
#include "../driver/bk4819-regs.h"
|
||||
#include "../driver/bk4819.h"
|
||||
#include "../driver/gpio.h"
|
||||
#include "../driver/keyboard.h"
|
||||
#include "../driver/st7565.h"
|
||||
#include "../driver/system.h"
|
||||
#include "../driver/systick.h"
|
||||
#include "../external/printf/printf.h"
|
||||
#include "../font.h"
|
||||
#include "../helper/battery.h"
|
||||
#include "../misc.h"
|
||||
#include "../radio.h"
|
||||
#include "../settings.h"
|
||||
#include "../ui/helper.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
static const uint8_t DrawingEndY = 40;
|
||||
|
||||
static const uint8_t U8RssiMap[] = {
|
||||
121, 115, 109, 103, 97, 91, 85, 79, 73, 63,
|
||||
};
|
||||
|
||||
static const uint16_t scanStepValues[] = {
|
||||
1, 10, 50, 100, 250, 500, 625, 833,
|
||||
1000, 1250, 1500, 2000, 2500, 5000, 10000,
|
||||
};
|
||||
|
||||
static const uint16_t scanStepBWRegValues[] = {
|
||||
// RX RXw TX BW
|
||||
// 0b0 000 000 001 01 1000
|
||||
// 1
|
||||
0b0000000001011000, // 6.25
|
||||
// 10
|
||||
0b0000000001011000, // 6.25
|
||||
// 50
|
||||
0b0000000001011000, // 6.25
|
||||
// 100
|
||||
0b0000000001011000, // 6.25
|
||||
// 250
|
||||
0b0000000001011000, // 6.25
|
||||
// 500
|
||||
0b0010010001011000, // 6.25
|
||||
// 625
|
||||
0b0100100001011000, // 6.25
|
||||
// 833
|
||||
0b0110110001001000, // 6.25
|
||||
// 1000
|
||||
0b0110110001001000, // 6.25
|
||||
// 1250
|
||||
0b0111111100001000, // 6.25
|
||||
// 2500
|
||||
0b0011011000101000, // 25
|
||||
// 10000
|
||||
0b0011011000101000, // 25
|
||||
};
|
||||
|
||||
static const uint16_t listenBWRegValues[] = {
|
||||
0b0011011000101000, // 25
|
||||
0b0111111100001000, // 12.5
|
||||
0b0100100001011000, // 6.25
|
||||
};
|
||||
|
||||
typedef enum State {
|
||||
SPECTRUM,
|
||||
FREQ_INPUT,
|
||||
STILL,
|
||||
} State;
|
||||
|
||||
typedef enum StepsCount {
|
||||
STEPS_128,
|
||||
STEPS_64,
|
||||
STEPS_32,
|
||||
STEPS_16,
|
||||
} StepsCount;
|
||||
|
||||
typedef enum ScanStep {
|
||||
S_STEP_0_01kHz,
|
||||
S_STEP_0_1kHz,
|
||||
S_STEP_0_5kHz,
|
||||
S_STEP_1_0kHz,
|
||||
|
||||
S_STEP_2_5kHz,
|
||||
S_STEP_5_0kHz,
|
||||
S_STEP_6_25kHz,
|
||||
S_STEP_8_33kHz,
|
||||
S_STEP_10_0kHz,
|
||||
S_STEP_12_5kHz,
|
||||
S_STEP_15_0kHz,
|
||||
S_STEP_20_0kHz,
|
||||
S_STEP_25_0kHz,
|
||||
S_STEP_50_0kHz,
|
||||
S_STEP_100_0kHz,
|
||||
} ScanStep;
|
||||
|
||||
typedef struct SpectrumSettings {
|
||||
uint32_t frequencyChangeStep;
|
||||
StepsCount stepsCount;
|
||||
ScanStep scanStepIndex;
|
||||
uint16_t scanDelay;
|
||||
uint16_t rssiTriggerLevel;
|
||||
BK4819_FilterBandwidth_t bw;
|
||||
BK4819_FilterBandwidth_t listenBw;
|
||||
int dbMin;
|
||||
int dbMax;
|
||||
ModulationMode_t modulationType;
|
||||
bool backlightState;
|
||||
} SpectrumSettings;
|
||||
|
||||
typedef struct KeyboardState {
|
||||
KEY_Code_t current;
|
||||
KEY_Code_t prev;
|
||||
uint8_t counter;
|
||||
} KeyboardState;
|
||||
|
||||
typedef struct ScanInfo {
|
||||
uint16_t rssi, rssiMin, rssiMax;
|
||||
uint16_t i, iPeak;
|
||||
uint32_t f, fPeak;
|
||||
uint16_t scanStep;
|
||||
uint16_t measurementsCount;
|
||||
} ScanInfo;
|
||||
|
||||
typedef struct PeakInfo {
|
||||
uint16_t t;
|
||||
uint16_t rssi;
|
||||
uint32_t f;
|
||||
uint16_t i;
|
||||
} PeakInfo;
|
||||
|
||||
void APP_RunSpectrum(void);
|
||||
|
||||
#endif /* ifndef SPECTRUM_H */
|
||||
|
||||
// vim: ft=c
|
||||
624
app/uart.c
Normal file
624
app/uart.c
Normal file
@@ -0,0 +1,624 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(ENABLE_OVERLAY)
|
||||
#include "ARMCM0.h"
|
||||
#endif
|
||||
#ifdef ENABLE_FMRADIO
|
||||
#include "app/fm.h"
|
||||
#endif
|
||||
#include "app/uart.h"
|
||||
#include "board.h"
|
||||
#include "bsp/dp32g030/dma.h"
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "driver/aes.h"
|
||||
#include "driver/backlight.h"
|
||||
#include "driver/bk4819.h"
|
||||
#include "driver/crc.h"
|
||||
#include "driver/eeprom.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "functions.h"
|
||||
#include "misc.h"
|
||||
#include "settings.h"
|
||||
#include "version.h"
|
||||
|
||||
#if defined(ENABLE_OVERLAY)
|
||||
#include "sram-overlay.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define DMA_INDEX(x, y) (((x) + (y)) % sizeof(UART_DMA_Buffer))
|
||||
|
||||
typedef struct {
|
||||
uint16_t ID;
|
||||
uint16_t Size;
|
||||
} Header_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t Padding[2];
|
||||
uint16_t ID;
|
||||
} Footer_t;
|
||||
|
||||
typedef struct {
|
||||
Header_t Header;
|
||||
uint32_t Timestamp;
|
||||
} CMD_0514_t;
|
||||
|
||||
typedef struct {
|
||||
Header_t Header;
|
||||
struct {
|
||||
char Version[16];
|
||||
bool bHasCustomAesKey;
|
||||
bool bIsInLockScreen;
|
||||
uint8_t Padding[2];
|
||||
uint32_t Challenge[4];
|
||||
} Data;
|
||||
} REPLY_0514_t;
|
||||
|
||||
typedef struct {
|
||||
Header_t Header;
|
||||
uint16_t Offset;
|
||||
uint8_t Size;
|
||||
uint8_t Padding;
|
||||
uint32_t Timestamp;
|
||||
} CMD_051B_t;
|
||||
|
||||
typedef struct {
|
||||
Header_t Header;
|
||||
struct {
|
||||
uint16_t Offset;
|
||||
uint8_t Size;
|
||||
uint8_t Padding;
|
||||
uint8_t Data[128];
|
||||
} Data;
|
||||
} REPLY_051B_t;
|
||||
|
||||
typedef struct {
|
||||
Header_t Header;
|
||||
uint16_t Offset;
|
||||
uint8_t Size;
|
||||
bool bAllowPassword;
|
||||
uint32_t Timestamp;
|
||||
uint8_t Data[0];
|
||||
} CMD_051D_t;
|
||||
|
||||
typedef struct {
|
||||
Header_t Header;
|
||||
struct {
|
||||
uint16_t Offset;
|
||||
} Data;
|
||||
} REPLY_051D_t;
|
||||
|
||||
typedef struct {
|
||||
Header_t Header;
|
||||
struct {
|
||||
uint16_t RSSI;
|
||||
uint8_t ExNoiseIndicator;
|
||||
uint8_t GlitchIndicator;
|
||||
} Data;
|
||||
} REPLY_0527_t;
|
||||
|
||||
typedef struct {
|
||||
Header_t Header;
|
||||
struct {
|
||||
uint16_t Voltage;
|
||||
uint16_t Current;
|
||||
} Data;
|
||||
} REPLY_0529_t;
|
||||
|
||||
typedef struct {
|
||||
Header_t Header;
|
||||
uint32_t Response[4];
|
||||
} CMD_052D_t;
|
||||
|
||||
typedef struct {
|
||||
Header_t Header;
|
||||
struct {
|
||||
bool bIsLocked;
|
||||
uint8_t Padding[3];
|
||||
} Data;
|
||||
} REPLY_052D_t;
|
||||
|
||||
typedef struct {
|
||||
Header_t Header;
|
||||
uint32_t Timestamp;
|
||||
} CMD_052F_t;
|
||||
|
||||
static const uint8_t Obfuscation[16] =
|
||||
{
|
||||
0x16, 0x6C, 0x14, 0xE6, 0x2E, 0x91, 0x0D, 0x40, 0x21, 0x35, 0xD5, 0x40, 0x13, 0x03, 0xE9, 0x80
|
||||
};
|
||||
|
||||
static union
|
||||
{
|
||||
uint8_t Buffer[256];
|
||||
struct
|
||||
{
|
||||
Header_t Header;
|
||||
uint8_t Data[252];
|
||||
};
|
||||
} UART_Command;
|
||||
|
||||
static uint32_t Timestamp;
|
||||
static uint16_t gUART_WriteIndex;
|
||||
static bool bIsEncrypted = true;
|
||||
|
||||
static void SendReply(void *pReply, uint16_t Size)
|
||||
{
|
||||
Header_t Header;
|
||||
Footer_t Footer;
|
||||
|
||||
if (bIsEncrypted)
|
||||
{
|
||||
uint8_t *pBytes = (uint8_t *)pReply;
|
||||
unsigned int i;
|
||||
for (i = 0; i < Size; i++)
|
||||
pBytes[i] ^= Obfuscation[i % 16];
|
||||
}
|
||||
|
||||
Header.ID = 0xCDAB;
|
||||
Header.Size = Size;
|
||||
UART_Send(&Header, sizeof(Header));
|
||||
UART_Send(pReply, Size);
|
||||
|
||||
if (bIsEncrypted)
|
||||
{
|
||||
Footer.Padding[0] = Obfuscation[(Size + 0) % 16] ^ 0xFF;
|
||||
Footer.Padding[1] = Obfuscation[(Size + 1) % 16] ^ 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
Footer.Padding[0] = 0xFF;
|
||||
Footer.Padding[1] = 0xFF;
|
||||
}
|
||||
Footer.ID = 0xBADC;
|
||||
|
||||
UART_Send(&Footer, sizeof(Footer));
|
||||
}
|
||||
|
||||
static void SendVersion(void)
|
||||
{
|
||||
REPLY_0514_t Reply;
|
||||
|
||||
Reply.Header.ID = 0x0515;
|
||||
Reply.Header.Size = sizeof(Reply.Data);
|
||||
strcpy(Reply.Data.Version, Version);
|
||||
Reply.Data.bHasCustomAesKey = bHasCustomAesKey;
|
||||
Reply.Data.bIsInLockScreen = bIsInLockScreen;
|
||||
Reply.Data.Challenge[0] = gChallenge[0];
|
||||
Reply.Data.Challenge[1] = gChallenge[1];
|
||||
Reply.Data.Challenge[2] = gChallenge[2];
|
||||
Reply.Data.Challenge[3] = gChallenge[3];
|
||||
|
||||
SendReply(&Reply, sizeof(Reply));
|
||||
}
|
||||
|
||||
static bool IsBadChallenge(const uint32_t *pKey, const uint32_t *pIn, const uint32_t *pResponse)
|
||||
{
|
||||
unsigned int i;
|
||||
uint32_t IV[4];
|
||||
|
||||
IV[0] = 0;
|
||||
IV[1] = 0;
|
||||
IV[2] = 0;
|
||||
IV[3] = 0;
|
||||
|
||||
AES_Encrypt(pKey, IV, pIn, IV, true);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
if (IV[i] != pResponse[i])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// session init, sends back version info and state
|
||||
// timestamp is a session id really
|
||||
static void CMD_0514(const uint8_t *pBuffer)
|
||||
{
|
||||
const CMD_0514_t *pCmd = (const CMD_0514_t *)pBuffer;
|
||||
|
||||
Timestamp = pCmd->Timestamp;
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
gFmRadioCountdown_500ms = fm_radio_countdown_500ms;
|
||||
#endif
|
||||
|
||||
gSerialConfigCountDown_500ms = 12; // 6 sec
|
||||
|
||||
// turn the LCD backlight off
|
||||
BACKLIGHT_TurnOff();
|
||||
|
||||
SendVersion();
|
||||
}
|
||||
|
||||
// read eeprom
|
||||
static void CMD_051B(const uint8_t *pBuffer)
|
||||
{
|
||||
const CMD_051B_t *pCmd = (const CMD_051B_t *)pBuffer;
|
||||
REPLY_051B_t Reply;
|
||||
bool bLocked = false;
|
||||
|
||||
if (pCmd->Timestamp != Timestamp)
|
||||
return;
|
||||
|
||||
gSerialConfigCountDown_500ms = 12; // 6 sec
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
gFmRadioCountdown_500ms = fm_radio_countdown_500ms;
|
||||
#endif
|
||||
|
||||
memset(&Reply, 0, sizeof(Reply));
|
||||
Reply.Header.ID = 0x051C;
|
||||
Reply.Header.Size = pCmd->Size + 4;
|
||||
Reply.Data.Offset = pCmd->Offset;
|
||||
Reply.Data.Size = pCmd->Size;
|
||||
|
||||
if (bHasCustomAesKey)
|
||||
bLocked = gIsLocked;
|
||||
|
||||
if (!bLocked)
|
||||
EEPROM_ReadBuffer(pCmd->Offset, Reply.Data.Data, pCmd->Size);
|
||||
|
||||
SendReply(&Reply, pCmd->Size + 8);
|
||||
}
|
||||
|
||||
// write eeprom
|
||||
static void CMD_051D(const uint8_t *pBuffer)
|
||||
{
|
||||
const CMD_051D_t *pCmd = (const CMD_051D_t *)pBuffer;
|
||||
REPLY_051D_t Reply;
|
||||
bool bReloadEeprom;
|
||||
bool bIsLocked;
|
||||
|
||||
if (pCmd->Timestamp != Timestamp)
|
||||
return;
|
||||
|
||||
gSerialConfigCountDown_500ms = 12; // 6 sec
|
||||
|
||||
bReloadEeprom = false;
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
gFmRadioCountdown_500ms = fm_radio_countdown_500ms;
|
||||
#endif
|
||||
|
||||
Reply.Header.ID = 0x051E;
|
||||
Reply.Header.Size = sizeof(Reply.Data);
|
||||
Reply.Data.Offset = pCmd->Offset;
|
||||
|
||||
bIsLocked = bHasCustomAesKey ? gIsLocked : bHasCustomAesKey;
|
||||
|
||||
if (!bIsLocked)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < (pCmd->Size / 8); i++)
|
||||
{
|
||||
const uint16_t Offset = pCmd->Offset + (i * 8U);
|
||||
|
||||
if (Offset >= 0x0F30 && Offset < 0x0F40)
|
||||
if (!gIsLocked)
|
||||
bReloadEeprom = true;
|
||||
|
||||
if ((Offset < 0x0E98 || Offset >= 0x0EA0) || !bIsInLockScreen || pCmd->bAllowPassword)
|
||||
EEPROM_WriteBuffer(Offset, &pCmd->Data[i * 8U]);
|
||||
}
|
||||
|
||||
if (bReloadEeprom)
|
||||
SETTINGS_InitEEPROM();
|
||||
}
|
||||
|
||||
SendReply(&Reply, sizeof(Reply));
|
||||
}
|
||||
|
||||
// read RSSI
|
||||
static void CMD_0527(void)
|
||||
{
|
||||
REPLY_0527_t Reply;
|
||||
|
||||
Reply.Header.ID = 0x0528;
|
||||
Reply.Header.Size = sizeof(Reply.Data);
|
||||
Reply.Data.RSSI = BK4819_ReadRegister(BK4819_REG_67) & 0x01FF;
|
||||
Reply.Data.ExNoiseIndicator = BK4819_ReadRegister(BK4819_REG_65) & 0x007F;
|
||||
Reply.Data.GlitchIndicator = BK4819_ReadRegister(BK4819_REG_63);
|
||||
|
||||
SendReply(&Reply, sizeof(Reply));
|
||||
}
|
||||
|
||||
// read ADC
|
||||
static void CMD_0529(void)
|
||||
{
|
||||
REPLY_0529_t Reply;
|
||||
|
||||
Reply.Header.ID = 0x52A;
|
||||
Reply.Header.Size = sizeof(Reply.Data);
|
||||
|
||||
// Original doesn't actually send current!
|
||||
BOARD_ADC_GetBatteryInfo(&Reply.Data.Voltage, &Reply.Data.Current);
|
||||
|
||||
SendReply(&Reply, sizeof(Reply));
|
||||
}
|
||||
|
||||
static void CMD_052D(const uint8_t *pBuffer)
|
||||
{
|
||||
const CMD_052D_t *pCmd = (const CMD_052D_t *)pBuffer;
|
||||
REPLY_052D_t Reply;
|
||||
bool bIsLocked;
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
gFmRadioCountdown_500ms = fm_radio_countdown_500ms;
|
||||
#endif
|
||||
Reply.Header.ID = 0x052E;
|
||||
Reply.Header.Size = sizeof(Reply.Data);
|
||||
|
||||
bIsLocked = bHasCustomAesKey;
|
||||
|
||||
if (!bIsLocked)
|
||||
bIsLocked = IsBadChallenge(gCustomAesKey, gChallenge, pCmd->Response);
|
||||
|
||||
if (!bIsLocked)
|
||||
{
|
||||
bIsLocked = IsBadChallenge(gDefaultAesKey, gChallenge, pCmd->Response);
|
||||
if (bIsLocked)
|
||||
gTryCount++;
|
||||
}
|
||||
|
||||
if (gTryCount < 3)
|
||||
{
|
||||
if (!bIsLocked)
|
||||
gTryCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
gTryCount = 3;
|
||||
bIsLocked = true;
|
||||
}
|
||||
|
||||
gIsLocked = bIsLocked;
|
||||
Reply.Data.bIsLocked = bIsLocked;
|
||||
|
||||
SendReply(&Reply, sizeof(Reply));
|
||||
}
|
||||
|
||||
// session init, sends back version info and state
|
||||
// timestamp is a session id really
|
||||
// this command also disables dual watch, crossband,
|
||||
// DTMF side tones, freq reverse, PTT ID, DTMF decoding, frequency offset
|
||||
// exits power save, sets main VFO to upper,
|
||||
static void CMD_052F(const uint8_t *pBuffer)
|
||||
{
|
||||
const CMD_052F_t *pCmd = (const CMD_052F_t *)pBuffer;
|
||||
|
||||
gEeprom.DUAL_WATCH = DUAL_WATCH_OFF;
|
||||
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
|
||||
gEeprom.RX_VFO = 0;
|
||||
gEeprom.DTMF_SIDE_TONE = false;
|
||||
gEeprom.VfoInfo[0].FrequencyReverse = false;
|
||||
gEeprom.VfoInfo[0].pRX = &gEeprom.VfoInfo[0].freq_config_RX;
|
||||
gEeprom.VfoInfo[0].pTX = &gEeprom.VfoInfo[0].freq_config_TX;
|
||||
gEeprom.VfoInfo[0].TX_OFFSET_FREQUENCY_DIRECTION = TX_OFFSET_FREQUENCY_DIRECTION_OFF;
|
||||
gEeprom.VfoInfo[0].DTMF_PTT_ID_TX_MODE = PTT_ID_OFF;
|
||||
#ifdef ENABLE_DTMF_CALLING
|
||||
gEeprom.VfoInfo[0].DTMF_DECODING_ENABLE = false;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_NOAA
|
||||
gIsNoaaMode = false;
|
||||
#endif
|
||||
|
||||
if (gCurrentFunction == FUNCTION_POWER_SAVE)
|
||||
FUNCTION_Select(FUNCTION_FOREGROUND);
|
||||
|
||||
gSerialConfigCountDown_500ms = 12; // 6 sec
|
||||
|
||||
Timestamp = pCmd->Timestamp;
|
||||
|
||||
// turn the LCD backlight off
|
||||
BACKLIGHT_TurnOff();
|
||||
|
||||
SendVersion();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_UART_RW_BK_REGS
|
||||
static void CMD_0601_ReadBK4819Reg(const uint8_t *pBuffer)
|
||||
{
|
||||
typedef struct __attribute__((__packed__)) {
|
||||
Header_t header;
|
||||
uint8_t reg;
|
||||
} CMD_0601_t;
|
||||
|
||||
CMD_0601_t *cmd = (CMD_0601_t*) pBuffer;
|
||||
|
||||
struct __attribute__((__packed__)) {
|
||||
Header_t header;
|
||||
struct __attribute__((__packed__)) {
|
||||
uint8_t reg;
|
||||
uint16_t value;
|
||||
} data;
|
||||
} reply;
|
||||
|
||||
reply.header.ID = 0x0601;
|
||||
reply.header.Size = sizeof(reply.data);
|
||||
reply.data.reg = cmd->reg;
|
||||
reply.data.value = BK4819_ReadRegister(cmd->reg);
|
||||
SendReply(&reply, sizeof(reply));
|
||||
}
|
||||
|
||||
static void CMD_0602_WriteBK4819Reg(const uint8_t *pBuffer)
|
||||
{
|
||||
typedef struct __attribute__((__packed__)) {
|
||||
Header_t header;
|
||||
uint8_t reg;
|
||||
uint16_t value;
|
||||
} CMD_0602_t;
|
||||
|
||||
CMD_0602_t *cmd = (CMD_0602_t*) pBuffer;
|
||||
BK4819_WriteRegister(cmd->reg, cmd->value);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool UART_IsCommandAvailable(void)
|
||||
{
|
||||
uint16_t Index;
|
||||
uint16_t TailIndex;
|
||||
uint16_t Size;
|
||||
uint16_t CRC;
|
||||
uint16_t CommandLength;
|
||||
uint16_t DmaLength = DMA_CH0->ST & 0xFFFU;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (gUART_WriteIndex == DmaLength)
|
||||
return false;
|
||||
|
||||
while (gUART_WriteIndex != DmaLength && UART_DMA_Buffer[gUART_WriteIndex] != 0xABU)
|
||||
gUART_WriteIndex = DMA_INDEX(gUART_WriteIndex, 1);
|
||||
|
||||
if (gUART_WriteIndex == DmaLength)
|
||||
return false;
|
||||
|
||||
if (gUART_WriteIndex < DmaLength)
|
||||
CommandLength = DmaLength - gUART_WriteIndex;
|
||||
else
|
||||
CommandLength = (DmaLength + sizeof(UART_DMA_Buffer)) - gUART_WriteIndex;
|
||||
|
||||
if (CommandLength < 8)
|
||||
return 0;
|
||||
|
||||
if (UART_DMA_Buffer[DMA_INDEX(gUART_WriteIndex, 1)] == 0xCD)
|
||||
break;
|
||||
|
||||
gUART_WriteIndex = DMA_INDEX(gUART_WriteIndex, 1);
|
||||
}
|
||||
|
||||
Index = DMA_INDEX(gUART_WriteIndex, 2);
|
||||
Size = (UART_DMA_Buffer[DMA_INDEX(Index, 1)] << 8) | UART_DMA_Buffer[Index];
|
||||
|
||||
if ((Size + 8u) > sizeof(UART_DMA_Buffer))
|
||||
{
|
||||
gUART_WriteIndex = DmaLength;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CommandLength < (Size + 8))
|
||||
return false;
|
||||
|
||||
Index = DMA_INDEX(Index, 2);
|
||||
TailIndex = DMA_INDEX(Index, Size + 2);
|
||||
|
||||
if (UART_DMA_Buffer[TailIndex] != 0xDC || UART_DMA_Buffer[DMA_INDEX(TailIndex, 1)] != 0xBA)
|
||||
{
|
||||
gUART_WriteIndex = DmaLength;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TailIndex < Index)
|
||||
{
|
||||
const uint16_t ChunkSize = sizeof(UART_DMA_Buffer) - Index;
|
||||
memcpy(UART_Command.Buffer, UART_DMA_Buffer + Index, ChunkSize);
|
||||
memcpy(UART_Command.Buffer + ChunkSize, UART_DMA_Buffer, TailIndex);
|
||||
}
|
||||
else
|
||||
memcpy(UART_Command.Buffer, UART_DMA_Buffer + Index, TailIndex - Index);
|
||||
|
||||
TailIndex = DMA_INDEX(TailIndex, 2);
|
||||
if (TailIndex < gUART_WriteIndex)
|
||||
{
|
||||
memset(UART_DMA_Buffer + gUART_WriteIndex, 0, sizeof(UART_DMA_Buffer) - gUART_WriteIndex);
|
||||
memset(UART_DMA_Buffer, 0, TailIndex);
|
||||
}
|
||||
else
|
||||
memset(UART_DMA_Buffer + gUART_WriteIndex, 0, TailIndex - gUART_WriteIndex);
|
||||
|
||||
gUART_WriteIndex = TailIndex;
|
||||
|
||||
if (UART_Command.Header.ID == 0x0514)
|
||||
bIsEncrypted = false;
|
||||
|
||||
if (UART_Command.Header.ID == 0x6902)
|
||||
bIsEncrypted = true;
|
||||
|
||||
if (bIsEncrypted)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < (Size + 2u); i++)
|
||||
UART_Command.Buffer[i] ^= Obfuscation[i % 16];
|
||||
}
|
||||
|
||||
CRC = UART_Command.Buffer[Size] | (UART_Command.Buffer[Size + 1] << 8);
|
||||
|
||||
return (CRC_Calculate(UART_Command.Buffer, Size) != CRC) ? false : true;
|
||||
}
|
||||
|
||||
void UART_HandleCommand(void)
|
||||
{
|
||||
switch (UART_Command.Header.ID)
|
||||
{
|
||||
case 0x0514:
|
||||
CMD_0514(UART_Command.Buffer);
|
||||
break;
|
||||
|
||||
case 0x051B:
|
||||
CMD_051B(UART_Command.Buffer);
|
||||
break;
|
||||
|
||||
case 0x051D:
|
||||
CMD_051D(UART_Command.Buffer);
|
||||
break;
|
||||
|
||||
case 0x051F: // Not implementing non-authentic command
|
||||
break;
|
||||
|
||||
case 0x0521: // Not implementing non-authentic command
|
||||
break;
|
||||
|
||||
case 0x0527:
|
||||
CMD_0527();
|
||||
break;
|
||||
|
||||
case 0x0529:
|
||||
CMD_0529();
|
||||
break;
|
||||
|
||||
case 0x052D:
|
||||
CMD_052D(UART_Command.Buffer);
|
||||
break;
|
||||
|
||||
case 0x052F:
|
||||
CMD_052F(UART_Command.Buffer);
|
||||
break;
|
||||
|
||||
case 0x05DD: // reset
|
||||
#if defined(ENABLE_OVERLAY)
|
||||
overlay_FLASH_RebootToBootloader();
|
||||
#else
|
||||
NVIC_SystemReset();
|
||||
#endif
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_UART_RW_BK_REGS
|
||||
case 0x0601:
|
||||
CMD_0601_ReadBK4819Reg(UART_Command.Buffer);
|
||||
break;
|
||||
|
||||
case 0x0602:
|
||||
CMD_0602_WriteBK4819Reg(UART_Command.Buffer);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
26
app/uart.h
Normal file
26
app/uart.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APP_UART_H
|
||||
#define APP_UART_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool UART_IsCommandAvailable(void);
|
||||
void UART_HandleCommand(void);
|
||||
|
||||
#endif
|
||||
|
||||
442
audio.c
Normal file
442
audio.c
Normal file
@@ -0,0 +1,442 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
#include "app/fm.h"
|
||||
#endif
|
||||
#include "audio.h"
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#ifdef ENABLE_FMRADIO
|
||||
#include "driver/bk1080.h"
|
||||
#endif
|
||||
#include "driver/bk4819.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/system.h"
|
||||
#include "driver/systick.h"
|
||||
#include "functions.h"
|
||||
#include "misc.h"
|
||||
#include "settings.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
|
||||
BEEP_Type_t gBeepToPlay = BEEP_NONE;
|
||||
|
||||
void AUDIO_PlayBeep(BEEP_Type_t Beep)
|
||||
{
|
||||
|
||||
if (Beep != BEEP_880HZ_60MS_TRIPLE_BEEP &&
|
||||
Beep != BEEP_500HZ_60MS_DOUBLE_BEEP &&
|
||||
Beep != BEEP_440HZ_500MS &&
|
||||
Beep != BEEP_880HZ_200MS &&
|
||||
Beep != BEEP_880HZ_500MS &&
|
||||
!gEeprom.BEEP_CONTROL)
|
||||
return;
|
||||
|
||||
#ifdef ENABLE_AIRCOPY
|
||||
if (gScreenToDisplay == DISPLAY_AIRCOPY)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (gCurrentFunction == FUNCTION_RECEIVE)
|
||||
return;
|
||||
|
||||
if (gCurrentFunction == FUNCTION_MONITOR)
|
||||
return;
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (gFmRadioMode)
|
||||
BK1080_Mute(true);
|
||||
#endif
|
||||
|
||||
AUDIO_AudioPathOff();
|
||||
|
||||
if (gCurrentFunction == FUNCTION_POWER_SAVE && gRxIdleMode)
|
||||
BK4819_RX_TurnOn();
|
||||
|
||||
SYSTEM_DelayMs(20);
|
||||
|
||||
uint16_t ToneConfig = BK4819_ReadRegister(BK4819_REG_71);
|
||||
|
||||
uint16_t ToneFrequency;
|
||||
switch (Beep)
|
||||
{
|
||||
default:
|
||||
case BEEP_NONE:
|
||||
ToneFrequency = 220;
|
||||
break;
|
||||
case BEEP_1KHZ_60MS_OPTIONAL:
|
||||
ToneFrequency = 1000;
|
||||
break;
|
||||
case BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL:
|
||||
case BEEP_500HZ_60MS_DOUBLE_BEEP:
|
||||
ToneFrequency = 500;
|
||||
break;
|
||||
case BEEP_440HZ_40MS_OPTIONAL:
|
||||
case BEEP_440HZ_500MS:
|
||||
ToneFrequency = 440;
|
||||
break;
|
||||
case BEEP_880HZ_40MS_OPTIONAL:
|
||||
case BEEP_880HZ_60MS_TRIPLE_BEEP:
|
||||
case BEEP_880HZ_200MS:
|
||||
case BEEP_880HZ_500MS:
|
||||
ToneFrequency = 880;
|
||||
break;
|
||||
}
|
||||
|
||||
BK4819_PlayTone(ToneFrequency, true);
|
||||
|
||||
SYSTEM_DelayMs(2);
|
||||
|
||||
AUDIO_AudioPathOn();
|
||||
|
||||
SYSTEM_DelayMs(60);
|
||||
|
||||
uint16_t Duration;
|
||||
switch (Beep)
|
||||
{
|
||||
case BEEP_880HZ_60MS_TRIPLE_BEEP:
|
||||
BK4819_ExitTxMute();
|
||||
SYSTEM_DelayMs(60);
|
||||
BK4819_EnterTxMute();
|
||||
SYSTEM_DelayMs(20);
|
||||
__attribute__((fallthrough));
|
||||
case BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL:
|
||||
case BEEP_500HZ_60MS_DOUBLE_BEEP:
|
||||
BK4819_ExitTxMute();
|
||||
SYSTEM_DelayMs(60);
|
||||
BK4819_EnterTxMute();
|
||||
SYSTEM_DelayMs(20);
|
||||
__attribute__((fallthrough));
|
||||
case BEEP_1KHZ_60MS_OPTIONAL:
|
||||
BK4819_ExitTxMute();
|
||||
Duration = 60;
|
||||
break;
|
||||
case BEEP_880HZ_40MS_OPTIONAL:
|
||||
case BEEP_440HZ_40MS_OPTIONAL:
|
||||
BK4819_ExitTxMute();
|
||||
Duration = 40;
|
||||
break;
|
||||
case BEEP_880HZ_200MS:
|
||||
BK4819_ExitTxMute();
|
||||
Duration = 200;
|
||||
break;
|
||||
case BEEP_440HZ_500MS:
|
||||
case BEEP_880HZ_500MS:
|
||||
default:
|
||||
BK4819_ExitTxMute();
|
||||
Duration = 500;
|
||||
break;
|
||||
}
|
||||
|
||||
SYSTEM_DelayMs(Duration);
|
||||
BK4819_EnterTxMute();
|
||||
SYSTEM_DelayMs(20);
|
||||
|
||||
AUDIO_AudioPathOff();
|
||||
|
||||
SYSTEM_DelayMs(5);
|
||||
BK4819_TurnsOffTones_TurnsOnRX();
|
||||
SYSTEM_DelayMs(5);
|
||||
BK4819_WriteRegister(BK4819_REG_71, ToneConfig);
|
||||
|
||||
if (gEnableSpeaker)
|
||||
AUDIO_AudioPathOn();
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (gFmRadioMode)
|
||||
BK1080_Mute(false);
|
||||
#endif
|
||||
|
||||
if (gCurrentFunction == FUNCTION_POWER_SAVE && gRxIdleMode)
|
||||
BK4819_Sleep();
|
||||
|
||||
#ifdef ENABLE_VOX
|
||||
gVoxResumeCountdown = 80;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
|
||||
static const uint8_t VoiceClipLengthChinese[58] =
|
||||
{
|
||||
0x32, 0x32, 0x32, 0x37, 0x37, 0x32, 0x32, 0x32,
|
||||
0x32, 0x37, 0x37, 0x32, 0x64, 0x64, 0x64, 0x64,
|
||||
0x64, 0x69, 0x64, 0x69, 0x5A, 0x5F, 0x5F, 0x64,
|
||||
0x64, 0x69, 0x64, 0x64, 0x69, 0x69, 0x69, 0x64,
|
||||
0x64, 0x6E, 0x69, 0x5F, 0x64, 0x64, 0x64, 0x69,
|
||||
0x69, 0x69, 0x64, 0x69, 0x64, 0x64, 0x55, 0x5F,
|
||||
0x5A, 0x4B, 0x4B, 0x46, 0x46, 0x69, 0x64, 0x6E,
|
||||
0x5A, 0x64,
|
||||
};
|
||||
|
||||
static const uint8_t VoiceClipLengthEnglish[76] =
|
||||
{
|
||||
0x50, 0x32, 0x2D, 0x2D, 0x2D, 0x37, 0x37, 0x37,
|
||||
0x32, 0x32, 0x3C, 0x37, 0x46, 0x46, 0x4B, 0x82,
|
||||
0x82, 0x6E, 0x82, 0x46, 0x96, 0x64, 0x46, 0x6E,
|
||||
0x78, 0x6E, 0x87, 0x64, 0x96, 0x96, 0x46, 0x9B,
|
||||
0x91, 0x82, 0x82, 0x73, 0x78, 0x64, 0x82, 0x6E,
|
||||
0x78, 0x82, 0x87, 0x6E, 0x55, 0x78, 0x64, 0x69,
|
||||
0x9B, 0x5A, 0x50, 0x3C, 0x32, 0x55, 0x64, 0x64,
|
||||
0x50, 0x46, 0x46, 0x46, 0x4B, 0x4B, 0x50, 0x50,
|
||||
0x55, 0x4B, 0x4B, 0x32, 0x32, 0x32, 0x32, 0x37,
|
||||
0x41, 0x32, 0x3C, 0x37,
|
||||
};
|
||||
|
||||
VOICE_ID_t gVoiceID[8];
|
||||
uint8_t gVoiceReadIndex;
|
||||
uint8_t gVoiceWriteIndex;
|
||||
volatile uint16_t gCountdownToPlayNextVoice_10ms;
|
||||
volatile bool gFlagPlayQueuedVoice;
|
||||
VOICE_ID_t gAnotherVoiceID = VOICE_ID_INVALID;
|
||||
|
||||
|
||||
static void AUDIO_PlayVoice(uint8_t VoiceID)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0);
|
||||
SYSTEM_DelayMs(20);
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if ((VoiceID & 0x80U) == 0)
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_VOICE_1);
|
||||
else
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_VOICE_1);
|
||||
|
||||
SYSTICK_DelayUs(1000);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0);
|
||||
SYSTICK_DelayUs(1200);
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_VOICE_0);
|
||||
VoiceID <<= 1;
|
||||
SYSTICK_DelayUs(200);
|
||||
}
|
||||
}
|
||||
|
||||
void AUDIO_PlaySingleVoice(bool bFlag)
|
||||
{
|
||||
uint8_t VoiceID;
|
||||
uint8_t Delay;
|
||||
|
||||
VoiceID = gVoiceID[0];
|
||||
|
||||
if (gEeprom.VOICE_PROMPT != VOICE_PROMPT_OFF && gVoiceWriteIndex > 0)
|
||||
{
|
||||
if (gEeprom.VOICE_PROMPT == VOICE_PROMPT_CHINESE)
|
||||
{ // Chinese
|
||||
if (VoiceID >= ARRAY_SIZE(VoiceClipLengthChinese))
|
||||
goto Bailout;
|
||||
|
||||
Delay = VoiceClipLengthChinese[VoiceID];
|
||||
VoiceID += VOICE_ID_CHI_BASE;
|
||||
}
|
||||
else
|
||||
{ // English
|
||||
if (VoiceID >= ARRAY_SIZE(VoiceClipLengthEnglish))
|
||||
goto Bailout;
|
||||
|
||||
Delay = VoiceClipLengthEnglish[VoiceID];
|
||||
VoiceID += VOICE_ID_ENG_BASE;
|
||||
}
|
||||
|
||||
if (FUNCTION_IsRx()) // 1of11
|
||||
BK4819_SetAF(BK4819_AF_MUTE);
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (gFmRadioMode)
|
||||
BK1080_Mute(true);
|
||||
#endif
|
||||
|
||||
AUDIO_AudioPathOn();
|
||||
|
||||
#ifdef ENABLE_VOX
|
||||
gVoxResumeCountdown = 2000;
|
||||
#endif
|
||||
|
||||
SYSTEM_DelayMs(5);
|
||||
AUDIO_PlayVoice(VoiceID);
|
||||
|
||||
if (gVoiceWriteIndex == 1)
|
||||
Delay += 3;
|
||||
|
||||
if (bFlag)
|
||||
{
|
||||
SYSTEM_DelayMs(Delay * 10);
|
||||
|
||||
if (FUNCTION_IsRx()) // 1of11
|
||||
RADIO_SetModulation(gRxVfo->Modulation);
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (gFmRadioMode)
|
||||
BK1080_Mute(false);
|
||||
#endif
|
||||
|
||||
if (!gEnableSpeaker)
|
||||
AUDIO_AudioPathOff();
|
||||
|
||||
gVoiceWriteIndex = 0;
|
||||
gVoiceReadIndex = 0;
|
||||
|
||||
#ifdef ENABLE_VOX
|
||||
gVoxResumeCountdown = 80;
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gVoiceReadIndex = 1;
|
||||
gCountdownToPlayNextVoice_10ms = Delay;
|
||||
gFlagPlayQueuedVoice = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Bailout:
|
||||
gVoiceReadIndex = 0;
|
||||
gVoiceWriteIndex = 0;
|
||||
}
|
||||
|
||||
void AUDIO_SetVoiceID(uint8_t Index, VOICE_ID_t VoiceID)
|
||||
{
|
||||
if (Index >= ARRAY_SIZE(gVoiceID))
|
||||
return;
|
||||
|
||||
if (Index == 0)
|
||||
{
|
||||
gVoiceWriteIndex = 0;
|
||||
gVoiceReadIndex = 0;
|
||||
}
|
||||
|
||||
gVoiceID[Index] = VoiceID;
|
||||
|
||||
gVoiceWriteIndex++;
|
||||
}
|
||||
|
||||
uint8_t AUDIO_SetDigitVoice(uint8_t Index, uint16_t Value)
|
||||
{
|
||||
uint16_t Remainder;
|
||||
uint8_t Result;
|
||||
uint8_t Count;
|
||||
|
||||
if (Index == 0)
|
||||
{
|
||||
gVoiceWriteIndex = 0;
|
||||
gVoiceReadIndex = 0;
|
||||
}
|
||||
|
||||
Count = 0;
|
||||
Result = Value / 1000U;
|
||||
Remainder = Value % 1000U;
|
||||
if (Remainder < 100U)
|
||||
{
|
||||
if (Remainder < 10U)
|
||||
goto Skip;
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = Remainder / 100U;
|
||||
gVoiceID[gVoiceWriteIndex++] = (VOICE_ID_t)Result;
|
||||
Count++;
|
||||
Remainder -= Result * 100U;
|
||||
}
|
||||
Result = Remainder / 10U;
|
||||
gVoiceID[gVoiceWriteIndex++] = (VOICE_ID_t)Result;
|
||||
Count++;
|
||||
Remainder -= Result * 10U;
|
||||
|
||||
Skip:
|
||||
gVoiceID[gVoiceWriteIndex++] = (VOICE_ID_t)Remainder;
|
||||
|
||||
return Count + 1U;
|
||||
}
|
||||
|
||||
void AUDIO_PlayQueuedVoice(void)
|
||||
{
|
||||
uint8_t VoiceID;
|
||||
uint8_t Delay;
|
||||
bool Skip;
|
||||
|
||||
Skip = false;
|
||||
|
||||
if (gVoiceReadIndex != gVoiceWriteIndex && gEeprom.VOICE_PROMPT != VOICE_PROMPT_OFF)
|
||||
{
|
||||
VoiceID = gVoiceID[gVoiceReadIndex];
|
||||
if (gEeprom.VOICE_PROMPT == VOICE_PROMPT_CHINESE)
|
||||
{
|
||||
if (VoiceID < ARRAY_SIZE(VoiceClipLengthChinese))
|
||||
{
|
||||
Delay = VoiceClipLengthChinese[VoiceID];
|
||||
VoiceID += VOICE_ID_CHI_BASE;
|
||||
}
|
||||
else
|
||||
Skip = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (VoiceID < ARRAY_SIZE(VoiceClipLengthEnglish))
|
||||
{
|
||||
Delay = VoiceClipLengthEnglish[VoiceID];
|
||||
VoiceID += VOICE_ID_ENG_BASE;
|
||||
}
|
||||
else
|
||||
Skip = true;
|
||||
}
|
||||
|
||||
gVoiceReadIndex++;
|
||||
|
||||
if (!Skip)
|
||||
{
|
||||
if (gVoiceReadIndex == gVoiceWriteIndex)
|
||||
Delay += 3;
|
||||
|
||||
AUDIO_PlayVoice(VoiceID);
|
||||
|
||||
gCountdownToPlayNextVoice_10ms = Delay;
|
||||
gFlagPlayQueuedVoice = false;
|
||||
|
||||
#ifdef ENABLE_VOX
|
||||
gVoxResumeCountdown = 2000;
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (FUNCTION_IsRx())
|
||||
{
|
||||
RADIO_SetModulation(gRxVfo->Modulation); // 1of11
|
||||
}
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
if (gFmRadioMode)
|
||||
BK1080_Mute(false);
|
||||
#endif
|
||||
|
||||
if (!gEnableSpeaker)
|
||||
AUDIO_AudioPathOff();
|
||||
|
||||
#ifdef ENABLE_VOX
|
||||
gVoxResumeCountdown = 80;
|
||||
#endif
|
||||
|
||||
gVoiceWriteIndex = 0;
|
||||
gVoiceReadIndex = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
158
audio.h
Normal file
158
audio.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_H
|
||||
#define AUDIO_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
enum BEEP_Type_t
|
||||
{
|
||||
BEEP_NONE = 0,
|
||||
BEEP_1KHZ_60MS_OPTIONAL,
|
||||
BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL,
|
||||
BEEP_440HZ_500MS,
|
||||
BEEP_880HZ_200MS,
|
||||
BEEP_880HZ_500MS,
|
||||
BEEP_500HZ_60MS_DOUBLE_BEEP,
|
||||
BEEP_440HZ_40MS_OPTIONAL,
|
||||
BEEP_880HZ_40MS_OPTIONAL,
|
||||
BEEP_880HZ_60MS_TRIPLE_BEEP
|
||||
};
|
||||
|
||||
typedef enum BEEP_Type_t BEEP_Type_t;
|
||||
|
||||
extern BEEP_Type_t gBeepToPlay;
|
||||
|
||||
void AUDIO_PlayBeep(BEEP_Type_t Beep);
|
||||
|
||||
enum
|
||||
{
|
||||
VOICE_ID_CHI_BASE = 0x10U,
|
||||
VOICE_ID_ENG_BASE = 0x60U,
|
||||
};
|
||||
|
||||
enum VOICE_ID_t
|
||||
{
|
||||
VOICE_ID_0 = 0x00U,
|
||||
VOICE_ID_1 = 0x01U,
|
||||
VOICE_ID_2 = 0x02U,
|
||||
VOICE_ID_3 = 0x03U,
|
||||
VOICE_ID_4 = 0x04U,
|
||||
VOICE_ID_5 = 0x05U,
|
||||
VOICE_ID_6 = 0x06U,
|
||||
VOICE_ID_7 = 0x07U,
|
||||
VOICE_ID_8 = 0x08U,
|
||||
VOICE_ID_9 = 0x09U,
|
||||
VOICE_ID_10 = 0x0AU,
|
||||
VOICE_ID_100 = 0x0BU,
|
||||
VOICE_ID_WELCOME = 0x0CU,
|
||||
VOICE_ID_LOCK = 0x0DU,
|
||||
VOICE_ID_UNLOCK = 0x0EU,
|
||||
VOICE_ID_SCANNING_BEGIN = 0x0FU,
|
||||
VOICE_ID_SCANNING_STOP = 0x10U,
|
||||
VOICE_ID_SCRAMBLER_ON = 0x11U,
|
||||
VOICE_ID_SCRAMBLER_OFF = 0x12U,
|
||||
VOICE_ID_FUNCTION = 0x13U,
|
||||
VOICE_ID_CTCSS = 0x14U,
|
||||
VOICE_ID_DCS = 0x15U,
|
||||
VOICE_ID_POWER = 0x16U,
|
||||
VOICE_ID_SAVE_MODE = 0x17U,
|
||||
VOICE_ID_MEMORY_CHANNEL = 0x18U,
|
||||
VOICE_ID_DELETE_CHANNEL = 0x19U,
|
||||
VOICE_ID_FREQUENCY_STEP = 0x1AU,
|
||||
VOICE_ID_SQUELCH = 0x1BU,
|
||||
VOICE_ID_TRANSMIT_OVER_TIME = 0x1CU,
|
||||
VOICE_ID_BACKLIGHT_SELECTION = 0x1DU,
|
||||
VOICE_ID_VOX = 0x1EU,
|
||||
VOICE_ID_TX_OFFSET_FREQUENCY_DIRECTION = 0x1FU,
|
||||
VOICE_ID_TX_OFFSET_FREQUENCY = 0x20U,
|
||||
VOICE_ID_TRANSMITING_MEMORY = 0x21U,
|
||||
VOICE_ID_RECEIVING_MEMORY = 0x22U,
|
||||
VOICE_ID_EMERGENCY_CALL = 0x23U,
|
||||
VOICE_ID_LOW_VOLTAGE = 0x24U,
|
||||
VOICE_ID_CHANNEL_MODE = 0x25U,
|
||||
VOICE_ID_FREQUENCY_MODE = 0x26U,
|
||||
VOICE_ID_VOICE_PROMPT = 0x27U,
|
||||
VOICE_ID_BAND_SELECTION = 0x28U,
|
||||
VOICE_ID_DUAL_STANDBY = 0x29U,
|
||||
VOICE_ID_CHANNEL_BANDWIDTH = 0x2AU,
|
||||
VOICE_ID_OPTIONAL_SIGNAL = 0x2BU,
|
||||
VOICE_ID_MUTE_MODE = 0x2CU,
|
||||
VOICE_ID_BUSY_LOCKOUT = 0x2DU,
|
||||
VOICE_ID_BEEP_PROMPT = 0x2EU,
|
||||
VOICE_ID_ANI_CODE = 0x2FU,
|
||||
VOICE_ID_INITIALISATION = 0x30U,
|
||||
VOICE_ID_CONFIRM = 0x31U,
|
||||
VOICE_ID_CANCEL = 0x32U,
|
||||
VOICE_ID_ON = 0x33U,
|
||||
VOICE_ID_OFF = 0x34U,
|
||||
VOICE_ID_2_TONE = 0x35U,
|
||||
VOICE_ID_5_TONE = 0x36U,
|
||||
VOICE_ID_DIGITAL_SIGNAL = 0x37U,
|
||||
VOICE_ID_REPEATER = 0x38U,
|
||||
VOICE_ID_MENU = 0x39U,
|
||||
VOICE_ID_11 = 0x3AU,
|
||||
VOICE_ID_12 = 0x3BU,
|
||||
VOICE_ID_13 = 0x3CU,
|
||||
VOICE_ID_14 = 0x3DU,
|
||||
VOICE_ID_15 = 0x3EU,
|
||||
VOICE_ID_16 = 0x3FU,
|
||||
VOICE_ID_17 = 0x40U,
|
||||
VOICE_ID_18 = 0x41U,
|
||||
VOICE_ID_19 = 0x42U,
|
||||
VOICE_ID_20 = 0x43U,
|
||||
VOICE_ID_30 = 0x44U,
|
||||
VOICE_ID_40 = 0x45U,
|
||||
VOICE_ID_50 = 0x46U,
|
||||
VOICE_ID_60 = 0x47U,
|
||||
VOICE_ID_70 = 0x48U,
|
||||
VOICE_ID_80 = 0x49U,
|
||||
VOICE_ID_90 = 0x4AU,
|
||||
VOICE_ID_END = 0x4BU,
|
||||
|
||||
VOICE_ID_INVALID = 0xFFU,
|
||||
};
|
||||
|
||||
typedef enum VOICE_ID_t VOICE_ID_t;
|
||||
|
||||
static inline void AUDIO_AudioPathOn(void) {
|
||||
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
|
||||
}
|
||||
|
||||
static inline void AUDIO_AudioPathOff(void) {
|
||||
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
extern VOICE_ID_t gVoiceID[8];
|
||||
extern uint8_t gVoiceReadIndex;
|
||||
extern uint8_t gVoiceWriteIndex;
|
||||
extern volatile uint16_t gCountdownToPlayNextVoice_10ms;
|
||||
extern volatile bool gFlagPlayQueuedVoice;
|
||||
extern VOICE_ID_t gAnotherVoiceID;
|
||||
|
||||
void AUDIO_PlaySingleVoice(bool bFlag);
|
||||
void AUDIO_SetVoiceID(uint8_t Index, VOICE_ID_t VoiceID);
|
||||
uint8_t AUDIO_SetDigitVoice(uint8_t Index, uint16_t Value);
|
||||
void AUDIO_PlayQueuedVoice(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
327
bitmaps.c
Normal file
327
bitmaps.c
Normal file
@@ -0,0 +1,327 @@
|
||||
|
||||
#include "bitmaps.h"
|
||||
|
||||
// all these images are on their right sides
|
||||
// turn your monitor 90-deg anti-clockwise to see the images
|
||||
|
||||
const uint8_t BITMAP_POWERSAVE[8] =
|
||||
{
|
||||
// "PS"
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b00010001,
|
||||
0b00001110,
|
||||
0b00000000,
|
||||
0b01000110,
|
||||
0b01001001,
|
||||
0b00110001
|
||||
|
||||
};
|
||||
|
||||
const uint8_t BITMAP_TX[8] =
|
||||
{ // "TX"
|
||||
0b00000000,
|
||||
0b00000001,
|
||||
0b00000001,
|
||||
0b01111111,
|
||||
0b00000001,
|
||||
0b00000001,
|
||||
0b00000000,
|
||||
0b00000000
|
||||
};
|
||||
|
||||
const uint8_t BITMAP_RX[8] =
|
||||
{ // "RX"
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b00001001,
|
||||
0b00011001,
|
||||
0b01100110,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000
|
||||
};
|
||||
|
||||
const uint8_t BITMAP_FM[10] =
|
||||
{ // "FM"
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b00001001,
|
||||
0b00000001,
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b00000010,
|
||||
0b00001100,
|
||||
0b00000010,
|
||||
0b01111111
|
||||
};
|
||||
|
||||
const uint8_t BITMAP_BatteryLevel[2] =
|
||||
{
|
||||
0b01011101,
|
||||
0b01011101
|
||||
};
|
||||
|
||||
#ifndef ENABLE_REVERSE_BAT_SYMBOL
|
||||
// Quansheng way (+ pole to the left)
|
||||
const uint8_t BITMAP_BatteryLevel1[17] =
|
||||
{
|
||||
0b00000000,
|
||||
0b00111110,
|
||||
0b00100010,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01111111
|
||||
};
|
||||
#else
|
||||
// reversed (+ pole to the right)
|
||||
const uint8_t BITMAP_BatteryLevel1[17] =
|
||||
{
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b00100010,
|
||||
0b00111110
|
||||
};
|
||||
#endif
|
||||
|
||||
const uint8_t BITMAP_USB_C[9] =
|
||||
{ // USB symbol
|
||||
0b00000000,
|
||||
0b00011100,
|
||||
0b00100111,
|
||||
0b01000100,
|
||||
0b01000100,
|
||||
0b01000100,
|
||||
0b01000100,
|
||||
0b00100111,
|
||||
0b00011100
|
||||
};
|
||||
|
||||
const uint8_t BITMAP_KeyLock[6] =
|
||||
{ // teeny padlock symbol
|
||||
0b00000000,
|
||||
0b01111100,
|
||||
0b01000110,
|
||||
0b01000101,
|
||||
0b01000110,
|
||||
0b01111100
|
||||
};
|
||||
|
||||
const uint8_t BITMAP_F_Key[6] =
|
||||
{ // F-Key symbol
|
||||
0b00000000,
|
||||
0b01011111,
|
||||
0b01000101,
|
||||
0b01000101,
|
||||
0b01000101,
|
||||
0b01000001
|
||||
};
|
||||
|
||||
#ifdef ENABLE_VOX
|
||||
const uint8_t BITMAP_VOX[18] =
|
||||
{ // "VOX"
|
||||
0b00000000,
|
||||
0b00011111,
|
||||
0b00100000,
|
||||
0b01000000,
|
||||
0b00100000,
|
||||
0b00011111,
|
||||
0b00000000,
|
||||
0b00111110,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b00111110,
|
||||
0b00000000,
|
||||
0b01100011,
|
||||
0b00010100,
|
||||
0b00001000,
|
||||
0b00010100,
|
||||
0b01100011
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
// 'XB' (cross-band/cross-VFO)
|
||||
const uint8_t BITMAP_XB[12] =
|
||||
{ // "XB"
|
||||
0b00000000,
|
||||
0b01100011,
|
||||
0b00010100,
|
||||
0b00001000,
|
||||
0b00010100,
|
||||
0b01100011,
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b01001001,
|
||||
0b01001001,
|
||||
0b01001001,
|
||||
0b00110110
|
||||
};
|
||||
|
||||
|
||||
const uint8_t BITMAP_TDR1[16] =
|
||||
{ // "DWR"
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b00111110,
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b00100000,
|
||||
0b00011000,
|
||||
0b00100000,
|
||||
0b01111111,
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b00011001,
|
||||
0b00101001,
|
||||
0b01000110
|
||||
};
|
||||
|
||||
const uint8_t BITMAP_TDR2[10] =
|
||||
{ // "><" .. DW on hold
|
||||
0b00000000,
|
||||
0b00100010,
|
||||
0b00110110,
|
||||
0b00011100,
|
||||
0b00001000,
|
||||
0b00000000,
|
||||
0b00001000,
|
||||
0b00011100,
|
||||
0b00110110,
|
||||
0b00100010,
|
||||
};
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
const uint8_t BITMAP_VoicePrompt[9] =
|
||||
{
|
||||
0b00000000,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00100100,
|
||||
0b00100100,
|
||||
0b01000010,
|
||||
0b01000010,
|
||||
0b11111111,
|
||||
0b00011000
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_NOAA
|
||||
const uint8_t BITMAP_NOAA[11] =
|
||||
{ // "NS"
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b00000100,
|
||||
0b00001000,
|
||||
0b00010000,
|
||||
0b01111111,
|
||||
0b00000000,
|
||||
0b01000110,
|
||||
0b01001001,
|
||||
0b01001001,
|
||||
0b00110001
|
||||
};
|
||||
#endif
|
||||
|
||||
const uint8_t BITMAP_Antenna[5] =
|
||||
{
|
||||
0b00000011,
|
||||
0b00000101,
|
||||
0b01111111,
|
||||
0b00000101,
|
||||
0b00000011
|
||||
};
|
||||
|
||||
const uint8_t BITMAP_VFO_Default[8] =
|
||||
{
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b01111111,
|
||||
0b00111110,
|
||||
0b00111110,
|
||||
0b00011100,
|
||||
0b00011100,
|
||||
0b00001000
|
||||
};
|
||||
|
||||
const uint8_t BITMAP_VFO_NotDefault[8] =
|
||||
{
|
||||
0b00000000,
|
||||
0b01000001,
|
||||
0b01000001,
|
||||
0b00100010,
|
||||
0b00100010,
|
||||
0b00010100,
|
||||
0b00010100,
|
||||
0b00001000
|
||||
};
|
||||
|
||||
const uint8_t BITMAP_ScanList1[6] =
|
||||
{ // 'I' symbol
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b01000010,
|
||||
0b01111110,
|
||||
0b01000010,
|
||||
0b00000000
|
||||
};
|
||||
|
||||
const uint8_t BITMAP_ScanList2[6] =
|
||||
{ // 'II' symbol
|
||||
0b00000000,
|
||||
0b01000010,
|
||||
0b01111110,
|
||||
0b01000010,
|
||||
0b01111110,
|
||||
0b01000010
|
||||
};
|
||||
|
||||
const uint8_t BITMAP_compand[6] =
|
||||
{
|
||||
0b00000000,
|
||||
0b00111100,
|
||||
0b01000010,
|
||||
0b01000010,
|
||||
0b01000010,
|
||||
0b00100100
|
||||
};
|
||||
|
||||
#ifndef ENABLE_CUSTOM_MENU_LAYOUT
|
||||
const uint8_t BITMAP_CurrentIndicator[8] = {
|
||||
0xFF,
|
||||
0xFF,
|
||||
0x7E,
|
||||
0x7E,
|
||||
0x3C,
|
||||
0x3C,
|
||||
0x18,
|
||||
0x18
|
||||
};
|
||||
#endif
|
||||
51
bitmaps.h
Normal file
51
bitmaps.h
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
#ifndef BITMAP_H
|
||||
#define BITMAP_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern const uint8_t BITMAP_POWERSAVE[8];
|
||||
extern const uint8_t BITMAP_TX[8];
|
||||
extern const uint8_t BITMAP_RX[8];
|
||||
extern const uint8_t BITMAP_FM[10];
|
||||
extern const uint8_t BITMAP_BatteryLevel[2];
|
||||
extern const uint8_t BITMAP_BatteryLevel1[17];
|
||||
|
||||
extern const uint8_t BITMAP_USB_C[9];
|
||||
|
||||
extern const uint8_t BITMAP_KeyLock[6];
|
||||
|
||||
extern const uint8_t BITMAP_F_Key[6];
|
||||
|
||||
#ifdef ENABLE_VOX
|
||||
extern const uint8_t BITMAP_VOX[18];
|
||||
#endif
|
||||
|
||||
extern const uint8_t BITMAP_XB[12];
|
||||
|
||||
extern const uint8_t BITMAP_TDR1[16];
|
||||
extern const uint8_t BITMAP_TDR2[10];
|
||||
|
||||
#ifdef ENABLE_VOICE
|
||||
extern const uint8_t BITMAP_VoicePrompt[9];
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_NOAA
|
||||
extern const uint8_t BITMAP_NOAA[11];
|
||||
#endif
|
||||
|
||||
extern const uint8_t BITMAP_Antenna[5];
|
||||
|
||||
extern const uint8_t BITMAP_VFO_Default[8];
|
||||
extern const uint8_t BITMAP_VFO_NotDefault[8];
|
||||
|
||||
extern const uint8_t BITMAP_ScanList1[6];
|
||||
extern const uint8_t BITMAP_ScanList2[6];
|
||||
|
||||
extern const uint8_t BITMAP_compand[6];
|
||||
|
||||
#ifndef ENABLE_CUSTOM_MENU_LAYOUT
|
||||
extern const uint8_t BITMAP_CurrentIndicator[8];
|
||||
#endif
|
||||
|
||||
#endif
|
||||
505
board.c
Normal file
505
board.c
Normal file
@@ -0,0 +1,505 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ENABLE_FMRADIO
|
||||
#include "app/fm.h"
|
||||
#endif
|
||||
#include "board.h"
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "bsp/dp32g030/portcon.h"
|
||||
#include "bsp/dp32g030/saradc.h"
|
||||
#include "bsp/dp32g030/syscon.h"
|
||||
#include "driver/adc.h"
|
||||
#include "driver/backlight.h"
|
||||
#ifdef ENABLE_FMRADIO
|
||||
#include "driver/bk1080.h"
|
||||
#endif
|
||||
|
||||
#include "driver/crc.h"
|
||||
#include "driver/eeprom.h"
|
||||
#include "driver/flash.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/system.h"
|
||||
#include "driver/st7565.h"
|
||||
#include "frequencies.h"
|
||||
#include "helper/battery.h"
|
||||
#include "misc.h"
|
||||
#include "settings.h"
|
||||
#if defined(ENABLE_OVERLAY)
|
||||
#include "sram-overlay.h"
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_OVERLAY)
|
||||
void BOARD_FLASH_Init(void)
|
||||
{
|
||||
FLASH_Init(FLASH_READ_MODE_1_CYCLE);
|
||||
FLASH_ConfigureTrimValues();
|
||||
SYSTEM_ConfigureClocks();
|
||||
|
||||
overlay_FLASH_MainClock = 48000000;
|
||||
overlay_FLASH_ClockMultiplier = 48;
|
||||
|
||||
FLASH_Init(FLASH_READ_MODE_2_CYCLE);
|
||||
}
|
||||
#endif
|
||||
|
||||
void BOARD_GPIO_Init(void)
|
||||
{
|
||||
GPIOA->DIR |= 0
|
||||
// A7 = UART1 TX default as OUTPUT from bootloader!
|
||||
// A8 = UART1 RX default as INPUT from bootloader!
|
||||
// Key pad + I2C
|
||||
| GPIO_DIR_10_BITS_OUTPUT
|
||||
// Key pad + I2C
|
||||
| GPIO_DIR_11_BITS_OUTPUT
|
||||
// Key pad + Voice chip
|
||||
| GPIO_DIR_12_BITS_OUTPUT
|
||||
// Key pad + Voice chip
|
||||
| GPIO_DIR_13_BITS_OUTPUT
|
||||
;
|
||||
GPIOA->DIR &= ~(0
|
||||
// Key pad
|
||||
| GPIO_DIR_3_MASK // INPUT
|
||||
// Key pad
|
||||
| GPIO_DIR_4_MASK // INPUT
|
||||
// Key pad
|
||||
| GPIO_DIR_5_MASK // INPUT
|
||||
// Key pad
|
||||
| GPIO_DIR_6_MASK // INPUT
|
||||
);
|
||||
GPIOB->DIR |= 0
|
||||
// ST7565
|
||||
| GPIO_DIR_9_BITS_OUTPUT
|
||||
// ST7565 + SWD IO
|
||||
| GPIO_DIR_11_BITS_OUTPUT
|
||||
// B14 = SWD_CLK assumed INPUT by default
|
||||
// BK1080
|
||||
| GPIO_DIR_15_BITS_OUTPUT
|
||||
;
|
||||
GPIOC->DIR |= 0
|
||||
// BK4819 SCN
|
||||
| GPIO_DIR_0_BITS_OUTPUT
|
||||
// BK4819 SCL
|
||||
| GPIO_DIR_1_BITS_OUTPUT
|
||||
// BK4819 SDA
|
||||
| GPIO_DIR_2_BITS_OUTPUT
|
||||
// Flash light
|
||||
| GPIO_DIR_3_BITS_OUTPUT
|
||||
// Speaker
|
||||
| GPIO_DIR_4_BITS_OUTPUT
|
||||
;
|
||||
GPIOC->DIR &= ~(0
|
||||
// PTT button
|
||||
| GPIO_DIR_5_MASK // INPUT
|
||||
);
|
||||
|
||||
#if defined(ENABLE_FMRADIO)
|
||||
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_BK1080);
|
||||
#endif
|
||||
}
|
||||
|
||||
void BOARD_PORTCON_Init(void)
|
||||
{
|
||||
// PORT A pin selection
|
||||
|
||||
PORTCON_PORTA_SEL0 &= ~(0
|
||||
// Key pad
|
||||
| PORTCON_PORTA_SEL0_A3_MASK
|
||||
// Key pad
|
||||
| PORTCON_PORTA_SEL0_A4_MASK
|
||||
// Key pad
|
||||
| PORTCON_PORTA_SEL0_A5_MASK
|
||||
// Key pad
|
||||
| PORTCON_PORTA_SEL0_A6_MASK
|
||||
);
|
||||
PORTCON_PORTA_SEL0 |= 0
|
||||
// Key pad
|
||||
| PORTCON_PORTA_SEL0_A3_BITS_GPIOA3
|
||||
// Key pad
|
||||
| PORTCON_PORTA_SEL0_A4_BITS_GPIOA4
|
||||
// Key pad
|
||||
| PORTCON_PORTA_SEL0_A5_BITS_GPIOA5
|
||||
// Key pad
|
||||
| PORTCON_PORTA_SEL0_A6_BITS_GPIOA6
|
||||
// UART1 TX, wasn't cleared in previous step / relying on default value!
|
||||
| PORTCON_PORTA_SEL0_A7_BITS_UART1_TX
|
||||
;
|
||||
|
||||
PORTCON_PORTA_SEL1 &= ~(0
|
||||
// Key pad + I2C
|
||||
| PORTCON_PORTA_SEL1_A10_MASK
|
||||
// Key pad + I2C
|
||||
| PORTCON_PORTA_SEL1_A11_MASK
|
||||
// Key pad + Voice chip
|
||||
| PORTCON_PORTA_SEL1_A12_MASK
|
||||
// Key pad + Voice chip
|
||||
| PORTCON_PORTA_SEL1_A13_MASK
|
||||
);
|
||||
PORTCON_PORTA_SEL1 |= 0
|
||||
// UART1 RX, wasn't cleared in previous step / relying on default value!
|
||||
| PORTCON_PORTA_SEL1_A8_BITS_UART1_RX
|
||||
// Battery voltage, wasn't cleared in previous step / relying on default value!
|
||||
| PORTCON_PORTA_SEL1_A9_BITS_SARADC_CH4
|
||||
// Key pad + I2C
|
||||
| PORTCON_PORTA_SEL1_A10_BITS_GPIOA10
|
||||
// Key pad + I2C
|
||||
| PORTCON_PORTA_SEL1_A11_BITS_GPIOA11
|
||||
// Key pad + Voice chip
|
||||
| PORTCON_PORTA_SEL1_A12_BITS_GPIOA12
|
||||
// Key pad + Voice chip
|
||||
| PORTCON_PORTA_SEL1_A13_BITS_GPIOA13
|
||||
// Battery Current, wasn't cleared in previous step / relying on default value!
|
||||
| PORTCON_PORTA_SEL1_A14_BITS_SARADC_CH9
|
||||
;
|
||||
|
||||
// PORT B pin selection
|
||||
|
||||
PORTCON_PORTB_SEL0 &= ~(0
|
||||
// SPI0 SSN
|
||||
| PORTCON_PORTB_SEL0_B7_MASK
|
||||
);
|
||||
PORTCON_PORTB_SEL0 |= 0
|
||||
// SPI0 SSN
|
||||
| PORTCON_PORTB_SEL0_B7_BITS_SPI0_SSN
|
||||
;
|
||||
|
||||
PORTCON_PORTB_SEL1 &= ~(0
|
||||
// ST7565
|
||||
| PORTCON_PORTB_SEL1_B9_MASK
|
||||
// ST7565 + SWD IO
|
||||
| PORTCON_PORTB_SEL1_B11_MASK
|
||||
// SWD CLK
|
||||
| PORTCON_PORTB_SEL1_B14_MASK
|
||||
// BK1080
|
||||
| PORTCON_PORTB_SEL1_B15_MASK
|
||||
);
|
||||
PORTCON_PORTB_SEL1 |= 0
|
||||
// SPI0 CLK, wasn't cleared in previous step / relying on default value!
|
||||
| PORTCON_PORTB_SEL1_B8_BITS_SPI0_CLK
|
||||
// ST7565
|
||||
| PORTCON_PORTB_SEL1_B9_BITS_GPIOB9
|
||||
// SPI0 MOSI, wasn't cleared in previous step / relying on default value!
|
||||
| PORTCON_PORTB_SEL1_B10_BITS_SPI0_MOSI
|
||||
#if defined(ENABLE_SWD)
|
||||
// SWD IO
|
||||
| PORTCON_PORTB_SEL1_B11_BITS_SWDIO
|
||||
// SWD CLK
|
||||
| PORTCON_PORTB_SEL1_B14_BITS_SWCLK
|
||||
#else
|
||||
// ST7565
|
||||
| PORTCON_PORTB_SEL1_B11_BITS_GPIOB11
|
||||
#endif
|
||||
;
|
||||
|
||||
// PORT C pin selection
|
||||
|
||||
PORTCON_PORTC_SEL0 &= ~(0
|
||||
// BK4819 SCN
|
||||
| PORTCON_PORTC_SEL0_C0_MASK
|
||||
// BK4819 SCL
|
||||
| PORTCON_PORTC_SEL0_C1_MASK
|
||||
// BK4819 SDA
|
||||
| PORTCON_PORTC_SEL0_C2_MASK
|
||||
// Flash light
|
||||
| PORTCON_PORTC_SEL0_C3_MASK
|
||||
// Speaker
|
||||
| PORTCON_PORTC_SEL0_C4_MASK
|
||||
// PTT button
|
||||
| PORTCON_PORTC_SEL0_C5_MASK
|
||||
);
|
||||
|
||||
// PORT A pin configuration
|
||||
|
||||
PORTCON_PORTA_IE |= 0
|
||||
// Keypad
|
||||
| PORTCON_PORTA_IE_A3_BITS_ENABLE
|
||||
// Keypad
|
||||
| PORTCON_PORTA_IE_A4_BITS_ENABLE
|
||||
// Keypad
|
||||
| PORTCON_PORTA_IE_A5_BITS_ENABLE
|
||||
// Keypad
|
||||
| PORTCON_PORTA_IE_A6_BITS_ENABLE
|
||||
// A7 = UART1 TX disabled by default
|
||||
// UART1 RX
|
||||
| PORTCON_PORTA_IE_A8_BITS_ENABLE
|
||||
;
|
||||
PORTCON_PORTA_IE &= ~(0
|
||||
// Keypad + I2C
|
||||
| PORTCON_PORTA_IE_A10_MASK
|
||||
// Keypad + I2C
|
||||
| PORTCON_PORTA_IE_A11_MASK
|
||||
// Keypad + Voice chip
|
||||
| PORTCON_PORTA_IE_A12_MASK
|
||||
// Keypad + Voice chip
|
||||
| PORTCON_PORTA_IE_A13_MASK
|
||||
);
|
||||
|
||||
PORTCON_PORTA_PU |= 0
|
||||
// Keypad
|
||||
| PORTCON_PORTA_PU_A3_BITS_ENABLE
|
||||
// Keypad
|
||||
| PORTCON_PORTA_PU_A4_BITS_ENABLE
|
||||
// Keypad
|
||||
| PORTCON_PORTA_PU_A5_BITS_ENABLE
|
||||
// Keypad
|
||||
| PORTCON_PORTA_PU_A6_BITS_ENABLE
|
||||
;
|
||||
PORTCON_PORTA_PU &= ~(0
|
||||
// Keypad + I2C
|
||||
| PORTCON_PORTA_PU_A10_MASK
|
||||
// Keypad + I2C
|
||||
| PORTCON_PORTA_PU_A11_MASK
|
||||
// Keypad + Voice chip
|
||||
| PORTCON_PORTA_PU_A12_MASK
|
||||
// Keypad + Voice chip
|
||||
| PORTCON_PORTA_PU_A13_MASK
|
||||
);
|
||||
|
||||
PORTCON_PORTA_PD &= ~(0
|
||||
// Keypad
|
||||
| PORTCON_PORTA_PD_A3_MASK
|
||||
// Keypad
|
||||
| PORTCON_PORTA_PD_A4_MASK
|
||||
// Keypad
|
||||
| PORTCON_PORTA_PD_A5_MASK
|
||||
// Keypad
|
||||
| PORTCON_PORTA_PD_A6_MASK
|
||||
// Keypad + I2C
|
||||
| PORTCON_PORTA_PD_A10_MASK
|
||||
// Keypad + I2C
|
||||
| PORTCON_PORTA_PD_A11_MASK
|
||||
// Keypad + Voice chip
|
||||
| PORTCON_PORTA_PD_A12_MASK
|
||||
// Keypad + Voice chip
|
||||
| PORTCON_PORTA_PD_A13_MASK
|
||||
);
|
||||
|
||||
PORTCON_PORTA_OD |= 0
|
||||
// Keypad
|
||||
| PORTCON_PORTA_OD_A3_BITS_ENABLE
|
||||
// Keypad
|
||||
| PORTCON_PORTA_OD_A4_BITS_ENABLE
|
||||
// Keypad
|
||||
| PORTCON_PORTA_OD_A5_BITS_ENABLE
|
||||
// Keypad
|
||||
| PORTCON_PORTA_OD_A6_BITS_ENABLE
|
||||
;
|
||||
PORTCON_PORTA_OD &= ~(0
|
||||
// Keypad + I2C
|
||||
| PORTCON_PORTA_OD_A10_MASK
|
||||
// Keypad + I2C
|
||||
| PORTCON_PORTA_OD_A11_MASK
|
||||
// Keypad + Voice chip
|
||||
| PORTCON_PORTA_OD_A12_MASK
|
||||
// Keypad + Voice chip
|
||||
| PORTCON_PORTA_OD_A13_MASK
|
||||
);
|
||||
|
||||
// PORT B pin configuration
|
||||
|
||||
PORTCON_PORTB_IE |= 0
|
||||
| PORTCON_PORTB_IE_B14_BITS_ENABLE
|
||||
;
|
||||
PORTCON_PORTB_IE &= ~(0
|
||||
// Back light
|
||||
| PORTCON_PORTB_IE_B6_MASK
|
||||
// UART1
|
||||
| PORTCON_PORTB_IE_B7_MASK
|
||||
| PORTCON_PORTB_IE_B8_MASK
|
||||
// ST7565
|
||||
| PORTCON_PORTB_IE_B9_MASK
|
||||
// SPI0 MOSI
|
||||
| PORTCON_PORTB_IE_B10_MASK
|
||||
#if !defined(ENABLE_SWD)
|
||||
// ST7565
|
||||
| PORTCON_PORTB_IE_B11_MASK
|
||||
#endif
|
||||
// BK1080
|
||||
| PORTCON_PORTB_IE_B15_MASK
|
||||
);
|
||||
|
||||
PORTCON_PORTB_PU &= ~(0
|
||||
// Back light
|
||||
| PORTCON_PORTB_PU_B6_MASK
|
||||
// ST7565
|
||||
| PORTCON_PORTB_PU_B9_MASK
|
||||
// ST7565 + SWD IO
|
||||
| PORTCON_PORTB_PU_B11_MASK
|
||||
// SWD CLK
|
||||
| PORTCON_PORTB_PU_B14_MASK
|
||||
// BK1080
|
||||
| PORTCON_PORTB_PU_B15_MASK
|
||||
);
|
||||
|
||||
PORTCON_PORTB_PD &= ~(0
|
||||
// Back light
|
||||
| PORTCON_PORTB_PD_B6_MASK
|
||||
// ST7565
|
||||
| PORTCON_PORTB_PD_B9_MASK
|
||||
// ST7565 + SWD IO
|
||||
| PORTCON_PORTB_PD_B11_MASK
|
||||
// SWD CLK
|
||||
| PORTCON_PORTB_PD_B14_MASK
|
||||
// BK1080
|
||||
| PORTCON_PORTB_PD_B15_MASK
|
||||
);
|
||||
|
||||
PORTCON_PORTB_OD &= ~(0
|
||||
// Back light
|
||||
| PORTCON_PORTB_OD_B6_MASK
|
||||
// ST7565
|
||||
| PORTCON_PORTB_OD_B9_MASK
|
||||
// ST7565 + SWD IO
|
||||
| PORTCON_PORTB_OD_B11_MASK
|
||||
// BK1080
|
||||
| PORTCON_PORTB_OD_B15_MASK
|
||||
);
|
||||
|
||||
PORTCON_PORTB_OD |= 0
|
||||
// SWD CLK
|
||||
| PORTCON_PORTB_OD_B14_BITS_ENABLE
|
||||
;
|
||||
|
||||
// PORT C pin configuration
|
||||
|
||||
PORTCON_PORTC_IE |= 0
|
||||
// PTT button
|
||||
| PORTCON_PORTC_IE_C5_BITS_ENABLE
|
||||
;
|
||||
PORTCON_PORTC_IE &= ~(0
|
||||
// BK4819 SCN
|
||||
| PORTCON_PORTC_IE_C0_MASK
|
||||
// BK4819 SCL
|
||||
| PORTCON_PORTC_IE_C1_MASK
|
||||
// BK4819 SDA
|
||||
| PORTCON_PORTC_IE_C2_MASK
|
||||
// Flash Light
|
||||
| PORTCON_PORTC_IE_C3_MASK
|
||||
// Speaker
|
||||
| PORTCON_PORTC_IE_C4_MASK
|
||||
);
|
||||
|
||||
PORTCON_PORTC_PU |= 0
|
||||
// PTT button
|
||||
| PORTCON_PORTC_PU_C5_BITS_ENABLE
|
||||
;
|
||||
PORTCON_PORTC_PU &= ~(0
|
||||
// BK4819 SCN
|
||||
| PORTCON_PORTC_PU_C0_MASK
|
||||
// BK4819 SCL
|
||||
| PORTCON_PORTC_PU_C1_MASK
|
||||
// BK4819 SDA
|
||||
| PORTCON_PORTC_PU_C2_MASK
|
||||
// Flash Light
|
||||
| PORTCON_PORTC_PU_C3_MASK
|
||||
// Speaker
|
||||
| PORTCON_PORTC_PU_C4_MASK
|
||||
);
|
||||
|
||||
PORTCON_PORTC_PD &= ~(0
|
||||
// BK4819 SCN
|
||||
| PORTCON_PORTC_PD_C0_MASK
|
||||
// BK4819 SCL
|
||||
| PORTCON_PORTC_PD_C1_MASK
|
||||
// BK4819 SDA
|
||||
| PORTCON_PORTC_PD_C2_MASK
|
||||
// Flash Light
|
||||
| PORTCON_PORTC_PD_C3_MASK
|
||||
// Speaker
|
||||
| PORTCON_PORTC_PD_C4_MASK
|
||||
// PTT Button
|
||||
| PORTCON_PORTC_PD_C5_MASK
|
||||
);
|
||||
|
||||
PORTCON_PORTC_OD &= ~(0
|
||||
// BK4819 SCN
|
||||
| PORTCON_PORTC_OD_C0_MASK
|
||||
// BK4819 SCL
|
||||
| PORTCON_PORTC_OD_C1_MASK
|
||||
// BK4819 SDA
|
||||
| PORTCON_PORTC_OD_C2_MASK
|
||||
// Flash Light
|
||||
| PORTCON_PORTC_OD_C3_MASK
|
||||
// Speaker
|
||||
| PORTCON_PORTC_OD_C4_MASK
|
||||
);
|
||||
PORTCON_PORTC_OD |= 0
|
||||
// BK4819 SCN
|
||||
| PORTCON_PORTC_OD_C0_BITS_DISABLE
|
||||
// BK4819 SCL
|
||||
| PORTCON_PORTC_OD_C1_BITS_DISABLE
|
||||
// BK4819 SDA
|
||||
| PORTCON_PORTC_OD_C2_BITS_DISABLE
|
||||
// Flash Light
|
||||
| PORTCON_PORTC_OD_C3_BITS_DISABLE
|
||||
// Speaker
|
||||
| PORTCON_PORTC_OD_C4_BITS_DISABLE
|
||||
// PTT button
|
||||
| PORTCON_PORTC_OD_C5_BITS_ENABLE
|
||||
;
|
||||
}
|
||||
|
||||
void BOARD_ADC_Init(void)
|
||||
{
|
||||
ADC_Config_t Config;
|
||||
|
||||
Config.CLK_SEL = SYSCON_CLK_SEL_W_SARADC_SMPL_VALUE_DIV2;
|
||||
Config.CH_SEL = ADC_CH4 | ADC_CH9;
|
||||
Config.AVG = SARADC_CFG_AVG_VALUE_8_SAMPLE;
|
||||
Config.CONT = SARADC_CFG_CONT_VALUE_SINGLE;
|
||||
Config.MEM_MODE = SARADC_CFG_MEM_MODE_VALUE_CHANNEL;
|
||||
Config.SMPL_CLK = SARADC_CFG_SMPL_CLK_VALUE_INTERNAL;
|
||||
Config.SMPL_WIN = SARADC_CFG_SMPL_WIN_VALUE_15_CYCLE;
|
||||
Config.SMPL_SETUP = SARADC_CFG_SMPL_SETUP_VALUE_1_CYCLE;
|
||||
Config.ADC_TRIG = SARADC_CFG_ADC_TRIG_VALUE_CPU;
|
||||
Config.CALIB_KD_VALID = SARADC_CALIB_KD_VALID_VALUE_YES;
|
||||
Config.CALIB_OFFSET_VALID = SARADC_CALIB_OFFSET_VALID_VALUE_YES;
|
||||
Config.DMA_EN = SARADC_CFG_DMA_EN_VALUE_DISABLE;
|
||||
Config.IE_CHx_EOC = SARADC_IE_CHx_EOC_VALUE_NONE;
|
||||
Config.IE_FIFO_FULL = SARADC_IE_FIFO_FULL_VALUE_DISABLE;
|
||||
Config.IE_FIFO_HFULL = SARADC_IE_FIFO_HFULL_VALUE_DISABLE;
|
||||
|
||||
ADC_Configure(&Config);
|
||||
ADC_Enable();
|
||||
ADC_SoftReset();
|
||||
}
|
||||
|
||||
void BOARD_ADC_GetBatteryInfo(uint16_t *pVoltage, uint16_t *pCurrent)
|
||||
{
|
||||
ADC_Start();
|
||||
while (!ADC_CheckEndOfConversion(ADC_CH9)) {}
|
||||
*pVoltage = ADC_GetValue(ADC_CH4);
|
||||
*pCurrent = ADC_GetValue(ADC_CH9);
|
||||
}
|
||||
|
||||
void BOARD_Init(void)
|
||||
{
|
||||
BOARD_PORTCON_Init();
|
||||
BOARD_GPIO_Init();
|
||||
BACKLIGHT_InitHardware();
|
||||
BOARD_ADC_Init();
|
||||
ST7565_Init();
|
||||
#ifdef ENABLE_FMRADIO
|
||||
BK1080_Init0();
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_UART) || defined(ENABLED_AIRCOPY)
|
||||
CRC_Init();
|
||||
#endif
|
||||
|
||||
}
|
||||
31
board.h
Normal file
31
board.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BOARD_H
|
||||
#define BOARD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
void BOARD_FLASH_Init(void);
|
||||
void BOARD_GPIO_Init(void);
|
||||
void BOARD_PORTCON_Init(void);
|
||||
void BOARD_ADC_Init(void);
|
||||
void BOARD_ADC_GetBatteryInfo(uint16_t *pVoltage, uint16_t *pCurrent);
|
||||
void BOARD_Init(void);
|
||||
|
||||
#endif
|
||||
|
||||
87
bsp/dp32g030/aes.h
Normal file
87
bsp/dp32g030/aes.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HARDWARE_DP32G030_AES_H
|
||||
#define HARDWARE_DP32G030_AES_H
|
||||
|
||||
#if !defined(__ASSEMBLY__)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* -------- AES -------- */
|
||||
#define AES_BASE_ADDR 0x400BD000U
|
||||
#define AES_BASE_SIZE 0x00000800U
|
||||
|
||||
#define AES_CR_ADDR (AES_BASE_ADDR + 0x0000U)
|
||||
#define AES_CR (*(volatile uint32_t *)AES_CR_ADDR)
|
||||
#define AES_CR_EN_SHIFT 0
|
||||
#define AES_CR_EN_WIDTH 1
|
||||
#define AES_CR_EN_MASK (((1U << AES_CR_EN_WIDTH) - 1U) << AES_CR_EN_SHIFT)
|
||||
#define AES_CR_EN_VALUE_DISABLE 0U
|
||||
#define AES_CR_EN_BITS_DISABLE (AES_CR_EN_VALUE_DISABLE << AES_CR_EN_SHIFT)
|
||||
#define AES_CR_EN_VALUE_ENABLE 1U
|
||||
#define AES_CR_EN_BITS_ENABLE (AES_CR_EN_VALUE_ENABLE << AES_CR_EN_SHIFT)
|
||||
|
||||
#define AES_CR_CHMOD_SHIFT 5
|
||||
#define AES_CR_CHMOD_WIDTH 2
|
||||
#define AES_CR_CHMOD_MASK (((1U << AES_CR_CHMOD_WIDTH) - 1U) << AES_CR_CHMOD_SHIFT)
|
||||
#define AES_CR_CHMOD_VALUE_ECB 0U
|
||||
#define AES_CR_CHMOD_BITS_ECB (AES_CR_CHMOD_VALUE_ECB << AES_CR_CHMOD_SHIFT)
|
||||
#define AES_CR_CHMOD_VALUE_CBC 1U
|
||||
#define AES_CR_CHMOD_BITS_CBC (AES_CR_CHMOD_VALUE_CBC << AES_CR_CHMOD_SHIFT)
|
||||
#define AES_CR_CHMOD_VALUE_CTR 2U
|
||||
#define AES_CR_CHMOD_BITS_CTR (AES_CR_CHMOD_VALUE_CTR << AES_CR_CHMOD_SHIFT)
|
||||
|
||||
#define AES_CR_CCFC_SHIFT 7
|
||||
#define AES_CR_CCFC_WIDTH 1
|
||||
#define AES_CR_CCFC_MASK (((1U << AES_CR_CCFC_WIDTH) - 1U) << AES_CR_CCFC_SHIFT)
|
||||
#define AES_CR_CCFC_VALUE_SET 1U
|
||||
#define AES_CR_CCFC_BITS_SET (AES_CR_CCFC_VALUE_SET << AES_CR_CCFC_SHIFT)
|
||||
|
||||
#define AES_SR_ADDR (AES_BASE_ADDR + 0x0004U)
|
||||
#define AES_SR (*(volatile uint32_t *)AES_SR_ADDR)
|
||||
#define AES_SR_CCF_SHIFT 0
|
||||
#define AES_SR_CCF_WIDTH 1
|
||||
#define AES_SR_CCF_MASK (((1U << AES_SR_CCF_WIDTH) - 1U) << AES_SR_CCF_SHIFT)
|
||||
#define AES_SR_CCF_VALUE_NOT_COMPLETE 0U
|
||||
#define AES_SR_CCF_BITS_NOT_COMPLETE (AES_SR_CCF_VALUE_NOT_COMPLETE << AES_SR_CCF_SHIFT)
|
||||
#define AES_SR_CCF_VALUE_COMPLETE 1U
|
||||
#define AES_SR_CCF_BITS_COMPLETE (AES_SR_CCF_VALUE_COMPLETE << AES_SR_CCF_SHIFT)
|
||||
|
||||
#define AES_DINR_ADDR (AES_BASE_ADDR + 0x0008U)
|
||||
#define AES_DINR (*(volatile uint32_t *)AES_DINR_ADDR)
|
||||
#define AES_DOUTR_ADDR (AES_BASE_ADDR + 0x000CU)
|
||||
#define AES_DOUTR (*(volatile uint32_t *)AES_DOUTR_ADDR)
|
||||
#define AES_KEYR0_ADDR (AES_BASE_ADDR + 0x0010U)
|
||||
#define AES_KEYR0 (*(volatile uint32_t *)AES_KEYR0_ADDR)
|
||||
#define AES_KEYR1_ADDR (AES_BASE_ADDR + 0x0014U)
|
||||
#define AES_KEYR1 (*(volatile uint32_t *)AES_KEYR1_ADDR)
|
||||
#define AES_KEYR2_ADDR (AES_BASE_ADDR + 0x0018U)
|
||||
#define AES_KEYR2 (*(volatile uint32_t *)AES_KEYR2_ADDR)
|
||||
#define AES_KEYR3_ADDR (AES_BASE_ADDR + 0x001CU)
|
||||
#define AES_KEYR3 (*(volatile uint32_t *)AES_KEYR3_ADDR)
|
||||
#define AES_IVR0_ADDR (AES_BASE_ADDR + 0x0020U)
|
||||
#define AES_IVR0 (*(volatile uint32_t *)AES_IVR0_ADDR)
|
||||
#define AES_IVR1_ADDR (AES_BASE_ADDR + 0x0024U)
|
||||
#define AES_IVR1 (*(volatile uint32_t *)AES_IVR1_ADDR)
|
||||
#define AES_IVR2_ADDR (AES_BASE_ADDR + 0x0028U)
|
||||
#define AES_IVR2 (*(volatile uint32_t *)AES_IVR2_ADDR)
|
||||
#define AES_IVR3_ADDR (AES_BASE_ADDR + 0x002CU)
|
||||
#define AES_IVR3 (*(volatile uint32_t *)AES_IVR3_ADDR)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
109
bsp/dp32g030/crc.h
Normal file
109
bsp/dp32g030/crc.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HARDWARE_DP32G030_CRC_H
|
||||
#define HARDWARE_DP32G030_CRC_H
|
||||
|
||||
#if !defined(__ASSEMBLY__)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* -------- CRC -------- */
|
||||
#define CRC_BASE_ADDR 0x40003000U
|
||||
#define CRC_BASE_SIZE 0x00000800U
|
||||
|
||||
#define CRC_CR_ADDR (CRC_BASE_ADDR + 0x0000U)
|
||||
#define CRC_CR (*(volatile uint32_t *)CRC_CR_ADDR)
|
||||
#define CRC_CR_CRC_EN_SHIFT 0
|
||||
#define CRC_CR_CRC_EN_WIDTH 1
|
||||
#define CRC_CR_CRC_EN_MASK (((1U << CRC_CR_CRC_EN_WIDTH) - 1U) << CRC_CR_CRC_EN_SHIFT)
|
||||
#define CRC_CR_CRC_EN_VALUE_DISABLE 0U
|
||||
#define CRC_CR_CRC_EN_BITS_DISABLE (CRC_CR_CRC_EN_VALUE_DISABLE << CRC_CR_CRC_EN_SHIFT)
|
||||
#define CRC_CR_CRC_EN_VALUE_ENABLE 1U
|
||||
#define CRC_CR_CRC_EN_BITS_ENABLE (CRC_CR_CRC_EN_VALUE_ENABLE << CRC_CR_CRC_EN_SHIFT)
|
||||
|
||||
#define CRC_CR_INPUT_REV_SHIFT 1
|
||||
#define CRC_CR_INPUT_REV_WIDTH 1
|
||||
#define CRC_CR_INPUT_REV_MASK (((1U << CRC_CR_INPUT_REV_WIDTH) - 1U) << CRC_CR_INPUT_REV_SHIFT)
|
||||
#define CRC_CR_INPUT_REV_VALUE_NORMAL 0U
|
||||
#define CRC_CR_INPUT_REV_BITS_NORMAL (CRC_CR_INPUT_REV_VALUE_NORMAL << CRC_CR_INPUT_REV_SHIFT)
|
||||
#define CRC_CR_INPUT_REV_VALUE_REVERSED 1U
|
||||
#define CRC_CR_INPUT_REV_BITS_REVERSED (CRC_CR_INPUT_REV_VALUE_REVERSED << CRC_CR_INPUT_REV_SHIFT)
|
||||
|
||||
#define CRC_CR_INPUT_INV_SHIFT 2
|
||||
#define CRC_CR_INPUT_INV_WIDTH 2
|
||||
#define CRC_CR_INPUT_INV_MASK (((1U << CRC_CR_INPUT_INV_WIDTH) - 1U) << CRC_CR_INPUT_INV_SHIFT)
|
||||
#define CRC_CR_INPUT_INV_VALUE_NORMAL 0U
|
||||
#define CRC_CR_INPUT_INV_BITS_NORMAL (CRC_CR_INPUT_INV_VALUE_NORMAL << CRC_CR_INPUT_INV_SHIFT)
|
||||
#define CRC_CR_INPUT_INV_VALUE_BIT_INVERTED 1U
|
||||
#define CRC_CR_INPUT_INV_BITS_BIT_INVERTED (CRC_CR_INPUT_INV_VALUE_BIT_INVERTED << CRC_CR_INPUT_INV_SHIFT)
|
||||
#define CRC_CR_INPUT_INV_VALUE_BYTE_INVERTED 2U
|
||||
#define CRC_CR_INPUT_INV_BITS_BYTE_INVERTED (CRC_CR_INPUT_INV_VALUE_BYTE_INVERTED << CRC_CR_INPUT_INV_SHIFT)
|
||||
#define CRC_CR_INPUT_INV_VALUE_BIT_BYTE_INVERTED 3U
|
||||
#define CRC_CR_INPUT_INV_BITS_BIT_BYTE_INVERTED (CRC_CR_INPUT_INV_VALUE_BIT_BYTE_INVERTED << CRC_CR_INPUT_INV_SHIFT)
|
||||
|
||||
#define CRC_CR_OUTPUT_REV_SHIFT 4
|
||||
#define CRC_CR_OUTPUT_REV_WIDTH 1
|
||||
#define CRC_CR_OUTPUT_REV_MASK (((1U << CRC_CR_OUTPUT_REV_WIDTH) - 1U) << CRC_CR_OUTPUT_REV_SHIFT)
|
||||
#define CRC_CR_OUTPUT_REV_VALUE_NORMAL 0U
|
||||
#define CRC_CR_OUTPUT_REV_BITS_NORMAL (CRC_CR_OUTPUT_REV_VALUE_NORMAL << CRC_CR_OUTPUT_REV_SHIFT)
|
||||
#define CRC_CR_OUTPUT_REV_VALUE_REVERSED 1U
|
||||
#define CRC_CR_OUTPUT_REV_BITS_REVERSED (CRC_CR_OUTPUT_REV_VALUE_REVERSED << CRC_CR_OUTPUT_REV_SHIFT)
|
||||
|
||||
#define CRC_CR_OUTPUT_INV_SHIFT 5
|
||||
#define CRC_CR_OUTPUT_INV_WIDTH 2
|
||||
#define CRC_CR_OUTPUT_INV_MASK (((1U << CRC_CR_OUTPUT_INV_WIDTH) - 1U) << CRC_CR_OUTPUT_INV_SHIFT)
|
||||
#define CRC_CR_OUTPUT_INV_VALUE_NORMAL 0U
|
||||
#define CRC_CR_OUTPUT_INV_BITS_NORMAL (CRC_CR_OUTPUT_INV_VALUE_NORMAL << CRC_CR_OUTPUT_INV_SHIFT)
|
||||
#define CRC_CR_OUTPUT_INV_VALUE_BIT_INVERTED 1U
|
||||
#define CRC_CR_OUTPUT_INV_BITS_BIT_INVERTED (CRC_CR_OUTPUT_INV_VALUE_BIT_INVERTED << CRC_CR_OUTPUT_INV_SHIFT)
|
||||
#define CRC_CR_OUTPUT_INV_VALUE_BYTE_INVERTED 2U
|
||||
#define CRC_CR_OUTPUT_INV_BITS_BYTE_INVERTED (CRC_CR_OUTPUT_INV_VALUE_BYTE_INVERTED << CRC_CR_OUTPUT_INV_SHIFT)
|
||||
#define CRC_CR_OUTPUT_INV_VALUE_BIT_BYTE_INVERTED 3U
|
||||
#define CRC_CR_OUTPUT_INV_BITS_BIT_BYTE_INVERTED (CRC_CR_OUTPUT_INV_VALUE_BIT_BYTE_INVERTED << CRC_CR_OUTPUT_INV_SHIFT)
|
||||
|
||||
#define CRC_CR_DATA_WIDTH_SHIFT 7
|
||||
#define CRC_CR_DATA_WIDTH_WIDTH 2
|
||||
#define CRC_CR_DATA_WIDTH_MASK (((1U << CRC_CR_DATA_WIDTH_WIDTH) - 1U) << CRC_CR_DATA_WIDTH_SHIFT)
|
||||
#define CRC_CR_DATA_WIDTH_VALUE_32 0U
|
||||
#define CRC_CR_DATA_WIDTH_BITS_32 (CRC_CR_DATA_WIDTH_VALUE_32 << CRC_CR_DATA_WIDTH_SHIFT)
|
||||
#define CRC_CR_DATA_WIDTH_VALUE_16 1U
|
||||
#define CRC_CR_DATA_WIDTH_BITS_16 (CRC_CR_DATA_WIDTH_VALUE_16 << CRC_CR_DATA_WIDTH_SHIFT)
|
||||
#define CRC_CR_DATA_WIDTH_VALUE_8 2U
|
||||
#define CRC_CR_DATA_WIDTH_BITS_8 (CRC_CR_DATA_WIDTH_VALUE_8 << CRC_CR_DATA_WIDTH_SHIFT)
|
||||
|
||||
#define CRC_CR_CRC_SEL_SHIFT 9
|
||||
#define CRC_CR_CRC_SEL_WIDTH 2
|
||||
#define CRC_CR_CRC_SEL_MASK (((1U << CRC_CR_CRC_SEL_WIDTH) - 1U) << CRC_CR_CRC_SEL_SHIFT)
|
||||
#define CRC_CR_CRC_SEL_VALUE_CRC_16_CCITT 0U
|
||||
#define CRC_CR_CRC_SEL_BITS_CRC_16_CCITT (CRC_CR_CRC_SEL_VALUE_CRC_16_CCITT << CRC_CR_CRC_SEL_SHIFT)
|
||||
#define CRC_CR_CRC_SEL_VALUE_CRC_8_ATM 1U
|
||||
#define CRC_CR_CRC_SEL_BITS_CRC_8_ATM (CRC_CR_CRC_SEL_VALUE_CRC_8_ATM << CRC_CR_CRC_SEL_SHIFT)
|
||||
#define CRC_CR_CRC_SEL_VALUE_CRC_16 2U
|
||||
#define CRC_CR_CRC_SEL_BITS_CRC_16 (CRC_CR_CRC_SEL_VALUE_CRC_16 << CRC_CR_CRC_SEL_SHIFT)
|
||||
#define CRC_CR_CRC_SEL_VALUE_CRC_32_IEEE802_3 3U
|
||||
#define CRC_CR_CRC_SEL_BITS_CRC_32_IEEE802_3 (CRC_CR_CRC_SEL_VALUE_CRC_32_IEEE802_3 << CRC_CR_CRC_SEL_SHIFT)
|
||||
|
||||
#define CRC_IV_ADDR (CRC_BASE_ADDR + 0x0004U)
|
||||
#define CRC_IV (*(volatile uint32_t *)CRC_IV_ADDR)
|
||||
#define CRC_DATAIN_ADDR (CRC_BASE_ADDR + 0x0008U)
|
||||
#define CRC_DATAIN (*(volatile uint32_t *)CRC_DATAIN_ADDR)
|
||||
#define CRC_DATAOUT_ADDR (CRC_BASE_ADDR + 0x000CU)
|
||||
#define CRC_DATAOUT (*(volatile uint32_t *)CRC_DATAOUT_ADDR)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
319
bsp/dp32g030/dma.h
Normal file
319
bsp/dp32g030/dma.h
Normal file
@@ -0,0 +1,319 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HARDWARE_DP32G030_DMA_H
|
||||
#define HARDWARE_DP32G030_DMA_H
|
||||
|
||||
#if !defined(__ASSEMBLY__)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* -------- DMA -------- */
|
||||
#define DMA_BASE_ADDR 0x40001000U
|
||||
#define DMA_BASE_SIZE 0x00000100U
|
||||
|
||||
#define DMA_CTR_ADDR (DMA_BASE_ADDR + 0x0000U)
|
||||
#define DMA_CTR (*(volatile uint32_t *)DMA_CTR_ADDR)
|
||||
#define DMA_CTR_DMAEN_SHIFT 0
|
||||
#define DMA_CTR_DMAEN_WIDTH 1
|
||||
#define DMA_CTR_DMAEN_MASK (((1U << DMA_CTR_DMAEN_WIDTH) - 1U) << DMA_CTR_DMAEN_SHIFT)
|
||||
#define DMA_CTR_DMAEN_VALUE_DISABLE 0U
|
||||
#define DMA_CTR_DMAEN_BITS_DISABLE (DMA_CTR_DMAEN_VALUE_DISABLE << DMA_CTR_DMAEN_SHIFT)
|
||||
#define DMA_CTR_DMAEN_VALUE_ENABLE 1U
|
||||
#define DMA_CTR_DMAEN_BITS_ENABLE (DMA_CTR_DMAEN_VALUE_ENABLE << DMA_CTR_DMAEN_SHIFT)
|
||||
|
||||
#define DMA_INTEN_ADDR (DMA_BASE_ADDR + 0x0004U)
|
||||
#define DMA_INTEN (*(volatile uint32_t *)DMA_INTEN_ADDR)
|
||||
#define DMA_INTEN_CH0_TC_INTEN_SHIFT 0
|
||||
#define DMA_INTEN_CH0_TC_INTEN_WIDTH 1
|
||||
#define DMA_INTEN_CH0_TC_INTEN_MASK (((1U << DMA_INTEN_CH0_TC_INTEN_WIDTH) - 1U) << DMA_INTEN_CH0_TC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH0_TC_INTEN_VALUE_DISABLE 0U
|
||||
#define DMA_INTEN_CH0_TC_INTEN_BITS_DISABLE (DMA_INTEN_CH0_TC_INTEN_VALUE_DISABLE << DMA_INTEN_CH0_TC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH0_TC_INTEN_VALUE_ENABLE 1U
|
||||
#define DMA_INTEN_CH0_TC_INTEN_BITS_ENABLE (DMA_INTEN_CH0_TC_INTEN_VALUE_ENABLE << DMA_INTEN_CH0_TC_INTEN_SHIFT)
|
||||
|
||||
#define DMA_INTEN_CH1_TC_INTEN_SHIFT 1
|
||||
#define DMA_INTEN_CH1_TC_INTEN_WIDTH 1
|
||||
#define DMA_INTEN_CH1_TC_INTEN_MASK (((1U << DMA_INTEN_CH1_TC_INTEN_WIDTH) - 1U) << DMA_INTEN_CH1_TC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH1_TC_INTEN_VALUE_DISABLE 0U
|
||||
#define DMA_INTEN_CH1_TC_INTEN_BITS_DISABLE (DMA_INTEN_CH1_TC_INTEN_VALUE_DISABLE << DMA_INTEN_CH1_TC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH1_TC_INTEN_VALUE_ENABLE 1U
|
||||
#define DMA_INTEN_CH1_TC_INTEN_BITS_ENABLE (DMA_INTEN_CH1_TC_INTEN_VALUE_ENABLE << DMA_INTEN_CH1_TC_INTEN_SHIFT)
|
||||
|
||||
#define DMA_INTEN_CH2_TC_INTEN_SHIFT 2
|
||||
#define DMA_INTEN_CH2_TC_INTEN_WIDTH 1
|
||||
#define DMA_INTEN_CH2_TC_INTEN_MASK (((1U << DMA_INTEN_CH2_TC_INTEN_WIDTH) - 1U) << DMA_INTEN_CH2_TC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH2_TC_INTEN_VALUE_DISABLE 0U
|
||||
#define DMA_INTEN_CH2_TC_INTEN_BITS_DISABLE (DMA_INTEN_CH2_TC_INTEN_VALUE_DISABLE << DMA_INTEN_CH2_TC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH2_TC_INTEN_VALUE_ENABLE 1U
|
||||
#define DMA_INTEN_CH2_TC_INTEN_BITS_ENABLE (DMA_INTEN_CH2_TC_INTEN_VALUE_ENABLE << DMA_INTEN_CH2_TC_INTEN_SHIFT)
|
||||
|
||||
#define DMA_INTEN_CH3_TC_INTEN_SHIFT 3
|
||||
#define DMA_INTEN_CH3_TC_INTEN_WIDTH 1
|
||||
#define DMA_INTEN_CH3_TC_INTEN_MASK (((1U << DMA_INTEN_CH3_TC_INTEN_WIDTH) - 1U) << DMA_INTEN_CH3_TC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH3_TC_INTEN_VALUE_DISABLE 0U
|
||||
#define DMA_INTEN_CH3_TC_INTEN_BITS_DISABLE (DMA_INTEN_CH3_TC_INTEN_VALUE_DISABLE << DMA_INTEN_CH3_TC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH3_TC_INTEN_VALUE_ENABLE 1U
|
||||
#define DMA_INTEN_CH3_TC_INTEN_BITS_ENABLE (DMA_INTEN_CH3_TC_INTEN_VALUE_ENABLE << DMA_INTEN_CH3_TC_INTEN_SHIFT)
|
||||
|
||||
#define DMA_INTEN_CH0_THC_INTEN_SHIFT 8
|
||||
#define DMA_INTEN_CH0_THC_INTEN_WIDTH 1
|
||||
#define DMA_INTEN_CH0_THC_INTEN_MASK (((1U << DMA_INTEN_CH0_THC_INTEN_WIDTH) - 1U) << DMA_INTEN_CH0_THC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH0_THC_INTEN_VALUE_DISABLE 0U
|
||||
#define DMA_INTEN_CH0_THC_INTEN_BITS_DISABLE (DMA_INTEN_CH0_THC_INTEN_VALUE_DISABLE << DMA_INTEN_CH0_THC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH0_THC_INTEN_VALUE_ENABLE 1U
|
||||
#define DMA_INTEN_CH0_THC_INTEN_BITS_ENABLE (DMA_INTEN_CH0_THC_INTEN_VALUE_ENABLE << DMA_INTEN_CH0_THC_INTEN_SHIFT)
|
||||
|
||||
#define DMA_INTEN_CH1_THC_INTEN_SHIFT 9
|
||||
#define DMA_INTEN_CH1_THC_INTEN_WIDTH 1
|
||||
#define DMA_INTEN_CH1_THC_INTEN_MASK (((1U << DMA_INTEN_CH1_THC_INTEN_WIDTH) - 1U) << DMA_INTEN_CH1_THC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH1_THC_INTEN_VALUE_DISABLE 0U
|
||||
#define DMA_INTEN_CH1_THC_INTEN_BITS_DISABLE (DMA_INTEN_CH1_THC_INTEN_VALUE_DISABLE << DMA_INTEN_CH1_THC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH1_THC_INTEN_VALUE_ENABLE 1U
|
||||
#define DMA_INTEN_CH1_THC_INTEN_BITS_ENABLE (DMA_INTEN_CH1_THC_INTEN_VALUE_ENABLE << DMA_INTEN_CH1_THC_INTEN_SHIFT)
|
||||
|
||||
#define DMA_INTEN_CH2_THC_INTEN_SHIFT 10
|
||||
#define DMA_INTEN_CH2_THC_INTEN_WIDTH 1
|
||||
#define DMA_INTEN_CH2_THC_INTEN_MASK (((1U << DMA_INTEN_CH2_THC_INTEN_WIDTH) - 1U) << DMA_INTEN_CH2_THC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH2_THC_INTEN_VALUE_DISABLE 0U
|
||||
#define DMA_INTEN_CH2_THC_INTEN_BITS_DISABLE (DMA_INTEN_CH2_THC_INTEN_VALUE_DISABLE << DMA_INTEN_CH2_THC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH2_THC_INTEN_VALUE_ENABLE 1U
|
||||
#define DMA_INTEN_CH2_THC_INTEN_BITS_ENABLE (DMA_INTEN_CH2_THC_INTEN_VALUE_ENABLE << DMA_INTEN_CH2_THC_INTEN_SHIFT)
|
||||
|
||||
#define DMA_INTEN_CH3_THC_INTEN_SHIFT 11
|
||||
#define DMA_INTEN_CH3_THC_INTEN_WIDTH 1
|
||||
#define DMA_INTEN_CH3_THC_INTEN_MASK (((1U << DMA_INTEN_CH3_THC_INTEN_WIDTH) - 1U) << DMA_INTEN_CH3_THC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH3_THC_INTEN_VALUE_DISABLE 0U
|
||||
#define DMA_INTEN_CH3_THC_INTEN_BITS_DISABLE (DMA_INTEN_CH3_THC_INTEN_VALUE_DISABLE << DMA_INTEN_CH3_THC_INTEN_SHIFT)
|
||||
#define DMA_INTEN_CH3_THC_INTEN_VALUE_ENABLE 1U
|
||||
#define DMA_INTEN_CH3_THC_INTEN_BITS_ENABLE (DMA_INTEN_CH3_THC_INTEN_VALUE_ENABLE << DMA_INTEN_CH3_THC_INTEN_SHIFT)
|
||||
|
||||
#define DMA_INTST_ADDR (DMA_BASE_ADDR + 0x0008U)
|
||||
#define DMA_INTST (*(volatile uint32_t *)DMA_INTST_ADDR)
|
||||
#define DMA_INTST_CH0_TC_INTST_SHIFT 0
|
||||
#define DMA_INTST_CH0_TC_INTST_WIDTH 1
|
||||
#define DMA_INTST_CH0_TC_INTST_MASK (((1U << DMA_INTST_CH0_TC_INTST_WIDTH) - 1U) << DMA_INTST_CH0_TC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH0_TC_INTST_VALUE_NOT_SET 0U
|
||||
#define DMA_INTST_CH0_TC_INTST_BITS_NOT_SET (DMA_INTST_CH0_TC_INTST_VALUE_NOT_SET << DMA_INTST_CH0_TC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH0_TC_INTST_VALUE_SET 1U
|
||||
#define DMA_INTST_CH0_TC_INTST_BITS_SET (DMA_INTST_CH0_TC_INTST_VALUE_SET << DMA_INTST_CH0_TC_INTST_SHIFT)
|
||||
|
||||
#define DMA_INTST_CH1_TC_INTST_SHIFT 1
|
||||
#define DMA_INTST_CH1_TC_INTST_WIDTH 1
|
||||
#define DMA_INTST_CH1_TC_INTST_MASK (((1U << DMA_INTST_CH1_TC_INTST_WIDTH) - 1U) << DMA_INTST_CH1_TC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH1_TC_INTST_VALUE_NOT_SET 0U
|
||||
#define DMA_INTST_CH1_TC_INTST_BITS_NOT_SET (DMA_INTST_CH1_TC_INTST_VALUE_NOT_SET << DMA_INTST_CH1_TC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH1_TC_INTST_VALUE_SET 1U
|
||||
#define DMA_INTST_CH1_TC_INTST_BITS_SET (DMA_INTST_CH1_TC_INTST_VALUE_SET << DMA_INTST_CH1_TC_INTST_SHIFT)
|
||||
|
||||
#define DMA_INTST_CH2_TC_INTST_SHIFT 2
|
||||
#define DMA_INTST_CH2_TC_INTST_WIDTH 1
|
||||
#define DMA_INTST_CH2_TC_INTST_MASK (((1U << DMA_INTST_CH2_TC_INTST_WIDTH) - 1U) << DMA_INTST_CH2_TC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH2_TC_INTST_VALUE_NOT_SET 0U
|
||||
#define DMA_INTST_CH2_TC_INTST_BITS_NOT_SET (DMA_INTST_CH2_TC_INTST_VALUE_NOT_SET << DMA_INTST_CH2_TC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH2_TC_INTST_VALUE_SET 1U
|
||||
#define DMA_INTST_CH2_TC_INTST_BITS_SET (DMA_INTST_CH2_TC_INTST_VALUE_SET << DMA_INTST_CH2_TC_INTST_SHIFT)
|
||||
|
||||
#define DMA_INTST_CH3_TC_INTST_SHIFT 3
|
||||
#define DMA_INTST_CH3_TC_INTST_WIDTH 1
|
||||
#define DMA_INTST_CH3_TC_INTST_MASK (((1U << DMA_INTST_CH3_TC_INTST_WIDTH) - 1U) << DMA_INTST_CH3_TC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH3_TC_INTST_VALUE_NOT_SET 0U
|
||||
#define DMA_INTST_CH3_TC_INTST_BITS_NOT_SET (DMA_INTST_CH3_TC_INTST_VALUE_NOT_SET << DMA_INTST_CH3_TC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH3_TC_INTST_VALUE_SET 1U
|
||||
#define DMA_INTST_CH3_TC_INTST_BITS_SET (DMA_INTST_CH3_TC_INTST_VALUE_SET << DMA_INTST_CH3_TC_INTST_SHIFT)
|
||||
|
||||
#define DMA_INTST_CH0_THC_INTST_SHIFT 8
|
||||
#define DMA_INTST_CH0_THC_INTST_WIDTH 1
|
||||
#define DMA_INTST_CH0_THC_INTST_MASK (((1U << DMA_INTST_CH0_THC_INTST_WIDTH) - 1U) << DMA_INTST_CH0_THC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH0_THC_INTST_VALUE_NOT_SET 0U
|
||||
#define DMA_INTST_CH0_THC_INTST_BITS_NOT_SET (DMA_INTST_CH0_THC_INTST_VALUE_NOT_SET << DMA_INTST_CH0_THC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH0_THC_INTST_VALUE_SET 1U
|
||||
#define DMA_INTST_CH0_THC_INTST_BITS_SET (DMA_INTST_CH0_THC_INTST_VALUE_SET << DMA_INTST_CH0_THC_INTST_SHIFT)
|
||||
|
||||
#define DMA_INTST_CH1_THC_INTST_SHIFT 9
|
||||
#define DMA_INTST_CH1_THC_INTST_WIDTH 1
|
||||
#define DMA_INTST_CH1_THC_INTST_MASK (((1U << DMA_INTST_CH1_THC_INTST_WIDTH) - 1U) << DMA_INTST_CH1_THC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH1_THC_INTST_VALUE_NOT_SET 0U
|
||||
#define DMA_INTST_CH1_THC_INTST_BITS_NOT_SET (DMA_INTST_CH1_THC_INTST_VALUE_NOT_SET << DMA_INTST_CH1_THC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH1_THC_INTST_VALUE_SET 1U
|
||||
#define DMA_INTST_CH1_THC_INTST_BITS_SET (DMA_INTST_CH1_THC_INTST_VALUE_SET << DMA_INTST_CH1_THC_INTST_SHIFT)
|
||||
|
||||
#define DMA_INTST_CH2_THC_INTST_SHIFT 10
|
||||
#define DMA_INTST_CH2_THC_INTST_WIDTH 1
|
||||
#define DMA_INTST_CH2_THC_INTST_MASK (((1U << DMA_INTST_CH2_THC_INTST_WIDTH) - 1U) << DMA_INTST_CH2_THC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH2_THC_INTST_VALUE_NOT_SET 0U
|
||||
#define DMA_INTST_CH2_THC_INTST_BITS_NOT_SET (DMA_INTST_CH2_THC_INTST_VALUE_NOT_SET << DMA_INTST_CH2_THC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH2_THC_INTST_VALUE_SET 1U
|
||||
#define DMA_INTST_CH2_THC_INTST_BITS_SET (DMA_INTST_CH2_THC_INTST_VALUE_SET << DMA_INTST_CH2_THC_INTST_SHIFT)
|
||||
|
||||
#define DMA_INTST_CH3_THC_INTST_SHIFT 11
|
||||
#define DMA_INTST_CH3_THC_INTST_WIDTH 1
|
||||
#define DMA_INTST_CH3_THC_INTST_MASK (((1U << DMA_INTST_CH3_THC_INTST_WIDTH) - 1U) << DMA_INTST_CH3_THC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH3_THC_INTST_VALUE_NOT_SET 0U
|
||||
#define DMA_INTST_CH3_THC_INTST_BITS_NOT_SET (DMA_INTST_CH3_THC_INTST_VALUE_NOT_SET << DMA_INTST_CH3_THC_INTST_SHIFT)
|
||||
#define DMA_INTST_CH3_THC_INTST_VALUE_SET 1U
|
||||
#define DMA_INTST_CH3_THC_INTST_BITS_SET (DMA_INTST_CH3_THC_INTST_VALUE_SET << DMA_INTST_CH3_THC_INTST_SHIFT)
|
||||
|
||||
/* -------- DMA_CH0 -------- */
|
||||
#define DMA_CH0_BASE_ADDR 0x40001100U
|
||||
#define DMA_CH0_BASE_SIZE 0x00000020U
|
||||
#define DMA_CH0 ((volatile DMA_Channel_t *)DMA_CH0_BASE_ADDR)
|
||||
|
||||
/* -------- DMA_CH1 -------- */
|
||||
#define DMA_CH1_BASE_ADDR 0x40001120U
|
||||
#define DMA_CH1_BASE_SIZE 0x00000020U
|
||||
#define DMA_CH1 ((volatile DMA_Channel_t *)DMA_CH1_BASE_ADDR)
|
||||
|
||||
/* -------- DMA_CH2 -------- */
|
||||
#define DMA_CH2_BASE_ADDR 0x40001140U
|
||||
#define DMA_CH2_BASE_SIZE 0x00000020U
|
||||
#define DMA_CH2 ((volatile DMA_Channel_t *)DMA_CH2_BASE_ADDR)
|
||||
|
||||
/* -------- DMA_CH3 -------- */
|
||||
#define DMA_CH3_BASE_ADDR 0x40001160U
|
||||
#define DMA_CH3_BASE_SIZE 0x00000020U
|
||||
#define DMA_CH3 ((volatile DMA_Channel_t *)DMA_CH3_BASE_ADDR)
|
||||
|
||||
/* -------- DMA_CH -------- */
|
||||
|
||||
typedef struct {
|
||||
uint32_t CTR;
|
||||
uint32_t MOD;
|
||||
uint32_t MSADDR;
|
||||
uint32_t MDADDR;
|
||||
uint32_t ST;
|
||||
} DMA_Channel_t;
|
||||
|
||||
#define DMA_CH_CTR_CH_EN_SHIFT 0
|
||||
#define DMA_CH_CTR_CH_EN_WIDTH 1
|
||||
#define DMA_CH_CTR_CH_EN_MASK (((1U << DMA_CH_CTR_CH_EN_WIDTH) - 1U) << DMA_CH_CTR_CH_EN_SHIFT)
|
||||
#define DMA_CH_CTR_CH_EN_VALUE_DISABLE 0U
|
||||
#define DMA_CH_CTR_CH_EN_BITS_DISABLE (DMA_CH_CTR_CH_EN_VALUE_DISABLE << DMA_CH_CTR_CH_EN_SHIFT)
|
||||
#define DMA_CH_CTR_CH_EN_VALUE_ENABLE 1U
|
||||
#define DMA_CH_CTR_CH_EN_BITS_ENABLE (DMA_CH_CTR_CH_EN_VALUE_ENABLE << DMA_CH_CTR_CH_EN_SHIFT)
|
||||
|
||||
#define DMA_CH_CTR_LENGTH_SHIFT 1
|
||||
#define DMA_CH_CTR_LENGTH_WIDTH 12
|
||||
#define DMA_CH_CTR_LENGTH_MASK (((1U << DMA_CH_CTR_LENGTH_WIDTH) - 1U) << DMA_CH_CTR_LENGTH_SHIFT)
|
||||
#define DMA_CH_CTR_LOOP_SHIFT 13
|
||||
#define DMA_CH_CTR_LOOP_WIDTH 1
|
||||
#define DMA_CH_CTR_LOOP_MASK (((1U << DMA_CH_CTR_LOOP_WIDTH) - 1U) << DMA_CH_CTR_LOOP_SHIFT)
|
||||
#define DMA_CH_CTR_LOOP_VALUE_DISABLE 0U
|
||||
#define DMA_CH_CTR_LOOP_BITS_DISABLE (DMA_CH_CTR_LOOP_VALUE_DISABLE << DMA_CH_CTR_LOOP_SHIFT)
|
||||
#define DMA_CH_CTR_LOOP_VALUE_ENABLE 1U
|
||||
#define DMA_CH_CTR_LOOP_BITS_ENABLE (DMA_CH_CTR_LOOP_VALUE_ENABLE << DMA_CH_CTR_LOOP_SHIFT)
|
||||
|
||||
#define DMA_CH_CTR_PRI_SHIFT 14
|
||||
#define DMA_CH_CTR_PRI_WIDTH 2
|
||||
#define DMA_CH_CTR_PRI_MASK (((1U << DMA_CH_CTR_PRI_WIDTH) - 1U) << DMA_CH_CTR_PRI_SHIFT)
|
||||
#define DMA_CH_CTR_PRI_VALUE_LOW 0U
|
||||
#define DMA_CH_CTR_PRI_BITS_LOW (DMA_CH_CTR_PRI_VALUE_LOW << DMA_CH_CTR_PRI_SHIFT)
|
||||
#define DMA_CH_CTR_PRI_VALUE_MEDIUM 1U
|
||||
#define DMA_CH_CTR_PRI_BITS_MEDIUM (DMA_CH_CTR_PRI_VALUE_MEDIUM << DMA_CH_CTR_PRI_SHIFT)
|
||||
#define DMA_CH_CTR_PRI_VALUE_HIGH 2U
|
||||
#define DMA_CH_CTR_PRI_BITS_HIGH (DMA_CH_CTR_PRI_VALUE_HIGH << DMA_CH_CTR_PRI_SHIFT)
|
||||
#define DMA_CH_CTR_PRI_VALUE_HIGHEST 3U
|
||||
#define DMA_CH_CTR_PRI_BITS_HIGHEST (DMA_CH_CTR_PRI_VALUE_HIGHEST << DMA_CH_CTR_PRI_SHIFT)
|
||||
|
||||
#define DMA_CH_CTR_SWREQ_SHIFT 16
|
||||
#define DMA_CH_CTR_SWREQ_WIDTH 1
|
||||
#define DMA_CH_CTR_SWREQ_MASK (((1U << DMA_CH_CTR_SWREQ_WIDTH) - 1U) << DMA_CH_CTR_SWREQ_SHIFT)
|
||||
#define DMA_CH_CTR_SWREQ_VALUE_SET 1U
|
||||
#define DMA_CH_CTR_SWREQ_BITS_SET (DMA_CH_CTR_SWREQ_VALUE_SET << DMA_CH_CTR_SWREQ_SHIFT)
|
||||
|
||||
#define DMA_CH_MOD_MS_ADDMOD_SHIFT 0
|
||||
#define DMA_CH_MOD_MS_ADDMOD_WIDTH 1
|
||||
#define DMA_CH_MOD_MS_ADDMOD_MASK (((1U << DMA_CH_MOD_MS_ADDMOD_WIDTH) - 1U) << DMA_CH_MOD_MS_ADDMOD_SHIFT)
|
||||
#define DMA_CH_MOD_MS_ADDMOD_VALUE_NONE 0U
|
||||
#define DMA_CH_MOD_MS_ADDMOD_BITS_NONE (DMA_CH_MOD_MS_ADDMOD_VALUE_NONE << DMA_CH_MOD_MS_ADDMOD_SHIFT)
|
||||
#define DMA_CH_MOD_MS_ADDMOD_VALUE_INCREMENT 1U
|
||||
#define DMA_CH_MOD_MS_ADDMOD_BITS_INCREMENT (DMA_CH_MOD_MS_ADDMOD_VALUE_INCREMENT << DMA_CH_MOD_MS_ADDMOD_SHIFT)
|
||||
|
||||
#define DMA_CH_MOD_MS_SIZE_SHIFT 1
|
||||
#define DMA_CH_MOD_MS_SIZE_WIDTH 2
|
||||
#define DMA_CH_MOD_MS_SIZE_MASK (((1U << DMA_CH_MOD_MS_SIZE_WIDTH) - 1U) << DMA_CH_MOD_MS_SIZE_SHIFT)
|
||||
#define DMA_CH_MOD_MS_SIZE_VALUE_8BIT 0U
|
||||
#define DMA_CH_MOD_MS_SIZE_BITS_8BIT (DMA_CH_MOD_MS_SIZE_VALUE_8BIT << DMA_CH_MOD_MS_SIZE_SHIFT)
|
||||
#define DMA_CH_MOD_MS_SIZE_VALUE_16BIT 1U
|
||||
#define DMA_CH_MOD_MS_SIZE_BITS_16BIT (DMA_CH_MOD_MS_SIZE_VALUE_16BIT << DMA_CH_MOD_MS_SIZE_SHIFT)
|
||||
#define DMA_CH_MOD_MS_SIZE_VALUE_32BIT 2U
|
||||
#define DMA_CH_MOD_MS_SIZE_BITS_32BIT (DMA_CH_MOD_MS_SIZE_VALUE_32BIT << DMA_CH_MOD_MS_SIZE_SHIFT)
|
||||
#define DMA_CH_MOD_MS_SIZE_VALUE_KEEP 3U
|
||||
#define DMA_CH_MOD_MS_SIZE_BITS_KEEP (DMA_CH_MOD_MS_SIZE_VALUE_KEEP << DMA_CH_MOD_MS_SIZE_SHIFT)
|
||||
|
||||
#define DMA_CH_MOD_MS_SEL_SHIFT 3
|
||||
#define DMA_CH_MOD_MS_SEL_WIDTH 3
|
||||
#define DMA_CH_MOD_MS_SEL_MASK (((1U << DMA_CH_MOD_MS_SEL_WIDTH) - 1U) << DMA_CH_MOD_MS_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MS_SEL_VALUE_SRAM 0U
|
||||
#define DMA_CH_MOD_MS_SEL_BITS_SRAM (DMA_CH_MOD_MS_SEL_VALUE_SRAM << DMA_CH_MOD_MS_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MS_SEL_VALUE_HSREQ_MS0 1U
|
||||
#define DMA_CH_MOD_MS_SEL_BITS_HSREQ_MS0 (DMA_CH_MOD_MS_SEL_VALUE_HSREQ_MS0 << DMA_CH_MOD_MS_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MS_SEL_VALUE_HSREQ_MS1 2U
|
||||
#define DMA_CH_MOD_MS_SEL_BITS_HSREQ_MS1 (DMA_CH_MOD_MS_SEL_VALUE_HSREQ_MS1 << DMA_CH_MOD_MS_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MS_SEL_VALUE_HSREQ_MS2 3U
|
||||
#define DMA_CH_MOD_MS_SEL_BITS_HSREQ_MS2 (DMA_CH_MOD_MS_SEL_VALUE_HSREQ_MS2 << DMA_CH_MOD_MS_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MS_SEL_VALUE_HSREQ_MS3 4U
|
||||
#define DMA_CH_MOD_MS_SEL_BITS_HSREQ_MS3 (DMA_CH_MOD_MS_SEL_VALUE_HSREQ_MS3 << DMA_CH_MOD_MS_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MS_SEL_VALUE_HSREQ_MS4 5U
|
||||
#define DMA_CH_MOD_MS_SEL_BITS_HSREQ_MS4 (DMA_CH_MOD_MS_SEL_VALUE_HSREQ_MS4 << DMA_CH_MOD_MS_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MS_SEL_VALUE_HSREQ_MS5 6U
|
||||
#define DMA_CH_MOD_MS_SEL_BITS_HSREQ_MS5 (DMA_CH_MOD_MS_SEL_VALUE_HSREQ_MS5 << DMA_CH_MOD_MS_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MS_SEL_VALUE_HSREQ_MS6 7U
|
||||
#define DMA_CH_MOD_MS_SEL_BITS_HSREQ_MS6 (DMA_CH_MOD_MS_SEL_VALUE_HSREQ_MS6 << DMA_CH_MOD_MS_SEL_SHIFT)
|
||||
|
||||
#define DMA_CH_MOD_MD_ADDMOD_SHIFT 8
|
||||
#define DMA_CH_MOD_MD_ADDMOD_WIDTH 1
|
||||
#define DMA_CH_MOD_MD_ADDMOD_MASK (((1U << DMA_CH_MOD_MD_ADDMOD_WIDTH) - 1U) << DMA_CH_MOD_MD_ADDMOD_SHIFT)
|
||||
#define DMA_CH_MOD_MD_ADDMOD_VALUE_NONE 0U
|
||||
#define DMA_CH_MOD_MD_ADDMOD_BITS_NONE (DMA_CH_MOD_MD_ADDMOD_VALUE_NONE << DMA_CH_MOD_MD_ADDMOD_SHIFT)
|
||||
#define DMA_CH_MOD_MD_ADDMOD_VALUE_INCREMENT 1U
|
||||
#define DMA_CH_MOD_MD_ADDMOD_BITS_INCREMENT (DMA_CH_MOD_MD_ADDMOD_VALUE_INCREMENT << DMA_CH_MOD_MD_ADDMOD_SHIFT)
|
||||
|
||||
#define DMA_CH_MOD_MD_SIZE_SHIFT 9
|
||||
#define DMA_CH_MOD_MD_SIZE_WIDTH 2
|
||||
#define DMA_CH_MOD_MD_SIZE_MASK (((1U << DMA_CH_MOD_MD_SIZE_WIDTH) - 1U) << DMA_CH_MOD_MD_SIZE_SHIFT)
|
||||
#define DMA_CH_MOD_MD_SIZE_VALUE_8BIT 0U
|
||||
#define DMA_CH_MOD_MD_SIZE_BITS_8BIT (DMA_CH_MOD_MD_SIZE_VALUE_8BIT << DMA_CH_MOD_MD_SIZE_SHIFT)
|
||||
#define DMA_CH_MOD_MD_SIZE_VALUE_16BIT 1U
|
||||
#define DMA_CH_MOD_MD_SIZE_BITS_16BIT (DMA_CH_MOD_MD_SIZE_VALUE_16BIT << DMA_CH_MOD_MD_SIZE_SHIFT)
|
||||
#define DMA_CH_MOD_MD_SIZE_VALUE_32BIT 2U
|
||||
#define DMA_CH_MOD_MD_SIZE_BITS_32BIT (DMA_CH_MOD_MD_SIZE_VALUE_32BIT << DMA_CH_MOD_MD_SIZE_SHIFT)
|
||||
#define DMA_CH_MOD_MD_SIZE_VALUE_KEEP 3U
|
||||
#define DMA_CH_MOD_MD_SIZE_BITS_KEEP (DMA_CH_MOD_MD_SIZE_VALUE_KEEP << DMA_CH_MOD_MD_SIZE_SHIFT)
|
||||
|
||||
#define DMA_CH_MOD_MD_SEL_SHIFT 11
|
||||
#define DMA_CH_MOD_MD_SEL_WIDTH 3
|
||||
#define DMA_CH_MOD_MD_SEL_MASK (((1U << DMA_CH_MOD_MD_SEL_WIDTH) - 1U) << DMA_CH_MOD_MD_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MD_SEL_VALUE_SRAM 0U
|
||||
#define DMA_CH_MOD_MD_SEL_BITS_SRAM (DMA_CH_MOD_MD_SEL_VALUE_SRAM << DMA_CH_MOD_MD_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MD_SEL_VALUE_HSREQ_MS0 1U
|
||||
#define DMA_CH_MOD_MD_SEL_BITS_HSREQ_MS0 (DMA_CH_MOD_MD_SEL_VALUE_HSREQ_MS0 << DMA_CH_MOD_MD_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MD_SEL_VALUE_HSREQ_MS1 2U
|
||||
#define DMA_CH_MOD_MD_SEL_BITS_HSREQ_MS1 (DMA_CH_MOD_MD_SEL_VALUE_HSREQ_MS1 << DMA_CH_MOD_MD_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MD_SEL_VALUE_HSREQ_MS2 3U
|
||||
#define DMA_CH_MOD_MD_SEL_BITS_HSREQ_MS2 (DMA_CH_MOD_MD_SEL_VALUE_HSREQ_MS2 << DMA_CH_MOD_MD_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MD_SEL_VALUE_HSREQ_MS3 4U
|
||||
#define DMA_CH_MOD_MD_SEL_BITS_HSREQ_MS3 (DMA_CH_MOD_MD_SEL_VALUE_HSREQ_MS3 << DMA_CH_MOD_MD_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MD_SEL_VALUE_HSREQ_MS4 5U
|
||||
#define DMA_CH_MOD_MD_SEL_BITS_HSREQ_MS4 (DMA_CH_MOD_MD_SEL_VALUE_HSREQ_MS4 << DMA_CH_MOD_MD_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MD_SEL_VALUE_HSREQ_MS5 6U
|
||||
#define DMA_CH_MOD_MD_SEL_BITS_HSREQ_MS5 (DMA_CH_MOD_MD_SEL_VALUE_HSREQ_MS5 << DMA_CH_MOD_MD_SEL_SHIFT)
|
||||
#define DMA_CH_MOD_MD_SEL_VALUE_HSREQ_MS6 7U
|
||||
#define DMA_CH_MOD_MD_SEL_BITS_HSREQ_MS6 (DMA_CH_MOD_MD_SEL_VALUE_HSREQ_MS6 << DMA_CH_MOD_MD_SEL_SHIFT)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
165
bsp/dp32g030/flash.h
Normal file
165
bsp/dp32g030/flash.h
Normal file
@@ -0,0 +1,165 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HARDWARE_DP32G030_FLASH_H
|
||||
#define HARDWARE_DP32G030_FLASH_H
|
||||
|
||||
#if !defined(__ASSEMBLY__)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* -------- FLASH -------- */
|
||||
#define FLASH_BASE_ADDR 0x4006F000U
|
||||
#define FLASH_BASE_SIZE 0x00000800U
|
||||
|
||||
#define FLASH_CFG_ADDR (FLASH_BASE_ADDR + 0x0000U)
|
||||
#define FLASH_CFG (*(volatile uint32_t *)FLASH_CFG_ADDR)
|
||||
#define FLASH_CFG_READ_MD_SHIFT 0
|
||||
#define FLASH_CFG_READ_MD_WIDTH 1
|
||||
#define FLASH_CFG_READ_MD_MASK (((1U << FLASH_CFG_READ_MD_WIDTH) - 1U) << FLASH_CFG_READ_MD_SHIFT)
|
||||
#define FLASH_CFG_READ_MD_VALUE_1_CYCLE 0U
|
||||
#define FLASH_CFG_READ_MD_BITS_1_CYCLE (FLASH_CFG_READ_MD_VALUE_1_CYCLE << FLASH_CFG_READ_MD_SHIFT)
|
||||
#define FLASH_CFG_READ_MD_VALUE_2_CYCLE 1U
|
||||
#define FLASH_CFG_READ_MD_BITS_2_CYCLE (FLASH_CFG_READ_MD_VALUE_2_CYCLE << FLASH_CFG_READ_MD_SHIFT)
|
||||
|
||||
#define FLASH_CFG_NVR_SEL_SHIFT 1
|
||||
#define FLASH_CFG_NVR_SEL_WIDTH 1
|
||||
#define FLASH_CFG_NVR_SEL_MASK (((1U << FLASH_CFG_NVR_SEL_WIDTH) - 1U) << FLASH_CFG_NVR_SEL_SHIFT)
|
||||
#define FLASH_CFG_NVR_SEL_VALUE_MAIN 0U
|
||||
#define FLASH_CFG_NVR_SEL_BITS_MAIN (FLASH_CFG_NVR_SEL_VALUE_MAIN << FLASH_CFG_NVR_SEL_SHIFT)
|
||||
#define FLASH_CFG_NVR_SEL_VALUE_NVR 1U
|
||||
#define FLASH_CFG_NVR_SEL_BITS_NVR (FLASH_CFG_NVR_SEL_VALUE_NVR << FLASH_CFG_NVR_SEL_SHIFT)
|
||||
|
||||
#define FLASH_CFG_MODE_SHIFT 2
|
||||
#define FLASH_CFG_MODE_WIDTH 3
|
||||
#define FLASH_CFG_MODE_MASK (((1U << FLASH_CFG_MODE_WIDTH) - 1U) << FLASH_CFG_MODE_SHIFT)
|
||||
#define FLASH_CFG_MODE_VALUE_READ_AHB 0U
|
||||
#define FLASH_CFG_MODE_BITS_READ_AHB (FLASH_CFG_MODE_VALUE_READ_AHB << FLASH_CFG_MODE_SHIFT)
|
||||
#define FLASH_CFG_MODE_VALUE_PROGRAM 1U
|
||||
#define FLASH_CFG_MODE_BITS_PROGRAM (FLASH_CFG_MODE_VALUE_PROGRAM << FLASH_CFG_MODE_SHIFT)
|
||||
#define FLASH_CFG_MODE_VALUE_ERASE 2U
|
||||
#define FLASH_CFG_MODE_BITS_ERASE (FLASH_CFG_MODE_VALUE_ERASE << FLASH_CFG_MODE_SHIFT)
|
||||
#define FLASH_CFG_MODE_VALUE_READ_APB 5U
|
||||
#define FLASH_CFG_MODE_BITS_READ_APB (FLASH_CFG_MODE_VALUE_READ_APB << FLASH_CFG_MODE_SHIFT)
|
||||
|
||||
#define FLASH_CFG_DEEP_PD_SHIFT 31
|
||||
#define FLASH_CFG_DEEP_PD_WIDTH 1
|
||||
#define FLASH_CFG_DEEP_PD_MASK (((1U << FLASH_CFG_DEEP_PD_WIDTH) - 1U) << FLASH_CFG_DEEP_PD_SHIFT)
|
||||
#define FLASH_CFG_DEEP_PD_VALUE_NORMAL 0U
|
||||
#define FLASH_CFG_DEEP_PD_BITS_NORMAL (FLASH_CFG_DEEP_PD_VALUE_NORMAL << FLASH_CFG_DEEP_PD_SHIFT)
|
||||
#define FLASH_CFG_DEEP_PD_VALUE_LOW_POWER 1U
|
||||
#define FLASH_CFG_DEEP_PD_BITS_LOW_POWER (FLASH_CFG_DEEP_PD_VALUE_LOW_POWER << FLASH_CFG_DEEP_PD_SHIFT)
|
||||
|
||||
#define FLASH_ADDR_ADDR (FLASH_BASE_ADDR + 0x0004U)
|
||||
#define FLASH_ADDR (*(volatile uint32_t *)FLASH_ADDR_ADDR)
|
||||
#define FLASH_WDATA_ADDR (FLASH_BASE_ADDR + 0x0008U)
|
||||
#define FLASH_WDATA (*(volatile uint32_t *)FLASH_WDATA_ADDR)
|
||||
#define FLASH_RDATA_ADDR (FLASH_BASE_ADDR + 0x000CU)
|
||||
#define FLASH_RDATA (*(volatile uint32_t *)FLASH_RDATA_ADDR)
|
||||
|
||||
#define FLASH_START_ADDR (FLASH_BASE_ADDR + 0x0010U)
|
||||
#define FLASH_START (*(volatile uint32_t *)FLASH_START_ADDR)
|
||||
#define FLASH_START_START_SHIFT 0
|
||||
#define FLASH_START_START_WIDTH 1
|
||||
#define FLASH_START_START_MASK (((1U << FLASH_START_START_WIDTH) - 1U) << FLASH_START_START_SHIFT)
|
||||
#define FLASH_START_START_VALUE_START 1U
|
||||
#define FLASH_START_START_BITS_START (FLASH_START_START_VALUE_START << FLASH_START_START_SHIFT)
|
||||
|
||||
#define FLASH_ST_ADDR (FLASH_BASE_ADDR + 0x0014U)
|
||||
#define FLASH_ST (*(volatile uint32_t *)FLASH_ST_ADDR)
|
||||
#define FLASH_ST_INIT_BUSY_SHIFT 0
|
||||
#define FLASH_ST_INIT_BUSY_WIDTH 1
|
||||
#define FLASH_ST_INIT_BUSY_MASK (((1U << FLASH_ST_INIT_BUSY_WIDTH) - 1U) << FLASH_ST_INIT_BUSY_SHIFT)
|
||||
#define FLASH_ST_INIT_BUSY_VALUE_COMPLETE 0U
|
||||
#define FLASH_ST_INIT_BUSY_BITS_COMPLETE (FLASH_ST_INIT_BUSY_VALUE_COMPLETE << FLASH_ST_INIT_BUSY_SHIFT)
|
||||
#define FLASH_ST_INIT_BUSY_VALUE_BUSY 1U
|
||||
#define FLASH_ST_INIT_BUSY_BITS_BUSY (FLASH_ST_INIT_BUSY_VALUE_BUSY << FLASH_ST_INIT_BUSY_SHIFT)
|
||||
|
||||
#define FLASH_ST_BUSY_SHIFT 1
|
||||
#define FLASH_ST_BUSY_WIDTH 1
|
||||
#define FLASH_ST_BUSY_MASK (((1U << FLASH_ST_BUSY_WIDTH) - 1U) << FLASH_ST_BUSY_SHIFT)
|
||||
#define FLASH_ST_BUSY_VALUE_READY 0U
|
||||
#define FLASH_ST_BUSY_BITS_READY (FLASH_ST_BUSY_VALUE_READY << FLASH_ST_BUSY_SHIFT)
|
||||
#define FLASH_ST_BUSY_VALUE_BUSY 1U
|
||||
#define FLASH_ST_BUSY_BITS_BUSY (FLASH_ST_BUSY_VALUE_BUSY << FLASH_ST_BUSY_SHIFT)
|
||||
|
||||
#define FLASH_ST_PROG_BUF_EMPTY_SHIFT 2
|
||||
#define FLASH_ST_PROG_BUF_EMPTY_WIDTH 1
|
||||
#define FLASH_ST_PROG_BUF_EMPTY_MASK (((1U << FLASH_ST_PROG_BUF_EMPTY_WIDTH) - 1U) << FLASH_ST_PROG_BUF_EMPTY_SHIFT)
|
||||
#define FLASH_ST_PROG_BUF_EMPTY_VALUE_NOT_EMPTY 0U
|
||||
#define FLASH_ST_PROG_BUF_EMPTY_BITS_NOT_EMPTY (FLASH_ST_PROG_BUF_EMPTY_VALUE_NOT_EMPTY << FLASH_ST_PROG_BUF_EMPTY_SHIFT)
|
||||
#define FLASH_ST_PROG_BUF_EMPTY_VALUE_EMPTY 1U
|
||||
#define FLASH_ST_PROG_BUF_EMPTY_BITS_EMPTY (FLASH_ST_PROG_BUF_EMPTY_VALUE_EMPTY << FLASH_ST_PROG_BUF_EMPTY_SHIFT)
|
||||
|
||||
#define FLASH_LOCK_ADDR (FLASH_BASE_ADDR + 0x0018U)
|
||||
#define FLASH_LOCK (*(volatile uint32_t *)FLASH_LOCK_ADDR)
|
||||
#define FLASH_LOCK_LOCK_SHIFT 0
|
||||
#define FLASH_LOCK_LOCK_WIDTH 8
|
||||
#define FLASH_LOCK_LOCK_MASK (((1U << FLASH_LOCK_LOCK_WIDTH) - 1U) << FLASH_LOCK_LOCK_SHIFT)
|
||||
#define FLASH_LOCK_LOCK_VALUE_LOCK 85U
|
||||
#define FLASH_LOCK_LOCK_BITS_LOCK (FLASH_LOCK_LOCK_VALUE_LOCK << FLASH_LOCK_LOCK_SHIFT)
|
||||
|
||||
#define FLASH_UNLOCK_ADDR (FLASH_BASE_ADDR + 0x001CU)
|
||||
#define FLASH_UNLOCK (*(volatile uint32_t *)FLASH_UNLOCK_ADDR)
|
||||
#define FLASH_UNLOCK_UNLOCK_SHIFT 0
|
||||
#define FLASH_UNLOCK_UNLOCK_WIDTH 8
|
||||
#define FLASH_UNLOCK_UNLOCK_MASK (((1U << FLASH_UNLOCK_UNLOCK_WIDTH) - 1U) << FLASH_UNLOCK_UNLOCK_SHIFT)
|
||||
#define FLASH_UNLOCK_UNLOCK_VALUE_UNLOCK 170U
|
||||
#define FLASH_UNLOCK_UNLOCK_BITS_UNLOCK (FLASH_UNLOCK_UNLOCK_VALUE_UNLOCK << FLASH_UNLOCK_UNLOCK_SHIFT)
|
||||
|
||||
#define FLASH_MASK_ADDR (FLASH_BASE_ADDR + 0x0020U)
|
||||
#define FLASH_MASK (*(volatile uint32_t *)FLASH_MASK_ADDR)
|
||||
#define FLASH_MASK_SEL_SHIFT 0
|
||||
#define FLASH_MASK_SEL_WIDTH 2
|
||||
#define FLASH_MASK_SEL_MASK (((1U << FLASH_MASK_SEL_WIDTH) - 1U) << FLASH_MASK_SEL_SHIFT)
|
||||
#define FLASH_MASK_SEL_VALUE_NONE 0U
|
||||
#define FLASH_MASK_SEL_BITS_NONE (FLASH_MASK_SEL_VALUE_NONE << FLASH_MASK_SEL_SHIFT)
|
||||
#define FLASH_MASK_SEL_VALUE_2KB 1U
|
||||
#define FLASH_MASK_SEL_BITS_2KB (FLASH_MASK_SEL_VALUE_2KB << FLASH_MASK_SEL_SHIFT)
|
||||
#define FLASH_MASK_SEL_VALUE_4KB 2U
|
||||
#define FLASH_MASK_SEL_BITS_4KB (FLASH_MASK_SEL_VALUE_4KB << FLASH_MASK_SEL_SHIFT)
|
||||
#define FLASH_MASK_SEL_VALUE_8KB 3U
|
||||
#define FLASH_MASK_SEL_BITS_8KB (FLASH_MASK_SEL_VALUE_8KB << FLASH_MASK_SEL_SHIFT)
|
||||
|
||||
#define FLASH_MASK_LOCK_SHIFT 2
|
||||
#define FLASH_MASK_LOCK_WIDTH 1
|
||||
#define FLASH_MASK_LOCK_MASK (((1U << FLASH_MASK_LOCK_WIDTH) - 1U) << FLASH_MASK_LOCK_SHIFT)
|
||||
#define FLASH_MASK_LOCK_VALUE_NOT_SET 0U
|
||||
#define FLASH_MASK_LOCK_BITS_NOT_SET (FLASH_MASK_LOCK_VALUE_NOT_SET << FLASH_MASK_LOCK_SHIFT)
|
||||
#define FLASH_MASK_LOCK_VALUE_SET 1U
|
||||
#define FLASH_MASK_LOCK_BITS_SET (FLASH_MASK_LOCK_VALUE_SET << FLASH_MASK_LOCK_SHIFT)
|
||||
|
||||
#define FLASH_ERASETIME_ADDR (FLASH_BASE_ADDR + 0x0024U)
|
||||
#define FLASH_ERASETIME (*(volatile uint32_t *)FLASH_ERASETIME_ADDR)
|
||||
#define FLASH_ERASETIME_TERASE_SHIFT 0
|
||||
#define FLASH_ERASETIME_TERASE_WIDTH 19
|
||||
#define FLASH_ERASETIME_TERASE_MASK (((1U << FLASH_ERASETIME_TERASE_WIDTH) - 1U) << FLASH_ERASETIME_TERASE_SHIFT)
|
||||
#define FLASH_ERASETIME_TRCV_SHIFT 19
|
||||
#define FLASH_ERASETIME_TRCV_WIDTH 12
|
||||
#define FLASH_ERASETIME_TRCV_MASK (((1U << FLASH_ERASETIME_TRCV_WIDTH) - 1U) << FLASH_ERASETIME_TRCV_SHIFT)
|
||||
|
||||
#define FLASH_PROGTIME_ADDR (FLASH_BASE_ADDR + 0x0028U)
|
||||
#define FLASH_PROGTIME (*(volatile uint32_t *)FLASH_PROGTIME_ADDR)
|
||||
#define FLASH_PROGTIME_TPROG_SHIFT 0
|
||||
#define FLASH_PROGTIME_TPROG_WIDTH 11
|
||||
#define FLASH_PROGTIME_TPROG_MASK (((1U << FLASH_PROGTIME_TPROG_WIDTH) - 1U) << FLASH_PROGTIME_TPROG_SHIFT)
|
||||
#define FLASH_PROGTIME_TPGS_SHIFT 11
|
||||
#define FLASH_PROGTIME_TPGS_WIDTH 11
|
||||
#define FLASH_PROGTIME_TPGS_MASK (((1U << FLASH_PROGTIME_TPGS_WIDTH) - 1U) << FLASH_PROGTIME_TPGS_SHIFT)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
176
bsp/dp32g030/gpio.h
Normal file
176
bsp/dp32g030/gpio.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HARDWARE_DP32G030_GPIO_H
|
||||
#define HARDWARE_DP32G030_GPIO_H
|
||||
|
||||
#if !defined(__ASSEMBLY__)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* -------- GPIOA -------- */
|
||||
#define GPIOA_BASE_ADDR 0x40060000U
|
||||
#define GPIOA_BASE_SIZE 0x00000800U
|
||||
#define GPIOA ((volatile GPIO_Bank_t *)GPIOA_BASE_ADDR)
|
||||
|
||||
/* -------- GPIOB -------- */
|
||||
#define GPIOB_BASE_ADDR 0x40060800U
|
||||
#define GPIOB_BASE_SIZE 0x00000800U
|
||||
#define GPIOB ((volatile GPIO_Bank_t *)GPIOB_BASE_ADDR)
|
||||
|
||||
/* -------- GPIOC -------- */
|
||||
#define GPIOC_BASE_ADDR 0x40061000U
|
||||
#define GPIOC_BASE_SIZE 0x00000800U
|
||||
#define GPIOC ((volatile GPIO_Bank_t *)GPIOC_BASE_ADDR)
|
||||
|
||||
/* -------- GPIO -------- */
|
||||
|
||||
typedef struct {
|
||||
uint32_t DATA;
|
||||
uint32_t DIR;
|
||||
} GPIO_Bank_t;
|
||||
|
||||
#define GPIO_DIR_0_SHIFT 0
|
||||
#define GPIO_DIR_0_WIDTH 1
|
||||
#define GPIO_DIR_0_MASK (((1U << GPIO_DIR_0_WIDTH) - 1U) << GPIO_DIR_0_SHIFT)
|
||||
#define GPIO_DIR_0_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_0_BITS_INPUT (GPIO_DIR_0_VALUE_INPUT << GPIO_DIR_0_SHIFT)
|
||||
#define GPIO_DIR_0_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_0_BITS_OUTPUT (GPIO_DIR_0_VALUE_OUTPUT << GPIO_DIR_0_SHIFT)
|
||||
|
||||
#define GPIO_DIR_1_SHIFT 1
|
||||
#define GPIO_DIR_1_WIDTH 1
|
||||
#define GPIO_DIR_1_MASK (((1U << GPIO_DIR_1_WIDTH) - 1U) << GPIO_DIR_1_SHIFT)
|
||||
#define GPIO_DIR_1_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_1_BITS_INPUT (GPIO_DIR_1_VALUE_INPUT << GPIO_DIR_1_SHIFT)
|
||||
#define GPIO_DIR_1_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_1_BITS_OUTPUT (GPIO_DIR_1_VALUE_OUTPUT << GPIO_DIR_1_SHIFT)
|
||||
|
||||
#define GPIO_DIR_2_SHIFT 2
|
||||
#define GPIO_DIR_2_WIDTH 1
|
||||
#define GPIO_DIR_2_MASK (((1U << GPIO_DIR_2_WIDTH) - 1U) << GPIO_DIR_2_SHIFT)
|
||||
#define GPIO_DIR_2_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_2_BITS_INPUT (GPIO_DIR_2_VALUE_INPUT << GPIO_DIR_2_SHIFT)
|
||||
#define GPIO_DIR_2_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_2_BITS_OUTPUT (GPIO_DIR_2_VALUE_OUTPUT << GPIO_DIR_2_SHIFT)
|
||||
|
||||
#define GPIO_DIR_3_SHIFT 3
|
||||
#define GPIO_DIR_3_WIDTH 1
|
||||
#define GPIO_DIR_3_MASK (((1U << GPIO_DIR_3_WIDTH) - 1U) << GPIO_DIR_3_SHIFT)
|
||||
#define GPIO_DIR_3_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_3_BITS_INPUT (GPIO_DIR_3_VALUE_INPUT << GPIO_DIR_3_SHIFT)
|
||||
#define GPIO_DIR_3_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_3_BITS_OUTPUT (GPIO_DIR_3_VALUE_OUTPUT << GPIO_DIR_3_SHIFT)
|
||||
|
||||
#define GPIO_DIR_4_SHIFT 4
|
||||
#define GPIO_DIR_4_WIDTH 1
|
||||
#define GPIO_DIR_4_MASK (((1U << GPIO_DIR_4_WIDTH) - 1U) << GPIO_DIR_4_SHIFT)
|
||||
#define GPIO_DIR_4_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_4_BITS_INPUT (GPIO_DIR_4_VALUE_INPUT << GPIO_DIR_4_SHIFT)
|
||||
#define GPIO_DIR_4_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_4_BITS_OUTPUT (GPIO_DIR_4_VALUE_OUTPUT << GPIO_DIR_4_SHIFT)
|
||||
|
||||
#define GPIO_DIR_5_SHIFT 5
|
||||
#define GPIO_DIR_5_WIDTH 1
|
||||
#define GPIO_DIR_5_MASK (((1U << GPIO_DIR_5_WIDTH) - 1U) << GPIO_DIR_5_SHIFT)
|
||||
#define GPIO_DIR_5_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_5_BITS_INPUT (GPIO_DIR_5_VALUE_INPUT << GPIO_DIR_5_SHIFT)
|
||||
#define GPIO_DIR_5_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_5_BITS_OUTPUT (GPIO_DIR_5_VALUE_OUTPUT << GPIO_DIR_5_SHIFT)
|
||||
|
||||
#define GPIO_DIR_6_SHIFT 6
|
||||
#define GPIO_DIR_6_WIDTH 1
|
||||
#define GPIO_DIR_6_MASK (((1U << GPIO_DIR_6_WIDTH) - 1U) << GPIO_DIR_6_SHIFT)
|
||||
#define GPIO_DIR_6_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_6_BITS_INPUT (GPIO_DIR_6_VALUE_INPUT << GPIO_DIR_6_SHIFT)
|
||||
#define GPIO_DIR_6_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_6_BITS_OUTPUT (GPIO_DIR_6_VALUE_OUTPUT << GPIO_DIR_6_SHIFT)
|
||||
|
||||
#define GPIO_DIR_7_SHIFT 7
|
||||
#define GPIO_DIR_7_WIDTH 1
|
||||
#define GPIO_DIR_7_MASK (((1U << GPIO_DIR_7_WIDTH) - 1U) << GPIO_DIR_7_SHIFT)
|
||||
#define GPIO_DIR_7_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_7_BITS_INPUT (GPIO_DIR_7_VALUE_INPUT << GPIO_DIR_7_SHIFT)
|
||||
#define GPIO_DIR_7_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_7_BITS_OUTPUT (GPIO_DIR_7_VALUE_OUTPUT << GPIO_DIR_7_SHIFT)
|
||||
|
||||
#define GPIO_DIR_8_SHIFT 8
|
||||
#define GPIO_DIR_8_WIDTH 1
|
||||
#define GPIO_DIR_8_MASK (((1U << GPIO_DIR_8_WIDTH) - 1U) << GPIO_DIR_8_SHIFT)
|
||||
#define GPIO_DIR_8_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_8_BITS_INPUT (GPIO_DIR_8_VALUE_INPUT << GPIO_DIR_8_SHIFT)
|
||||
#define GPIO_DIR_8_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_8_BITS_OUTPUT (GPIO_DIR_8_VALUE_OUTPUT << GPIO_DIR_8_SHIFT)
|
||||
|
||||
#define GPIO_DIR_9_SHIFT 9
|
||||
#define GPIO_DIR_9_WIDTH 1
|
||||
#define GPIO_DIR_9_MASK (((1U << GPIO_DIR_9_WIDTH) - 1U) << GPIO_DIR_9_SHIFT)
|
||||
#define GPIO_DIR_9_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_9_BITS_INPUT (GPIO_DIR_9_VALUE_INPUT << GPIO_DIR_9_SHIFT)
|
||||
#define GPIO_DIR_9_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_9_BITS_OUTPUT (GPIO_DIR_9_VALUE_OUTPUT << GPIO_DIR_9_SHIFT)
|
||||
|
||||
#define GPIO_DIR_10_SHIFT 10
|
||||
#define GPIO_DIR_10_WIDTH 1
|
||||
#define GPIO_DIR_10_MASK (((1U << GPIO_DIR_10_WIDTH) - 1U) << GPIO_DIR_10_SHIFT)
|
||||
#define GPIO_DIR_10_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_10_BITS_INPUT (GPIO_DIR_10_VALUE_INPUT << GPIO_DIR_10_SHIFT)
|
||||
#define GPIO_DIR_10_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_10_BITS_OUTPUT (GPIO_DIR_10_VALUE_OUTPUT << GPIO_DIR_10_SHIFT)
|
||||
|
||||
#define GPIO_DIR_11_SHIFT 11
|
||||
#define GPIO_DIR_11_WIDTH 1
|
||||
#define GPIO_DIR_11_MASK (((1U << GPIO_DIR_11_WIDTH) - 1U) << GPIO_DIR_11_SHIFT)
|
||||
#define GPIO_DIR_11_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_11_BITS_INPUT (GPIO_DIR_11_VALUE_INPUT << GPIO_DIR_11_SHIFT)
|
||||
#define GPIO_DIR_11_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_11_BITS_OUTPUT (GPIO_DIR_11_VALUE_OUTPUT << GPIO_DIR_11_SHIFT)
|
||||
|
||||
#define GPIO_DIR_12_SHIFT 12
|
||||
#define GPIO_DIR_12_WIDTH 1
|
||||
#define GPIO_DIR_12_MASK (((1U << GPIO_DIR_12_WIDTH) - 1U) << GPIO_DIR_12_SHIFT)
|
||||
#define GPIO_DIR_12_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_12_BITS_INPUT (GPIO_DIR_12_VALUE_INPUT << GPIO_DIR_12_SHIFT)
|
||||
#define GPIO_DIR_12_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_12_BITS_OUTPUT (GPIO_DIR_12_VALUE_OUTPUT << GPIO_DIR_12_SHIFT)
|
||||
|
||||
#define GPIO_DIR_13_SHIFT 13
|
||||
#define GPIO_DIR_13_WIDTH 1
|
||||
#define GPIO_DIR_13_MASK (((1U << GPIO_DIR_13_WIDTH) - 1U) << GPIO_DIR_13_SHIFT)
|
||||
#define GPIO_DIR_13_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_13_BITS_INPUT (GPIO_DIR_13_VALUE_INPUT << GPIO_DIR_13_SHIFT)
|
||||
#define GPIO_DIR_13_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_13_BITS_OUTPUT (GPIO_DIR_13_VALUE_OUTPUT << GPIO_DIR_13_SHIFT)
|
||||
|
||||
#define GPIO_DIR_14_SHIFT 14
|
||||
#define GPIO_DIR_14_WIDTH 1
|
||||
#define GPIO_DIR_14_MASK (((1U << GPIO_DIR_14_WIDTH) - 1U) << GPIO_DIR_14_SHIFT)
|
||||
#define GPIO_DIR_14_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_14_BITS_INPUT (GPIO_DIR_14_VALUE_INPUT << GPIO_DIR_14_SHIFT)
|
||||
#define GPIO_DIR_14_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_14_BITS_OUTPUT (GPIO_DIR_14_VALUE_OUTPUT << GPIO_DIR_14_SHIFT)
|
||||
|
||||
#define GPIO_DIR_15_SHIFT 15
|
||||
#define GPIO_DIR_15_WIDTH 1
|
||||
#define GPIO_DIR_15_MASK (((1U << GPIO_DIR_15_WIDTH) - 1U) << GPIO_DIR_15_SHIFT)
|
||||
#define GPIO_DIR_15_VALUE_INPUT 0U
|
||||
#define GPIO_DIR_15_BITS_INPUT (GPIO_DIR_15_VALUE_INPUT << GPIO_DIR_15_SHIFT)
|
||||
#define GPIO_DIR_15_VALUE_OUTPUT 1U
|
||||
#define GPIO_DIR_15_BITS_OUTPUT (GPIO_DIR_15_VALUE_OUTPUT << GPIO_DIR_15_SHIFT)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
40
bsp/dp32g030/irq.h
Normal file
40
bsp/dp32g030/irq.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef DP32G030_IRQ_H
|
||||
#define DP32G030_IRQ_H
|
||||
|
||||
enum {
|
||||
DP32_WWDT_IRQn = 0,
|
||||
DP32_IWDT_IRQn,
|
||||
DP32_RTC_IRQn,
|
||||
DP32_DMA_IRQn,
|
||||
DP32_SARADC_IRQn,
|
||||
DP32_TIMER_BASE0_IRQn,
|
||||
DP32_TIMER_BASE1_IRQn,
|
||||
DP32_TIMER_PLUS0_IRQn,
|
||||
DP32_TIMER_PLUS1_IRQn,
|
||||
DP32_PWM_BASE0_IRQn,
|
||||
DP32_PWM_BASE1_IRQn,
|
||||
DP32_PWM_PLUS0_IRQn,
|
||||
DP32_PWM_PLUS1_IRQn,
|
||||
DP32_UART0_IRQn,
|
||||
DP32_UART1_IRQn,
|
||||
DP32_UART2_IRQn,
|
||||
DP32_SPI0_IRQn,
|
||||
DP32_SPI1_IRQn,
|
||||
DP32_IIC0_IRQn,
|
||||
DP32_IIC1_IRQn,
|
||||
DP32_CMP_IRQn,
|
||||
DP32_TIMER_BASE2_IRQn,
|
||||
DP32_GPIOA5_IRQn,
|
||||
DP32_GPIOA6_IRQn,
|
||||
DP32_GPIOA7_IRQn,
|
||||
DP32_GPIOB0_IRQn,
|
||||
DP32_GPIOB1_IRQn,
|
||||
DP32_GPIOC0_IRQn,
|
||||
DP32_GPIOC1_IRQn,
|
||||
DP32_GPIOA_IRQn,
|
||||
DP32_GPIOB_IRQn,
|
||||
DP32_GPIOC_IRQn,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
65
bsp/dp32g030/pmu.h
Normal file
65
bsp/dp32g030/pmu.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HARDWARE_DP32G030_PMU_H
|
||||
#define HARDWARE_DP32G030_PMU_H
|
||||
|
||||
#if !defined(__ASSEMBLY__)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* -------- PMU -------- */
|
||||
#define PMU_BASE_ADDR 0x40000800U
|
||||
#define PMU_BASE_SIZE 0x00000800U
|
||||
|
||||
#define PMU_SRC_CFG_ADDR (PMU_BASE_ADDR + 0x0010U)
|
||||
#define PMU_SRC_CFG (*(volatile uint32_t *)PMU_SRC_CFG_ADDR)
|
||||
#define PMU_SRC_CFG_RCHF_EN_SHIFT 0
|
||||
#define PMU_SRC_CFG_RCHF_EN_WIDTH 1
|
||||
#define PMU_SRC_CFG_RCHF_EN_MASK (((1U << PMU_SRC_CFG_RCHF_EN_WIDTH) - 1U) << PMU_SRC_CFG_RCHF_EN_SHIFT)
|
||||
#define PMU_SRC_CFG_RCHF_EN_VALUE_DISABLE 0U
|
||||
#define PMU_SRC_CFG_RCHF_EN_BITS_DISABLE (PMU_SRC_CFG_RCHF_EN_VALUE_DISABLE << PMU_SRC_CFG_RCHF_EN_SHIFT)
|
||||
#define PMU_SRC_CFG_RCHF_EN_VALUE_ENABLE 1U
|
||||
#define PMU_SRC_CFG_RCHF_EN_BITS_ENABLE (PMU_SRC_CFG_RCHF_EN_VALUE_ENABLE << PMU_SRC_CFG_RCHF_EN_SHIFT)
|
||||
|
||||
#define PMU_SRC_CFG_RCHF_SEL_SHIFT 1
|
||||
#define PMU_SRC_CFG_RCHF_SEL_WIDTH 1
|
||||
#define PMU_SRC_CFG_RCHF_SEL_MASK (((1U << PMU_SRC_CFG_RCHF_SEL_WIDTH) - 1U) << PMU_SRC_CFG_RCHF_SEL_SHIFT)
|
||||
#define PMU_SRC_CFG_RCHF_SEL_VALUE_48MHZ 0U
|
||||
#define PMU_SRC_CFG_RCHF_SEL_BITS_48MHZ (PMU_SRC_CFG_RCHF_SEL_VALUE_48MHZ << PMU_SRC_CFG_RCHF_SEL_SHIFT)
|
||||
#define PMU_SRC_CFG_RCHF_SEL_VALUE_24MHZ 1U
|
||||
#define PMU_SRC_CFG_RCHF_SEL_BITS_24MHZ (PMU_SRC_CFG_RCHF_SEL_VALUE_24MHZ << PMU_SRC_CFG_RCHF_SEL_SHIFT)
|
||||
|
||||
#define PMU_TRIM_POW0_ADDR (PMU_BASE_ADDR + 0x0020U)
|
||||
#define PMU_TRIM_POW0 (*(volatile uint32_t *)PMU_TRIM_POW0_ADDR)
|
||||
#define PMU_TRIM_POW1_ADDR (PMU_BASE_ADDR + 0x0024U)
|
||||
#define PMU_TRIM_POW1 (*(volatile uint32_t *)PMU_TRIM_POW1_ADDR)
|
||||
#define PMU_TRIM_POW2_ADDR (PMU_BASE_ADDR + 0x0028U)
|
||||
#define PMU_TRIM_POW2 (*(volatile uint32_t *)PMU_TRIM_POW2_ADDR)
|
||||
#define PMU_TRIM_POW3_ADDR (PMU_BASE_ADDR + 0x002CU)
|
||||
#define PMU_TRIM_POW3 (*(volatile uint32_t *)PMU_TRIM_POW3_ADDR)
|
||||
#define PMU_TRIM_RCHF_ADDR (PMU_BASE_ADDR + 0x0030U)
|
||||
#define PMU_TRIM_RCHF (*(volatile uint32_t *)PMU_TRIM_RCHF_ADDR)
|
||||
#define PMU_TRIM_RCLF_ADDR (PMU_BASE_ADDR + 0x0034U)
|
||||
#define PMU_TRIM_RCLF (*(volatile uint32_t *)PMU_TRIM_RCLF_ADDR)
|
||||
#define PMU_TRIM_OPA_ADDR (PMU_BASE_ADDR + 0x0038U)
|
||||
#define PMU_TRIM_OPA (*(volatile uint32_t *)PMU_TRIM_OPA_ADDR)
|
||||
#define PMU_TRIM_PLL_ADDR (PMU_BASE_ADDR + 0x003CU)
|
||||
#define PMU_TRIM_PLL (*(volatile uint32_t *)PMU_TRIM_PLL_ADDR)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
2174
bsp/dp32g030/portcon.h
Normal file
2174
bsp/dp32g030/portcon.h
Normal file
File diff suppressed because it is too large
Load Diff
146
bsp/dp32g030/pwmplus.h
Normal file
146
bsp/dp32g030/pwmplus.h
Normal file
@@ -0,0 +1,146 @@
|
||||
#ifndef HARDWARE_DP32G030_PWMPLUS_H
|
||||
#define HARDWARE_DP32G030_PWMPLUS_H
|
||||
|
||||
#define PWM_PLUS0_BASE_ADDR 0x400B4000U
|
||||
|
||||
//---------------
|
||||
|
||||
#define PWMPLUS_CFG 0x00U
|
||||
|
||||
#define PWMPLUS_CFG_COUNTER_EN_SHIFT 0U
|
||||
#define PWMPLUS_CFG_COUNTER_EN_WIDTH 1U
|
||||
#define PWMPLUS_CFG_COUNTER_EN_MASK (((1U << PWMPLUS_CFG_COUNTER_EN_WIDTH) - 1U) << PWMPLUS_CFG_COUNTER_EN_SHIFT)
|
||||
#define PWMPLUS_CFG_COUNTER_EN_VALUE_ENABLE 1U
|
||||
#define PWMPLUS_CFG_COUNTER_EN_BITS_ENABLE (PWMPLUS_CFG_COUNTER_EN_VALUE_ENABLE << PWMPLUS_CFG_COUNTER_EN_SHIFT)
|
||||
|
||||
#define PWMPLUS_CFG_CNT_TYPE_SHIFT 1U
|
||||
|
||||
#define PWMPLUS_CFG_CNT_REP_SHIFT 2U
|
||||
#define PWMPLUS_CFG_CNT_REP_WIDTH 1U
|
||||
#define PWMPLUS_CFG_CNT_REP_VALUE_ENABLE 1U
|
||||
#define PWMPLUS_CFG_CNT_REP_BITS_ENABLE (PWMPLUS_CFG_CNT_REP_VALUE_ENABLE << PWMPLUS_CFG_CNT_REP_SHIFT)
|
||||
|
||||
#define PWMPLUS_CFG_OUT_MODE_SHIFT 3U
|
||||
#define PWMPLUS_CFG_OUT_MODE_VALUE_ENABLE 1U
|
||||
#define PWMPLUS_CFG_OUT_MODE_BITS_ENABLE (PWMPLUS_CFG_OUT_MODE_VALUE_ENABLE << PWMPLUS_CFG_OUT_MODE_SHIFT)
|
||||
|
||||
#define PWMPLUS_CFG_AUTO_RELOAD_SHIFT 8U
|
||||
|
||||
//---------------
|
||||
|
||||
#define PWMPLUS_GEN 0x04U
|
||||
|
||||
#define PWMPLUS_GEN_CH0_OE_SHIFT 24U
|
||||
#define PWMPLUS_GEN_CH0_OE_WIDTH 1U
|
||||
#define PWMPLUS_GEN_CH0_OE_VALUE_ENABLE 1U
|
||||
#define PWMPLUS_GEN_CH0_OE_BITS_ENABLE (PWMPLUS_GEN_CH0_OE_VALUE_ENABLE << PWMPLUS_GEN_CH0_OE_SHIFT)
|
||||
|
||||
#define PWMPLUS_GEN_CH0_OUTINV_SHIFT 16U
|
||||
#define PWMPLUS_GEN_CH0_OUTINV_WIDTH 1U
|
||||
#define PWMPLUS_GEN_CH0_OUTINV_VALUE_ENABLE 1U
|
||||
#define PWMPLUS_GEN_CH0_OUTINV_BITS_ENABLE (PWMPLUS_GEN_CH0_OUTINV_VALUE_ENABLE << PWMPLUS_GEN_CH0_OUTINV_SHIFT)
|
||||
|
||||
#define PWMPLUS_GEN_CH0_START_SHIFT 8U
|
||||
#define PWMPLUS_GEN_CH0_START_WIDTH 1U
|
||||
#define PWMPLUS_GEN_CH0_START_VALUE_ENABLE 1U
|
||||
#define PWMPLUS_GEN_CH0_START_BITS_ENABLE (PWMPLUS_GEN_CH0_START_VALUE_ENABLE << PWMPLUS_GEN_CH0_START_SHIFT)
|
||||
|
||||
#define PWMPLUS_GEN_CH0_IDLE_SHIFT 0U
|
||||
#define PWMPLUS_GEN_CH0_IDLE_WIDTH 1U
|
||||
#define PWMPLUS_GEN_CH0_IDLE_VALUE_ENABLE 1U
|
||||
#define PWMPLUS_GEN_CH0_IDLE_BITS_ENABLE (PWMPLUS_GEN_CH0_IDLE_VALUE_ENABLE << PWMPLUS_GEN_CH0_IDLE_SHIFT)
|
||||
|
||||
//---------------
|
||||
|
||||
#define PWMPLUS_CLKSRC 0x08U
|
||||
#define PWMPLUS_BRAKE_CFG 0x0CU
|
||||
#define PWMPLUS_MASK_LEV 0x10U
|
||||
#define PWMPLUS_PERIOD 0x1CU
|
||||
#define PWMPLUS_CH0_COMP 0x20U
|
||||
#define PWMPLUS_CH1_COMP 0x24U
|
||||
#define PWMPLUS_CH2_COMP 0x28U
|
||||
#define PWMPLUS_CH0_DT 0x30U
|
||||
#define PWMPLUS_CH1_DT 0x34U
|
||||
#define PWMPLUS_CH2_DT 0x38U
|
||||
#define PWMPLUS_TRIG_COMP 0x40U
|
||||
#define PWMPLUS_TRIG_CFG 0x44U
|
||||
#define PWMPLUS_IE 0x60U
|
||||
#define PWMPLUS_IF 0x64U
|
||||
#define PWMPLUS_SWLOAD 0x84U
|
||||
#define PWMPLUS_MASK_EN 0x88
|
||||
#define PWMPLUS_CNT_ST 0xE0
|
||||
#define PWMPLUS_BRAKE_ST 0xE4
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define PWM_PLUS0_CFG_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_CFG)
|
||||
#define PWM_PLUS0_CFG (*(volatile uint32_t *)PWM_PLUS0_CFG_ADDR)
|
||||
|
||||
#define PWM_PLUS0_GEN_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_GEN)
|
||||
#define PWM_PLUS0_GEN (*(volatile uint32_t *)PWM_PLUS0_GEN_ADDR)
|
||||
|
||||
#define PWM_PLUS0_CLKSRC_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_CLKSRC)
|
||||
#define PWM_PLUS0_CLKSRC (*(volatile uint32_t *)PWM_PLUS0_CLKSRC_ADDR)
|
||||
|
||||
#define PWM_PLUS0_BRAKE_CFG_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_BRAKE_CFG)
|
||||
#define PWM_PLUS0_BRAKE_CFG (*(volatile uint32_t *)PWM_PLUS0_BRAKE_CFG_ADDR)
|
||||
|
||||
#define PWM_PLUS0_MASK_LEV_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_MASK_LEV)
|
||||
#define PWM_PLUS0_MASK_LEV (*(volatile uint32_t *)PWM_PLUS0_MASK_LEV_ADDR)
|
||||
|
||||
#define PWM_PLUS0_PERIOD_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_PERIOD)
|
||||
#define PWM_PLUS0_PERIOD (*(volatile uint32_t *)PWM_PLUS0_PERIOD_ADDR)
|
||||
|
||||
#define PWM_PLUS0_CH0_COMP_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_CH0_COMP)
|
||||
#define PWM_PLUS0_CH0_COMP (*(volatile uint32_t *)PWM_PLUS0_CH0_COMP_ADDR)
|
||||
|
||||
#define PWM_PLUS0_CH1_COMP_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_CH1_COMP)
|
||||
#define PWM_PLUS0_CH1_COMP (*(volatile uint32_t *)PWM_PLUS0_CH1_COMP_ADDR)
|
||||
|
||||
#define PWM_PLUS0_CH2_COMP_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_CH2_COMP)
|
||||
#define PWM_PLUS0_CH2_COMP (*(volatile uint32_t *)PWM_PLUS0_CH2_COMP_ADDR)
|
||||
|
||||
#define PWM_PLUS0_CH0_DT_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_CH0_DT)
|
||||
#define PWM_PLUS0_CH0_DT (*(volatile uint32_t *)PWM_PLUS0_CH0_DT_ADDR)
|
||||
|
||||
#define PWM_PLUS0_CH1_DT_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_CH1_DT)
|
||||
#define PWM_PLUS0_CH1_DT (*(volatile uint32_t *)PWM_PLUS0_CH1_DT_ADDR)
|
||||
|
||||
#define PWM_PLUS0_CH2_DT_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_CH2_DT)
|
||||
#define PWM_PLUS0_CH2_DT (*(volatile uint32_t *)PWM_PLUS0_CH2_DT_ADDR)
|
||||
|
||||
#define PWM_PLUS0_TRIG_COMP_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_TRIG_COMP)
|
||||
#define PWM_PLUS0_TRIG_COMP (*(volatile uint32_t *)PWM_PLUS0_TRIG_COMP_ADDR)
|
||||
|
||||
#define PWM_PLUS0_TRIG_CFG_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_TRIG_CFG)
|
||||
#define PWM_PLUS0_TRIG_CFG (*(volatile uint32_t *)PWM_PLUS0_TRIG_CFG_ADDR)
|
||||
|
||||
#define PWM_PLUS0_IE_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_IE)
|
||||
#define PWM_PLUS0_IE (*(volatile uint32_t *)PWM_PLUS0_IE_ADDR)
|
||||
|
||||
#define PWM_PLUS0_IF_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_IF)
|
||||
#define PWM_PLUS0_IF (*(volatile uint32_t *)PWM_PLUS0_IF_ADDR)
|
||||
|
||||
#define PWM_PLUS0_SWLOAD_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_SWLOAD)
|
||||
#define PWM_PLUS0_SWLOAD (*(volatile uint32_t *)PWM_PLUS0_SWLOAD_ADDR)
|
||||
|
||||
#define PWM_PLUS0_MASK_EN_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_MASK_EN)
|
||||
#define PWM_PLUS0_MASK_EN (*(volatile uint32_t *)PWM_PLUS0_MASK_EN_ADDR)
|
||||
|
||||
#define PWM_PLUS0_CNT_ST_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_CNT_ST)
|
||||
#define PWM_PLUS0_CNT_ST (*(volatile uint32_t *)PWM_PLUS0_CNT_ST_ADDR)
|
||||
|
||||
#define PWM_PLUS0_BRAKE_ST_ADDR (PWM_PLUS0_BASE_ADDR + PWMPLUS_BRAKE_ST)
|
||||
#define PWM_PLUS0_BRAKE_ST (*(volatile uint32_t *)PWM_PLUS0_BRAKE_ST_ADDR)
|
||||
|
||||
#endif
|
||||
253
bsp/dp32g030/saradc.h
Normal file
253
bsp/dp32g030/saradc.h
Normal file
@@ -0,0 +1,253 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HARDWARE_DP32G030_SARADC_H
|
||||
#define HARDWARE_DP32G030_SARADC_H
|
||||
|
||||
#if !defined(__ASSEMBLY__)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* -------- SARADC -------- */
|
||||
#define SARADC_BASE_ADDR 0x400BA000U
|
||||
#define SARADC_BASE_SIZE 0x00000800U
|
||||
|
||||
#define SARADC_CFG_ADDR (SARADC_BASE_ADDR + 0x0000U)
|
||||
#define SARADC_CFG (*(volatile uint32_t *)SARADC_CFG_ADDR)
|
||||
#define SARADC_CFG_CH_SEL_SHIFT 0
|
||||
#define SARADC_CFG_CH_SEL_WIDTH 15
|
||||
#define SARADC_CFG_CH_SEL_MASK (((1U << SARADC_CFG_CH_SEL_WIDTH) - 1U) << SARADC_CFG_CH_SEL_SHIFT)
|
||||
#define SARADC_CFG_AVG_SHIFT 16
|
||||
#define SARADC_CFG_AVG_WIDTH 2
|
||||
#define SARADC_CFG_AVG_MASK (((1U << SARADC_CFG_AVG_WIDTH) - 1U) << SARADC_CFG_AVG_SHIFT)
|
||||
#define SARADC_CFG_AVG_VALUE_1_SAMPLE 0U
|
||||
#define SARADC_CFG_AVG_BITS_1_SAMPLE (SARADC_CFG_AVG_VALUE_1_SAMPLE << SARADC_CFG_AVG_SHIFT)
|
||||
#define SARADC_CFG_AVG_VALUE_2_SAMPLE 1U
|
||||
#define SARADC_CFG_AVG_BITS_2_SAMPLE (SARADC_CFG_AVG_VALUE_2_SAMPLE << SARADC_CFG_AVG_SHIFT)
|
||||
#define SARADC_CFG_AVG_VALUE_4_SAMPLE 2U
|
||||
#define SARADC_CFG_AVG_BITS_4_SAMPLE (SARADC_CFG_AVG_VALUE_4_SAMPLE << SARADC_CFG_AVG_SHIFT)
|
||||
#define SARADC_CFG_AVG_VALUE_8_SAMPLE 3U
|
||||
#define SARADC_CFG_AVG_BITS_8_SAMPLE (SARADC_CFG_AVG_VALUE_8_SAMPLE << SARADC_CFG_AVG_SHIFT)
|
||||
|
||||
#define SARADC_CFG_CONT_SHIFT 18
|
||||
#define SARADC_CFG_CONT_WIDTH 1
|
||||
#define SARADC_CFG_CONT_MASK (((1U << SARADC_CFG_CONT_WIDTH) - 1U) << SARADC_CFG_CONT_SHIFT)
|
||||
#define SARADC_CFG_CONT_VALUE_SINGLE 0U
|
||||
#define SARADC_CFG_CONT_BITS_SINGLE (SARADC_CFG_CONT_VALUE_SINGLE << SARADC_CFG_CONT_SHIFT)
|
||||
#define SARADC_CFG_CONT_VALUE_CONTINUOUS 1U
|
||||
#define SARADC_CFG_CONT_BITS_CONTINUOUS (SARADC_CFG_CONT_VALUE_CONTINUOUS << SARADC_CFG_CONT_SHIFT)
|
||||
|
||||
#define SARADC_CFG_SMPL_SETUP_SHIFT 19
|
||||
#define SARADC_CFG_SMPL_SETUP_WIDTH 3
|
||||
#define SARADC_CFG_SMPL_SETUP_MASK (((1U << SARADC_CFG_SMPL_SETUP_WIDTH) - 1U) << SARADC_CFG_SMPL_SETUP_SHIFT)
|
||||
#define SARADC_CFG_SMPL_SETUP_VALUE_1_CYCLE 0U
|
||||
#define SARADC_CFG_SMPL_SETUP_BITS_1_CYCLE (SARADC_CFG_SMPL_SETUP_VALUE_1_CYCLE << SARADC_CFG_SMPL_SETUP_SHIFT)
|
||||
#define SARADC_CFG_SMPL_SETUP_VALUE_2_CYCLE 1U
|
||||
#define SARADC_CFG_SMPL_SETUP_BITS_2_CYCLE (SARADC_CFG_SMPL_SETUP_VALUE_2_CYCLE << SARADC_CFG_SMPL_SETUP_SHIFT)
|
||||
#define SARADC_CFG_SMPL_SETUP_VALUE_4_CYCLE 2U
|
||||
#define SARADC_CFG_SMPL_SETUP_BITS_4_CYCLE (SARADC_CFG_SMPL_SETUP_VALUE_4_CYCLE << SARADC_CFG_SMPL_SETUP_SHIFT)
|
||||
#define SARADC_CFG_SMPL_SETUP_VALUE_8_CYCLE 3U
|
||||
#define SARADC_CFG_SMPL_SETUP_BITS_8_CYCLE (SARADC_CFG_SMPL_SETUP_VALUE_8_CYCLE << SARADC_CFG_SMPL_SETUP_SHIFT)
|
||||
#define SARADC_CFG_SMPL_SETUP_VALUE_16_CYCLE 4U
|
||||
#define SARADC_CFG_SMPL_SETUP_BITS_16_CYCLE (SARADC_CFG_SMPL_SETUP_VALUE_16_CYCLE << SARADC_CFG_SMPL_SETUP_SHIFT)
|
||||
#define SARADC_CFG_SMPL_SETUP_VALUE_32_CYCLE 5U
|
||||
#define SARADC_CFG_SMPL_SETUP_BITS_32_CYCLE (SARADC_CFG_SMPL_SETUP_VALUE_32_CYCLE << SARADC_CFG_SMPL_SETUP_SHIFT)
|
||||
#define SARADC_CFG_SMPL_SETUP_VALUE_64_CYCLE 6U
|
||||
#define SARADC_CFG_SMPL_SETUP_BITS_64_CYCLE (SARADC_CFG_SMPL_SETUP_VALUE_64_CYCLE << SARADC_CFG_SMPL_SETUP_SHIFT)
|
||||
#define SARADC_CFG_SMPL_SETUP_VALUE_128_CYCLE 7U
|
||||
#define SARADC_CFG_SMPL_SETUP_BITS_128_CYCLE (SARADC_CFG_SMPL_SETUP_VALUE_128_CYCLE << SARADC_CFG_SMPL_SETUP_SHIFT)
|
||||
|
||||
#define SARADC_CFG_MEM_MODE_SHIFT 22
|
||||
#define SARADC_CFG_MEM_MODE_WIDTH 1
|
||||
#define SARADC_CFG_MEM_MODE_MASK (((1U << SARADC_CFG_MEM_MODE_WIDTH) - 1U) << SARADC_CFG_MEM_MODE_SHIFT)
|
||||
#define SARADC_CFG_MEM_MODE_VALUE_FIFO 0U
|
||||
#define SARADC_CFG_MEM_MODE_BITS_FIFO (SARADC_CFG_MEM_MODE_VALUE_FIFO << SARADC_CFG_MEM_MODE_SHIFT)
|
||||
#define SARADC_CFG_MEM_MODE_VALUE_CHANNEL 1U
|
||||
#define SARADC_CFG_MEM_MODE_BITS_CHANNEL (SARADC_CFG_MEM_MODE_VALUE_CHANNEL << SARADC_CFG_MEM_MODE_SHIFT)
|
||||
|
||||
#define SARADC_CFG_SMPL_CLK_SHIFT 23
|
||||
#define SARADC_CFG_SMPL_CLK_WIDTH 1
|
||||
#define SARADC_CFG_SMPL_CLK_MASK (((1U << SARADC_CFG_SMPL_CLK_WIDTH) - 1U) << SARADC_CFG_SMPL_CLK_SHIFT)
|
||||
#define SARADC_CFG_SMPL_CLK_VALUE_EXTERNAL 0U
|
||||
#define SARADC_CFG_SMPL_CLK_BITS_EXTERNAL (SARADC_CFG_SMPL_CLK_VALUE_EXTERNAL << SARADC_CFG_SMPL_CLK_SHIFT)
|
||||
#define SARADC_CFG_SMPL_CLK_VALUE_INTERNAL 1U
|
||||
#define SARADC_CFG_SMPL_CLK_BITS_INTERNAL (SARADC_CFG_SMPL_CLK_VALUE_INTERNAL << SARADC_CFG_SMPL_CLK_SHIFT)
|
||||
|
||||
#define SARADC_CFG_SMPL_WIN_SHIFT 24
|
||||
#define SARADC_CFG_SMPL_WIN_WIDTH 3
|
||||
#define SARADC_CFG_SMPL_WIN_MASK (((1U << SARADC_CFG_SMPL_WIN_WIDTH) - 1U) << SARADC_CFG_SMPL_WIN_SHIFT)
|
||||
#define SARADC_CFG_SMPL_WIN_VALUE_1_CYCLE 0U
|
||||
#define SARADC_CFG_SMPL_WIN_BITS_1_CYCLE (SARADC_CFG_SMPL_WIN_VALUE_1_CYCLE << SARADC_CFG_SMPL_WIN_SHIFT)
|
||||
#define SARADC_CFG_SMPL_WIN_VALUE_3_CYCLE 1U
|
||||
#define SARADC_CFG_SMPL_WIN_BITS_3_CYCLE (SARADC_CFG_SMPL_WIN_VALUE_3_CYCLE << SARADC_CFG_SMPL_WIN_SHIFT)
|
||||
#define SARADC_CFG_SMPL_WIN_VALUE_5_CYCLE 2U
|
||||
#define SARADC_CFG_SMPL_WIN_BITS_5_CYCLE (SARADC_CFG_SMPL_WIN_VALUE_5_CYCLE << SARADC_CFG_SMPL_WIN_SHIFT)
|
||||
#define SARADC_CFG_SMPL_WIN_VALUE_7_CYCLE 3U
|
||||
#define SARADC_CFG_SMPL_WIN_BITS_7_CYCLE (SARADC_CFG_SMPL_WIN_VALUE_7_CYCLE << SARADC_CFG_SMPL_WIN_SHIFT)
|
||||
#define SARADC_CFG_SMPL_WIN_VALUE_9_CYCLE 4U
|
||||
#define SARADC_CFG_SMPL_WIN_BITS_9_CYCLE (SARADC_CFG_SMPL_WIN_VALUE_9_CYCLE << SARADC_CFG_SMPL_WIN_SHIFT)
|
||||
#define SARADC_CFG_SMPL_WIN_VALUE_11_CYCLE 5U
|
||||
#define SARADC_CFG_SMPL_WIN_BITS_11_CYCLE (SARADC_CFG_SMPL_WIN_VALUE_11_CYCLE << SARADC_CFG_SMPL_WIN_SHIFT)
|
||||
#define SARADC_CFG_SMPL_WIN_VALUE_13_CYCLE 6U
|
||||
#define SARADC_CFG_SMPL_WIN_BITS_13_CYCLE (SARADC_CFG_SMPL_WIN_VALUE_13_CYCLE << SARADC_CFG_SMPL_WIN_SHIFT)
|
||||
#define SARADC_CFG_SMPL_WIN_VALUE_15_CYCLE 7U
|
||||
#define SARADC_CFG_SMPL_WIN_BITS_15_CYCLE (SARADC_CFG_SMPL_WIN_VALUE_15_CYCLE << SARADC_CFG_SMPL_WIN_SHIFT)
|
||||
|
||||
#define SARADC_CFG_ADC_EN_SHIFT 27
|
||||
#define SARADC_CFG_ADC_EN_WIDTH 1
|
||||
#define SARADC_CFG_ADC_EN_MASK (((1U << SARADC_CFG_ADC_EN_WIDTH) - 1U) << SARADC_CFG_ADC_EN_SHIFT)
|
||||
#define SARADC_CFG_ADC_EN_VALUE_DISABLE 0U
|
||||
#define SARADC_CFG_ADC_EN_BITS_DISABLE (SARADC_CFG_ADC_EN_VALUE_DISABLE << SARADC_CFG_ADC_EN_SHIFT)
|
||||
#define SARADC_CFG_ADC_EN_VALUE_ENABLE 1U
|
||||
#define SARADC_CFG_ADC_EN_BITS_ENABLE (SARADC_CFG_ADC_EN_VALUE_ENABLE << SARADC_CFG_ADC_EN_SHIFT)
|
||||
|
||||
#define SARADC_CFG_ADC_TRIG_SHIFT 28
|
||||
#define SARADC_CFG_ADC_TRIG_WIDTH 1
|
||||
#define SARADC_CFG_ADC_TRIG_MASK (((1U << SARADC_CFG_ADC_TRIG_WIDTH) - 1U) << SARADC_CFG_ADC_TRIG_SHIFT)
|
||||
#define SARADC_CFG_ADC_TRIG_VALUE_CPU 0U
|
||||
#define SARADC_CFG_ADC_TRIG_BITS_CPU (SARADC_CFG_ADC_TRIG_VALUE_CPU << SARADC_CFG_ADC_TRIG_SHIFT)
|
||||
#define SARADC_CFG_ADC_TRIG_VALUE_EXTERNAL 1U
|
||||
#define SARADC_CFG_ADC_TRIG_BITS_EXTERNAL (SARADC_CFG_ADC_TRIG_VALUE_EXTERNAL << SARADC_CFG_ADC_TRIG_SHIFT)
|
||||
|
||||
#define SARADC_CFG_DMA_EN_SHIFT 29
|
||||
#define SARADC_CFG_DMA_EN_WIDTH 1
|
||||
#define SARADC_CFG_DMA_EN_MASK (((1U << SARADC_CFG_DMA_EN_WIDTH) - 1U) << SARADC_CFG_DMA_EN_SHIFT)
|
||||
#define SARADC_CFG_DMA_EN_VALUE_DISABLE 0U
|
||||
#define SARADC_CFG_DMA_EN_BITS_DISABLE (SARADC_CFG_DMA_EN_VALUE_DISABLE << SARADC_CFG_DMA_EN_SHIFT)
|
||||
#define SARADC_CFG_DMA_EN_VALUE_ENABLE 1U
|
||||
#define SARADC_CFG_DMA_EN_BITS_ENABLE (SARADC_CFG_DMA_EN_VALUE_ENABLE << SARADC_CFG_DMA_EN_SHIFT)
|
||||
|
||||
#define SARADC_START_ADDR (SARADC_BASE_ADDR + 0x0004U)
|
||||
#define SARADC_START (*(volatile uint32_t *)SARADC_START_ADDR)
|
||||
#define SARADC_START_START_SHIFT 0
|
||||
#define SARADC_START_START_WIDTH 1
|
||||
#define SARADC_START_START_MASK (((1U << SARADC_START_START_WIDTH) - 1U) << SARADC_START_START_SHIFT)
|
||||
#define SARADC_START_START_VALUE_DISABLE 0U
|
||||
#define SARADC_START_START_BITS_DISABLE (SARADC_START_START_VALUE_DISABLE << SARADC_START_START_SHIFT)
|
||||
#define SARADC_START_START_VALUE_ENABLE 1U
|
||||
#define SARADC_START_START_BITS_ENABLE (SARADC_START_START_VALUE_ENABLE << SARADC_START_START_SHIFT)
|
||||
|
||||
#define SARADC_START_SOFT_RESET_SHIFT 2
|
||||
#define SARADC_START_SOFT_RESET_WIDTH 1
|
||||
#define SARADC_START_SOFT_RESET_MASK (((1U << SARADC_START_SOFT_RESET_WIDTH) - 1U) << SARADC_START_SOFT_RESET_SHIFT)
|
||||
#define SARADC_START_SOFT_RESET_VALUE_ASSERT 0U
|
||||
#define SARADC_START_SOFT_RESET_BITS_ASSERT (SARADC_START_SOFT_RESET_VALUE_ASSERT << SARADC_START_SOFT_RESET_SHIFT)
|
||||
#define SARADC_START_SOFT_RESET_VALUE_DEASSERT 1U
|
||||
#define SARADC_START_SOFT_RESET_BITS_DEASSERT (SARADC_START_SOFT_RESET_VALUE_DEASSERT << SARADC_START_SOFT_RESET_SHIFT)
|
||||
|
||||
#define SARADC_IE_ADDR (SARADC_BASE_ADDR + 0x0008U)
|
||||
#define SARADC_IE (*(volatile uint32_t *)SARADC_IE_ADDR)
|
||||
#define SARADC_IE_CHx_EOC_SHIFT 0
|
||||
#define SARADC_IE_CHx_EOC_WIDTH 16
|
||||
#define SARADC_IE_CHx_EOC_MASK (((1U << SARADC_IE_CHx_EOC_WIDTH) - 1U) << SARADC_IE_CHx_EOC_SHIFT)
|
||||
#define SARADC_IE_CHx_EOC_VALUE_NONE 0U
|
||||
#define SARADC_IE_CHx_EOC_BITS_NONE (SARADC_IE_CHx_EOC_VALUE_NONE << SARADC_IE_CHx_EOC_SHIFT)
|
||||
#define SARADC_IE_CHx_EOC_VALUE_ALL 65535U
|
||||
#define SARADC_IE_CHx_EOC_BITS_ALL (SARADC_IE_CHx_EOC_VALUE_ALL << SARADC_IE_CHx_EOC_SHIFT)
|
||||
|
||||
#define SARADC_IE_FIFO_FULL_SHIFT 16
|
||||
#define SARADC_IE_FIFO_FULL_WIDTH 1
|
||||
#define SARADC_IE_FIFO_FULL_MASK (((1U << SARADC_IE_FIFO_FULL_WIDTH) - 1U) << SARADC_IE_FIFO_FULL_SHIFT)
|
||||
#define SARADC_IE_FIFO_FULL_VALUE_DISABLE 0U
|
||||
#define SARADC_IE_FIFO_FULL_BITS_DISABLE (SARADC_IE_FIFO_FULL_VALUE_DISABLE << SARADC_IE_FIFO_FULL_SHIFT)
|
||||
#define SARADC_IE_FIFO_FULL_VALUE_ENABLE 1U
|
||||
#define SARADC_IE_FIFO_FULL_BITS_ENABLE (SARADC_IE_FIFO_FULL_VALUE_ENABLE << SARADC_IE_FIFO_FULL_SHIFT)
|
||||
|
||||
#define SARADC_IE_FIFO_HFULL_SHIFT 17
|
||||
#define SARADC_IE_FIFO_HFULL_WIDTH 1
|
||||
#define SARADC_IE_FIFO_HFULL_MASK (((1U << SARADC_IE_FIFO_HFULL_WIDTH) - 1U) << SARADC_IE_FIFO_HFULL_SHIFT)
|
||||
#define SARADC_IE_FIFO_HFULL_VALUE_DISABLE 0U
|
||||
#define SARADC_IE_FIFO_HFULL_BITS_DISABLE (SARADC_IE_FIFO_HFULL_VALUE_DISABLE << SARADC_IE_FIFO_HFULL_SHIFT)
|
||||
#define SARADC_IE_FIFO_HFULL_VALUE_ENABLE 1U
|
||||
#define SARADC_IE_FIFO_HFULL_BITS_ENABLE (SARADC_IE_FIFO_HFULL_VALUE_ENABLE << SARADC_IE_FIFO_HFULL_SHIFT)
|
||||
|
||||
#define SARADC_IF_ADDR (SARADC_BASE_ADDR + 0x000CU)
|
||||
#define SARADC_IF (*(volatile uint32_t *)SARADC_IF_ADDR)
|
||||
#define SARADC_IF_CHx_EOC_SHIFT 0
|
||||
#define SARADC_IF_CHx_EOC_WIDTH 16
|
||||
#define SARADC_IF_CHx_EOC_MASK (((1U << SARADC_IF_CHx_EOC_WIDTH) - 1U) << SARADC_IF_CHx_EOC_SHIFT)
|
||||
#define SARADC_IF_FIFO_FULL_SHIFT 16
|
||||
#define SARADC_IF_FIFO_FULL_WIDTH 1
|
||||
#define SARADC_IF_FIFO_FULL_MASK (((1U << SARADC_IF_FIFO_FULL_WIDTH) - 1U) << SARADC_IF_FIFO_FULL_SHIFT)
|
||||
#define SARADC_IF_FIFO_FULL_VALUE_NOT_SET 0U
|
||||
#define SARADC_IF_FIFO_FULL_BITS_NOT_SET (SARADC_IF_FIFO_FULL_VALUE_NOT_SET << SARADC_IF_FIFO_FULL_SHIFT)
|
||||
#define SARADC_IF_FIFO_FULL_VALUE_SET 1U
|
||||
#define SARADC_IF_FIFO_FULL_BITS_SET (SARADC_IF_FIFO_FULL_VALUE_SET << SARADC_IF_FIFO_FULL_SHIFT)
|
||||
|
||||
#define SARADC_IF_FIFO_HFULL_SHIFT 17
|
||||
#define SARADC_IF_FIFO_HFULL_WIDTH 1
|
||||
#define SARADC_IF_FIFO_HFULL_MASK (((1U << SARADC_IF_FIFO_HFULL_WIDTH) - 1U) << SARADC_IF_FIFO_HFULL_SHIFT)
|
||||
#define SARADC_IF_FIFO_HFULL_VALUE_NOT_SET 0U
|
||||
#define SARADC_IF_FIFO_HFULL_BITS_NOT_SET (SARADC_IF_FIFO_HFULL_VALUE_NOT_SET << SARADC_IF_FIFO_HFULL_SHIFT)
|
||||
#define SARADC_IF_FIFO_HFULL_VALUE_SET 1U
|
||||
#define SARADC_IF_FIFO_HFULL_BITS_SET (SARADC_IF_FIFO_HFULL_VALUE_SET << SARADC_IF_FIFO_HFULL_SHIFT)
|
||||
|
||||
#define SARADC_CH0_ADDR (SARADC_BASE_ADDR + 0x0010U)
|
||||
#define SARADC_CH0 (*(volatile uint32_t *)SARADC_CH0_ADDR)
|
||||
#define SARADC_EXTTRIG_SEL_ADDR (SARADC_BASE_ADDR + 0x00B0U)
|
||||
#define SARADC_EXTTRIG_SEL (*(volatile uint32_t *)SARADC_EXTTRIG_SEL_ADDR)
|
||||
|
||||
#define SARADC_CALIB_OFFSET_ADDR (SARADC_BASE_ADDR + 0x00F0U)
|
||||
#define SARADC_CALIB_OFFSET (*(volatile uint32_t *)SARADC_CALIB_OFFSET_ADDR)
|
||||
#define SARADC_CALIB_OFFSET_OFFSET_SHIFT 0
|
||||
#define SARADC_CALIB_OFFSET_OFFSET_WIDTH 8
|
||||
#define SARADC_CALIB_OFFSET_OFFSET_MASK (((1U << SARADC_CALIB_OFFSET_OFFSET_WIDTH) - 1U) << SARADC_CALIB_OFFSET_OFFSET_SHIFT)
|
||||
#define SARADC_CALIB_OFFSET_VALID_SHIFT 16
|
||||
#define SARADC_CALIB_OFFSET_VALID_WIDTH 1
|
||||
#define SARADC_CALIB_OFFSET_VALID_MASK (((1U << SARADC_CALIB_OFFSET_VALID_WIDTH) - 1U) << SARADC_CALIB_OFFSET_VALID_SHIFT)
|
||||
#define SARADC_CALIB_OFFSET_VALID_VALUE_NO 0U
|
||||
#define SARADC_CALIB_OFFSET_VALID_BITS_NO (SARADC_CALIB_OFFSET_VALID_VALUE_NO << SARADC_CALIB_OFFSET_VALID_SHIFT)
|
||||
#define SARADC_CALIB_OFFSET_VALID_VALUE_YES 1U
|
||||
#define SARADC_CALIB_OFFSET_VALID_BITS_YES (SARADC_CALIB_OFFSET_VALID_VALUE_YES << SARADC_CALIB_OFFSET_VALID_SHIFT)
|
||||
|
||||
#define SARADC_CALIB_KD_ADDR (SARADC_BASE_ADDR + 0x00F4U)
|
||||
#define SARADC_CALIB_KD (*(volatile uint32_t *)SARADC_CALIB_KD_ADDR)
|
||||
#define SARADC_CALIB_KD_KD_SHIFT 0
|
||||
#define SARADC_CALIB_KD_KD_WIDTH 8
|
||||
#define SARADC_CALIB_KD_KD_MASK (((1U << SARADC_CALIB_KD_KD_WIDTH) - 1U) << SARADC_CALIB_KD_KD_SHIFT)
|
||||
#define SARADC_CALIB_KD_VALID_SHIFT 16
|
||||
#define SARADC_CALIB_KD_VALID_WIDTH 1
|
||||
#define SARADC_CALIB_KD_VALID_MASK (((1U << SARADC_CALIB_KD_VALID_WIDTH) - 1U) << SARADC_CALIB_KD_VALID_SHIFT)
|
||||
#define SARADC_CALIB_KD_VALID_VALUE_NO 0U
|
||||
#define SARADC_CALIB_KD_VALID_BITS_NO (SARADC_CALIB_KD_VALID_VALUE_NO << SARADC_CALIB_KD_VALID_SHIFT)
|
||||
#define SARADC_CALIB_KD_VALID_VALUE_YES 1U
|
||||
#define SARADC_CALIB_KD_VALID_BITS_YES (SARADC_CALIB_KD_VALID_VALUE_YES << SARADC_CALIB_KD_VALID_SHIFT)
|
||||
|
||||
/* -------- ADC_CHx -------- */
|
||||
|
||||
typedef struct {
|
||||
uint32_t STAT;
|
||||
uint32_t DATA;
|
||||
} ADC_Channel_t;
|
||||
|
||||
#define ADC_CHx_STAT_EOC_SHIFT 0
|
||||
#define ADC_CHx_STAT_EOC_WIDTH 1
|
||||
#define ADC_CHx_STAT_EOC_MASK (((1U << ADC_CHx_STAT_EOC_WIDTH) - 1U) << ADC_CHx_STAT_EOC_SHIFT)
|
||||
#define ADC_CHx_STAT_EOC_VALUE_NOT_COMPLETE 0U
|
||||
#define ADC_CHx_STAT_EOC_BITS_NOT_COMPLETE (ADC_CHx_STAT_EOC_VALUE_NOT_COMPLETE << ADC_CHx_STAT_EOC_SHIFT)
|
||||
#define ADC_CHx_STAT_EOC_VALUE_COMPLETE 1U
|
||||
#define ADC_CHx_STAT_EOC_BITS_COMPLETE (ADC_CHx_STAT_EOC_VALUE_COMPLETE << ADC_CHx_STAT_EOC_SHIFT)
|
||||
|
||||
#define ADC_CHx_DATA_DATA_SHIFT 0
|
||||
#define ADC_CHx_DATA_DATA_WIDTH 12
|
||||
#define ADC_CHx_DATA_DATA_MASK (((1U << ADC_CHx_DATA_DATA_WIDTH) - 1U) << ADC_CHx_DATA_DATA_SHIFT)
|
||||
#define ADC_CHx_DATA_NUM_SHIFT 12
|
||||
#define ADC_CHx_DATA_NUM_WIDTH 4
|
||||
#define ADC_CHx_DATA_NUM_MASK (((1U << ADC_CHx_DATA_NUM_WIDTH) - 1U) << ADC_CHx_DATA_NUM_SHIFT)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
240
bsp/dp32g030/spi.h
Normal file
240
bsp/dp32g030/spi.h
Normal file
@@ -0,0 +1,240 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HARDWARE_DP32G030_SPI_H
|
||||
#define HARDWARE_DP32G030_SPI_H
|
||||
|
||||
#if !defined(__ASSEMBLY__)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* -------- SPI0 -------- */
|
||||
#define SPI0_BASE_ADDR 0x400B8000U
|
||||
#define SPI0_BASE_SIZE 0x00000800U
|
||||
#define SPI0 ((volatile SPI_Port_t *)SPI0_BASE_ADDR)
|
||||
|
||||
/* -------- SPI1 -------- */
|
||||
#define SPI1_BASE_ADDR 0x400B8800U
|
||||
#define SPI1_BASE_SIZE 0x00000800U
|
||||
#define SPI1 ((volatile SPI_Port_t *)SPI1_BASE_ADDR)
|
||||
|
||||
/* -------- SPI -------- */
|
||||
|
||||
typedef struct {
|
||||
uint32_t CR;
|
||||
uint32_t WDR;
|
||||
uint32_t RDR;
|
||||
uint32_t Reserved_000C[1];
|
||||
uint32_t IE;
|
||||
uint32_t IF;
|
||||
uint32_t FIFOST;
|
||||
} SPI_Port_t;
|
||||
|
||||
#define SPI_CR_SPR_SHIFT 0
|
||||
#define SPI_CR_SPR_WIDTH 3
|
||||
#define SPI_CR_SPR_MASK (((1U << SPI_CR_SPR_WIDTH) - 1U) << SPI_CR_SPR_SHIFT)
|
||||
#define SPI_CR_SPR_VALUE_FPCLK_DIV_4 0U
|
||||
#define SPI_CR_SPR_BITS_FPCLK_DIV_4 (SPI_CR_SPR_VALUE_FPCLK_DIV_4 << SPI_CR_SPR_SHIFT)
|
||||
#define SPI_CR_SPR_VALUE_FPCLK_DIV_8 1U
|
||||
#define SPI_CR_SPR_BITS_FPCLK_DIV_8 (SPI_CR_SPR_VALUE_FPCLK_DIV_8 << SPI_CR_SPR_SHIFT)
|
||||
#define SPI_CR_SPR_VALUE_FPCLK_DIV_16 2U
|
||||
#define SPI_CR_SPR_BITS_FPCLK_DIV_16 (SPI_CR_SPR_VALUE_FPCLK_DIV_16 << SPI_CR_SPR_SHIFT)
|
||||
#define SPI_CR_SPR_VALUE_FPCLK_DIV_32 3U
|
||||
#define SPI_CR_SPR_BITS_FPCLK_DIV_32 (SPI_CR_SPR_VALUE_FPCLK_DIV_32 << SPI_CR_SPR_SHIFT)
|
||||
#define SPI_CR_SPR_VALUE_FPCLK_DIV_64 4U
|
||||
#define SPI_CR_SPR_BITS_FPCLK_DIV_64 (SPI_CR_SPR_VALUE_FPCLK_DIV_64 << SPI_CR_SPR_SHIFT)
|
||||
#define SPI_CR_SPR_VALUE_FPCLK_DIV_128 5U
|
||||
#define SPI_CR_SPR_BITS_FPCLK_DIV_128 (SPI_CR_SPR_VALUE_FPCLK_DIV_128 << SPI_CR_SPR_SHIFT)
|
||||
#define SPI_CR_SPR_VALUE_FPCLK_DIV_256 6U
|
||||
#define SPI_CR_SPR_BITS_FPCLK_DIV_256 (SPI_CR_SPR_VALUE_FPCLK_DIV_256 << SPI_CR_SPR_SHIFT)
|
||||
#define SPI_CR_SPR_VALUE_FPCLK_DIV_512 7U
|
||||
#define SPI_CR_SPR_BITS_FPCLK_DIV_512 (SPI_CR_SPR_VALUE_FPCLK_DIV_512 << SPI_CR_SPR_SHIFT)
|
||||
|
||||
#define SPI_CR_SPE_SHIFT 3
|
||||
#define SPI_CR_SPE_WIDTH 1
|
||||
#define SPI_CR_SPE_MASK (((1U << SPI_CR_SPE_WIDTH) - 1U) << SPI_CR_SPE_SHIFT)
|
||||
#define SPI_CR_SPE_VALUE_DISABLE 0U
|
||||
#define SPI_CR_SPE_BITS_DISABLE (SPI_CR_SPE_VALUE_DISABLE << SPI_CR_SPE_SHIFT)
|
||||
#define SPI_CR_SPE_VALUE_ENABLE 1U
|
||||
#define SPI_CR_SPE_BITS_ENABLE (SPI_CR_SPE_VALUE_ENABLE << SPI_CR_SPE_SHIFT)
|
||||
|
||||
#define SPI_CR_CPHA_SHIFT 4
|
||||
#define SPI_CR_CPHA_WIDTH 1
|
||||
#define SPI_CR_CPHA_MASK (((1U << SPI_CR_CPHA_WIDTH) - 1U) << SPI_CR_CPHA_SHIFT)
|
||||
#define SPI_CR_CPOL_SHIFT 5
|
||||
#define SPI_CR_CPOL_WIDTH 1
|
||||
#define SPI_CR_CPOL_MASK (((1U << SPI_CR_CPOL_WIDTH) - 1U) << SPI_CR_CPOL_SHIFT)
|
||||
#define SPI_CR_MSTR_SHIFT 6
|
||||
#define SPI_CR_MSTR_WIDTH 1
|
||||
#define SPI_CR_MSTR_MASK (((1U << SPI_CR_MSTR_WIDTH) - 1U) << SPI_CR_MSTR_SHIFT)
|
||||
#define SPI_CR_LSB_SHIFT 7
|
||||
#define SPI_CR_LSB_WIDTH 1
|
||||
#define SPI_CR_LSB_MASK (((1U << SPI_CR_LSB_WIDTH) - 1U) << SPI_CR_LSB_SHIFT)
|
||||
#define SPI_CR_CPHA_DATA_HOLD_S_SHIFT 8
|
||||
#define SPI_CR_CPHA_DATA_HOLD_S_WIDTH 4
|
||||
#define SPI_CR_CPHA_DATA_HOLD_S_MASK (((1U << SPI_CR_CPHA_DATA_HOLD_S_WIDTH) - 1U) << SPI_CR_CPHA_DATA_HOLD_S_SHIFT)
|
||||
#define SPI_CR_MSR_SSN_SHIFT 12
|
||||
#define SPI_CR_MSR_SSN_WIDTH 1
|
||||
#define SPI_CR_MSR_SSN_MASK (((1U << SPI_CR_MSR_SSN_WIDTH) - 1U) << SPI_CR_MSR_SSN_SHIFT)
|
||||
#define SPI_CR_MSR_SSN_VALUE_DISABLE 0U
|
||||
#define SPI_CR_MSR_SSN_BITS_DISABLE (SPI_CR_MSR_SSN_VALUE_DISABLE << SPI_CR_MSR_SSN_SHIFT)
|
||||
#define SPI_CR_MSR_SSN_VALUE_ENABLE 1U
|
||||
#define SPI_CR_MSR_SSN_BITS_ENABLE (SPI_CR_MSR_SSN_VALUE_ENABLE << SPI_CR_MSR_SSN_SHIFT)
|
||||
|
||||
#define SPI_CR_RXDMAEN_SHIFT 13
|
||||
#define SPI_CR_RXDMAEN_WIDTH 1
|
||||
#define SPI_CR_RXDMAEN_MASK (((1U << SPI_CR_RXDMAEN_WIDTH) - 1U) << SPI_CR_RXDMAEN_SHIFT)
|
||||
#define SPI_CR_TXDMAEN_SHIFT 14
|
||||
#define SPI_CR_TXDMAEN_WIDTH 1
|
||||
#define SPI_CR_TXDMAEN_MASK (((1U << SPI_CR_TXDMAEN_WIDTH) - 1U) << SPI_CR_TXDMAEN_SHIFT)
|
||||
#define SPI_CR_RF_CLR_SHIFT 15
|
||||
#define SPI_CR_RF_CLR_WIDTH 1
|
||||
#define SPI_CR_RF_CLR_MASK (((1U << SPI_CR_RF_CLR_WIDTH) - 1U) << SPI_CR_RF_CLR_SHIFT)
|
||||
#define SPI_CR_TF_CLR_SHIFT 16
|
||||
#define SPI_CR_TF_CLR_WIDTH 1
|
||||
#define SPI_CR_TF_CLR_MASK (((1U << SPI_CR_TF_CLR_WIDTH) - 1U) << SPI_CR_TF_CLR_SHIFT)
|
||||
|
||||
#define SPI_IE_RXFIFO_OVF_SHIFT 0
|
||||
#define SPI_IE_RXFIFO_OVF_WIDTH 1
|
||||
#define SPI_IE_RXFIFO_OVF_MASK (((1U << SPI_IE_RXFIFO_OVF_WIDTH) - 1U) << SPI_IE_RXFIFO_OVF_SHIFT)
|
||||
#define SPI_IE_RXFIFO_OVF_VALUE_DISABLE 0U
|
||||
#define SPI_IE_RXFIFO_OVF_BITS_DISABLE (SPI_IE_RXFIFO_OVF_VALUE_DISABLE << SPI_IE_RXFIFO_OVF_SHIFT)
|
||||
#define SPI_IE_RXFIFO_OVF_VALUE_ENABLE 1U
|
||||
#define SPI_IE_RXFIFO_OVF_BITS_ENABLE (SPI_IE_RXFIFO_OVF_VALUE_ENABLE << SPI_IE_RXFIFO_OVF_SHIFT)
|
||||
|
||||
#define SPI_IE_RXFIFO_FULL_SHIFT 1
|
||||
#define SPI_IE_RXFIFO_FULL_WIDTH 1
|
||||
#define SPI_IE_RXFIFO_FULL_MASK (((1U << SPI_IE_RXFIFO_FULL_WIDTH) - 1U) << SPI_IE_RXFIFO_FULL_SHIFT)
|
||||
#define SPI_IE_RXFIFO_FULL_VALUE_DISABLE 0U
|
||||
#define SPI_IE_RXFIFO_FULL_BITS_DISABLE (SPI_IE_RXFIFO_FULL_VALUE_DISABLE << SPI_IE_RXFIFO_FULL_SHIFT)
|
||||
#define SPI_IE_RXFIFO_FULL_VALUE_ENABLE 1U
|
||||
#define SPI_IE_RXFIFO_FULL_BITS_ENABLE (SPI_IE_RXFIFO_FULL_VALUE_ENABLE << SPI_IE_RXFIFO_FULL_SHIFT)
|
||||
|
||||
#define SPI_IE_RXFIFO_HFULL_SHIFT 2
|
||||
#define SPI_IE_RXFIFO_HFULL_WIDTH 1
|
||||
#define SPI_IE_RXFIFO_HFULL_MASK (((1U << SPI_IE_RXFIFO_HFULL_WIDTH) - 1U) << SPI_IE_RXFIFO_HFULL_SHIFT)
|
||||
#define SPI_IE_RXFIFO_HFULL_VALUE_DISABLE 0U
|
||||
#define SPI_IE_RXFIFO_HFULL_BITS_DISABLE (SPI_IE_RXFIFO_HFULL_VALUE_DISABLE << SPI_IE_RXFIFO_HFULL_SHIFT)
|
||||
#define SPI_IE_RXFIFO_HFULL_VALUE_ENABLE 1U
|
||||
#define SPI_IE_RXFIFO_HFULL_BITS_ENABLE (SPI_IE_RXFIFO_HFULL_VALUE_ENABLE << SPI_IE_RXFIFO_HFULL_SHIFT)
|
||||
|
||||
#define SPI_IE_TXFIFO_EMPTY_SHIFT 3
|
||||
#define SPI_IE_TXFIFO_EMPTY_WIDTH 1
|
||||
#define SPI_IE_TXFIFO_EMPTY_MASK (((1U << SPI_IE_TXFIFO_EMPTY_WIDTH) - 1U) << SPI_IE_TXFIFO_EMPTY_SHIFT)
|
||||
#define SPI_IE_TXFIFO_EMPTY_VALUE_DISABLE 0U
|
||||
#define SPI_IE_TXFIFO_EMPTY_BITS_DISABLE (SPI_IE_TXFIFO_EMPTY_VALUE_DISABLE << SPI_IE_TXFIFO_EMPTY_SHIFT)
|
||||
#define SPI_IE_TXFIFO_EMPTY_VALUE_ENABLE 1U
|
||||
#define SPI_IE_TXFIFO_EMPTY_BITS_ENABLE (SPI_IE_TXFIFO_EMPTY_VALUE_ENABLE << SPI_IE_TXFIFO_EMPTY_SHIFT)
|
||||
|
||||
#define SPI_IE_TXFIFO_HFULL_SHIFT 4
|
||||
#define SPI_IE_TXFIFO_HFULL_WIDTH 1
|
||||
#define SPI_IE_TXFIFO_HFULL_MASK (((1U << SPI_IE_TXFIFO_HFULL_WIDTH) - 1U) << SPI_IE_TXFIFO_HFULL_SHIFT)
|
||||
#define SPI_IE_TXFIFO_HFULL_VALUE_DISABLE 0U
|
||||
#define SPI_IE_TXFIFO_HFULL_BITS_DISABLE (SPI_IE_TXFIFO_HFULL_VALUE_DISABLE << SPI_IE_TXFIFO_HFULL_SHIFT)
|
||||
#define SPI_IE_TXFIFO_HFULL_VALUE_ENABLE 1U
|
||||
#define SPI_IE_TXFIFO_HFULL_BITS_ENABLE (SPI_IE_TXFIFO_HFULL_VALUE_ENABLE << SPI_IE_TXFIFO_HFULL_SHIFT)
|
||||
|
||||
#define SPI_FIFOST_RFE_SHIFT 0
|
||||
#define SPI_FIFOST_RFE_WIDTH 1
|
||||
#define SPI_FIFOST_RFE_MASK (((1U << SPI_FIFOST_RFE_WIDTH) - 1U) << SPI_FIFOST_RFE_SHIFT)
|
||||
#define SPI_FIFOST_RFE_VALUE_NOT_EMPTY 0U
|
||||
#define SPI_FIFOST_RFE_BITS_NOT_EMPTY (SPI_FIFOST_RFE_VALUE_NOT_EMPTY << SPI_FIFOST_RFE_SHIFT)
|
||||
#define SPI_FIFOST_RFE_VALUE_EMPTY 1U
|
||||
#define SPI_FIFOST_RFE_BITS_EMPTY (SPI_FIFOST_RFE_VALUE_EMPTY << SPI_FIFOST_RFE_SHIFT)
|
||||
|
||||
#define SPI_FIFOST_RFF_SHIFT 1
|
||||
#define SPI_FIFOST_RFF_WIDTH 1
|
||||
#define SPI_FIFOST_RFF_MASK (((1U << SPI_FIFOST_RFF_WIDTH) - 1U) << SPI_FIFOST_RFF_SHIFT)
|
||||
#define SPI_FIFOST_RFF_VALUE_NOT_FULL 0U
|
||||
#define SPI_FIFOST_RFF_BITS_NOT_FULL (SPI_FIFOST_RFF_VALUE_NOT_FULL << SPI_FIFOST_RFF_SHIFT)
|
||||
#define SPI_FIFOST_RFF_VALUE_FULL 1U
|
||||
#define SPI_FIFOST_RFF_BITS_FULL (SPI_FIFOST_RFF_VALUE_FULL << SPI_FIFOST_RFF_SHIFT)
|
||||
|
||||
#define SPI_FIFOST_RFHF_SHIFT 2
|
||||
#define SPI_FIFOST_RFHF_WIDTH 1
|
||||
#define SPI_FIFOST_RFHF_MASK (((1U << SPI_FIFOST_RFHF_WIDTH) - 1U) << SPI_FIFOST_RFHF_SHIFT)
|
||||
#define SPI_FIFOST_RFHF_VALUE_NOT_HALF_FULL 0U
|
||||
#define SPI_FIFOST_RFHF_BITS_NOT_HALF_FULL (SPI_FIFOST_RFHF_VALUE_NOT_HALF_FULL << SPI_FIFOST_RFHF_SHIFT)
|
||||
#define SPI_FIFOST_RFHF_VALUE_HALF_FULL 1U
|
||||
#define SPI_FIFOST_RFHF_BITS_HALF_FULL (SPI_FIFOST_RFHF_VALUE_HALF_FULL << SPI_FIFOST_RFHF_SHIFT)
|
||||
|
||||
#define SPI_FIFOST_TFE_SHIFT 3
|
||||
#define SPI_FIFOST_TFE_WIDTH 1
|
||||
#define SPI_FIFOST_TFE_MASK (((1U << SPI_FIFOST_TFE_WIDTH) - 1U) << SPI_FIFOST_TFE_SHIFT)
|
||||
#define SPI_FIFOST_TFE_VALUE_NOT_EMPTY 0U
|
||||
#define SPI_FIFOST_TFE_BITS_NOT_EMPTY (SPI_FIFOST_TFE_VALUE_NOT_EMPTY << SPI_FIFOST_TFE_SHIFT)
|
||||
#define SPI_FIFOST_TFE_VALUE_EMPTY 1U
|
||||
#define SPI_FIFOST_TFE_BITS_EMPTY (SPI_FIFOST_TFE_VALUE_EMPTY << SPI_FIFOST_TFE_SHIFT)
|
||||
|
||||
#define SPI_FIFOST_TFF_SHIFT 4
|
||||
#define SPI_FIFOST_TFF_WIDTH 1
|
||||
#define SPI_FIFOST_TFF_MASK (((1U << SPI_FIFOST_TFF_WIDTH) - 1U) << SPI_FIFOST_TFF_SHIFT)
|
||||
#define SPI_FIFOST_TFF_VALUE_NOT_FULL 0U
|
||||
#define SPI_FIFOST_TFF_BITS_NOT_FULL (SPI_FIFOST_TFF_VALUE_NOT_FULL << SPI_FIFOST_TFF_SHIFT)
|
||||
#define SPI_FIFOST_TFF_VALUE_FULL 1U
|
||||
#define SPI_FIFOST_TFF_BITS_FULL (SPI_FIFOST_TFF_VALUE_FULL << SPI_FIFOST_TFF_SHIFT)
|
||||
|
||||
#define SPI_FIFOST_TFHF_SHIFT 5
|
||||
#define SPI_FIFOST_TFHF_WIDTH 1
|
||||
#define SPI_FIFOST_TFHF_MASK (((1U << SPI_FIFOST_TFHF_WIDTH) - 1U) << SPI_FIFOST_TFHF_SHIFT)
|
||||
#define SPI_FIFOST_TFHF_VALUE_NOT_HALF_FULL 0U
|
||||
#define SPI_FIFOST_TFHF_BITS_NOT_HALF_FULL (SPI_FIFOST_TFHF_VALUE_NOT_HALF_FULL << SPI_FIFOST_TFHF_SHIFT)
|
||||
#define SPI_FIFOST_TFHF_VALUE_HALF_FULL 1U
|
||||
#define SPI_FIFOST_TFHF_BITS_HALF_FULL (SPI_FIFOST_TFHF_VALUE_HALF_FULL << SPI_FIFOST_TFHF_SHIFT)
|
||||
|
||||
#define SPI_FIFOST_RF_LEVEL_SHIFT 6
|
||||
#define SPI_FIFOST_RF_LEVEL_WIDTH 3
|
||||
#define SPI_FIFOST_RF_LEVEL_MASK (((1U << SPI_FIFOST_RF_LEVEL_WIDTH) - 1U) << SPI_FIFOST_RF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_RF_LEVEL_VALUE_0_BYTE 0U
|
||||
#define SPI_FIFOST_RF_LEVEL_BITS_0_BYTE (SPI_FIFOST_RF_LEVEL_VALUE_0_BYTE << SPI_FIFOST_RF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_RF_LEVEL_VALUE_1_BYTE 1U
|
||||
#define SPI_FIFOST_RF_LEVEL_BITS_1_BYTE (SPI_FIFOST_RF_LEVEL_VALUE_1_BYTE << SPI_FIFOST_RF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_RF_LEVEL_VALUE_2_BYTE 2U
|
||||
#define SPI_FIFOST_RF_LEVEL_BITS_2_BYTE (SPI_FIFOST_RF_LEVEL_VALUE_2_BYTE << SPI_FIFOST_RF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_RF_LEVEL_VALUE_3_BYTE 3U
|
||||
#define SPI_FIFOST_RF_LEVEL_BITS_3_BYTE (SPI_FIFOST_RF_LEVEL_VALUE_3_BYTE << SPI_FIFOST_RF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_RF_LEVEL_VALUE_4_BYTE 4U
|
||||
#define SPI_FIFOST_RF_LEVEL_BITS_4_BYTE (SPI_FIFOST_RF_LEVEL_VALUE_4_BYTE << SPI_FIFOST_RF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_RF_LEVEL_VALUE_5_BYTE 5U
|
||||
#define SPI_FIFOST_RF_LEVEL_BITS_5_BYTE (SPI_FIFOST_RF_LEVEL_VALUE_5_BYTE << SPI_FIFOST_RF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_RF_LEVEL_VALUE_6_BYTE 6U
|
||||
#define SPI_FIFOST_RF_LEVEL_BITS_6_BYTE (SPI_FIFOST_RF_LEVEL_VALUE_6_BYTE << SPI_FIFOST_RF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_RF_LEVEL_VALUE_7_BYTE 7U
|
||||
#define SPI_FIFOST_RF_LEVEL_BITS_7_BYTE (SPI_FIFOST_RF_LEVEL_VALUE_7_BYTE << SPI_FIFOST_RF_LEVEL_SHIFT)
|
||||
|
||||
#define SPI_FIFOST_TF_LEVEL_SHIFT 9
|
||||
#define SPI_FIFOST_TF_LEVEL_WIDTH 3
|
||||
#define SPI_FIFOST_TF_LEVEL_MASK (((1U << SPI_FIFOST_TF_LEVEL_WIDTH) - 1U) << SPI_FIFOST_TF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_TF_LEVEL_VALUE_0_BYTE 0U
|
||||
#define SPI_FIFOST_TF_LEVEL_BITS_0_BYTE (SPI_FIFOST_TF_LEVEL_VALUE_0_BYTE << SPI_FIFOST_TF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_TF_LEVEL_VALUE_1_BYTE 1U
|
||||
#define SPI_FIFOST_TF_LEVEL_BITS_1_BYTE (SPI_FIFOST_TF_LEVEL_VALUE_1_BYTE << SPI_FIFOST_TF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_TF_LEVEL_VALUE_2_BYTE 2U
|
||||
#define SPI_FIFOST_TF_LEVEL_BITS_2_BYTE (SPI_FIFOST_TF_LEVEL_VALUE_2_BYTE << SPI_FIFOST_TF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_TF_LEVEL_VALUE_3_BYTE 3U
|
||||
#define SPI_FIFOST_TF_LEVEL_BITS_3_BYTE (SPI_FIFOST_TF_LEVEL_VALUE_3_BYTE << SPI_FIFOST_TF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_TF_LEVEL_VALUE_4_BYTE 4U
|
||||
#define SPI_FIFOST_TF_LEVEL_BITS_4_BYTE (SPI_FIFOST_TF_LEVEL_VALUE_4_BYTE << SPI_FIFOST_TF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_TF_LEVEL_VALUE_5_BYTE 5U
|
||||
#define SPI_FIFOST_TF_LEVEL_BITS_5_BYTE (SPI_FIFOST_TF_LEVEL_VALUE_5_BYTE << SPI_FIFOST_TF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_TF_LEVEL_VALUE_6_BYTE 6U
|
||||
#define SPI_FIFOST_TF_LEVEL_BITS_6_BYTE (SPI_FIFOST_TF_LEVEL_VALUE_6_BYTE << SPI_FIFOST_TF_LEVEL_SHIFT)
|
||||
#define SPI_FIFOST_TF_LEVEL_VALUE_7_BYTE 7U
|
||||
#define SPI_FIFOST_TF_LEVEL_BITS_7_BYTE (SPI_FIFOST_TF_LEVEL_VALUE_7_BYTE << SPI_FIFOST_TF_LEVEL_SHIFT)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
348
bsp/dp32g030/syscon.h
Normal file
348
bsp/dp32g030/syscon.h
Normal file
@@ -0,0 +1,348 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HARDWARE_DP32G030_SYSCON_H
|
||||
#define HARDWARE_DP32G030_SYSCON_H
|
||||
|
||||
#if !defined(__ASSEMBLY__)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* -------- SYSCON -------- */
|
||||
#define SYSCON_BASE_ADDR 0x40000000U
|
||||
#define SYSCON_BASE_SIZE 0x00000800U
|
||||
|
||||
#define SYSCON_CLK_SEL_ADDR (SYSCON_BASE_ADDR + 0x0000U)
|
||||
#define SYSCON_CLK_SEL (*(volatile uint32_t *)SYSCON_CLK_SEL_ADDR)
|
||||
#define SYSCON_CLK_SEL_SYS_SHIFT 0
|
||||
#define SYSCON_CLK_SEL_SYS_WIDTH 1
|
||||
#define SYSCON_CLK_SEL_SYS_MASK (((1U << SYSCON_CLK_SEL_SYS_WIDTH) - 1U) << SYSCON_CLK_SEL_SYS_SHIFT)
|
||||
#define SYSCON_CLK_SEL_SYS_VALUE_RCHF 0U
|
||||
#define SYSCON_CLK_SEL_SYS_BITS_RCHF (SYSCON_CLK_SEL_SYS_VALUE_RCHF << SYSCON_CLK_SEL_SYS_SHIFT)
|
||||
#define SYSCON_CLK_SEL_SYS_VALUE_DIV_CLK 1U
|
||||
#define SYSCON_CLK_SEL_SYS_BITS_DIV_CLK (SYSCON_CLK_SEL_SYS_VALUE_DIV_CLK << SYSCON_CLK_SEL_SYS_SHIFT)
|
||||
|
||||
#define SYSCON_CLK_SEL_DIV_SHIFT 1
|
||||
#define SYSCON_CLK_SEL_DIV_WIDTH 3
|
||||
#define SYSCON_CLK_SEL_DIV_MASK (((1U << SYSCON_CLK_SEL_DIV_WIDTH) - 1U) << SYSCON_CLK_SEL_DIV_SHIFT)
|
||||
#define SYSCON_CLK_SEL_DIV_VALUE_1 0U
|
||||
#define SYSCON_CLK_SEL_DIV_BITS_1 (SYSCON_CLK_SEL_DIV_VALUE_1 << SYSCON_CLK_SEL_DIV_SHIFT)
|
||||
#define SYSCON_CLK_SEL_DIV_VALUE_2 1U
|
||||
#define SYSCON_CLK_SEL_DIV_BITS_2 (SYSCON_CLK_SEL_DIV_VALUE_2 << SYSCON_CLK_SEL_DIV_SHIFT)
|
||||
#define SYSCON_CLK_SEL_DIV_VALUE_4 2U
|
||||
#define SYSCON_CLK_SEL_DIV_BITS_4 (SYSCON_CLK_SEL_DIV_VALUE_4 << SYSCON_CLK_SEL_DIV_SHIFT)
|
||||
#define SYSCON_CLK_SEL_DIV_VALUE_8 3U
|
||||
#define SYSCON_CLK_SEL_DIV_BITS_8 (SYSCON_CLK_SEL_DIV_VALUE_8 << SYSCON_CLK_SEL_DIV_SHIFT)
|
||||
#define SYSCON_CLK_SEL_DIV_VALUE_16 4U
|
||||
#define SYSCON_CLK_SEL_DIV_BITS_16 (SYSCON_CLK_SEL_DIV_VALUE_16 << SYSCON_CLK_SEL_DIV_SHIFT)
|
||||
#define SYSCON_CLK_SEL_DIV_VALUE_32 5U
|
||||
#define SYSCON_CLK_SEL_DIV_BITS_32 (SYSCON_CLK_SEL_DIV_VALUE_32 << SYSCON_CLK_SEL_DIV_SHIFT)
|
||||
|
||||
#define SYSCON_CLK_SEL_SRC_SHIFT 4
|
||||
#define SYSCON_CLK_SEL_SRC_WIDTH 3
|
||||
#define SYSCON_CLK_SEL_SRC_MASK (((1U << SYSCON_CLK_SEL_SRC_WIDTH) - 1U) << SYSCON_CLK_SEL_SRC_SHIFT)
|
||||
#define SYSCON_CLK_SEL_SRC_VALUE_RCHF 0U
|
||||
#define SYSCON_CLK_SEL_SRC_BITS_RCHF (SYSCON_CLK_SEL_SRC_VALUE_RCHF << SYSCON_CLK_SEL_SRC_SHIFT)
|
||||
#define SYSCON_CLK_SEL_SRC_VALUE_RCLF 1U
|
||||
#define SYSCON_CLK_SEL_SRC_BITS_RCLF (SYSCON_CLK_SEL_SRC_VALUE_RCLF << SYSCON_CLK_SEL_SRC_SHIFT)
|
||||
#define SYSCON_CLK_SEL_SRC_VALUE_XTAH 2U
|
||||
#define SYSCON_CLK_SEL_SRC_BITS_XTAH (SYSCON_CLK_SEL_SRC_VALUE_XTAH << SYSCON_CLK_SEL_SRC_SHIFT)
|
||||
#define SYSCON_CLK_SEL_SRC_VALUE_XTAL 3U
|
||||
#define SYSCON_CLK_SEL_SRC_BITS_XTAL (SYSCON_CLK_SEL_SRC_VALUE_XTAL << SYSCON_CLK_SEL_SRC_SHIFT)
|
||||
#define SYSCON_CLK_SEL_SRC_VALUE_PLL 4U
|
||||
#define SYSCON_CLK_SEL_SRC_BITS_PLL (SYSCON_CLK_SEL_SRC_VALUE_PLL << SYSCON_CLK_SEL_SRC_SHIFT)
|
||||
|
||||
#define SYSCON_CLK_SEL_W_PLL_SHIFT 7
|
||||
#define SYSCON_CLK_SEL_W_PLL_WIDTH 1
|
||||
#define SYSCON_CLK_SEL_W_PLL_MASK (((1U << SYSCON_CLK_SEL_W_PLL_WIDTH) - 1U) << SYSCON_CLK_SEL_W_PLL_SHIFT)
|
||||
#define SYSCON_CLK_SEL_W_PLL_VALUE_RCHF 0U
|
||||
#define SYSCON_CLK_SEL_W_PLL_BITS_RCHF (SYSCON_CLK_SEL_W_PLL_VALUE_RCHF << SYSCON_CLK_SEL_W_PLL_SHIFT)
|
||||
#define SYSCON_CLK_SEL_W_PLL_VALUE_XTAH 1U
|
||||
#define SYSCON_CLK_SEL_W_PLL_BITS_XTAH (SYSCON_CLK_SEL_W_PLL_VALUE_XTAH << SYSCON_CLK_SEL_W_PLL_SHIFT)
|
||||
|
||||
#define SYSCON_CLK_SEL_R_SARADC_SMPL_SHIFT 9
|
||||
#define SYSCON_CLK_SEL_R_SARADC_SMPL_WIDTH 2
|
||||
#define SYSCON_CLK_SEL_R_SARADC_SMPL_MASK (((1U << SYSCON_CLK_SEL_R_SARADC_SMPL_WIDTH) - 1U) << SYSCON_CLK_SEL_R_SARADC_SMPL_SHIFT)
|
||||
#define SYSCON_CLK_SEL_R_SARADC_SMPL_VALUE_DIV1 0U
|
||||
#define SYSCON_CLK_SEL_R_SARADC_SMPL_BITS_DIV1 (SYSCON_CLK_SEL_R_SARADC_SMPL_VALUE_DIV1 << SYSCON_CLK_SEL_R_SARADC_SMPL_SHIFT)
|
||||
#define SYSCON_CLK_SEL_R_SARADC_SMPL_VALUE_DIV2 1U
|
||||
#define SYSCON_CLK_SEL_R_SARADC_SMPL_BITS_DIV2 (SYSCON_CLK_SEL_R_SARADC_SMPL_VALUE_DIV2 << SYSCON_CLK_SEL_R_SARADC_SMPL_SHIFT)
|
||||
#define SYSCON_CLK_SEL_R_SARADC_SMPL_VALUE_DIV4 2U
|
||||
#define SYSCON_CLK_SEL_R_SARADC_SMPL_BITS_DIV4 (SYSCON_CLK_SEL_R_SARADC_SMPL_VALUE_DIV4 << SYSCON_CLK_SEL_R_SARADC_SMPL_SHIFT)
|
||||
#define SYSCON_CLK_SEL_R_SARADC_SMPL_VALUE_DIV8 3U
|
||||
#define SYSCON_CLK_SEL_R_SARADC_SMPL_BITS_DIV8 (SYSCON_CLK_SEL_R_SARADC_SMPL_VALUE_DIV8 << SYSCON_CLK_SEL_R_SARADC_SMPL_SHIFT)
|
||||
|
||||
#define SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT 10
|
||||
#define SYSCON_CLK_SEL_W_SARADC_SMPL_WIDTH 2
|
||||
#define SYSCON_CLK_SEL_W_SARADC_SMPL_MASK (((1U << SYSCON_CLK_SEL_W_SARADC_SMPL_WIDTH) - 1U) << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT)
|
||||
#define SYSCON_CLK_SEL_W_SARADC_SMPL_VALUE_DIV1 0U
|
||||
#define SYSCON_CLK_SEL_W_SARADC_SMPL_BITS_DIV1 (SYSCON_CLK_SEL_W_SARADC_SMPL_VALUE_DIV1 << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT)
|
||||
#define SYSCON_CLK_SEL_W_SARADC_SMPL_VALUE_DIV2 1U
|
||||
#define SYSCON_CLK_SEL_W_SARADC_SMPL_BITS_DIV2 (SYSCON_CLK_SEL_W_SARADC_SMPL_VALUE_DIV2 << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT)
|
||||
#define SYSCON_CLK_SEL_W_SARADC_SMPL_VALUE_DIV4 2U
|
||||
#define SYSCON_CLK_SEL_W_SARADC_SMPL_BITS_DIV4 (SYSCON_CLK_SEL_W_SARADC_SMPL_VALUE_DIV4 << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT)
|
||||
#define SYSCON_CLK_SEL_W_SARADC_SMPL_VALUE_DIV8 3U
|
||||
#define SYSCON_CLK_SEL_W_SARADC_SMPL_BITS_DIV8 (SYSCON_CLK_SEL_W_SARADC_SMPL_VALUE_DIV8 << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT)
|
||||
|
||||
#define SYSCON_CLK_SEL_R_PLL_SHIFT 11
|
||||
#define SYSCON_CLK_SEL_R_PLL_WIDTH 1
|
||||
#define SYSCON_CLK_SEL_R_PLL_MASK (((1U << SYSCON_CLK_SEL_R_PLL_WIDTH) - 1U) << SYSCON_CLK_SEL_R_PLL_SHIFT)
|
||||
#define SYSCON_CLK_SEL_R_PLL_VALUE_RCHF 0U
|
||||
#define SYSCON_CLK_SEL_R_PLL_BITS_RCHF (SYSCON_CLK_SEL_R_PLL_VALUE_RCHF << SYSCON_CLK_SEL_R_PLL_SHIFT)
|
||||
#define SYSCON_CLK_SEL_R_PLL_VALUE_XTAH 1U
|
||||
#define SYSCON_CLK_SEL_R_PLL_BITS_XTAH (SYSCON_CLK_SEL_R_PLL_VALUE_XTAH << SYSCON_CLK_SEL_R_PLL_SHIFT)
|
||||
|
||||
#define SYSCON_DIV_CLK_GATE_ADDR (SYSCON_BASE_ADDR + 0x0004U)
|
||||
#define SYSCON_DIV_CLK_GATE (*(volatile uint32_t *)SYSCON_DIV_CLK_GATE_ADDR)
|
||||
#define SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_SHIFT 0
|
||||
#define SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_WIDTH 1
|
||||
#define SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_MASK (((1U << SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_WIDTH) - 1U) << SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_SHIFT)
|
||||
#define SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_VALUE_DISABLE 0U
|
||||
#define SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_BITS_DISABLE (SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_VALUE_DISABLE << SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_SHIFT)
|
||||
#define SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_VALUE_ENABLE 1U
|
||||
#define SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_BITS_ENABLE (SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_VALUE_ENABLE << SYSCON_DIV_CLK_GATE_DIV_CLK_GATE_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_ADDR (SYSCON_BASE_ADDR + 0x0008U)
|
||||
#define SYSCON_DEV_CLK_GATE (*(volatile uint32_t *)SYSCON_DEV_CLK_GATE_ADDR)
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOA_SHIFT 0
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOA_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOA_MASK (((1U << SYSCON_DEV_CLK_GATE_GPIOA_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_GPIOA_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOA_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOA_BITS_DISABLE (SYSCON_DEV_CLK_GATE_GPIOA_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_GPIOA_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOA_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOA_BITS_ENABLE (SYSCON_DEV_CLK_GATE_GPIOA_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_GPIOA_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOB_SHIFT 1
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOB_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOB_MASK (((1U << SYSCON_DEV_CLK_GATE_GPIOB_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_GPIOB_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOB_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOB_BITS_DISABLE (SYSCON_DEV_CLK_GATE_GPIOB_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_GPIOB_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOB_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOB_BITS_ENABLE (SYSCON_DEV_CLK_GATE_GPIOB_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_GPIOB_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOC_SHIFT 2
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOC_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOC_MASK (((1U << SYSCON_DEV_CLK_GATE_GPIOC_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_GPIOC_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOC_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOC_BITS_DISABLE (SYSCON_DEV_CLK_GATE_GPIOC_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_GPIOC_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOC_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_GPIOC_BITS_ENABLE (SYSCON_DEV_CLK_GATE_GPIOC_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_GPIOC_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_IIC0_SHIFT 4
|
||||
#define SYSCON_DEV_CLK_GATE_IIC0_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_IIC0_MASK (((1U << SYSCON_DEV_CLK_GATE_IIC0_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_IIC0_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_IIC0_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_IIC0_BITS_DISABLE (SYSCON_DEV_CLK_GATE_IIC0_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_IIC0_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_IIC0_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_IIC0_BITS_ENABLE (SYSCON_DEV_CLK_GATE_IIC0_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_IIC0_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_IIC1_SHIFT 5
|
||||
#define SYSCON_DEV_CLK_GATE_IIC1_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_IIC1_MASK (((1U << SYSCON_DEV_CLK_GATE_IIC1_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_IIC1_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_IIC1_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_IIC1_BITS_DISABLE (SYSCON_DEV_CLK_GATE_IIC1_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_IIC1_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_IIC1_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_IIC1_BITS_ENABLE (SYSCON_DEV_CLK_GATE_IIC1_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_IIC1_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_UART0_SHIFT 6
|
||||
#define SYSCON_DEV_CLK_GATE_UART0_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_UART0_MASK (((1U << SYSCON_DEV_CLK_GATE_UART0_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_UART0_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_UART0_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_UART0_BITS_DISABLE (SYSCON_DEV_CLK_GATE_UART0_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_UART0_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_UART0_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_UART0_BITS_ENABLE (SYSCON_DEV_CLK_GATE_UART0_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_UART0_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_UART1_SHIFT 7
|
||||
#define SYSCON_DEV_CLK_GATE_UART1_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_UART1_MASK (((1U << SYSCON_DEV_CLK_GATE_UART1_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_UART1_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_UART1_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_UART1_BITS_DISABLE (SYSCON_DEV_CLK_GATE_UART1_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_UART1_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_UART1_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_UART1_BITS_ENABLE (SYSCON_DEV_CLK_GATE_UART1_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_UART1_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_UART2_SHIFT 8
|
||||
#define SYSCON_DEV_CLK_GATE_UART2_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_UART2_MASK (((1U << SYSCON_DEV_CLK_GATE_UART2_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_UART2_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_UART2_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_UART2_BITS_DISABLE (SYSCON_DEV_CLK_GATE_UART2_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_UART2_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_UART2_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_UART2_BITS_ENABLE (SYSCON_DEV_CLK_GATE_UART2_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_UART2_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_SPI0_SHIFT 10
|
||||
#define SYSCON_DEV_CLK_GATE_SPI0_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_SPI0_MASK (((1U << SYSCON_DEV_CLK_GATE_SPI0_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_SPI0_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_SPI0_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_SPI0_BITS_DISABLE (SYSCON_DEV_CLK_GATE_SPI0_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_SPI0_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_SPI0_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_SPI0_BITS_ENABLE (SYSCON_DEV_CLK_GATE_SPI0_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_SPI0_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_SPI1_SHIFT 11
|
||||
#define SYSCON_DEV_CLK_GATE_SPI1_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_SPI1_MASK (((1U << SYSCON_DEV_CLK_GATE_SPI1_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_SPI1_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_SPI1_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_SPI1_BITS_DISABLE (SYSCON_DEV_CLK_GATE_SPI1_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_SPI1_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_SPI1_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_SPI1_BITS_ENABLE (SYSCON_DEV_CLK_GATE_SPI1_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_SPI1_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE0_SHIFT 12
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE0_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE0_MASK (((1U << SYSCON_DEV_CLK_GATE_TIMER_BASE0_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_TIMER_BASE0_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE0_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE0_BITS_DISABLE (SYSCON_DEV_CLK_GATE_TIMER_BASE0_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_TIMER_BASE0_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE0_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE0_BITS_ENABLE (SYSCON_DEV_CLK_GATE_TIMER_BASE0_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_TIMER_BASE0_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE1_SHIFT 13
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE1_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE1_MASK (((1U << SYSCON_DEV_CLK_GATE_TIMER_BASE1_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_TIMER_BASE1_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE1_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE1_BITS_DISABLE (SYSCON_DEV_CLK_GATE_TIMER_BASE1_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_TIMER_BASE1_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE1_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE1_BITS_ENABLE (SYSCON_DEV_CLK_GATE_TIMER_BASE1_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_TIMER_BASE1_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE2_SHIFT 14
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE2_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE2_MASK (((1U << SYSCON_DEV_CLK_GATE_TIMER_BASE2_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_TIMER_BASE2_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE2_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE2_BITS_DISABLE (SYSCON_DEV_CLK_GATE_TIMER_BASE2_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_TIMER_BASE2_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE2_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_BASE2_BITS_ENABLE (SYSCON_DEV_CLK_GATE_TIMER_BASE2_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_TIMER_BASE2_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_PLUS0_SHIFT 15
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_PLUS0_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_PLUS0_MASK (((1U << SYSCON_DEV_CLK_GATE_TIMER_PLUS0_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_TIMER_PLUS0_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_PLUS0_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_PLUS0_BITS_DISABLE (SYSCON_DEV_CLK_GATE_TIMER_PLUS0_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_TIMER_PLUS0_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_PLUS0_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_PLUS0_BITS_ENABLE (SYSCON_DEV_CLK_GATE_TIMER_PLUS0_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_TIMER_PLUS0_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_PLUS1_SHIFT 16
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_PLUS1_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_PLUS1_MASK (((1U << SYSCON_DEV_CLK_GATE_TIMER_PLUS1_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_TIMER_PLUS1_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_PLUS1_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_PLUS1_BITS_DISABLE (SYSCON_DEV_CLK_GATE_TIMER_PLUS1_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_TIMER_PLUS1_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_PLUS1_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_TIMER_PLUS1_BITS_ENABLE (SYSCON_DEV_CLK_GATE_TIMER_PLUS1_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_TIMER_PLUS1_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_BASE0_SHIFT 17
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_BASE0_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_BASE0_MASK (((1U << SYSCON_DEV_CLK_GATE_PWM_BASE0_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_PWM_BASE0_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_BASE0_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_BASE0_BITS_DISABLE (SYSCON_DEV_CLK_GATE_PWM_BASE0_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_PWM_BASE0_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_BASE0_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_BASE0_BITS_ENABLE (SYSCON_DEV_CLK_GATE_PWM_BASE0_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_PWM_BASE0_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_BASE1_SHIFT 18
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_BASE1_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_BASE1_MASK (((1U << SYSCON_DEV_CLK_GATE_PWM_BASE1_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_PWM_BASE1_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_BASE1_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_BASE1_BITS_DISABLE (SYSCON_DEV_CLK_GATE_PWM_BASE1_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_PWM_BASE1_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_BASE1_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_BASE1_BITS_ENABLE (SYSCON_DEV_CLK_GATE_PWM_BASE1_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_PWM_BASE1_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_PLUS0_SHIFT 20
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_PLUS0_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_PLUS0_MASK (((1U << SYSCON_DEV_CLK_GATE_PWM_PLUS0_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_PWM_PLUS0_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_PLUS0_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_PLUS0_BITS_DISABLE (SYSCON_DEV_CLK_GATE_PWM_PLUS0_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_PWM_PLUS0_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_PLUS0_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_PLUS0_BITS_ENABLE (SYSCON_DEV_CLK_GATE_PWM_PLUS0_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_PWM_PLUS0_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_PLUS1_SHIFT 21
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_PLUS1_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_PLUS1_MASK (((1U << SYSCON_DEV_CLK_GATE_PWM_PLUS1_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_PWM_PLUS1_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_PLUS1_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_PLUS1_BITS_DISABLE (SYSCON_DEV_CLK_GATE_PWM_PLUS1_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_PWM_PLUS1_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_PLUS1_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_PWM_PLUS1_BITS_ENABLE (SYSCON_DEV_CLK_GATE_PWM_PLUS1_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_PWM_PLUS1_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_RTC_SHIFT 22
|
||||
#define SYSCON_DEV_CLK_GATE_RTC_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_RTC_MASK (((1U << SYSCON_DEV_CLK_GATE_RTC_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_RTC_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_RTC_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_RTC_BITS_DISABLE (SYSCON_DEV_CLK_GATE_RTC_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_RTC_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_RTC_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_RTC_BITS_ENABLE (SYSCON_DEV_CLK_GATE_RTC_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_RTC_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_IWDT_SHIFT 23
|
||||
#define SYSCON_DEV_CLK_GATE_IWDT_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_IWDT_MASK (((1U << SYSCON_DEV_CLK_GATE_IWDT_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_IWDT_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_IWDT_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_IWDT_BITS_DISABLE (SYSCON_DEV_CLK_GATE_IWDT_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_IWDT_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_IWDT_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_IWDT_BITS_ENABLE (SYSCON_DEV_CLK_GATE_IWDT_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_IWDT_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_WWDT_SHIFT 24
|
||||
#define SYSCON_DEV_CLK_GATE_WWDT_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_WWDT_MASK (((1U << SYSCON_DEV_CLK_GATE_WWDT_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_WWDT_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_WWDT_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_WWDT_BITS_DISABLE (SYSCON_DEV_CLK_GATE_WWDT_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_WWDT_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_WWDT_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_WWDT_BITS_ENABLE (SYSCON_DEV_CLK_GATE_WWDT_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_WWDT_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_SARADC_SHIFT 25
|
||||
#define SYSCON_DEV_CLK_GATE_SARADC_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_SARADC_MASK (((1U << SYSCON_DEV_CLK_GATE_SARADC_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_SARADC_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_SARADC_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_SARADC_BITS_DISABLE (SYSCON_DEV_CLK_GATE_SARADC_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_SARADC_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_SARADC_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_SARADC_BITS_ENABLE (SYSCON_DEV_CLK_GATE_SARADC_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_SARADC_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_CRC_SHIFT 27
|
||||
#define SYSCON_DEV_CLK_GATE_CRC_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_CRC_MASK (((1U << SYSCON_DEV_CLK_GATE_CRC_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_CRC_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_CRC_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_CRC_BITS_DISABLE (SYSCON_DEV_CLK_GATE_CRC_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_CRC_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_CRC_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_CRC_BITS_ENABLE (SYSCON_DEV_CLK_GATE_CRC_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_CRC_SHIFT)
|
||||
|
||||
#define SYSCON_DEV_CLK_GATE_AES_SHIFT 28
|
||||
#define SYSCON_DEV_CLK_GATE_AES_WIDTH 1
|
||||
#define SYSCON_DEV_CLK_GATE_AES_MASK (((1U << SYSCON_DEV_CLK_GATE_AES_WIDTH) - 1U) << SYSCON_DEV_CLK_GATE_AES_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_AES_VALUE_DISABLE 0U
|
||||
#define SYSCON_DEV_CLK_GATE_AES_BITS_DISABLE (SYSCON_DEV_CLK_GATE_AES_VALUE_DISABLE << SYSCON_DEV_CLK_GATE_AES_SHIFT)
|
||||
#define SYSCON_DEV_CLK_GATE_AES_VALUE_ENABLE 1U
|
||||
#define SYSCON_DEV_CLK_GATE_AES_BITS_ENABLE (SYSCON_DEV_CLK_GATE_AES_VALUE_ENABLE << SYSCON_DEV_CLK_GATE_AES_SHIFT)
|
||||
|
||||
#define SYSCON_RC_FREQ_DELTA_ADDR (SYSCON_BASE_ADDR + 0x0078U)
|
||||
#define SYSCON_RC_FREQ_DELTA (*(volatile uint32_t *)SYSCON_RC_FREQ_DELTA_ADDR)
|
||||
#define SYSCON_RC_FREQ_DELTA_RCLF_DELTA_SHIFT 0
|
||||
#define SYSCON_RC_FREQ_DELTA_RCLF_DELTA_WIDTH 10
|
||||
#define SYSCON_RC_FREQ_DELTA_RCLF_DELTA_MASK (((1U << SYSCON_RC_FREQ_DELTA_RCLF_DELTA_WIDTH) - 1U) << SYSCON_RC_FREQ_DELTA_RCLF_DELTA_SHIFT)
|
||||
#define SYSCON_RC_FREQ_DELTA_RCLF_SIG_SHIFT 10
|
||||
#define SYSCON_RC_FREQ_DELTA_RCLF_SIG_WIDTH 1
|
||||
#define SYSCON_RC_FREQ_DELTA_RCLF_SIG_MASK (((1U << SYSCON_RC_FREQ_DELTA_RCLF_SIG_WIDTH) - 1U) << SYSCON_RC_FREQ_DELTA_RCLF_SIG_SHIFT)
|
||||
#define SYSCON_RC_FREQ_DELTA_RCHF_DELTA_SHIFT 11
|
||||
#define SYSCON_RC_FREQ_DELTA_RCHF_DELTA_WIDTH 20
|
||||
#define SYSCON_RC_FREQ_DELTA_RCHF_DELTA_MASK (((1U << SYSCON_RC_FREQ_DELTA_RCHF_DELTA_WIDTH) - 1U) << SYSCON_RC_FREQ_DELTA_RCHF_DELTA_SHIFT)
|
||||
#define SYSCON_RC_FREQ_DELTA_RCHF_SIG_SHIFT 31
|
||||
#define SYSCON_RC_FREQ_DELTA_RCHF_SIG_WIDTH 1
|
||||
#define SYSCON_RC_FREQ_DELTA_RCHF_SIG_MASK (((1U << SYSCON_RC_FREQ_DELTA_RCHF_SIG_WIDTH) - 1U) << SYSCON_RC_FREQ_DELTA_RCHF_SIG_SHIFT)
|
||||
|
||||
#define SYSCON_VREF_VOLT_DELTA_ADDR (SYSCON_BASE_ADDR + 0x007CU)
|
||||
#define SYSCON_VREF_VOLT_DELTA (*(volatile uint32_t *)SYSCON_VREF_VOLT_DELTA_ADDR)
|
||||
#define SYSCON_CHIP_ID0_ADDR (SYSCON_BASE_ADDR + 0x0080U)
|
||||
#define SYSCON_CHIP_ID0 (*(volatile uint32_t *)SYSCON_CHIP_ID0_ADDR)
|
||||
#define SYSCON_CHIP_ID1_ADDR (SYSCON_BASE_ADDR + 0x0084U)
|
||||
#define SYSCON_CHIP_ID1 (*(volatile uint32_t *)SYSCON_CHIP_ID1_ADDR)
|
||||
#define SYSCON_CHIP_ID2_ADDR (SYSCON_BASE_ADDR + 0x0088U)
|
||||
#define SYSCON_CHIP_ID2 (*(volatile uint32_t *)SYSCON_CHIP_ID2_ADDR)
|
||||
#define SYSCON_CHIP_ID3_ADDR (SYSCON_BASE_ADDR + 0x008CU)
|
||||
#define SYSCON_CHIP_ID3 (*(volatile uint32_t *)SYSCON_CHIP_ID3_ADDR)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
439
bsp/dp32g030/uart.h
Normal file
439
bsp/dp32g030/uart.h
Normal file
@@ -0,0 +1,439 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HARDWARE_DP32G030_UART_H
|
||||
#define HARDWARE_DP32G030_UART_H
|
||||
|
||||
#if !defined(__ASSEMBLY__)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* -------- UART0 -------- */
|
||||
#define UART0_BASE_ADDR 0x4006B000U
|
||||
#define UART0_BASE_SIZE 0x00000800U
|
||||
#define UART0 ((volatile UART_Port_t *)UART0_BASE_ADDR)
|
||||
|
||||
/* -------- UART1 -------- */
|
||||
#define UART1_BASE_ADDR 0x4006B800U
|
||||
#define UART1_BASE_SIZE 0x00000800U
|
||||
#define UART1 ((volatile UART_Port_t *)UART1_BASE_ADDR)
|
||||
|
||||
/* -------- UART2 -------- */
|
||||
#define UART2_BASE_ADDR 0x4006C000U
|
||||
#define UART2_BASE_SIZE 0x00000800U
|
||||
#define UART2 ((volatile UART_Port_t *)UART2_BASE_ADDR)
|
||||
|
||||
/* -------- UART -------- */
|
||||
|
||||
typedef struct {
|
||||
uint32_t CTRL;
|
||||
uint32_t BAUD;
|
||||
uint32_t TDR;
|
||||
uint32_t RDR;
|
||||
uint32_t IE;
|
||||
uint32_t IF;
|
||||
uint32_t FIFO;
|
||||
uint32_t FC;
|
||||
uint32_t RXTO;
|
||||
} UART_Port_t;
|
||||
|
||||
#define UART_CTRL_UARTEN_SHIFT 0
|
||||
#define UART_CTRL_UARTEN_WIDTH 1
|
||||
#define UART_CTRL_UARTEN_MASK (((1U << UART_CTRL_UARTEN_WIDTH) - 1U) << UART_CTRL_UARTEN_SHIFT)
|
||||
#define UART_CTRL_UARTEN_VALUE_DISABLE 0U
|
||||
#define UART_CTRL_UARTEN_BITS_DISABLE (UART_CTRL_UARTEN_VALUE_DISABLE << UART_CTRL_UARTEN_SHIFT)
|
||||
#define UART_CTRL_UARTEN_VALUE_ENABLE 1U
|
||||
#define UART_CTRL_UARTEN_BITS_ENABLE (UART_CTRL_UARTEN_VALUE_ENABLE << UART_CTRL_UARTEN_SHIFT)
|
||||
|
||||
#define UART_CTRL_RXEN_SHIFT 1
|
||||
#define UART_CTRL_RXEN_WIDTH 1
|
||||
#define UART_CTRL_RXEN_MASK (((1U << UART_CTRL_RXEN_WIDTH) - 1U) << UART_CTRL_RXEN_SHIFT)
|
||||
#define UART_CTRL_RXEN_VALUE_DISABLE 0U
|
||||
#define UART_CTRL_RXEN_BITS_DISABLE (UART_CTRL_RXEN_VALUE_DISABLE << UART_CTRL_RXEN_SHIFT)
|
||||
#define UART_CTRL_RXEN_VALUE_ENABLE 1U
|
||||
#define UART_CTRL_RXEN_BITS_ENABLE (UART_CTRL_RXEN_VALUE_ENABLE << UART_CTRL_RXEN_SHIFT)
|
||||
|
||||
#define UART_CTRL_TXEN_SHIFT 2
|
||||
#define UART_CTRL_TXEN_WIDTH 1
|
||||
#define UART_CTRL_TXEN_MASK (((1U << UART_CTRL_TXEN_WIDTH) - 1U) << UART_CTRL_TXEN_SHIFT)
|
||||
#define UART_CTRL_TXEN_VALUE_DISABLE 0U
|
||||
#define UART_CTRL_TXEN_BITS_DISABLE (UART_CTRL_TXEN_VALUE_DISABLE << UART_CTRL_TXEN_SHIFT)
|
||||
#define UART_CTRL_TXEN_VALUE_ENABLE 1U
|
||||
#define UART_CTRL_TXEN_BITS_ENABLE (UART_CTRL_TXEN_VALUE_ENABLE << UART_CTRL_TXEN_SHIFT)
|
||||
|
||||
#define UART_CTRL_RXDMAEN_SHIFT 3
|
||||
#define UART_CTRL_RXDMAEN_WIDTH 1
|
||||
#define UART_CTRL_RXDMAEN_MASK (((1U << UART_CTRL_RXDMAEN_WIDTH) - 1U) << UART_CTRL_RXDMAEN_SHIFT)
|
||||
#define UART_CTRL_RXDMAEN_VALUE_DISABLE 0U
|
||||
#define UART_CTRL_RXDMAEN_BITS_DISABLE (UART_CTRL_RXDMAEN_VALUE_DISABLE << UART_CTRL_RXDMAEN_SHIFT)
|
||||
#define UART_CTRL_RXDMAEN_VALUE_ENABLE 1U
|
||||
#define UART_CTRL_RXDMAEN_BITS_ENABLE (UART_CTRL_RXDMAEN_VALUE_ENABLE << UART_CTRL_RXDMAEN_SHIFT)
|
||||
|
||||
#define UART_CTRL_TXDMAEN_SHIFT 4
|
||||
#define UART_CTRL_TXDMAEN_WIDTH 1
|
||||
#define UART_CTRL_TXDMAEN_MASK (((1U << UART_CTRL_TXDMAEN_WIDTH) - 1U) << UART_CTRL_TXDMAEN_SHIFT)
|
||||
#define UART_CTRL_TXDMAEN_VALUE_DISABLE 0U
|
||||
#define UART_CTRL_TXDMAEN_BITS_DISABLE (UART_CTRL_TXDMAEN_VALUE_DISABLE << UART_CTRL_TXDMAEN_SHIFT)
|
||||
#define UART_CTRL_TXDMAEN_VALUE_ENABLE 1U
|
||||
#define UART_CTRL_TXDMAEN_BITS_ENABLE (UART_CTRL_TXDMAEN_VALUE_ENABLE << UART_CTRL_TXDMAEN_SHIFT)
|
||||
|
||||
#define UART_CTRL_NINEBIT_SHIFT 5
|
||||
#define UART_CTRL_NINEBIT_WIDTH 1
|
||||
#define UART_CTRL_NINEBIT_MASK (((1U << UART_CTRL_NINEBIT_WIDTH) - 1U) << UART_CTRL_NINEBIT_SHIFT)
|
||||
#define UART_CTRL_NINEBIT_VALUE_DISABLE 0U
|
||||
#define UART_CTRL_NINEBIT_BITS_DISABLE (UART_CTRL_NINEBIT_VALUE_DISABLE << UART_CTRL_NINEBIT_SHIFT)
|
||||
#define UART_CTRL_NINEBIT_VALUE_ENABLE 1U
|
||||
#define UART_CTRL_NINEBIT_BITS_ENABLE (UART_CTRL_NINEBIT_VALUE_ENABLE << UART_CTRL_NINEBIT_SHIFT)
|
||||
|
||||
#define UART_CTRL_PAREN_SHIFT 6
|
||||
#define UART_CTRL_PAREN_WIDTH 1
|
||||
#define UART_CTRL_PAREN_MASK (((1U << UART_CTRL_PAREN_WIDTH) - 1U) << UART_CTRL_PAREN_SHIFT)
|
||||
#define UART_CTRL_PAREN_VALUE_DISABLE 0U
|
||||
#define UART_CTRL_PAREN_BITS_DISABLE (UART_CTRL_PAREN_VALUE_DISABLE << UART_CTRL_PAREN_SHIFT)
|
||||
#define UART_CTRL_PAREN_VALUE_ENABLE 1U
|
||||
#define UART_CTRL_PAREN_BITS_ENABLE (UART_CTRL_PAREN_VALUE_ENABLE << UART_CTRL_PAREN_SHIFT)
|
||||
|
||||
#define UART_IE_TXDONE_SHIFT 2
|
||||
#define UART_IE_TXDONE_WIDTH 1
|
||||
#define UART_IE_TXDONE_MASK (((1U << UART_IE_TXDONE_WIDTH) - 1U) << UART_IE_TXDONE_SHIFT)
|
||||
#define UART_IE_TXDONE_VALUE_DISABLE 0U
|
||||
#define UART_IE_TXDONE_BITS_DISABLE (UART_IE_TXDONE_VALUE_DISABLE << UART_IE_TXDONE_SHIFT)
|
||||
#define UART_IE_TXDONE_VALUE_ENABLE 1U
|
||||
#define UART_IE_TXDONE_BITS_ENABLE (UART_IE_TXDONE_VALUE_ENABLE << UART_IE_TXDONE_SHIFT)
|
||||
|
||||
#define UART_IE_PARITYE_SHIFT 3
|
||||
#define UART_IE_PARITYE_WIDTH 1
|
||||
#define UART_IE_PARITYE_MASK (((1U << UART_IE_PARITYE_WIDTH) - 1U) << UART_IE_PARITYE_SHIFT)
|
||||
#define UART_IE_PARITYE_VALUE_DISABLE 0U
|
||||
#define UART_IE_PARITYE_BITS_DISABLE (UART_IE_PARITYE_VALUE_DISABLE << UART_IE_PARITYE_SHIFT)
|
||||
#define UART_IE_PARITYE_VALUE_ENABLE 1U
|
||||
#define UART_IE_PARITYE_BITS_ENABLE (UART_IE_PARITYE_VALUE_ENABLE << UART_IE_PARITYE_SHIFT)
|
||||
|
||||
#define UART_IE_STOPE_SHIFT 4
|
||||
#define UART_IE_STOPE_WIDTH 1
|
||||
#define UART_IE_STOPE_MASK (((1U << UART_IE_STOPE_WIDTH) - 1U) << UART_IE_STOPE_SHIFT)
|
||||
#define UART_IE_STOPE_VALUE_DISABLE 0U
|
||||
#define UART_IE_STOPE_BITS_DISABLE (UART_IE_STOPE_VALUE_DISABLE << UART_IE_STOPE_SHIFT)
|
||||
#define UART_IE_STOPE_VALUE_ENABLE 1U
|
||||
#define UART_IE_STOPE_BITS_ENABLE (UART_IE_STOPE_VALUE_ENABLE << UART_IE_STOPE_SHIFT)
|
||||
|
||||
#define UART_IE_RXTO_SHIFT 5
|
||||
#define UART_IE_RXTO_WIDTH 1
|
||||
#define UART_IE_RXTO_MASK (((1U << UART_IE_RXTO_WIDTH) - 1U) << UART_IE_RXTO_SHIFT)
|
||||
#define UART_IE_RXTO_VALUE_DISABLE 0U
|
||||
#define UART_IE_RXTO_BITS_DISABLE (UART_IE_RXTO_VALUE_DISABLE << UART_IE_RXTO_SHIFT)
|
||||
#define UART_IE_RXTO_VALUE_ENABLE 1U
|
||||
#define UART_IE_RXTO_BITS_ENABLE (UART_IE_RXTO_VALUE_ENABLE << UART_IE_RXTO_SHIFT)
|
||||
|
||||
#define UART_IE_RXFIFO_SHIFT 6
|
||||
#define UART_IE_RXFIFO_WIDTH 1
|
||||
#define UART_IE_RXFIFO_MASK (((1U << UART_IE_RXFIFO_WIDTH) - 1U) << UART_IE_RXFIFO_SHIFT)
|
||||
#define UART_IE_RXFIFO_VALUE_DISABLE 0U
|
||||
#define UART_IE_RXFIFO_BITS_DISABLE (UART_IE_RXFIFO_VALUE_DISABLE << UART_IE_RXFIFO_SHIFT)
|
||||
#define UART_IE_RXFIFO_VALUE_ENABLE 1U
|
||||
#define UART_IE_RXFIFO_BITS_ENABLE (UART_IE_RXFIFO_VALUE_ENABLE << UART_IE_RXFIFO_SHIFT)
|
||||
|
||||
#define UART_IE_TXFIFO_SHIFT 7
|
||||
#define UART_IE_TXFIFO_WIDTH 1
|
||||
#define UART_IE_TXFIFO_MASK (((1U << UART_IE_TXFIFO_WIDTH) - 1U) << UART_IE_TXFIFO_SHIFT)
|
||||
#define UART_IE_TXFIFO_VALUE_DISABLE 0U
|
||||
#define UART_IE_TXFIFO_BITS_DISABLE (UART_IE_TXFIFO_VALUE_DISABLE << UART_IE_TXFIFO_SHIFT)
|
||||
#define UART_IE_TXFIFO_VALUE_ENABLE 1U
|
||||
#define UART_IE_TXFIFO_BITS_ENABLE (UART_IE_TXFIFO_VALUE_ENABLE << UART_IE_TXFIFO_SHIFT)
|
||||
|
||||
#define UART_IE_RXFIFO_OVF_SHIFT 8
|
||||
#define UART_IE_RXFIFO_OVF_WIDTH 1
|
||||
#define UART_IE_RXFIFO_OVF_MASK (((1U << UART_IE_RXFIFO_OVF_WIDTH) - 1U) << UART_IE_RXFIFO_OVF_SHIFT)
|
||||
#define UART_IE_RXFIFO_OVF_VALUE_DISABLE 0U
|
||||
#define UART_IE_RXFIFO_OVF_BITS_DISABLE (UART_IE_RXFIFO_OVF_VALUE_DISABLE << UART_IE_RXFIFO_OVF_SHIFT)
|
||||
#define UART_IE_RXFIFO_OVF_VALUE_ENABLE 1U
|
||||
#define UART_IE_RXFIFO_OVF_BITS_ENABLE (UART_IE_RXFIFO_OVF_VALUE_ENABLE << UART_IE_RXFIFO_OVF_SHIFT)
|
||||
|
||||
#define UART_IE_ABRD_OVF_SHIFT 9
|
||||
#define UART_IE_ABRD_OVF_WIDTH 1
|
||||
#define UART_IE_ABRD_OVF_MASK (((1U << UART_IE_ABRD_OVF_WIDTH) - 1U) << UART_IE_ABRD_OVF_SHIFT)
|
||||
#define UART_IE_ABRD_OVF_VALUE_DISABLE 0U
|
||||
#define UART_IE_ABRD_OVF_BITS_DISABLE (UART_IE_ABRD_OVF_VALUE_DISABLE << UART_IE_ABRD_OVF_SHIFT)
|
||||
#define UART_IE_ABRD_OVF_VALUE_ENABLE 1U
|
||||
#define UART_IE_ABRD_OVF_BITS_ENABLE (UART_IE_ABRD_OVF_VALUE_ENABLE << UART_IE_ABRD_OVF_SHIFT)
|
||||
|
||||
#define UART_IF_TXDONE_SHIFT 2
|
||||
#define UART_IF_TXDONE_WIDTH 1
|
||||
#define UART_IF_TXDONE_MASK (((1U << UART_IF_TXDONE_WIDTH) - 1U) << UART_IF_TXDONE_SHIFT)
|
||||
#define UART_IF_TXDONE_VALUE_NOT_SET 0U
|
||||
#define UART_IF_TXDONE_BITS_NOT_SET (UART_IF_TXDONE_VALUE_NOT_SET << UART_IF_TXDONE_SHIFT)
|
||||
#define UART_IF_TXDONE_VALUE_SET 1U
|
||||
#define UART_IF_TXDONE_BITS_SET (UART_IF_TXDONE_VALUE_SET << UART_IF_TXDONE_SHIFT)
|
||||
|
||||
#define UART_IF_PARITYE_SHIFT 3
|
||||
#define UART_IF_PARITYE_WIDTH 1
|
||||
#define UART_IF_PARITYE_MASK (((1U << UART_IF_PARITYE_WIDTH) - 1U) << UART_IF_PARITYE_SHIFT)
|
||||
#define UART_IF_PARITYE_VALUE_NOT_SET 0U
|
||||
#define UART_IF_PARITYE_BITS_NOT_SET (UART_IF_PARITYE_VALUE_NOT_SET << UART_IF_PARITYE_SHIFT)
|
||||
#define UART_IF_PARITYE_VALUE_SET 1U
|
||||
#define UART_IF_PARITYE_BITS_SET (UART_IF_PARITYE_VALUE_SET << UART_IF_PARITYE_SHIFT)
|
||||
|
||||
#define UART_IF_STOPE_SHIFT 4
|
||||
#define UART_IF_STOPE_WIDTH 1
|
||||
#define UART_IF_STOPE_MASK (((1U << UART_IF_STOPE_WIDTH) - 1U) << UART_IF_STOPE_SHIFT)
|
||||
#define UART_IF_STOPE_VALUE_NOT_SET 0U
|
||||
#define UART_IF_STOPE_BITS_NOT_SET (UART_IF_STOPE_VALUE_NOT_SET << UART_IF_STOPE_SHIFT)
|
||||
#define UART_IF_STOPE_VALUE_SET 1U
|
||||
#define UART_IF_STOPE_BITS_SET (UART_IF_STOPE_VALUE_SET << UART_IF_STOPE_SHIFT)
|
||||
|
||||
#define UART_IF_RXTO_SHIFT 5
|
||||
#define UART_IF_RXTO_WIDTH 1
|
||||
#define UART_IF_RXTO_MASK (((1U << UART_IF_RXTO_WIDTH) - 1U) << UART_IF_RXTO_SHIFT)
|
||||
#define UART_IF_RXTO_VALUE_NOT_SET 0U
|
||||
#define UART_IF_RXTO_BITS_NOT_SET (UART_IF_RXTO_VALUE_NOT_SET << UART_IF_RXTO_SHIFT)
|
||||
#define UART_IF_RXTO_VALUE_SET 1U
|
||||
#define UART_IF_RXTO_BITS_SET (UART_IF_RXTO_VALUE_SET << UART_IF_RXTO_SHIFT)
|
||||
|
||||
#define UART_IF_RXFIFO_SHIFT 6
|
||||
#define UART_IF_RXFIFO_WIDTH 1
|
||||
#define UART_IF_RXFIFO_MASK (((1U << UART_IF_RXFIFO_WIDTH) - 1U) << UART_IF_RXFIFO_SHIFT)
|
||||
#define UART_IF_RXFIFO_VALUE_NOT_SET 0U
|
||||
#define UART_IF_RXFIFO_BITS_NOT_SET (UART_IF_RXFIFO_VALUE_NOT_SET << UART_IF_RXFIFO_SHIFT)
|
||||
#define UART_IF_RXFIFO_VALUE_SET 1U
|
||||
#define UART_IF_RXFIFO_BITS_SET (UART_IF_RXFIFO_VALUE_SET << UART_IF_RXFIFO_SHIFT)
|
||||
|
||||
#define UART_IF_TXFIFO_SHIFT 7
|
||||
#define UART_IF_TXFIFO_WIDTH 1
|
||||
#define UART_IF_TXFIFO_MASK (((1U << UART_IF_TXFIFO_WIDTH) - 1U) << UART_IF_TXFIFO_SHIFT)
|
||||
#define UART_IF_TXFIFO_VALUE_NOT_SET 0U
|
||||
#define UART_IF_TXFIFO_BITS_NOT_SET (UART_IF_TXFIFO_VALUE_NOT_SET << UART_IF_TXFIFO_SHIFT)
|
||||
#define UART_IF_TXFIFO_VALUE_SET 1U
|
||||
#define UART_IF_TXFIFO_BITS_SET (UART_IF_TXFIFO_VALUE_SET << UART_IF_TXFIFO_SHIFT)
|
||||
|
||||
#define UART_IF_RXFIFO_OVF_SHIFT 8
|
||||
#define UART_IF_RXFIFO_OVF_WIDTH 1
|
||||
#define UART_IF_RXFIFO_OVF_MASK (((1U << UART_IF_RXFIFO_OVF_WIDTH) - 1U) << UART_IF_RXFIFO_OVF_SHIFT)
|
||||
#define UART_IF_RXFIFO_OVF_VALUE_NOT_SET 0U
|
||||
#define UART_IF_RXFIFO_OVF_BITS_NOT_SET (UART_IF_RXFIFO_OVF_VALUE_NOT_SET << UART_IF_RXFIFO_OVF_SHIFT)
|
||||
#define UART_IF_RXFIFO_OVF_VALUE_SET 1U
|
||||
#define UART_IF_RXFIFO_OVF_BITS_SET (UART_IF_RXFIFO_OVF_VALUE_SET << UART_IF_RXFIFO_OVF_SHIFT)
|
||||
|
||||
#define UART_IF_ABRD_OVF_SHIFT 9
|
||||
#define UART_IF_ABRD_OVF_WIDTH 1
|
||||
#define UART_IF_ABRD_OVF_MASK (((1U << UART_IF_ABRD_OVF_WIDTH) - 1U) << UART_IF_ABRD_OVF_SHIFT)
|
||||
#define UART_IF_ABRD_OVF_VALUE_NOT_SET 0U
|
||||
#define UART_IF_ABRD_OVF_BITS_NOT_SET (UART_IF_ABRD_OVF_VALUE_NOT_SET << UART_IF_ABRD_OVF_SHIFT)
|
||||
#define UART_IF_ABRD_OVF_VALUE_SET 1U
|
||||
#define UART_IF_ABRD_OVF_BITS_SET (UART_IF_ABRD_OVF_VALUE_SET << UART_IF_ABRD_OVF_SHIFT)
|
||||
|
||||
#define UART_IF_RXFIFO_EMPTY_SHIFT 10
|
||||
#define UART_IF_RXFIFO_EMPTY_WIDTH 1
|
||||
#define UART_IF_RXFIFO_EMPTY_MASK (((1U << UART_IF_RXFIFO_EMPTY_WIDTH) - 1U) << UART_IF_RXFIFO_EMPTY_SHIFT)
|
||||
#define UART_IF_RXFIFO_EMPTY_VALUE_NOT_SET 0U
|
||||
#define UART_IF_RXFIFO_EMPTY_BITS_NOT_SET (UART_IF_RXFIFO_EMPTY_VALUE_NOT_SET << UART_IF_RXFIFO_EMPTY_SHIFT)
|
||||
#define UART_IF_RXFIFO_EMPTY_VALUE_SET 1U
|
||||
#define UART_IF_RXFIFO_EMPTY_BITS_SET (UART_IF_RXFIFO_EMPTY_VALUE_SET << UART_IF_RXFIFO_EMPTY_SHIFT)
|
||||
|
||||
#define UART_IF_RXFIFO_FULL_SHIFT 11
|
||||
#define UART_IF_RXFIFO_FULL_WIDTH 1
|
||||
#define UART_IF_RXFIFO_FULL_MASK (((1U << UART_IF_RXFIFO_FULL_WIDTH) - 1U) << UART_IF_RXFIFO_FULL_SHIFT)
|
||||
#define UART_IF_RXFIFO_FULL_VALUE_NOT_SET 0U
|
||||
#define UART_IF_RXFIFO_FULL_BITS_NOT_SET (UART_IF_RXFIFO_FULL_VALUE_NOT_SET << UART_IF_RXFIFO_FULL_SHIFT)
|
||||
#define UART_IF_RXFIFO_FULL_VALUE_SET 1U
|
||||
#define UART_IF_RXFIFO_FULL_BITS_SET (UART_IF_RXFIFO_FULL_VALUE_SET << UART_IF_RXFIFO_FULL_SHIFT)
|
||||
|
||||
#define UART_IF_RXFIFO_HFULL_SHIFT 12
|
||||
#define UART_IF_RXFIFO_HFULL_WIDTH 1
|
||||
#define UART_IF_RXFIFO_HFULL_MASK (((1U << UART_IF_RXFIFO_HFULL_WIDTH) - 1U) << UART_IF_RXFIFO_HFULL_SHIFT)
|
||||
#define UART_IF_RXFIFO_HFULL_VALUE_NOT_SET 0U
|
||||
#define UART_IF_RXFIFO_HFULL_BITS_NOT_SET (UART_IF_RXFIFO_HFULL_VALUE_NOT_SET << UART_IF_RXFIFO_HFULL_SHIFT)
|
||||
#define UART_IF_RXFIFO_HFULL_VALUE_SET 1U
|
||||
#define UART_IF_RXFIFO_HFULL_BITS_SET (UART_IF_RXFIFO_HFULL_VALUE_SET << UART_IF_RXFIFO_HFULL_SHIFT)
|
||||
|
||||
#define UART_IF_TXFIFO_EMPTY_SHIFT 13
|
||||
#define UART_IF_TXFIFO_EMPTY_WIDTH 1
|
||||
#define UART_IF_TXFIFO_EMPTY_MASK (((1U << UART_IF_TXFIFO_EMPTY_WIDTH) - 1U) << UART_IF_TXFIFO_EMPTY_SHIFT)
|
||||
#define UART_IF_TXFIFO_EMPTY_VALUE_NOT_SET 0U
|
||||
#define UART_IF_TXFIFO_EMPTY_BITS_NOT_SET (UART_IF_TXFIFO_EMPTY_VALUE_NOT_SET << UART_IF_TXFIFO_EMPTY_SHIFT)
|
||||
#define UART_IF_TXFIFO_EMPTY_VALUE_SET 1U
|
||||
#define UART_IF_TXFIFO_EMPTY_BITS_SET (UART_IF_TXFIFO_EMPTY_VALUE_SET << UART_IF_TXFIFO_EMPTY_SHIFT)
|
||||
|
||||
#define UART_IF_TXFIFO_FULL_SHIFT 14
|
||||
#define UART_IF_TXFIFO_FULL_WIDTH 1
|
||||
#define UART_IF_TXFIFO_FULL_MASK (((1U << UART_IF_TXFIFO_FULL_WIDTH) - 1U) << UART_IF_TXFIFO_FULL_SHIFT)
|
||||
#define UART_IF_TXFIFO_FULL_VALUE_NOT_SET 0U
|
||||
#define UART_IF_TXFIFO_FULL_BITS_NOT_SET (UART_IF_TXFIFO_FULL_VALUE_NOT_SET << UART_IF_TXFIFO_FULL_SHIFT)
|
||||
#define UART_IF_TXFIFO_FULL_VALUE_SET 1U
|
||||
#define UART_IF_TXFIFO_FULL_BITS_SET (UART_IF_TXFIFO_FULL_VALUE_SET << UART_IF_TXFIFO_FULL_SHIFT)
|
||||
|
||||
#define UART_IF_TXFIFO_HFULL_SHIFT 15
|
||||
#define UART_IF_TXFIFO_HFULL_WIDTH 1
|
||||
#define UART_IF_TXFIFO_HFULL_MASK (((1U << UART_IF_TXFIFO_HFULL_WIDTH) - 1U) << UART_IF_TXFIFO_HFULL_SHIFT)
|
||||
#define UART_IF_TXFIFO_HFULL_VALUE_NOT_SET 0U
|
||||
#define UART_IF_TXFIFO_HFULL_BITS_NOT_SET (UART_IF_TXFIFO_HFULL_VALUE_NOT_SET << UART_IF_TXFIFO_HFULL_SHIFT)
|
||||
#define UART_IF_TXFIFO_HFULL_VALUE_SET 1U
|
||||
#define UART_IF_TXFIFO_HFULL_BITS_SET (UART_IF_TXFIFO_HFULL_VALUE_SET << UART_IF_TXFIFO_HFULL_SHIFT)
|
||||
|
||||
#define UART_IF_TXBUSY_SHIFT 16
|
||||
#define UART_IF_TXBUSY_WIDTH 1
|
||||
#define UART_IF_TXBUSY_MASK (((1U << UART_IF_TXBUSY_WIDTH) - 1U) << UART_IF_TXBUSY_SHIFT)
|
||||
#define UART_IF_TXBUSY_VALUE_NOT_SET 0U
|
||||
#define UART_IF_TXBUSY_BITS_NOT_SET (UART_IF_TXBUSY_VALUE_NOT_SET << UART_IF_TXBUSY_SHIFT)
|
||||
#define UART_IF_TXBUSY_VALUE_SET 1U
|
||||
#define UART_IF_TXBUSY_BITS_SET (UART_IF_TXBUSY_VALUE_SET << UART_IF_TXBUSY_SHIFT)
|
||||
|
||||
#define UART_IF_RF_LEVEL_SHIFT 17
|
||||
#define UART_IF_RF_LEVEL_WIDTH 3
|
||||
#define UART_IF_RF_LEVEL_MASK (((1U << UART_IF_RF_LEVEL_WIDTH) - 1U) << UART_IF_RF_LEVEL_SHIFT)
|
||||
#define UART_IF_RF_LEVEL_VALUE_0_8_BYTE 0U
|
||||
#define UART_IF_RF_LEVEL_BITS_0_8_BYTE (UART_IF_RF_LEVEL_VALUE_0_8_BYTE << UART_IF_RF_LEVEL_SHIFT)
|
||||
#define UART_IF_RF_LEVEL_VALUE_1_BYTE 1U
|
||||
#define UART_IF_RF_LEVEL_BITS_1_BYTE (UART_IF_RF_LEVEL_VALUE_1_BYTE << UART_IF_RF_LEVEL_SHIFT)
|
||||
#define UART_IF_RF_LEVEL_VALUE_2_BYTE 2U
|
||||
#define UART_IF_RF_LEVEL_BITS_2_BYTE (UART_IF_RF_LEVEL_VALUE_2_BYTE << UART_IF_RF_LEVEL_SHIFT)
|
||||
#define UART_IF_RF_LEVEL_VALUE_3_BYTE 3U
|
||||
#define UART_IF_RF_LEVEL_BITS_3_BYTE (UART_IF_RF_LEVEL_VALUE_3_BYTE << UART_IF_RF_LEVEL_SHIFT)
|
||||
#define UART_IF_RF_LEVEL_VALUE_4_BYTE 4U
|
||||
#define UART_IF_RF_LEVEL_BITS_4_BYTE (UART_IF_RF_LEVEL_VALUE_4_BYTE << UART_IF_RF_LEVEL_SHIFT)
|
||||
#define UART_IF_RF_LEVEL_VALUE_5_BYTE 5U
|
||||
#define UART_IF_RF_LEVEL_BITS_5_BYTE (UART_IF_RF_LEVEL_VALUE_5_BYTE << UART_IF_RF_LEVEL_SHIFT)
|
||||
#define UART_IF_RF_LEVEL_VALUE_6_BYTE 6U
|
||||
#define UART_IF_RF_LEVEL_BITS_6_BYTE (UART_IF_RF_LEVEL_VALUE_6_BYTE << UART_IF_RF_LEVEL_SHIFT)
|
||||
#define UART_IF_RF_LEVEL_VALUE_7_BYTE 7U
|
||||
#define UART_IF_RF_LEVEL_BITS_7_BYTE (UART_IF_RF_LEVEL_VALUE_7_BYTE << UART_IF_RF_LEVEL_SHIFT)
|
||||
|
||||
#define UART_IF_TF_LEVEL_SHIFT 20
|
||||
#define UART_IF_TF_LEVEL_WIDTH 3
|
||||
#define UART_IF_TF_LEVEL_MASK (((1U << UART_IF_TF_LEVEL_WIDTH) - 1U) << UART_IF_TF_LEVEL_SHIFT)
|
||||
#define UART_IF_TF_LEVEL_VALUE_0_8_BYTE 0U
|
||||
#define UART_IF_TF_LEVEL_BITS_0_8_BYTE (UART_IF_TF_LEVEL_VALUE_0_8_BYTE << UART_IF_TF_LEVEL_SHIFT)
|
||||
#define UART_IF_TF_LEVEL_VALUE_1_BYTE 1U
|
||||
#define UART_IF_TF_LEVEL_BITS_1_BYTE (UART_IF_TF_LEVEL_VALUE_1_BYTE << UART_IF_TF_LEVEL_SHIFT)
|
||||
#define UART_IF_TF_LEVEL_VALUE_2_BYTE 2U
|
||||
#define UART_IF_TF_LEVEL_BITS_2_BYTE (UART_IF_TF_LEVEL_VALUE_2_BYTE << UART_IF_TF_LEVEL_SHIFT)
|
||||
#define UART_IF_TF_LEVEL_VALUE_3_BYTE 3U
|
||||
#define UART_IF_TF_LEVEL_BITS_3_BYTE (UART_IF_TF_LEVEL_VALUE_3_BYTE << UART_IF_TF_LEVEL_SHIFT)
|
||||
#define UART_IF_TF_LEVEL_VALUE_4_BYTE 4U
|
||||
#define UART_IF_TF_LEVEL_BITS_4_BYTE (UART_IF_TF_LEVEL_VALUE_4_BYTE << UART_IF_TF_LEVEL_SHIFT)
|
||||
#define UART_IF_TF_LEVEL_VALUE_5_BYTE 5U
|
||||
#define UART_IF_TF_LEVEL_BITS_5_BYTE (UART_IF_TF_LEVEL_VALUE_5_BYTE << UART_IF_TF_LEVEL_SHIFT)
|
||||
#define UART_IF_TF_LEVEL_VALUE_6_BYTE 6U
|
||||
#define UART_IF_TF_LEVEL_BITS_6_BYTE (UART_IF_TF_LEVEL_VALUE_6_BYTE << UART_IF_TF_LEVEL_SHIFT)
|
||||
#define UART_IF_TF_LEVEL_VALUE_7_BYTE 7U
|
||||
#define UART_IF_TF_LEVEL_BITS_7_BYTE (UART_IF_TF_LEVEL_VALUE_7_BYTE << UART_IF_TF_LEVEL_SHIFT)
|
||||
|
||||
#define UART_FIFO_RF_LEVEL_SHIFT 0
|
||||
#define UART_FIFO_RF_LEVEL_WIDTH 3
|
||||
#define UART_FIFO_RF_LEVEL_MASK (((1U << UART_FIFO_RF_LEVEL_WIDTH) - 1U) << UART_FIFO_RF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_RF_LEVEL_VALUE_1_BYTE 0U
|
||||
#define UART_FIFO_RF_LEVEL_BITS_1_BYTE (UART_FIFO_RF_LEVEL_VALUE_1_BYTE << UART_FIFO_RF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_RF_LEVEL_VALUE_2_BYTE 1U
|
||||
#define UART_FIFO_RF_LEVEL_BITS_2_BYTE (UART_FIFO_RF_LEVEL_VALUE_2_BYTE << UART_FIFO_RF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_RF_LEVEL_VALUE_3_BYTE 2U
|
||||
#define UART_FIFO_RF_LEVEL_BITS_3_BYTE (UART_FIFO_RF_LEVEL_VALUE_3_BYTE << UART_FIFO_RF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_RF_LEVEL_VALUE_4_BYTE 3U
|
||||
#define UART_FIFO_RF_LEVEL_BITS_4_BYTE (UART_FIFO_RF_LEVEL_VALUE_4_BYTE << UART_FIFO_RF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_RF_LEVEL_VALUE_5_BYTE 4U
|
||||
#define UART_FIFO_RF_LEVEL_BITS_5_BYTE (UART_FIFO_RF_LEVEL_VALUE_5_BYTE << UART_FIFO_RF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_RF_LEVEL_VALUE_6_BYTE 5U
|
||||
#define UART_FIFO_RF_LEVEL_BITS_6_BYTE (UART_FIFO_RF_LEVEL_VALUE_6_BYTE << UART_FIFO_RF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_RF_LEVEL_VALUE_7_BYTE 6U
|
||||
#define UART_FIFO_RF_LEVEL_BITS_7_BYTE (UART_FIFO_RF_LEVEL_VALUE_7_BYTE << UART_FIFO_RF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_RF_LEVEL_VALUE_8_BYTE 7U
|
||||
#define UART_FIFO_RF_LEVEL_BITS_8_BYTE (UART_FIFO_RF_LEVEL_VALUE_8_BYTE << UART_FIFO_RF_LEVEL_SHIFT)
|
||||
|
||||
#define UART_FIFO_TF_LEVEL_SHIFT 3
|
||||
#define UART_FIFO_TF_LEVEL_WIDTH 3
|
||||
#define UART_FIFO_TF_LEVEL_MASK (((1U << UART_FIFO_TF_LEVEL_WIDTH) - 1U) << UART_FIFO_TF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_TF_LEVEL_VALUE_0_BYTE 0U
|
||||
#define UART_FIFO_TF_LEVEL_BITS_0_BYTE (UART_FIFO_TF_LEVEL_VALUE_0_BYTE << UART_FIFO_TF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_TF_LEVEL_VALUE_1_BYTE 1U
|
||||
#define UART_FIFO_TF_LEVEL_BITS_1_BYTE (UART_FIFO_TF_LEVEL_VALUE_1_BYTE << UART_FIFO_TF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_TF_LEVEL_VALUE_2_BYTE 2U
|
||||
#define UART_FIFO_TF_LEVEL_BITS_2_BYTE (UART_FIFO_TF_LEVEL_VALUE_2_BYTE << UART_FIFO_TF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_TF_LEVEL_VALUE_3_BYTE 3U
|
||||
#define UART_FIFO_TF_LEVEL_BITS_3_BYTE (UART_FIFO_TF_LEVEL_VALUE_3_BYTE << UART_FIFO_TF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_TF_LEVEL_VALUE_4_BYTE 4U
|
||||
#define UART_FIFO_TF_LEVEL_BITS_4_BYTE (UART_FIFO_TF_LEVEL_VALUE_4_BYTE << UART_FIFO_TF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_TF_LEVEL_VALUE_5_BYTE 5U
|
||||
#define UART_FIFO_TF_LEVEL_BITS_5_BYTE (UART_FIFO_TF_LEVEL_VALUE_5_BYTE << UART_FIFO_TF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_TF_LEVEL_VALUE_6_BYTE 6U
|
||||
#define UART_FIFO_TF_LEVEL_BITS_6_BYTE (UART_FIFO_TF_LEVEL_VALUE_6_BYTE << UART_FIFO_TF_LEVEL_SHIFT)
|
||||
#define UART_FIFO_TF_LEVEL_VALUE_7_BYTE 7U
|
||||
#define UART_FIFO_TF_LEVEL_BITS_7_BYTE (UART_FIFO_TF_LEVEL_VALUE_7_BYTE << UART_FIFO_TF_LEVEL_SHIFT)
|
||||
|
||||
#define UART_FIFO_RF_CLR_SHIFT 6
|
||||
#define UART_FIFO_RF_CLR_WIDTH 1
|
||||
#define UART_FIFO_RF_CLR_MASK (((1U << UART_FIFO_RF_CLR_WIDTH) - 1U) << UART_FIFO_RF_CLR_SHIFT)
|
||||
#define UART_FIFO_RF_CLR_VALUE_DISABLE 0U
|
||||
#define UART_FIFO_RF_CLR_BITS_DISABLE (UART_FIFO_RF_CLR_VALUE_DISABLE << UART_FIFO_RF_CLR_SHIFT)
|
||||
#define UART_FIFO_RF_CLR_VALUE_ENABLE 1U
|
||||
#define UART_FIFO_RF_CLR_BITS_ENABLE (UART_FIFO_RF_CLR_VALUE_ENABLE << UART_FIFO_RF_CLR_SHIFT)
|
||||
|
||||
#define UART_FIFO_TF_CLR_SHIFT 7
|
||||
#define UART_FIFO_TF_CLR_WIDTH 1
|
||||
#define UART_FIFO_TF_CLR_MASK (((1U << UART_FIFO_TF_CLR_WIDTH) - 1U) << UART_FIFO_TF_CLR_SHIFT)
|
||||
#define UART_FIFO_TF_CLR_VALUE_DISABLE 0U
|
||||
#define UART_FIFO_TF_CLR_BITS_DISABLE (UART_FIFO_TF_CLR_VALUE_DISABLE << UART_FIFO_TF_CLR_SHIFT)
|
||||
#define UART_FIFO_TF_CLR_VALUE_ENABLE 1U
|
||||
#define UART_FIFO_TF_CLR_BITS_ENABLE (UART_FIFO_TF_CLR_VALUE_ENABLE << UART_FIFO_TF_CLR_SHIFT)
|
||||
|
||||
#define UART_FC_CTSEN_SHIFT 0
|
||||
#define UART_FC_CTSEN_WIDTH 1
|
||||
#define UART_FC_CTSEN_MASK (((1U << UART_FC_CTSEN_WIDTH) - 1U) << UART_FC_CTSEN_SHIFT)
|
||||
#define UART_FC_CTSEN_VALUE_DISABLE 0U
|
||||
#define UART_FC_CTSEN_BITS_DISABLE (UART_FC_CTSEN_VALUE_DISABLE << UART_FC_CTSEN_SHIFT)
|
||||
#define UART_FC_CTSEN_VALUE_ENABLE 1U
|
||||
#define UART_FC_CTSEN_BITS_ENABLE (UART_FC_CTSEN_VALUE_ENABLE << UART_FC_CTSEN_SHIFT)
|
||||
|
||||
#define UART_FC_RTSEN_SHIFT 1
|
||||
#define UART_FC_RTSEN_WIDTH 1
|
||||
#define UART_FC_RTSEN_MASK (((1U << UART_FC_RTSEN_WIDTH) - 1U) << UART_FC_RTSEN_SHIFT)
|
||||
#define UART_FC_RTSEN_VALUE_DISABLE 0U
|
||||
#define UART_FC_RTSEN_BITS_DISABLE (UART_FC_RTSEN_VALUE_DISABLE << UART_FC_RTSEN_SHIFT)
|
||||
#define UART_FC_RTSEN_VALUE_ENABLE 1U
|
||||
#define UART_FC_RTSEN_BITS_ENABLE (UART_FC_RTSEN_VALUE_ENABLE << UART_FC_RTSEN_SHIFT)
|
||||
|
||||
#define UART_FC_CTSPOL_SHIFT 2
|
||||
#define UART_FC_CTSPOL_WIDTH 1
|
||||
#define UART_FC_CTSPOL_MASK (((1U << UART_FC_CTSPOL_WIDTH) - 1U) << UART_FC_CTSPOL_SHIFT)
|
||||
#define UART_FC_CTSPOL_VALUE_LOW 0U
|
||||
#define UART_FC_CTSPOL_BITS_LOW (UART_FC_CTSPOL_VALUE_LOW << UART_FC_CTSPOL_SHIFT)
|
||||
#define UART_FC_CTSPOL_VALUE_HIGH 1U
|
||||
#define UART_FC_CTSPOL_BITS_HIGH (UART_FC_CTSPOL_VALUE_HIGH << UART_FC_CTSPOL_SHIFT)
|
||||
|
||||
#define UART_FC_RTSPOL_SHIFT 3
|
||||
#define UART_FC_RTSPOL_WIDTH 1
|
||||
#define UART_FC_RTSPOL_MASK (((1U << UART_FC_RTSPOL_WIDTH) - 1U) << UART_FC_RTSPOL_SHIFT)
|
||||
#define UART_FC_RTSPOL_VALUE_LOW 0U
|
||||
#define UART_FC_RTSPOL_BITS_LOW (UART_FC_RTSPOL_VALUE_LOW << UART_FC_RTSPOL_SHIFT)
|
||||
#define UART_FC_RTSPOL_VALUE_HIGH 1U
|
||||
#define UART_FC_RTSPOL_BITS_HIGH (UART_FC_RTSPOL_VALUE_HIGH << UART_FC_RTSPOL_SHIFT)
|
||||
|
||||
#define UART_FC_CTS_SIGNAL_SHIFT 4
|
||||
#define UART_FC_CTS_SIGNAL_WIDTH 1
|
||||
#define UART_FC_CTS_SIGNAL_MASK (((1U << UART_FC_CTS_SIGNAL_WIDTH) - 1U) << UART_FC_CTS_SIGNAL_SHIFT)
|
||||
#define UART_FC_CTS_SIGNAL_VALUE_LOW 0U
|
||||
#define UART_FC_CTS_SIGNAL_BITS_LOW (UART_FC_CTS_SIGNAL_VALUE_LOW << UART_FC_CTS_SIGNAL_SHIFT)
|
||||
#define UART_FC_CTS_SIGNAL_VALUE_HIGH 1U
|
||||
#define UART_FC_CTS_SIGNAL_BITS_HIGH (UART_FC_CTS_SIGNAL_VALUE_HIGH << UART_FC_CTS_SIGNAL_SHIFT)
|
||||
|
||||
#define UART_FC_RTS_SIGNAL_SHIFT 5
|
||||
#define UART_FC_RTS_SIGNAL_WIDTH 1
|
||||
#define UART_FC_RTS_SIGNAL_MASK (((1U << UART_FC_RTS_SIGNAL_WIDTH) - 1U) << UART_FC_RTS_SIGNAL_SHIFT)
|
||||
#define UART_FC_RTS_SIGNAL_VALUE_LOW 0U
|
||||
#define UART_FC_RTS_SIGNAL_BITS_LOW (UART_FC_RTS_SIGNAL_VALUE_LOW << UART_FC_RTS_SIGNAL_SHIFT)
|
||||
#define UART_FC_RTS_SIGNAL_VALUE_HIGH 1U
|
||||
#define UART_FC_RTS_SIGNAL_BITS_HIGH (UART_FC_RTS_SIGNAL_VALUE_HIGH << UART_FC_RTS_SIGNAL_SHIFT)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
4
compile-with-docker.bat
Normal file
4
compile-with-docker.bat
Normal file
@@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
docker build -t uvk5 .
|
||||
docker run --rm -v %CD%\compiled-firmware:/app/compiled-firmware uvk5 /bin/bash -c "cd /app && make clean && make && cp firmware* compiled-firmware/"
|
||||
pause
|
||||
3
compile-with-docker.sh
Executable file
3
compile-with-docker.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
docker build -t uvk5 .
|
||||
docker run --rm -v ${PWD}/compiled-firmware:/app/compiled-firmware uvk5 /bin/bash -c "cd /app && make && cp firmware* compiled-firmware/"
|
||||
113
dcs.c
Normal file
113
dcs.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "dcs.h"
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||||
#endif
|
||||
|
||||
// CTCSS Hz * 10
|
||||
const uint16_t CTCSS_Options[50] = {
|
||||
670, 693, 719, 744, 770, 797, 825, 854, 885, 915,
|
||||
948, 974, 1000, 1035, 1072, 1109, 1148, 1188, 1230, 1273,
|
||||
1318, 1365, 1413, 1462, 1514, 1567, 1598, 1622, 1655, 1679,
|
||||
1713, 1738, 1773, 1799, 1835, 1862, 1899, 1928, 1966, 1995,
|
||||
2035, 2065, 2107, 2181, 2257, 2291, 2336, 2418, 2503, 2541
|
||||
};
|
||||
|
||||
const uint16_t DCS_Options[104] = {
|
||||
0x0013, 0x0015, 0x0016, 0x0019, 0x001A, 0x001E, 0x0023, 0x0027,
|
||||
0x0029, 0x002B, 0x002C, 0x0035, 0x0039, 0x003A, 0x003B, 0x003C,
|
||||
0x004C, 0x004D, 0x004E, 0x0052, 0x0055, 0x0059, 0x005A, 0x005C,
|
||||
0x0063, 0x0065, 0x006A, 0x006D, 0x006E, 0x0072, 0x0075, 0x007A,
|
||||
0x007C, 0x0085, 0x008A, 0x0093, 0x0095, 0x0096, 0x00A3, 0x00A4,
|
||||
0x00A5, 0x00A6, 0x00A9, 0x00AA, 0x00AD, 0x00B1, 0x00B3, 0x00B5,
|
||||
0x00B6, 0x00B9, 0x00BC, 0x00C6, 0x00C9, 0x00CD, 0x00D5, 0x00D9,
|
||||
0x00DA, 0x00E3, 0x00E6, 0x00E9, 0x00EE, 0x00F4, 0x00F5, 0x00F9,
|
||||
0x0109, 0x010A, 0x010B, 0x0113, 0x0119, 0x011A, 0x0125, 0x0126,
|
||||
0x012A, 0x012C, 0x012D, 0x0132, 0x0134, 0x0135, 0x0136, 0x0143,
|
||||
0x0146, 0x014E, 0x0153, 0x0156, 0x015A, 0x0166, 0x0175, 0x0186,
|
||||
0x018A, 0x0194, 0x0197, 0x0199, 0x019A, 0x01AC, 0x01B2, 0x01B4,
|
||||
0x01C3, 0x01CA, 0x01D3, 0x01D9, 0x01DA, 0x01DC, 0x01E3, 0x01EC,
|
||||
};
|
||||
|
||||
static uint32_t DCS_CalculateGolay(uint32_t CodeWord)
|
||||
{
|
||||
unsigned int i;
|
||||
uint32_t Word = CodeWord;
|
||||
for (i = 0; i < 12; i++)
|
||||
{
|
||||
Word <<= 1;
|
||||
if (Word & 0x1000)
|
||||
Word ^= 0x08EA;
|
||||
}
|
||||
return CodeWord | ((Word & 0x0FFE) << 11);
|
||||
}
|
||||
|
||||
uint32_t DCS_GetGolayCodeWord(DCS_CodeType_t CodeType, uint8_t Option)
|
||||
{
|
||||
uint32_t Code = DCS_CalculateGolay(DCS_Options[Option] + 0x800U);
|
||||
if (CodeType == CODE_TYPE_REVERSE_DIGITAL)
|
||||
Code ^= 0x7FFFFF;
|
||||
return Code;
|
||||
}
|
||||
|
||||
uint8_t DCS_GetCdcssCode(uint32_t Code)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < 23; i++)
|
||||
{
|
||||
uint32_t Shift;
|
||||
|
||||
if (((Code >> 9) & 0x7U) == 4)
|
||||
{
|
||||
unsigned int j;
|
||||
for (j = 0; j < ARRAY_SIZE(DCS_Options); j++)
|
||||
if (DCS_Options[j] == (Code & 0x1FF))
|
||||
if (DCS_GetGolayCodeWord(2, j) == Code)
|
||||
return j;
|
||||
}
|
||||
|
||||
Shift = Code >> 1;
|
||||
if (Code & 1U)
|
||||
Shift |= 0x400000U;
|
||||
Code = Shift;
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
uint8_t DCS_GetCtcssCode(int Code)
|
||||
{
|
||||
unsigned int i;
|
||||
uint8_t Result = 0xFF;
|
||||
int Smallest = ARRAY_SIZE(CTCSS_Options);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(CTCSS_Options); i++)
|
||||
{
|
||||
int Delta = Code - CTCSS_Options[i];
|
||||
if (Delta < 0)
|
||||
Delta = -(Code - CTCSS_Options[i]);
|
||||
if (Smallest > Delta)
|
||||
{
|
||||
Smallest = Delta;
|
||||
Result = i;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
45
dcs.h
Normal file
45
dcs.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DCS_H
|
||||
#define DCS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum DCS_CodeType_t
|
||||
{
|
||||
CODE_TYPE_OFF = 0,
|
||||
CODE_TYPE_CONTINUOUS_TONE,
|
||||
CODE_TYPE_DIGITAL,
|
||||
CODE_TYPE_REVERSE_DIGITAL
|
||||
};
|
||||
|
||||
typedef enum DCS_CodeType_t DCS_CodeType_t;
|
||||
|
||||
enum {
|
||||
CDCSS_POSITIVE_CODE = 1U,
|
||||
CDCSS_NEGATIVE_CODE = 2U,
|
||||
};
|
||||
|
||||
extern const uint16_t CTCSS_Options[50];
|
||||
extern const uint16_t DCS_Options[104];
|
||||
|
||||
uint32_t DCS_GetGolayCodeWord(DCS_CodeType_t CodeType, uint8_t Option);
|
||||
uint8_t DCS_GetCdcssCode(uint32_t Code);
|
||||
uint8_t DCS_GetCtcssCode(int Code);
|
||||
|
||||
#endif
|
||||
|
||||
48
debugging.h
Normal file
48
debugging.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef DEBUGGING_H
|
||||
#define DEBUGGING_H
|
||||
|
||||
#ifdef ENABLE_UART
|
||||
|
||||
#include "driver/uart.h"
|
||||
#include "driver/bk4819.h"
|
||||
#include "string.h"
|
||||
#include "external/printf/printf.h"
|
||||
#include "am_fix.h"
|
||||
|
||||
static inline void LogUart(const char *const str)
|
||||
{
|
||||
UART_Send(str, strlen(str));
|
||||
}
|
||||
|
||||
static inline void LogUartf(const char* format, ...)
|
||||
{
|
||||
char buffer[128];
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
vsnprintf(buffer, (size_t)-1, format, va);
|
||||
va_end(va);
|
||||
UART_Send(buffer, strlen(buffer));
|
||||
}
|
||||
|
||||
static inline void LogRegUart(uint16_t reg)
|
||||
{
|
||||
uint16_t regVal = BK4819_ReadRegister(reg);
|
||||
char buf[32];
|
||||
sprintf(buf, "reg%02X: %04X\n", reg, regVal);
|
||||
LogUart(buf);
|
||||
}
|
||||
|
||||
static inline void LogPrint()
|
||||
{
|
||||
uint16_t rssi = BK4819_GetRSSI();
|
||||
uint16_t reg7e = BK4819_ReadRegister(0x7E);
|
||||
char buf[32];
|
||||
sprintf(buf, "reg7E: %d %2d %6d %2d %d rssi: %d\n", (reg7e >> 15),
|
||||
(reg7e >> 12) & 0b111, (reg7e >> 5) & 0b1111111,
|
||||
(reg7e >> 2) & 0b111, (reg7e >> 0) & 0b11, rssi);
|
||||
LogUart(buf);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
120
dp32g030.cfg
Normal file
120
dp32g030.cfg
Normal 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
|
||||
165
driver/adc.c
Normal file
165
driver/adc.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ARMCM0.h"
|
||||
#include "adc.h"
|
||||
#include "bsp/dp32g030/irq.h"
|
||||
#include "bsp/dp32g030/saradc.h"
|
||||
#include "bsp/dp32g030/syscon.h"
|
||||
|
||||
uint8_t ADC_GetChannelNumber(ADC_CH_MASK Mask)
|
||||
{
|
||||
if (Mask & ADC_CH15) return 15U;
|
||||
if (Mask & ADC_CH14) return 14U;
|
||||
if (Mask & ADC_CH13) return 13U;
|
||||
if (Mask & ADC_CH12) return 12U;
|
||||
if (Mask & ADC_CH11) return 11U;
|
||||
if (Mask & ADC_CH10) return 10U;
|
||||
if (Mask & ADC_CH9) return 9U;
|
||||
if (Mask & ADC_CH8) return 8U;
|
||||
if (Mask & ADC_CH7) return 7U;
|
||||
if (Mask & ADC_CH6) return 6U;
|
||||
if (Mask & ADC_CH5) return 5U;
|
||||
if (Mask & ADC_CH4) return 4U;
|
||||
if (Mask & ADC_CH3) return 3U;
|
||||
if (Mask & ADC_CH2) return 2U;
|
||||
if (Mask & ADC_CH1) return 1U;
|
||||
if (Mask & ADC_CH0) return 0U;
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
void ADC_Disable(void)
|
||||
{
|
||||
SARADC_CFG = (SARADC_CFG & ~SARADC_CFG_ADC_EN_MASK) | SARADC_CFG_ADC_EN_BITS_DISABLE;
|
||||
}
|
||||
|
||||
void ADC_Enable(void)
|
||||
{
|
||||
SARADC_CFG = (SARADC_CFG & ~SARADC_CFG_ADC_EN_MASK) | SARADC_CFG_ADC_EN_BITS_ENABLE;
|
||||
}
|
||||
|
||||
void ADC_SoftReset(void)
|
||||
{
|
||||
SARADC_START = (SARADC_START & ~SARADC_START_SOFT_RESET_MASK) | SARADC_START_SOFT_RESET_BITS_ASSERT;
|
||||
SARADC_START = (SARADC_START & ~SARADC_START_SOFT_RESET_MASK) | SARADC_START_SOFT_RESET_BITS_DEASSERT;
|
||||
}
|
||||
|
||||
// The firmware thinks W_SARADC_SMPL_CLK_SEL is at [8:7] but the TRM says it's at [10:9]
|
||||
#define FW_R_SARADC_SMPL_SHIFT 7
|
||||
#define FW_R_SARADC_SMPL_MASK (3U << FW_R_SARADC_SMPL_SHIFT)
|
||||
|
||||
uint32_t ADC_GetClockConfig(void)
|
||||
{
|
||||
uint32_t Value;
|
||||
|
||||
Value = SYSCON_CLK_SEL;
|
||||
|
||||
Value = 0
|
||||
| (Value & ~(SYSCON_CLK_SEL_R_PLL_MASK | FW_R_SARADC_SMPL_MASK))
|
||||
| (((Value & SYSCON_CLK_SEL_R_PLL_MASK) >> SYSCON_CLK_SEL_R_PLL_SHIFT) << SYSCON_CLK_SEL_W_PLL_SHIFT)
|
||||
| (((Value & FW_R_SARADC_SMPL_MASK) >> FW_R_SARADC_SMPL_SHIFT) << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT)
|
||||
;
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
void ADC_Configure(ADC_Config_t *pAdc)
|
||||
{
|
||||
SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SARADC_MASK) | SYSCON_DEV_CLK_GATE_SARADC_BITS_ENABLE;
|
||||
|
||||
ADC_Disable();
|
||||
|
||||
SYSCON_CLK_SEL = (ADC_GetClockConfig() & ~SYSCON_CLK_SEL_W_SARADC_SMPL_MASK) | ((pAdc->CLK_SEL << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT) & SYSCON_CLK_SEL_W_SARADC_SMPL_MASK);
|
||||
|
||||
SARADC_CFG = 0
|
||||
| (SARADC_CFG & ~(0
|
||||
| SARADC_CFG_CH_SEL_MASK
|
||||
| SARADC_CFG_AVG_MASK
|
||||
| SARADC_CFG_CONT_MASK
|
||||
| SARADC_CFG_SMPL_SETUP_MASK
|
||||
| SARADC_CFG_MEM_MODE_MASK
|
||||
| SARADC_CFG_SMPL_CLK_MASK
|
||||
| SARADC_CFG_SMPL_WIN_MASK
|
||||
| SARADC_CFG_ADC_TRIG_MASK
|
||||
| SARADC_CFG_DMA_EN_MASK
|
||||
))
|
||||
| ((pAdc->CH_SEL << SARADC_CFG_CH_SEL_SHIFT) & SARADC_CFG_CH_SEL_MASK)
|
||||
| ((pAdc->AVG << SARADC_CFG_AVG_SHIFT) & SARADC_CFG_AVG_MASK)
|
||||
| ((pAdc->CONT << SARADC_CFG_CONT_SHIFT) & SARADC_CFG_CONT_MASK)
|
||||
| ((pAdc->SMPL_SETUP << SARADC_CFG_SMPL_SETUP_SHIFT) & SARADC_CFG_SMPL_SETUP_MASK)
|
||||
| ((pAdc->MEM_MODE << SARADC_CFG_MEM_MODE_SHIFT) & SARADC_CFG_MEM_MODE_MASK)
|
||||
| ((pAdc->SMPL_CLK << SARADC_CFG_SMPL_CLK_SHIFT) & SARADC_CFG_SMPL_CLK_MASK)
|
||||
| ((pAdc->SMPL_WIN << SARADC_CFG_SMPL_WIN_SHIFT) & SARADC_CFG_SMPL_WIN_MASK)
|
||||
| ((pAdc->ADC_TRIG << SARADC_CFG_ADC_TRIG_SHIFT) & SARADC_CFG_ADC_TRIG_MASK)
|
||||
| ((pAdc->DMA_EN << SARADC_CFG_DMA_EN_SHIFT) & SARADC_CFG_DMA_EN_MASK)
|
||||
;
|
||||
|
||||
SARADC_EXTTRIG_SEL = pAdc->EXTTRIG_SEL;
|
||||
|
||||
if (pAdc->CALIB_OFFSET_VALID) {
|
||||
SARADC_CALIB_OFFSET = (SARADC_CALIB_OFFSET & ~SARADC_CALIB_OFFSET_VALID_MASK) | SARADC_CALIB_OFFSET_VALID_BITS_YES;
|
||||
} else {
|
||||
SARADC_CALIB_OFFSET = (SARADC_CALIB_OFFSET & ~SARADC_CALIB_OFFSET_VALID_MASK) | SARADC_CALIB_OFFSET_VALID_BITS_NO;
|
||||
}
|
||||
if (pAdc->CALIB_KD_VALID) {
|
||||
SARADC_CALIB_KD = (SARADC_CALIB_KD & ~SARADC_CALIB_KD_VALID_MASK) | SARADC_CALIB_KD_VALID_BITS_YES;
|
||||
} else {
|
||||
SARADC_CALIB_KD = (SARADC_CALIB_KD & ~SARADC_CALIB_KD_VALID_MASK) | SARADC_CALIB_KD_VALID_BITS_NO;
|
||||
}
|
||||
|
||||
SARADC_IF = 0xFFFFFFFF;
|
||||
SARADC_IE = 0
|
||||
| (SARADC_IE & ~(0
|
||||
| SARADC_IE_CHx_EOC_MASK
|
||||
| SARADC_IE_FIFO_FULL_MASK
|
||||
| SARADC_IE_FIFO_HFULL_MASK
|
||||
))
|
||||
| ((pAdc->IE_CHx_EOC << SARADC_IE_CHx_EOC_SHIFT) & SARADC_IE_CHx_EOC_MASK)
|
||||
| ((pAdc->IE_FIFO_FULL << SARADC_IE_FIFO_FULL_SHIFT) & SARADC_IE_FIFO_FULL_MASK)
|
||||
| ((pAdc->IE_FIFO_HFULL << SARADC_IE_FIFO_HFULL_SHIFT) & SARADC_IE_FIFO_HFULL_MASK)
|
||||
;
|
||||
|
||||
if (SARADC_IE == 0) {
|
||||
NVIC_DisableIRQ((IRQn_Type)DP32_SARADC_IRQn);
|
||||
} else {
|
||||
NVIC_EnableIRQ((IRQn_Type)DP32_SARADC_IRQn);
|
||||
}
|
||||
}
|
||||
|
||||
void ADC_Start(void)
|
||||
{
|
||||
SARADC_START = (SARADC_START & ~SARADC_START_START_MASK) | SARADC_START_START_BITS_ENABLE;
|
||||
}
|
||||
|
||||
bool ADC_CheckEndOfConversion(ADC_CH_MASK Mask)
|
||||
{
|
||||
volatile ADC_Channel_t *pChannels = (volatile ADC_Channel_t *)&SARADC_CH0;
|
||||
uint8_t Channel = ADC_GetChannelNumber(Mask);
|
||||
|
||||
return (pChannels[Channel].STAT & ADC_CHx_STAT_EOC_MASK) >> ADC_CHx_STAT_EOC_SHIFT;
|
||||
}
|
||||
|
||||
uint16_t ADC_GetValue(ADC_CH_MASK Mask)
|
||||
{
|
||||
volatile ADC_Channel_t *pChannels = (volatile ADC_Channel_t *)&SARADC_CH0;
|
||||
uint8_t Channel = ADC_GetChannelNumber(Mask);
|
||||
|
||||
SARADC_IF = 1 << Channel; // TODO: Or just use 'Mask'
|
||||
|
||||
return (pChannels[Channel].DATA & ADC_CHx_DATA_DATA_MASK) >> ADC_CHx_DATA_DATA_SHIFT;
|
||||
}
|
||||
|
||||
75
driver/adc.h
Normal file
75
driver/adc.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_ADC_H
|
||||
#define DRIVER_ADC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum ADC_CH_MASK {
|
||||
ADC_CH0 = 0x0001U,
|
||||
ADC_CH1 = 0x0002U,
|
||||
ADC_CH2 = 0x0004U,
|
||||
ADC_CH3 = 0x0008U,
|
||||
ADC_CH4 = 0x0010U,
|
||||
ADC_CH5 = 0x0020U,
|
||||
ADC_CH6 = 0x0040U,
|
||||
ADC_CH7 = 0x0080U,
|
||||
ADC_CH8 = 0x0100U,
|
||||
ADC_CH9 = 0x0200U,
|
||||
ADC_CH10 = 0x0400U,
|
||||
ADC_CH11 = 0x0800U,
|
||||
ADC_CH12 = 0x1000U,
|
||||
ADC_CH13 = 0x2000U,
|
||||
ADC_CH14 = 0x4000U,
|
||||
ADC_CH15 = 0x8000U,
|
||||
};
|
||||
|
||||
typedef enum ADC_CH_MASK ADC_CH_MASK;
|
||||
|
||||
typedef struct {
|
||||
uint16_t EXTTRIG_SEL;
|
||||
uint16_t IE_CHx_EOC;
|
||||
ADC_CH_MASK CH_SEL;
|
||||
uint8_t CLK_SEL;
|
||||
uint8_t AVG;
|
||||
uint8_t CONT;
|
||||
uint8_t MEM_MODE;
|
||||
uint8_t SMPL_CLK;
|
||||
uint8_t SMPL_SETUP;
|
||||
uint8_t SMPL_WIN;
|
||||
uint8_t ADC_TRIG;
|
||||
uint8_t DMA_EN;
|
||||
uint8_t IE_FIFO_HFULL;
|
||||
uint8_t IE_FIFO_FULL;
|
||||
bool CALIB_OFFSET_VALID;
|
||||
bool CALIB_KD_VALID;
|
||||
uint8_t _pad[1];
|
||||
} ADC_Config_t;
|
||||
|
||||
uint8_t ADC_GetChannelNumber(ADC_CH_MASK Mask);
|
||||
void ADC_Disable(void);
|
||||
void ADC_Enable(void);
|
||||
void ADC_SoftReset(void);
|
||||
uint32_t ADC_GetClockConfig(void);
|
||||
void ADC_Configure(ADC_Config_t *pAdc);
|
||||
void ADC_Start(void);
|
||||
bool ADC_CheckEndOfConversion(ADC_CH_MASK Mask);
|
||||
uint16_t ADC_GetValue(ADC_CH_MASK Mask);
|
||||
|
||||
#endif
|
||||
|
||||
74
driver/aes.c
Normal file
74
driver/aes.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "bsp/dp32g030/aes.h"
|
||||
#include "driver/aes.h"
|
||||
|
||||
static void AES_Setup_ENC_CBC(bool IsDecrypt, const void *pKey, const void *pIv)
|
||||
{
|
||||
const uint32_t *pK = (const uint32_t *)pKey;
|
||||
const uint32_t *pI = (const uint32_t *)pIv;
|
||||
|
||||
(void)IsDecrypt; // unused
|
||||
|
||||
AES_CR = (AES_CR & ~AES_CR_EN_MASK) | AES_CR_EN_BITS_DISABLE;
|
||||
AES_CR = AES_CR_CHMOD_BITS_CBC;
|
||||
AES_KEYR3 = pK[0];
|
||||
AES_KEYR2 = pK[1];
|
||||
AES_KEYR1 = pK[2];
|
||||
AES_KEYR0 = pK[3];
|
||||
AES_IVR3 = pI[0];
|
||||
AES_IVR2 = pI[1];
|
||||
AES_IVR1 = pI[2];
|
||||
AES_IVR0 = pI[3];
|
||||
AES_CR = (AES_CR & ~AES_CR_EN_MASK) | AES_CR_EN_BITS_ENABLE;
|
||||
}
|
||||
|
||||
static void AES_Transform(const void *pIn, void *pOut)
|
||||
{
|
||||
const uint32_t *pI = (const uint32_t *)pIn;
|
||||
uint32_t *pO = (uint32_t *)pOut;
|
||||
|
||||
AES_DINR = pI[0];
|
||||
AES_DINR = pI[1];
|
||||
AES_DINR = pI[2];
|
||||
AES_DINR = pI[3];
|
||||
|
||||
while ((AES_SR & AES_SR_CCF_MASK) == AES_SR_CCF_BITS_NOT_COMPLETE) {
|
||||
}
|
||||
|
||||
pO[0] = AES_DOUTR;
|
||||
pO[1] = AES_DOUTR;
|
||||
pO[2] = AES_DOUTR;
|
||||
pO[3] = AES_DOUTR;
|
||||
|
||||
AES_CR |= AES_CR_CCFC_BITS_SET;
|
||||
}
|
||||
|
||||
void AES_Encrypt(const void *pKey, const void *pIv, const void *pIn, void *pOut, uint8_t NumBlocks)
|
||||
{
|
||||
const uint8_t *pI = (const uint8_t *)pIn;
|
||||
uint8_t *pO = (uint8_t *)pOut;
|
||||
uint8_t i;
|
||||
|
||||
AES_Setup_ENC_CBC(0, pKey, pIv);
|
||||
for (i = 0; i < NumBlocks; i++) {
|
||||
AES_Transform(pI + (i * 16), pO + (i * 16));
|
||||
}
|
||||
}
|
||||
|
||||
25
driver/aes.h
Normal file
25
driver/aes.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_AES_H
|
||||
#define DRIVER_AES_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void AES_Encrypt(const void *pKey, const void *pIv, const void *pIn, void *pOut, uint8_t NumBlocks);
|
||||
|
||||
#endif
|
||||
|
||||
118
driver/backlight.c
Normal file
118
driver/backlight.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "backlight.h"
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "bsp/dp32g030/pwmplus.h"
|
||||
#include "bsp/dp32g030/portcon.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "settings.h"
|
||||
|
||||
// this is decremented once every 500ms
|
||||
uint16_t gBacklightCountdown_500ms = 0;
|
||||
bool backlightOn;
|
||||
|
||||
void BACKLIGHT_InitHardware()
|
||||
{
|
||||
// 48MHz / 94 / 1024 ~ 500Hz
|
||||
const uint32_t PWM_FREQUENCY_HZ = 1000;
|
||||
PWM_PLUS0_CLKSRC |= ((48000000 / 1024 / PWM_FREQUENCY_HZ) << 16);
|
||||
PWM_PLUS0_PERIOD = 1023;
|
||||
|
||||
PORTCON_PORTB_SEL0 &= ~(0
|
||||
// Back light
|
||||
| PORTCON_PORTB_SEL0_B6_MASK
|
||||
);
|
||||
PORTCON_PORTB_SEL0 |= 0
|
||||
// Back light PWM
|
||||
| PORTCON_PORTB_SEL0_B6_BITS_PWMP0_CH0
|
||||
;
|
||||
|
||||
PWM_PLUS0_GEN =
|
||||
PWMPLUS_GEN_CH0_OE_BITS_ENABLE |
|
||||
PWMPLUS_GEN_CH0_OUTINV_BITS_ENABLE |
|
||||
0;
|
||||
|
||||
PWM_PLUS0_CFG =
|
||||
PWMPLUS_CFG_CNT_REP_BITS_ENABLE |
|
||||
PWMPLUS_CFG_COUNTER_EN_BITS_ENABLE |
|
||||
0;
|
||||
}
|
||||
|
||||
void BACKLIGHT_TurnOn(void)
|
||||
{
|
||||
if (gEeprom.BACKLIGHT_TIME == 0) {
|
||||
BACKLIGHT_TurnOff();
|
||||
return;
|
||||
}
|
||||
|
||||
backlightOn = true;
|
||||
BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MAX);
|
||||
|
||||
switch (gEeprom.BACKLIGHT_TIME) {
|
||||
default:
|
||||
case 1: // 5 sec
|
||||
case 2: // 10 sec
|
||||
case 3: // 20 sec
|
||||
gBacklightCountdown_500ms = 1 + (2 << (gEeprom.BACKLIGHT_TIME - 1)) * 5;
|
||||
break;
|
||||
case 4: // 1 min
|
||||
case 5: // 2 min
|
||||
case 6: // 4 min
|
||||
gBacklightCountdown_500ms = 1 + (2 << (gEeprom.BACKLIGHT_TIME - 4)) * 60;
|
||||
break;
|
||||
case 7: // always on
|
||||
gBacklightCountdown_500ms = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BACKLIGHT_TurnOff()
|
||||
{
|
||||
#ifdef ENABLE_BLMIN_TMP_OFF
|
||||
register uint8_t tmp;
|
||||
|
||||
if (gEeprom.BACKLIGHT_MIN_STAT == BLMIN_STAT_ON)
|
||||
tmp = gEeprom.BACKLIGHT_MIN;
|
||||
else
|
||||
tmp = 0;
|
||||
|
||||
BACKLIGHT_SetBrightness(tmp);
|
||||
#else
|
||||
BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MIN);
|
||||
#endif
|
||||
gBacklightCountdown_500ms = 0;
|
||||
backlightOn = false;
|
||||
}
|
||||
|
||||
bool BACKLIGHT_IsOn()
|
||||
{
|
||||
return backlightOn;
|
||||
}
|
||||
|
||||
static uint8_t currentBrightness;
|
||||
|
||||
void BACKLIGHT_SetBrightness(uint8_t brigtness)
|
||||
{
|
||||
currentBrightness = brigtness;
|
||||
PWM_PLUS0_CH0_COMP = (1 << brigtness) - 1;
|
||||
//PWM_PLUS0_SWLOAD = 1;
|
||||
}
|
||||
|
||||
uint8_t BACKLIGHT_GetBrightness(void)
|
||||
{
|
||||
return currentBrightness;
|
||||
}
|
||||
41
driver/backlight.h
Normal file
41
driver/backlight.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_BACKLIGHT_H
|
||||
#define DRIVER_BACKLIGHT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
extern uint16_t gBacklightCountdown_500ms;
|
||||
extern uint8_t gBacklightBrightness;
|
||||
|
||||
#ifdef ENABLE_BLMIN_TMP_OFF
|
||||
typedef enum {
|
||||
BLMIN_STAT_ON,
|
||||
BLMIN_STAT_OFF,
|
||||
BLMIN_STAT_UNKNOWN
|
||||
} BLMIN_STAT_t;
|
||||
#endif
|
||||
|
||||
void BACKLIGHT_InitHardware();
|
||||
void BACKLIGHT_TurnOn();
|
||||
void BACKLIGHT_TurnOff();
|
||||
bool BACKLIGHT_IsOn();
|
||||
void BACKLIGHT_SetBrightness(uint8_t brigtness);
|
||||
uint8_t BACKLIGHT_GetBrightness(void);
|
||||
|
||||
#endif
|
||||
57
driver/bk1080-regs.h
Normal file
57
driver/bk1080-regs.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BK1080_REGS_H
|
||||
#define BK1080_REGS_H
|
||||
|
||||
enum BK1080_Register_t {
|
||||
BK1080_REG_00 = 0x00U,
|
||||
BK1080_REG_02_POWER_CONFIGURATION = 0x02U,
|
||||
BK1080_REG_03_CHANNEL = 0x03U,
|
||||
BK1080_REG_05_SYSTEM_CONFIGURATION2 = 0x05U,
|
||||
BK1080_REG_07 = 0x07U,
|
||||
BK1080_REG_10 = 0x0AU,
|
||||
BK1080_REG_25_INTERNAL = 0x19U,
|
||||
};
|
||||
|
||||
typedef enum BK1080_Register_t BK1080_Register_t;
|
||||
|
||||
// REG 07
|
||||
|
||||
#define BK1080_REG_07_SHIFT_FREQD 4
|
||||
#define BK1080_REG_07_SHIFT_SNR 0
|
||||
|
||||
#define BK1080_REG_07_MASK_FREQD (0xFFFU << BK1080_REG_07_SHIFT_FREQD)
|
||||
#define BK1080_REG_07_MASK_SNR (0x00FU << BK1080_REG_07_SHIFT_SNR)
|
||||
|
||||
#define BK1080_REG_07_GET_FREQD(x) (((x) & BK1080_REG_07_MASK_FREQD) >> BK1080_REG_07_SHIFT_FREQD)
|
||||
#define BK1080_REG_07_GET_SNR(x) (((x) & BK1080_REG_07_MASK_SNR) >> BK1080_REG_07_SHIFT_SNR)
|
||||
|
||||
// REG 10
|
||||
|
||||
#define BK1080_REG_10_SHIFT_AFCRL 12
|
||||
#define BK1080_REG_10_SHIFT_RSSI 0
|
||||
|
||||
#define BK1080_REG_10_MASK_AFCRL (0x01U << BK1080_REG_10_SHIFT_AFCRL)
|
||||
#define BK1080_REG_10_MASK_RSSI (0xFFU << BK1080_REG_10_SHIFT_RSSI)
|
||||
|
||||
#define BK1080_REG_10_AFCRL_NOT_RAILED (0U << BK1080_REG_10_SHIFT_AFCRL)
|
||||
#define BK1080_REG_10_AFCRL_RAILED (1U << BK1080_REG_10_SHIFT_AFCRL)
|
||||
|
||||
#define BK1080_REG_10_GET_RSSI(x) (((x) & BK1080_REG_10_MASK_RSSI) >> BK1080_REG_10_SHIFT_RSSI)
|
||||
|
||||
#endif
|
||||
|
||||
144
driver/bk1080.c
Normal file
144
driver/bk1080.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "bk1080.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/system.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
#endif
|
||||
|
||||
static const uint16_t BK1080_RegisterTable[] =
|
||||
{
|
||||
0x0008, 0x1080, 0x0201, 0x0000, 0x40C0, 0x0A1F, 0x002E, 0x02FF,
|
||||
0x5B11, 0x0000, 0x411E, 0x0000, 0xCE00, 0x0000, 0x0000, 0x1000,
|
||||
0x3197, 0x0000, 0x13FF, 0x9852, 0x0000, 0x0000, 0x0008, 0x0000,
|
||||
0x51E1, 0xA8BC, 0x2645, 0x00E4, 0x1CD8, 0x3A50, 0xEAE0, 0x3000,
|
||||
0x0200, 0x0000,
|
||||
};
|
||||
|
||||
static bool gIsInitBK1080;
|
||||
|
||||
uint16_t BK1080_BaseFrequency;
|
||||
uint16_t BK1080_FrequencyDeviation;
|
||||
|
||||
void BK1080_Init0(void)
|
||||
{
|
||||
BK1080_Init(0,0/*,0*/);
|
||||
}
|
||||
|
||||
void BK1080_Init(uint16_t freq, uint8_t band/*, uint8_t space*/)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (freq) {
|
||||
GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_BK1080);
|
||||
|
||||
if (!gIsInitBK1080) {
|
||||
for (i = 0; i < ARRAY_SIZE(BK1080_RegisterTable); i++)
|
||||
BK1080_WriteRegister(i, BK1080_RegisterTable[i]);
|
||||
|
||||
SYSTEM_DelayMs(250);
|
||||
|
||||
BK1080_WriteRegister(BK1080_REG_25_INTERNAL, 0xA83C);
|
||||
BK1080_WriteRegister(BK1080_REG_25_INTERNAL, 0xA8BC);
|
||||
|
||||
SYSTEM_DelayMs(60);
|
||||
|
||||
gIsInitBK1080 = true;
|
||||
}
|
||||
else {
|
||||
BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, 0x0201);
|
||||
}
|
||||
|
||||
BK1080_WriteRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2, 0x0A1F);
|
||||
BK1080_SetFrequency(freq, band/*, space*/);
|
||||
}
|
||||
else {
|
||||
BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, 0x0241);
|
||||
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_BK1080);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t BK1080_ReadRegister(BK1080_Register_t Register)
|
||||
{
|
||||
uint8_t Value[2];
|
||||
|
||||
I2C_Start();
|
||||
I2C_Write(0x80);
|
||||
I2C_Write((Register << 1) | I2C_READ);
|
||||
I2C_ReadBuffer(Value, sizeof(Value));
|
||||
I2C_Stop();
|
||||
|
||||
return (Value[0] << 8) | Value[1];
|
||||
}
|
||||
|
||||
void BK1080_WriteRegister(BK1080_Register_t Register, uint16_t Value)
|
||||
{
|
||||
I2C_Start();
|
||||
I2C_Write(0x80);
|
||||
I2C_Write((Register << 1) | I2C_WRITE);
|
||||
Value = ((Value >> 8) & 0xFF) | ((Value & 0xFF) << 8);
|
||||
I2C_WriteBuffer(&Value, sizeof(Value));
|
||||
I2C_Stop();
|
||||
}
|
||||
|
||||
void BK1080_Mute(bool Mute)
|
||||
{
|
||||
BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, Mute ? 0x4201 : 0x0201);
|
||||
}
|
||||
|
||||
void BK1080_SetFrequency(uint16_t frequency, uint8_t band/*, uint8_t space*/)
|
||||
{
|
||||
//uint8_t spacings[] = {20,10,5};
|
||||
//space %= 3;
|
||||
|
||||
uint16_t channel = (frequency - BK1080_GetFreqLoLimit(band))/* * 10 / spacings[space]*/;
|
||||
|
||||
uint16_t regval = BK1080_ReadRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2);
|
||||
regval = (regval & ~(0b11 << 6)) | ((band & 0b11) << 6);
|
||||
//regval = (regval & ~(0b11 << 4)) | ((space & 0b11) << 4);
|
||||
|
||||
BK1080_WriteRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2, regval);
|
||||
|
||||
BK1080_WriteRegister(BK1080_REG_03_CHANNEL, channel);
|
||||
SYSTEM_DelayMs(10);
|
||||
BK1080_WriteRegister(BK1080_REG_03_CHANNEL, channel | 0x8000);
|
||||
}
|
||||
|
||||
void BK1080_GetFrequencyDeviation(uint16_t Frequency)
|
||||
{
|
||||
BK1080_BaseFrequency = Frequency;
|
||||
BK1080_FrequencyDeviation = BK1080_ReadRegister(BK1080_REG_07) / 16;
|
||||
}
|
||||
|
||||
uint16_t BK1080_GetFreqLoLimit(uint8_t band)
|
||||
{
|
||||
uint16_t lim[] = {875, 760, 760, 640};
|
||||
return lim[band % 4];
|
||||
}
|
||||
|
||||
uint16_t BK1080_GetFreqHiLimit(uint8_t band)
|
||||
{
|
||||
band %= 4;
|
||||
uint16_t lim[] = {1080, 1080, 900, 760};
|
||||
return lim[band % 4];
|
||||
}
|
||||
|
||||
38
driver/bk1080.h
Normal file
38
driver/bk1080.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_BK1080_H
|
||||
#define DRIVER_BK1080_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "driver/bk1080-regs.h"
|
||||
|
||||
extern uint16_t BK1080_BaseFrequency;
|
||||
extern uint16_t BK1080_FrequencyDeviation;
|
||||
|
||||
void BK1080_Init0(void);
|
||||
void BK1080_Init(uint16_t Frequency, uint8_t band/*, uint8_t space*/);
|
||||
uint16_t BK1080_ReadRegister(BK1080_Register_t Register);
|
||||
void BK1080_WriteRegister(BK1080_Register_t Register, uint16_t Value);
|
||||
void BK1080_Mute(bool Mute);
|
||||
uint16_t BK1080_GetFreqLoLimit(uint8_t band);
|
||||
uint16_t BK1080_GetFreqHiLimit(uint8_t band);
|
||||
void BK1080_SetFrequency(uint16_t frequency, uint8_t band/*, uint8_t space*/);
|
||||
void BK1080_GetFrequencyDeviation(uint16_t Frequency);
|
||||
|
||||
#endif
|
||||
|
||||
390
driver/bk4819-regs.h
Normal file
390
driver/bk4819-regs.h
Normal file
@@ -0,0 +1,390 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BK4819_REGS_H
|
||||
#define BK4819_REGS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
uint8_t num;
|
||||
uint8_t offset;
|
||||
uint16_t mask;
|
||||
uint16_t inc;
|
||||
} RegisterSpec;
|
||||
|
||||
static const RegisterSpec afcDisableRegSpec = {"AFC Disable", 0x73, 4, 1, 1};
|
||||
static const RegisterSpec afOutRegSpec = {"AF Output Select", 0x47, 8, 0xF, 1};
|
||||
static const RegisterSpec afDacGainRegSpec = {"AF DAC Gain", 0x48, 0, 0xF, 1};
|
||||
|
||||
enum BK4819_REGISTER_t {
|
||||
BK4819_REG_00 = 0x00U,
|
||||
BK4819_REG_02 = 0x02U,
|
||||
BK4819_REG_06 = 0x06U,
|
||||
BK4819_REG_07 = 0x07U,
|
||||
BK4819_REG_08 = 0x08U,
|
||||
BK4819_REG_09 = 0x09U,
|
||||
BK4819_REG_0B = 0x0BU,
|
||||
BK4819_REG_0C = 0x0CU,
|
||||
BK4819_REG_0D = 0x0DU,
|
||||
BK4819_REG_0E = 0x0EU,
|
||||
// RX AGC Gain Table[0]
|
||||
BK4819_REG_10 = 0x10U,
|
||||
// RX AGC Gain Table[1]
|
||||
BK4819_REG_11 = 0x11U,
|
||||
// RX AGC Gain Table[2]
|
||||
BK4819_REG_12 = 0x12U,
|
||||
// RX AGC Gain Table[3]
|
||||
BK4819_REG_13 = 0x13U,
|
||||
// RX AGC Gain Table[-1]
|
||||
BK4819_REG_14 = 0x14U,
|
||||
BK4819_REG_19 = 0x19U,
|
||||
BK4819_REG_1F = 0x1FU,
|
||||
BK4819_REG_20 = 0x20U,
|
||||
BK4819_REG_21 = 0x21U,
|
||||
BK4819_REG_24 = 0x24U,
|
||||
BK4819_REG_28 = 0x28U,
|
||||
BK4819_REG_29 = 0x29U,
|
||||
BK4819_REG_2B = 0x2BU,
|
||||
BK4819_REG_30 = 0x30U,
|
||||
BK4819_REG_31 = 0x31U,
|
||||
BK4819_REG_32 = 0x32U,
|
||||
BK4819_REG_33 = 0x33U,
|
||||
BK4819_REG_36 = 0x36U,
|
||||
BK4819_REG_37 = 0x37U,
|
||||
BK4819_REG_38 = 0x38U,
|
||||
BK4819_REG_39 = 0x39U,
|
||||
BK4819_REG_3A = 0x3AU,
|
||||
BK4819_REG_3B = 0x3BU,
|
||||
BK4819_REG_3C = 0x3CU,
|
||||
BK4819_REG_3D = 0x3DU,
|
||||
BK4819_REG_3E = 0x3EU,
|
||||
BK4819_REG_3F = 0x3FU,
|
||||
BK4819_REG_43 = 0x43U,
|
||||
BK4819_REG_46 = 0x46U,
|
||||
BK4819_REG_47 = 0x47U,
|
||||
BK4819_REG_48 = 0x48U,
|
||||
// REG_49<15:14> 0b00; High/Low Lo selection:
|
||||
// 0X: Auto High/Low Lo
|
||||
// 10: Low Lo
|
||||
// 11: High Lo
|
||||
// REG_49<13:7> 0x50; RF AGC high threshold, 1 dB/LSB
|
||||
// REG_49<6:0> 0x30; RF AGC low threshold, 1 dB/LSB
|
||||
BK4819_REG_49 = 0x49U,
|
||||
BK4819_REG_4D = 0x4DU,
|
||||
BK4819_REG_4E = 0x4EU,
|
||||
BK4819_REG_4F = 0x4FU,
|
||||
BK4819_REG_50 = 0x50U,
|
||||
BK4819_REG_51 = 0x51U,
|
||||
BK4819_REG_52 = 0x52U,
|
||||
BK4819_REG_58 = 0x58U,
|
||||
BK4819_REG_59 = 0x59U,
|
||||
BK4819_REG_5A = 0x5AU,
|
||||
BK4819_REG_5B = 0x5BU,
|
||||
BK4819_REG_5C = 0x5CU,
|
||||
BK4819_REG_5D = 0x5DU,
|
||||
BK4819_REG_5F = 0x5FU,
|
||||
BK4819_REG_63 = 0x63U,
|
||||
BK4819_REG_64 = 0x64U,
|
||||
BK4819_REG_65 = 0x65U,
|
||||
BK4819_REG_67 = 0x67U,
|
||||
BK4819_REG_68 = 0x68U,
|
||||
BK4819_REG_69 = 0x69U,
|
||||
BK4819_REG_6A = 0x6AU,
|
||||
BK4819_REG_6F = 0x6FU,
|
||||
BK4819_REG_70 = 0x70U,
|
||||
BK4819_REG_71 = 0x71U,
|
||||
BK4819_REG_72 = 0x72U,
|
||||
BK4819_REG_78 = 0x78U,
|
||||
BK4819_REG_79 = 0x79U,
|
||||
BK4819_REG_7A = 0x7AU,
|
||||
// REG_7B<15:0> 0xae34 RSSI table
|
||||
BK4819_REG_7B = 0x7BU,
|
||||
// REG_7C<15:0> 0x8000 RSSI table
|
||||
BK4819_REG_7C = 0x7CU,
|
||||
BK4819_REG_7D = 0x7DU,
|
||||
// REG_7E<15> 0; AGC fix mode:
|
||||
// 1: Fix
|
||||
// 0: Auto
|
||||
// REG_7E<14:12> 0b011; AGC fix index:
|
||||
// 011: Max.
|
||||
// …
|
||||
// 100: Min.
|
||||
// REG_7E<5:3> 0b101; DC filter bandwidth for TX (MIC in):
|
||||
// 000: Bypass DC filter
|
||||
// REG_7E<2:0> 0b110; DC filter bandwidth for RX (IF in):
|
||||
// 000: Bypass DC filter
|
||||
BK4819_REG_7E = 0x7EU,
|
||||
};
|
||||
|
||||
typedef enum BK4819_REGISTER_t BK4819_REGISTER_t;
|
||||
|
||||
enum BK4819_GPIO_PIN_t {
|
||||
BK4819_GPIO0_PIN28_RX_ENABLE = 0,
|
||||
BK4819_GPIO1_PIN29_PA_ENABLE = 1,
|
||||
BK4819_GPIO3_PIN31_UHF_LNA = 3,
|
||||
BK4819_GPIO4_PIN32_VHF_LNA = 4,
|
||||
BK4819_GPIO5_PIN1_RED = 5,
|
||||
BK4819_GPIO6_PIN2_GREEN = 6,
|
||||
};
|
||||
|
||||
typedef enum BK4819_GPIO_PIN_t BK4819_GPIO_PIN_t;
|
||||
|
||||
// REG 02
|
||||
|
||||
#define BK4819_REG_02_SHIFT_FSK_TX_FINISHED 15
|
||||
#define BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_EMPTY 14
|
||||
#define BK4819_REG_02_SHIFT_FSK_RX_FINISHED 13
|
||||
#define BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_FULL 12
|
||||
#define BK4819_REG_02_SHIFT_DTMF_5TONE_FOUND 11
|
||||
#define BK4819_REG_02_SHIFT_CxCSS_TAIL 10
|
||||
#define BK4819_REG_02_SHIFT_CDCSS_FOUND 9
|
||||
#define BK4819_REG_02_SHIFT_CDCSS_LOST 8
|
||||
#define BK4819_REG_02_SHIFT_CTCSS_FOUND 7
|
||||
#define BK4819_REG_02_SHIFT_CTCSS_LOST 6
|
||||
#define BK4819_REG_02_SHIFT_VOX_FOUND 5
|
||||
#define BK4819_REG_02_SHIFT_VOX_LOST 4
|
||||
#define BK4819_REG_02_SHIFT_SQUELCH_FOUND 3
|
||||
#define BK4819_REG_02_SHIFT_SQUELCH_LOST 2
|
||||
#define BK4819_REG_02_SHIFT_FSK_RX_SYNC 1
|
||||
|
||||
#define BK4819_REG_02_MASK_FSK_TX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_TX)
|
||||
#define BK4819_REG_02_MASK_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_EMPTY)
|
||||
#define BK4819_REG_02_MASK_FSK_RX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_RX_FINISHED)
|
||||
#define BK4819_REG_02_MASK_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_FULL)
|
||||
#define BK4819_REG_02_MASK_DTMF_5TONE_FOUND (1U << BK4819_REG_02_SHIFT_DTMF_5TONE_FOUND)
|
||||
#define BK4819_REG_02_MASK_CxCSS_TAIL (1U << BK4819_REG_02_SHIFT_CxCSS_TAIL)
|
||||
#define BK4819_REG_02_MASK_CDCSS_FOUND (1U << BK4819_REG_02_SHIFT_CDCSS_FOUND)
|
||||
#define BK4819_REG_02_MASK_CDCSS_LOST (1U << BK4819_REG_02_SHIFT_CDCSS_LOST)
|
||||
#define BK4819_REG_02_MASK_CTCSS_FOUND (1U << BK4819_REG_02_SHIFT_CTCSS_FOUND)
|
||||
#define BK4819_REG_02_MASK_CTCSS_LOST (1U << BK4819_REG_02_SHIFT_CTCSS_LOST)
|
||||
#define BK4819_REG_02_MASK_VOX_FOUND (1U << BK4819_REG_02_SHIFT_VOX_FOUND)
|
||||
#define BK4819_REG_02_MASK_VOX_LOST (1U << BK4819_REG_02_SHIFT_VOX_LOST)
|
||||
#define BK4819_REG_02_MASK_SQUELCH_FOUND (1U << BK4819_REG_02_SHIFT_SQUELCH_FOUND)
|
||||
#define BK4819_REG_02_MASK_SQUELCH_LOST (1U << BK4819_REG_02_SHIFT_SQUELCH_LOST)
|
||||
#define BK4819_REG_02_MASK_FSK_RX_SYNC (1U << BK4819_REG_02_SHIFT_FSK_RX_SYNC)
|
||||
|
||||
#define BK4819_REG_02_FSK_TX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_TX_FINISHED)
|
||||
#define BK4819_REG_02_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_EMPTY)
|
||||
#define BK4819_REG_02_FSK_RX_FINISHED (1U << BK4819_REG_02_SHIFT_FSK_RX_FINISHED)
|
||||
#define BK4819_REG_02_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_02_SHIFT_FSK_FIFO_ALMOST_FULL)
|
||||
#define BK4819_REG_02_DTMF_5TONE_FOUND (1U << BK4819_REG_02_SHIFT_DTMF_5TONE_FOUND)
|
||||
#define BK4819_REG_02_CxCSS_TAIL (1U << BK4819_REG_02_SHIFT_CxCSS_TAIL)
|
||||
#define BK4819_REG_02_CDCSS_FOUND (1U << BK4819_REG_02_SHIFT_CDCSS_FOUND)
|
||||
#define BK4819_REG_02_CDCSS_LOST (1U << BK4819_REG_02_SHIFT_CDCSS_LOST)
|
||||
#define BK4819_REG_02_CTCSS_FOUND (1U << BK4819_REG_02_SHIFT_CTCSS_FOUND)
|
||||
#define BK4819_REG_02_CTCSS_LOST (1U << BK4819_REG_02_SHIFT_CTCSS_LOST)
|
||||
#define BK4819_REG_02_VOX_FOUND (1U << BK4819_REG_02_SHIFT_VOX_FOUND)
|
||||
#define BK4819_REG_02_VOX_LOST (1U << BK4819_REG_02_SHIFT_VOX_LOST)
|
||||
#define BK4819_REG_02_SQUELCH_FOUND (1U << BK4819_REG_02_SHIFT_SQUELCH_FOUND)
|
||||
#define BK4819_REG_02_SQUELCH_LOST (1U << BK4819_REG_02_SHIFT_SQUELCH_LOST)
|
||||
#define BK4819_REG_02_FSK_RX_SYNC (1U << BK4819_REG_02_SHIFT_FSK_RX_SYNC)
|
||||
|
||||
// REG 07
|
||||
|
||||
#define BK4819_REG_07_SHIFT_FREQUENCY_MODE 13
|
||||
#define BK4819_REG_07_SHIFT_FREQUENCY 0
|
||||
|
||||
#define BK4819_REG_07_MASK_FREQUENCY_MODE (0x0007U << BK4819_REG_07_SHIFT_FREQUENCY_MODE)
|
||||
#define BK4819_REG_07_MASK_FREQUENCY (0x1FFFU << BK4819_REG_07_SHIFT_FREQUENCY)
|
||||
|
||||
#define BK4819_REG_07_MODE_CTC1 (0U << BK4819_REG_07_SHIFT_FREQUENCY_MODE)
|
||||
#define BK4819_REG_07_MODE_CTC2 (1U << BK4819_REG_07_SHIFT_FREQUENCY_MODE)
|
||||
#define BK4819_REG_07_MODE_CDCSS (2U << BK4819_REG_07_SHIFT_FREQUENCY_MODE)
|
||||
|
||||
// REG 24
|
||||
|
||||
#define BK4819_REG_24_SHIFT_UNKNOWN_15 15
|
||||
#define BK4819_REG_24_SHIFT_THRESHOLD 7
|
||||
#define BK4819_REG_24_SHIFT_UNKNOWN_6 6
|
||||
#define BK4819_REG_24_SHIFT_ENABLE 5
|
||||
#define BK4819_REG_24_SHIFT_SELECT 4
|
||||
#define BK4819_REG_24_SHIFT_MAX_SYMBOLS 0
|
||||
|
||||
#define BK4819_REG_24_MASK_THRESHOLD (0x2Fu << BK4819_REG_24_SHIFT_THRESHOLD)
|
||||
#define BK4819_REG_24_MASK_ENABLE (0x01u << BK4819_REG_24_SHIFT_ENABLE)
|
||||
#define BK4819_REG_24_MASK_SELECT (0x04u << BK4819_REG_24_SHIFT_SELECT)
|
||||
#define BK4819_REG_24_MASK_MAX_SYMBOLS (0x0Fu << BK4819_REG_24_SHIFT_MAX_SYMBOLS)
|
||||
|
||||
#define BK4819_REG_24_ENABLE (1u << BK4819_REG_24_SHIFT_ENABLE)
|
||||
#define BK4819_REG_24_DISABLE (0u << BK4819_REG_24_SHIFT_ENABLE)
|
||||
#define BK4819_REG_24_SELECT_DTMF (1u << BK4819_REG_24_SHIFT_SELECT)
|
||||
#define BK4819_REG_24_SELECT_SELCALL (0u << BK4819_REG_24_SHIFT_SELECT)
|
||||
|
||||
// REG 30
|
||||
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB 15
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_UNKNOWN 14
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_RX_LINK 10
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_AF_DAC 9
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_DISC_MODE 8
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_PLL_VCO 4
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_PA_GAIN 3
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_MIC_ADC 2
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_TX_DSP 1
|
||||
#define BK4819_REG_30_SHIFT_ENABLE_RX_DSP 0
|
||||
|
||||
#define BK4819_REG_30_MASK_ENABLE_VCO_CALIB (0x1U << BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB)
|
||||
#define BK4819_REG_30_MASK_ENABLE_UNKNOWN (0x1U << BK4819_REG_30_SHIFT_ENABLE_UNKNOWN)
|
||||
#define BK4819_REG_30_MASK_ENABLE_RX_LINK (0xFU << BK4819_REG_30_SHIFT_ENABLE_RX_LINK)
|
||||
#define BK4819_REG_30_MASK_ENABLE_AF_DAC (0x1U << BK4819_REG_30_SHIFT_ENABLE_AF_DAC)
|
||||
#define BK4819_REG_30_MASK_ENABLE_DISC_MODE (0x1U << BK4819_REG_30_SHIFT_ENABLE_DISC_MODE)
|
||||
#define BK4819_REG_30_MASK_ENABLE_PLL_VCO (0xFU << BK4819_REG_30_SHIFT_ENABLE_PLL_VCO)
|
||||
#define BK4819_REG_30_MASK_ENABLE_PA_GAIN (0x1U << BK4819_REG_30_SHIFT_ENABLE_PA_GAIN)
|
||||
#define BK4819_REG_30_MASK_ENABLE_MIC_ADC (0x1U << BK4819_REG_30_SHIFT_ENABLE_MIC_ADC)
|
||||
#define BK4819_REG_30_MASK_ENABLE_TX_DSP (0x1U << BK4819_REG_30_SHIFT_ENABLE_TX_DSP)
|
||||
#define BK4819_REG_30_MASK_ENABLE_RX_DSP (0x1U << BK4819_REG_30_SHIFT_ENABLE_RX_DSP)
|
||||
|
||||
enum {
|
||||
BK4819_REG_30_ENABLE_VCO_CALIB = (0x1U << BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB),
|
||||
BK4819_REG_30_DISABLE_VCO_CALIB = (0x0U << BK4819_REG_30_SHIFT_ENABLE_VCO_CALIB),
|
||||
BK4819_REG_30_ENABLE_UNKNOWN = (0x1U << BK4819_REG_30_SHIFT_ENABLE_UNKNOWN),
|
||||
BK4819_REG_30_DISABLE_UNKNOWN = (0x0U << BK4819_REG_30_SHIFT_ENABLE_UNKNOWN),
|
||||
BK4819_REG_30_ENABLE_RX_LINK = (0xFU << BK4819_REG_30_SHIFT_ENABLE_RX_LINK),
|
||||
BK4819_REG_30_DISABLE_RX_LINK = (0x0U << BK4819_REG_30_SHIFT_ENABLE_RX_LINK),
|
||||
BK4819_REG_30_ENABLE_AF_DAC = (0x1U << BK4819_REG_30_SHIFT_ENABLE_AF_DAC),
|
||||
BK4819_REG_30_DISABLE_AF_DAC = (0x0U << BK4819_REG_30_SHIFT_ENABLE_AF_DAC),
|
||||
BK4819_REG_30_ENABLE_DISC_MODE = (0x1U << BK4819_REG_30_SHIFT_ENABLE_DISC_MODE),
|
||||
BK4819_REG_30_DISABLE_DISC_MODE = (0x0U << BK4819_REG_30_SHIFT_ENABLE_DISC_MODE),
|
||||
BK4819_REG_30_ENABLE_PLL_VCO = (0xFU << BK4819_REG_30_SHIFT_ENABLE_PLL_VCO),
|
||||
BK4819_REG_30_DISABLE_PLL_VCO = (0x0U << BK4819_REG_30_SHIFT_ENABLE_PLL_VCO),
|
||||
BK4819_REG_30_ENABLE_PA_GAIN = (0x1U << BK4819_REG_30_SHIFT_ENABLE_PA_GAIN),
|
||||
BK4819_REG_30_DISABLE_PA_GAIN = (0x0U << BK4819_REG_30_SHIFT_ENABLE_PA_GAIN),
|
||||
BK4819_REG_30_ENABLE_MIC_ADC = (0x1U << BK4819_REG_30_SHIFT_ENABLE_MIC_ADC),
|
||||
BK4819_REG_30_DISABLE_MIC_ADC = (0x0U << BK4819_REG_30_SHIFT_ENABLE_MIC_ADC),
|
||||
BK4819_REG_30_ENABLE_TX_DSP = (0x1U << BK4819_REG_30_SHIFT_ENABLE_TX_DSP),
|
||||
BK4819_REG_30_DISABLE_TX_DSP = (0x0U << BK4819_REG_30_SHIFT_ENABLE_TX_DSP),
|
||||
BK4819_REG_30_ENABLE_RX_DSP = (0x1U << BK4819_REG_30_SHIFT_ENABLE_RX_DSP),
|
||||
BK4819_REG_30_DISABLE_RX_DSP = (0x0U << BK4819_REG_30_SHIFT_ENABLE_RX_DSP),
|
||||
};
|
||||
|
||||
// REG 3F
|
||||
|
||||
#define BK4819_REG_3F_SHIFT_FSK_TX_FINISHED 15
|
||||
#define BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_EMPTY 14
|
||||
#define BK4819_REG_3F_SHIFT_FSK_RX_FINISHED 13
|
||||
#define BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_FULL 12
|
||||
#define BK4819_REG_3F_SHIFT_DTMF_5TONE_FOUND 11
|
||||
#define BK4819_REG_3F_SHIFT_CxCSS_TAIL 10
|
||||
#define BK4819_REG_3F_SHIFT_CDCSS_FOUND 9
|
||||
#define BK4819_REG_3F_SHIFT_CDCSS_LOST 8
|
||||
#define BK4819_REG_3F_SHIFT_CTCSS_FOUND 7
|
||||
#define BK4819_REG_3F_SHIFT_CTCSS_LOST 6
|
||||
#define BK4819_REG_3F_SHIFT_VOX_FOUND 5
|
||||
#define BK4819_REG_3F_SHIFT_VOX_LOST 4
|
||||
#define BK4819_REG_3F_SHIFT_SQUELCH_FOUND 3
|
||||
#define BK4819_REG_3F_SHIFT_SQUELCH_LOST 2
|
||||
#define BK4819_REG_3F_SHIFT_FSK_RX_SYNC 1
|
||||
|
||||
#define BK4819_REG_3F_MASK_FSK_TX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_TX)
|
||||
#define BK4819_REG_3F_MASK_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_EMPTY)
|
||||
#define BK4819_REG_3F_MASK_FSK_RX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_RX_FINISHED)
|
||||
#define BK4819_REG_3F_MASK_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_FULL)
|
||||
#define BK4819_REG_3F_MASK_DTMF_5TONE_FOUND (1U << BK4819_REG_3F_SHIFT_DTMF_5TONE_FOUND)
|
||||
#define BK4819_REG_3F_MASK_CxCSS_TAIL (1U << BK4819_REG_3F_SHIFT_CxCSS_TAIL)
|
||||
#define BK4819_REG_3F_MASK_CDCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CDCSS_FOUND)
|
||||
#define BK4819_REG_3F_MASK_CDCSS_LOST (1U << BK4819_REG_3F_SHIFT_CDCSS_LOST)
|
||||
#define BK4819_REG_3F_MASK_CTCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CTCSS_FOUND)
|
||||
#define BK4819_REG_3F_MASK_CTCSS_LOST (1U << BK4819_REG_3F_SHIFT_CTCSS_LOST)
|
||||
#define BK4819_REG_3F_MASK_VOX_FOUND (1U << BK4819_REG_3F_SHIFT_VOX_FOUND)
|
||||
#define BK4819_REG_3F_MASK_VOX_LOST (1U << BK4819_REG_3F_SHIFT_VOX_LOST)
|
||||
#define BK4819_REG_3F_MASK_SQUELCH_FOUND (1U << BK4819_REG_3F_SHIFT_SQUELCH_FOUND)
|
||||
#define BK4819_REG_3F_MASK_SQUELCH_LOST (1U << BK4819_REG_3F_SHIFT_SQUELCH_LOST)
|
||||
#define BK4819_REG_3F_MASK_FSK_RX_SYNC (1U << BK4819_REG_3F_SHIFT_FSK_RX_SYNC)
|
||||
|
||||
#define BK4819_REG_3F_FSK_TX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_TX_FINISHED)
|
||||
#define BK4819_REG_3F_FSK_FIFO_ALMOST_EMPTY (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_EMPTY)
|
||||
#define BK4819_REG_3F_FSK_RX_FINISHED (1U << BK4819_REG_3F_SHIFT_FSK_RX_FINISHED)
|
||||
#define BK4819_REG_3F_FSK_FIFO_ALMOST_FULL (1U << BK4819_REG_3F_SHIFT_FSK_FIFO_ALMOST_FULL)
|
||||
#define BK4819_REG_3F_DTMF_5TONE_FOUND (1U << BK4819_REG_3F_SHIFT_DTMF_5TONE_FOUND)
|
||||
#define BK4819_REG_3F_CxCSS_TAIL (1U << BK4819_REG_3F_SHIFT_CxCSS_TAIL)
|
||||
#define BK4819_REG_3F_CDCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CDCSS_FOUND)
|
||||
#define BK4819_REG_3F_CDCSS_LOST (1U << BK4819_REG_3F_SHIFT_CDCSS_LOST)
|
||||
#define BK4819_REG_3F_CTCSS_FOUND (1U << BK4819_REG_3F_SHIFT_CTCSS_FOUND)
|
||||
#define BK4819_REG_3F_CTCSS_LOST (1U << BK4819_REG_3F_SHIFT_CTCSS_LOST)
|
||||
#define BK4819_REG_3F_VOX_FOUND (1U << BK4819_REG_3F_SHIFT_VOX_FOUND)
|
||||
#define BK4819_REG_3F_VOX_LOST (1U << BK4819_REG_3F_SHIFT_VOX_LOST)
|
||||
#define BK4819_REG_3F_SQUELCH_FOUND (1U << BK4819_REG_3F_SHIFT_SQUELCH_FOUND)
|
||||
#define BK4819_REG_3F_SQUELCH_LOST (1U << BK4819_REG_3F_SHIFT_SQUELCH_LOST)
|
||||
#define BK4819_REG_3F_FSK_RX_SYNC (1U << BK4819_REG_3F_SHIFT_FSK_RX_SYNC)
|
||||
|
||||
// REG 51
|
||||
|
||||
#define BK4819_REG_51_SHIFT_ENABLE_CxCSS 15
|
||||
#define BK4819_REG_51_SHIFT_GPIO6_PIN2_INPUT 14
|
||||
#define BK4819_REG_51_SHIFT_TX_CDCSS_POLARITY 13
|
||||
#define BK4819_REG_51_SHIFT_CxCSS_MODE 12
|
||||
#define BK4819_REG_51_SHIFT_CDCSS_BIT_WIDTH 11
|
||||
#define BK4819_REG_51_SHIFT_1050HZ_DETECTION 10
|
||||
#define BK4819_REG_51_SHIFT_AUTO_CDCSS_BW 9
|
||||
#define BK4819_REG_51_SHIFT_AUTO_CTCSS_BW 8
|
||||
#define BK4819_REG_51_SHIFT_CxCSS_TX_GAIN1 0
|
||||
|
||||
#define BK4819_REG_51_MASK_ENABLE_CxCSS (0x01U << BK4819_REG_51_SHIFT_ENABLE_CxCSS)
|
||||
#define BK4819_REG_51_MASK_GPIO6_PIN2_INPUT (0x01U << BK4819_REG_51_SHIFT_GPIO6_PIN2_INPUT)
|
||||
#define BK4819_REG_51_MASK_TX_CDCSS_POLARITY (0x01U << BK4819_REG_51_SHIFT_TX_CDCSS_POLARITY)
|
||||
#define BK4819_REG_51_MASK_CxCSS_MODE (0x01U << BK4819_REG_51_SHIFT_CxCSS_MODE)
|
||||
#define BK4819_REG_51_MASK_CDCSS_BIT_WIDTH (0x01U << BK4819_REG_51_SHIFT_CDCSS_BIT_WIDTH)
|
||||
#define BK4819_REG_51_MASK_1050HZ_DETECTION (0x01U << BK4819_REG_51_SHIFT_1050HZ_DETECTION)
|
||||
#define BK4819_REG_51_MASK_AUTO_CDCSS_BW (0x01U << BK4819_REG_51_SHIFT_AUTO_CDCSS_BW)
|
||||
#define BK4819_REG_51_MASK_AUTO_CTCSS_BW (0x01U << BK4819_REG_51_SHIFT_AUTO_CTCSS_BW)
|
||||
#define BK4819_REG_51_MASK_CxCSS_TX_GAIN1 (0x7FU << BK4819_REG_51_SHIFT_CxCSS_TX_GAIN1)
|
||||
|
||||
enum {
|
||||
BK4819_REG_51_ENABLE_CxCSS = (1U << BK4819_REG_51_SHIFT_ENABLE_CxCSS),
|
||||
BK4819_REG_51_DISABLE_CxCSS = (0U << BK4819_REG_51_SHIFT_ENABLE_CxCSS),
|
||||
|
||||
BK4819_REG_51_GPIO6_PIN2_INPUT = (1U << BK4819_REG_51_SHIFT_GPIO6_PIN2_INPUT),
|
||||
BK4819_REG_51_GPIO6_PIN2_NORMAL = (0U << BK4819_REG_51_SHIFT_GPIO6_PIN2_INPUT),
|
||||
|
||||
BK4819_REG_51_TX_CDCSS_NEGATIVE = (1U << BK4819_REG_51_SHIFT_TX_CDCSS_POLARITY),
|
||||
BK4819_REG_51_TX_CDCSS_POSITIVE = (0U << BK4819_REG_51_SHIFT_TX_CDCSS_POLARITY),
|
||||
|
||||
BK4819_REG_51_MODE_CTCSS = (1U << BK4819_REG_51_SHIFT_CxCSS_MODE),
|
||||
BK4819_REG_51_MODE_CDCSS = (0U << BK4819_REG_51_SHIFT_CxCSS_MODE),
|
||||
|
||||
BK4819_REG_51_CDCSS_24_BIT = (1U << BK4819_REG_51_SHIFT_CDCSS_BIT_WIDTH),
|
||||
BK4819_REG_51_CDCSS_23_BIT = (0U << BK4819_REG_51_SHIFT_CDCSS_BIT_WIDTH),
|
||||
|
||||
BK4819_REG_51_1050HZ_DETECTION = (1U << BK4819_REG_51_SHIFT_1050HZ_DETECTION),
|
||||
BK4819_REG_51_1050HZ_NO_DETECTION = (0U << BK4819_REG_51_SHIFT_1050HZ_DETECTION),
|
||||
|
||||
BK4819_REG_51_AUTO_CDCSS_BW_DISABLE = (1U << BK4819_REG_51_SHIFT_AUTO_CDCSS_BW),
|
||||
BK4819_REG_51_AUTO_CDCSS_BW_ENABLE = (0U << BK4819_REG_51_SHIFT_AUTO_CDCSS_BW),
|
||||
|
||||
BK4819_REG_51_AUTO_CTCSS_BW_DISABLE = (1U << BK4819_REG_51_SHIFT_AUTO_CTCSS_BW),
|
||||
BK4819_REG_51_AUTO_CTCSS_BW_ENABLE = (0U << BK4819_REG_51_SHIFT_AUTO_CTCSS_BW),
|
||||
};
|
||||
|
||||
// REG 70
|
||||
|
||||
#define BK4819_REG_70_SHIFT_ENABLE_TONE1 15
|
||||
#define BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN 8
|
||||
#define BK4819_REG_70_SHIFT_ENABLE_TONE2 7
|
||||
#define BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN 0
|
||||
|
||||
#define BK4819_REG_70_MASK_ENABLE_TONE1 (0x01U << BK4819_REG_70_SHIFT_ENABLE_TONE1)
|
||||
#define BK4819_REG_70_MASK_TONE1_TUNING_GAIN (0x7FU << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN)
|
||||
#define BK4819_REG_70_MASK_ENABLE_TONE2 (0x01U << BK4819_REG_70_SHIFT_ENABLE_TONE2)
|
||||
#define BK4819_REG_70_MASK_TONE2_TUNING_GAIN (0x7FU << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN)
|
||||
|
||||
enum {
|
||||
BK4819_REG_70_ENABLE_TONE1 = (1U << BK4819_REG_70_SHIFT_ENABLE_TONE1),
|
||||
BK4819_REG_70_ENABLE_TONE2 = (1U << BK4819_REG_70_SHIFT_ENABLE_TONE2),
|
||||
};
|
||||
|
||||
#endif
|
||||
1819
driver/bk4819.c
Normal file
1819
driver/bk4819.c
Normal file
File diff suppressed because it is too large
Load Diff
173
driver/bk4819.h
Normal file
173
driver/bk4819.h
Normal file
@@ -0,0 +1,173 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_BK4819_h
|
||||
#define DRIVER_BK4819_h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "driver/bk4819-regs.h"
|
||||
|
||||
enum BK4819_AF_Type_t
|
||||
{
|
||||
BK4819_AF_MUTE = 0u, //
|
||||
BK4819_AF_FM = 1u, // FM
|
||||
BK4819_AF_ALAM = 2u, //
|
||||
BK4819_AF_BEEP = 3u, //
|
||||
BK4819_AF_BASEBAND1 = 4u, // RAW
|
||||
BK4819_AF_BASEBAND2 = 5u, // USB
|
||||
BK4819_AF_CTCO = 6u, // strange LF audio .. maybe the CTCSS LF line ?
|
||||
BK4819_AF_AM = 7u, // AM
|
||||
BK4819_AF_FSKO = 8u, // nothing
|
||||
BK4819_AF_UNKNOWN3 = 9u, // BYP
|
||||
BK4819_AF_UNKNOWN4 = 10u, // nothing at all
|
||||
BK4819_AF_UNKNOWN5 = 11u, // distorted
|
||||
BK4819_AF_UNKNOWN6 = 12u, // distorted
|
||||
BK4819_AF_UNKNOWN7 = 13u, // interesting
|
||||
BK4819_AF_UNKNOWN8 = 14u, // interesting
|
||||
BK4819_AF_UNKNOWN9 = 15u // not a lot
|
||||
};
|
||||
|
||||
typedef enum BK4819_AF_Type_t BK4819_AF_Type_t;
|
||||
|
||||
enum BK4819_FilterBandwidth_t
|
||||
{
|
||||
BK4819_FILTER_BW_WIDE = 0,
|
||||
BK4819_FILTER_BW_NARROW,
|
||||
BK4819_FILTER_BW_NARROWER
|
||||
};
|
||||
|
||||
typedef enum BK4819_FilterBandwidth_t BK4819_FilterBandwidth_t;
|
||||
|
||||
enum BK4819_CssScanResult_t
|
||||
{
|
||||
BK4819_CSS_RESULT_NOT_FOUND = 0,
|
||||
BK4819_CSS_RESULT_CTCSS,
|
||||
BK4819_CSS_RESULT_CDCSS
|
||||
};
|
||||
|
||||
typedef enum BK4819_CssScanResult_t BK4819_CssScanResult_t;
|
||||
|
||||
// radio is asleep, not listening
|
||||
extern bool gRxIdleMode;
|
||||
|
||||
void BK4819_Init(void);
|
||||
uint16_t BK4819_ReadRegister(BK4819_REGISTER_t Register);
|
||||
void BK4819_WriteRegister(BK4819_REGISTER_t Register, uint16_t Data);
|
||||
void BK4819_SetRegValue(RegisterSpec s, uint16_t v);
|
||||
void BK4819_WriteU8(uint8_t Data);
|
||||
void BK4819_WriteU16(uint16_t Data);
|
||||
|
||||
void BK4819_SetAGC(bool enable);
|
||||
void BK4819_InitAGC(bool amModulation);
|
||||
|
||||
void BK4819_ToggleGpioOut(BK4819_GPIO_PIN_t Pin, bool bSet);
|
||||
|
||||
void BK4819_SetCDCSSCodeWord(uint32_t CodeWord);
|
||||
void BK4819_SetCTCSSFrequency(uint32_t BaudRate);
|
||||
void BK4819_SetTailDetection(const uint32_t freq_10Hz);
|
||||
void BK4819_EnableVox(uint16_t Vox1Threshold, uint16_t Vox0Threshold);
|
||||
void BK4819_SetFilterBandwidth(const BK4819_FilterBandwidth_t Bandwidth, const bool weak_no_different);
|
||||
void BK4819_SetupPowerAmplifier(const uint8_t bias, const uint32_t frequency);
|
||||
void BK4819_SetFrequency(uint32_t Frequency);
|
||||
void BK4819_SetupSquelch(
|
||||
uint8_t SquelchOpenRSSIThresh,
|
||||
uint8_t SquelchCloseRSSIThresh,
|
||||
uint8_t SquelchOpenNoiseThresh,
|
||||
uint8_t SquelchCloseNoiseThresh,
|
||||
uint8_t SquelchCloseGlitchThresh,
|
||||
uint8_t SquelchOpenGlitchThresh);
|
||||
|
||||
void BK4819_SetAF(BK4819_AF_Type_t AF);
|
||||
void BK4819_RX_TurnOn(void);
|
||||
void BK4819_PickRXFilterPathBasedOnFrequency(uint32_t Frequency);
|
||||
void BK4819_DisableScramble(void);
|
||||
void BK4819_EnableScramble(uint8_t Type);
|
||||
|
||||
bool BK4819_CompanderEnabled(void);
|
||||
void BK4819_SetCompander(const unsigned int mode);
|
||||
|
||||
void BK4819_DisableVox(void);
|
||||
void BK4819_DisableDTMF(void);
|
||||
void BK4819_EnableDTMF(void);
|
||||
void BK4819_PlayTone(uint16_t Frequency, bool bTuningGainSwitch);
|
||||
void BK4819_PlaySingleTone(const unsigned int tone_Hz, const unsigned int delay, const unsigned int level, const bool play_speaker);
|
||||
void BK4819_EnterTxMute(void);
|
||||
void BK4819_ExitTxMute(void);
|
||||
void BK4819_Sleep(void);
|
||||
void BK4819_TurnsOffTones_TurnsOnRX(void);
|
||||
#ifdef ENABLE_AIRCOPY
|
||||
void BK4819_SetupAircopy(void);
|
||||
#endif
|
||||
void BK4819_ResetFSK(void);
|
||||
void BK4819_Idle(void);
|
||||
void BK4819_ExitBypass(void);
|
||||
void BK4819_PrepareTransmit(void);
|
||||
void BK4819_TxOn_Beep(void);
|
||||
void BK4819_ExitSubAu(void);
|
||||
|
||||
void BK4819_Conditional_RX_TurnOn_and_GPIO6_Enable(void);
|
||||
|
||||
void BK4819_EnterDTMF_TX(bool bLocalLoopback);
|
||||
void BK4819_ExitDTMF_TX(bool bKeep);
|
||||
void BK4819_EnableTXLink(void);
|
||||
|
||||
void BK4819_PlayDTMF(char Code);
|
||||
void BK4819_PlayDTMFString(const char *pString, bool bDelayFirst, uint16_t FirstCodePersistTime, uint16_t HashCodePersistTime, uint16_t CodePersistTime, uint16_t CodeInternalTime);
|
||||
|
||||
void BK4819_TransmitTone(bool bLocalLoopback, uint32_t Frequency);
|
||||
|
||||
void BK4819_GenTail(uint8_t Tail);
|
||||
void BK4819_PlayCDCSSTail(void);
|
||||
void BK4819_PlayCTCSSTail(void);
|
||||
|
||||
uint16_t BK4819_GetRSSI(void);
|
||||
int8_t BK4819_GetRxGain_dB(void);
|
||||
int16_t BK4819_GetRSSI_dBm(void);
|
||||
uint8_t BK4819_GetGlitchIndicator(void);
|
||||
uint8_t BK4819_GetExNoiceIndicator(void);
|
||||
uint16_t BK4819_GetVoiceAmplitudeOut(void);
|
||||
uint8_t BK4819_GetAfTxRx(void);
|
||||
|
||||
bool BK4819_GetFrequencyScanResult(uint32_t *pFrequency);
|
||||
BK4819_CssScanResult_t BK4819_GetCxCSSScanResult(uint32_t *pCdcssFreq, uint16_t *pCtcssFreq);
|
||||
void BK4819_DisableFrequencyScan(void);
|
||||
void BK4819_EnableFrequencyScan(void);
|
||||
void BK4819_SetScanFrequency(uint32_t Frequency);
|
||||
|
||||
void BK4819_Disable(void);
|
||||
|
||||
void BK4819_StopScan(void);
|
||||
|
||||
uint8_t BK4819_GetDTMF_5TONE_Code(void);
|
||||
|
||||
uint8_t BK4819_GetCDCSSCodeType(void);
|
||||
uint8_t BK4819_GetCTCShift(void);
|
||||
uint8_t BK4819_GetCTCType(void);
|
||||
|
||||
void BK4819_SendFSKData(uint16_t *pData);
|
||||
void BK4819_PrepareFSKReceive(void);
|
||||
|
||||
void BK4819_PlayRoger(void);
|
||||
|
||||
void BK4819_Enable_AfDac_DiscMode_TxDsp(void);
|
||||
|
||||
void BK4819_GetVoxAmp(uint16_t *pResult);
|
||||
void BK4819_SetScrambleFrequencyControlWord(uint32_t Frequency);
|
||||
void BK4819_PlayDTMFEx(bool bLocalLoopback, char Code);
|
||||
|
||||
#endif
|
||||
49
driver/crc.c
Normal file
49
driver/crc.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "../bsp/dp32g030/crc.h"
|
||||
#include "crc.h"
|
||||
|
||||
void CRC_Init(void)
|
||||
{
|
||||
CRC_CR = 0
|
||||
| CRC_CR_CRC_EN_BITS_DISABLE
|
||||
| CRC_CR_INPUT_REV_BITS_NORMAL
|
||||
| CRC_CR_INPUT_INV_BITS_NORMAL
|
||||
| CRC_CR_OUTPUT_REV_BITS_NORMAL
|
||||
| CRC_CR_OUTPUT_INV_BITS_NORMAL
|
||||
| CRC_CR_DATA_WIDTH_BITS_8
|
||||
| CRC_CR_CRC_SEL_BITS_CRC_16_CCITT
|
||||
;
|
||||
CRC_IV = 0;
|
||||
}
|
||||
|
||||
uint16_t CRC_Calculate(const void *pBuffer, uint16_t Size)
|
||||
{
|
||||
const uint8_t *pData = (const uint8_t *)pBuffer;
|
||||
uint16_t i, Crc;
|
||||
|
||||
CRC_CR = (CRC_CR & ~CRC_CR_CRC_EN_MASK) | CRC_CR_CRC_EN_BITS_ENABLE;
|
||||
|
||||
for (i = 0; i < Size; i++) {
|
||||
CRC_DATAIN = pData[i];
|
||||
}
|
||||
Crc = (uint16_t)CRC_DATAOUT;
|
||||
|
||||
CRC_CR = (CRC_CR & ~CRC_CR_CRC_EN_MASK) | CRC_CR_CRC_EN_BITS_DISABLE;
|
||||
|
||||
return Crc;
|
||||
}
|
||||
26
driver/crc.h
Normal file
26
driver/crc.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_CRC_H
|
||||
#define DRIVER_CRC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void CRC_Init(void);
|
||||
uint16_t CRC_Calculate(const void *pBuffer, uint16_t Size);
|
||||
|
||||
#endif
|
||||
|
||||
63
driver/eeprom.c
Normal file
63
driver/eeprom.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "driver/eeprom.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/system.h"
|
||||
|
||||
void EEPROM_ReadBuffer(uint16_t Address, void *pBuffer, uint8_t Size)
|
||||
{
|
||||
I2C_Start();
|
||||
|
||||
I2C_Write(0xA0);
|
||||
|
||||
I2C_Write((Address >> 8) & 0xFF);
|
||||
I2C_Write((Address >> 0) & 0xFF);
|
||||
|
||||
I2C_Start();
|
||||
|
||||
I2C_Write(0xA1);
|
||||
|
||||
I2C_ReadBuffer(pBuffer, Size);
|
||||
|
||||
I2C_Stop();
|
||||
}
|
||||
|
||||
void EEPROM_WriteBuffer(uint16_t Address, const void *pBuffer)
|
||||
{
|
||||
if (pBuffer == NULL || Address >= 0x2000)
|
||||
return;
|
||||
|
||||
|
||||
uint8_t buffer[8];
|
||||
EEPROM_ReadBuffer(Address, buffer, 8);
|
||||
if (memcmp(pBuffer, buffer, 8) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
I2C_Start();
|
||||
I2C_Write(0xA0);
|
||||
I2C_Write((Address >> 8) & 0xFF);
|
||||
I2C_Write((Address >> 0) & 0xFF);
|
||||
I2C_WriteBuffer(pBuffer, 8);
|
||||
I2C_Stop();
|
||||
|
||||
// give the EEPROM time to burn the data in (apparently takes 5ms)
|
||||
SYSTEM_DelayMs(8);
|
||||
}
|
||||
26
driver/eeprom.h
Normal file
26
driver/eeprom.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_EEPROM_H
|
||||
#define DRIVER_EEPROM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void EEPROM_ReadBuffer(uint16_t Address, void *pBuffer, uint8_t Size);
|
||||
void EEPROM_WriteBuffer(uint16_t Address, const void *pBuffer);
|
||||
|
||||
#endif
|
||||
|
||||
33
driver/flash.c
Normal file
33
driver/flash.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "driver/flash.h"
|
||||
#include "sram-overlay.h"
|
||||
|
||||
void FLASH_Init(FLASH_READ_MODE ReadMode)
|
||||
{
|
||||
overlay_FLASH_Init(ReadMode);
|
||||
}
|
||||
|
||||
void FLASH_ConfigureTrimValues(void)
|
||||
{
|
||||
overlay_FLASH_ConfigureTrimValues();
|
||||
}
|
||||
|
||||
uint32_t FLASH_ReadNvrWord(uint32_t Address)
|
||||
{
|
||||
return overlay_FLASH_ReadNvrWord(Address);
|
||||
}
|
||||
59
driver/flash.h
Normal file
59
driver/flash.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_FLASH_H
|
||||
#define DRIVER_FLASH_H
|
||||
|
||||
#include "bsp/dp32g030/flash.h"
|
||||
|
||||
enum FLASH_READ_MODE {
|
||||
FLASH_READ_MODE_1_CYCLE = FLASH_CFG_READ_MD_VALUE_1_CYCLE,
|
||||
FLASH_READ_MODE_2_CYCLE = FLASH_CFG_READ_MD_VALUE_2_CYCLE,
|
||||
};
|
||||
|
||||
typedef enum FLASH_READ_MODE FLASH_READ_MODE;
|
||||
|
||||
enum FLASH_MASK_SELECTION {
|
||||
FLASH_MASK_SELECTION_NONE = FLASH_MASK_SEL_VALUE_NONE,
|
||||
FLASH_MASK_SELECTION_2KB = FLASH_MASK_SEL_VALUE_2KB,
|
||||
FLASH_MASK_SELECTION_4KB = FLASH_MASK_SEL_VALUE_4KB,
|
||||
FLASH_MASK_SELECTION_8KB = FLASH_MASK_SEL_VALUE_8KB,
|
||||
};
|
||||
|
||||
typedef enum FLASH_MASK_SELECTION FLASH_MASK_SELECTION;
|
||||
|
||||
enum FLASH_MODE {
|
||||
FLASH_MODE_READ_AHB = FLASH_CFG_MODE_VALUE_READ_AHB,
|
||||
FLASH_MODE_PROGRAM = FLASH_CFG_MODE_VALUE_PROGRAM,
|
||||
FLASH_MODE_ERASE = FLASH_CFG_MODE_VALUE_ERASE,
|
||||
FLASH_MODE_READ_APB = FLASH_CFG_MODE_VALUE_READ_APB,
|
||||
};
|
||||
|
||||
typedef enum FLASH_MODE FLASH_MODE;
|
||||
|
||||
enum FLASH_AREA {
|
||||
FLASH_AREA_MAIN = FLASH_CFG_NVR_SEL_VALUE_MAIN,
|
||||
FLASH_AREA_NVR = FLASH_CFG_NVR_SEL_VALUE_NVR,
|
||||
};
|
||||
|
||||
typedef enum FLASH_AREA FLASH_AREA;
|
||||
|
||||
void FLASH_Init(FLASH_READ_MODE ReadMode);
|
||||
void FLASH_ConfigureTrimValues(void);
|
||||
uint32_t FLASH_ReadNvrWord(uint32_t Address);
|
||||
|
||||
#endif
|
||||
|
||||
18
driver/gpio.c
Normal file
18
driver/gpio.c
Normal file
@@ -0,0 +1,18 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
78
driver/gpio.h
Normal file
78
driver/gpio.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_GPIO_H
|
||||
#define DRIVER_GPIO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum GPIOA_PINS {
|
||||
GPIOA_PIN_KEYBOARD_0 = 3,
|
||||
GPIOA_PIN_KEYBOARD_1 = 4,
|
||||
GPIOA_PIN_KEYBOARD_2 = 5,
|
||||
GPIOA_PIN_KEYBOARD_3 = 6,
|
||||
GPIOA_PIN_KEYBOARD_4 = 10, // Shared with I2C!
|
||||
GPIOA_PIN_KEYBOARD_5 = 11, // Shared with I2C!
|
||||
GPIOA_PIN_KEYBOARD_6 = 12, // Shared with voice chip!
|
||||
GPIOA_PIN_KEYBOARD_7 = 13, // Shared with voice chip!
|
||||
|
||||
GPIOA_PIN_I2C_SCL = 10, // Shared with keyboard!
|
||||
GPIOA_PIN_I2C_SDA = 11, // Shared with keyboard!
|
||||
|
||||
GPIOA_PIN_VOICE_0 = 12, // Shared with keyboard!
|
||||
GPIOA_PIN_VOICE_1 = 13 // Shared with keyboard!
|
||||
};
|
||||
|
||||
enum GPIOB_PINS {
|
||||
GPIOB_PIN_BACKLIGHT = 6,
|
||||
|
||||
GPIOB_PIN_ST7565_A0 = 9,
|
||||
GPIOB_PIN_ST7565_RES = 11, // Shared with SWD!
|
||||
|
||||
GPIOB_PIN_SWD_IO = 11, // Shared with ST7565!
|
||||
GPIOB_PIN_SWD_CLK = 14,
|
||||
|
||||
GPIOB_PIN_BK1080 = 15
|
||||
};
|
||||
|
||||
enum GPIOC_PINS {
|
||||
GPIOC_PIN_BK4819_SCN = 0,
|
||||
GPIOC_PIN_BK4819_SCL = 1,
|
||||
GPIOC_PIN_BK4819_SDA = 2,
|
||||
|
||||
GPIOC_PIN_FLASHLIGHT = 3,
|
||||
GPIOC_PIN_AUDIO_PATH = 4,
|
||||
GPIOC_PIN_PTT = 5
|
||||
};
|
||||
|
||||
static inline void GPIO_ClearBit(volatile uint32_t *pReg, uint8_t Bit) {
|
||||
*pReg &= ~(1U << Bit);
|
||||
}
|
||||
|
||||
static inline uint8_t GPIO_CheckBit(volatile uint32_t *pReg, uint8_t Bit) {
|
||||
return (*pReg >> Bit) & 1U;
|
||||
}
|
||||
|
||||
static inline void GPIO_FlipBit(volatile uint32_t *pReg, uint8_t Bit) {
|
||||
*pReg ^= 1U << Bit;
|
||||
}
|
||||
|
||||
static inline void GPIO_SetBit(volatile uint32_t *pReg, uint8_t Bit) {
|
||||
*pReg |= 1U << Bit;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
164
driver/i2c.c
Normal file
164
driver/i2c.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "bsp/dp32g030/portcon.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/systick.h"
|
||||
|
||||
void I2C_Start(void)
|
||||
{
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
}
|
||||
|
||||
void I2C_Stop(void)
|
||||
{
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
SYSTICK_DelayUs(1);
|
||||
}
|
||||
|
||||
uint8_t I2C_Read(bool bFinal)
|
||||
{
|
||||
uint8_t i, Data;
|
||||
|
||||
PORTCON_PORTA_IE |= PORTCON_PORTA_IE_A11_BITS_ENABLE;
|
||||
PORTCON_PORTA_OD &= ~PORTCON_PORTA_OD_A11_MASK;
|
||||
GPIOA->DIR &= ~GPIO_DIR_11_MASK;
|
||||
|
||||
Data = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
Data <<= 1;
|
||||
SYSTICK_DelayUs(1);
|
||||
if (GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA)) {
|
||||
Data |= 1U;
|
||||
}
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
}
|
||||
|
||||
PORTCON_PORTA_IE &= ~PORTCON_PORTA_IE_A11_MASK;
|
||||
PORTCON_PORTA_OD |= PORTCON_PORTA_OD_A11_BITS_ENABLE;
|
||||
GPIOA->DIR |= GPIO_DIR_11_BITS_OUTPUT;
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
if (bFinal) {
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
} else {
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
}
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
return Data;
|
||||
}
|
||||
|
||||
int I2C_Write(uint8_t Data)
|
||||
{
|
||||
uint8_t i;
|
||||
int ret = -1;
|
||||
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if ((Data & 0x80) == 0) {
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
} else {
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
}
|
||||
Data <<= 1;
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
}
|
||||
|
||||
PORTCON_PORTA_IE |= PORTCON_PORTA_IE_A11_BITS_ENABLE;
|
||||
PORTCON_PORTA_OD &= ~PORTCON_PORTA_OD_A11_MASK;
|
||||
GPIOA->DIR &= ~GPIO_DIR_11_MASK;
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
SYSTICK_DelayUs(1);
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
|
||||
for (i = 0; i < 255; i++) {
|
||||
if (GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA) == 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_I2C_SCL);
|
||||
SYSTICK_DelayUs(1);
|
||||
PORTCON_PORTA_IE &= ~PORTCON_PORTA_IE_A11_MASK;
|
||||
PORTCON_PORTA_OD |= PORTCON_PORTA_OD_A11_BITS_ENABLE;
|
||||
GPIOA->DIR |= GPIO_DIR_11_BITS_OUTPUT;
|
||||
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_I2C_SDA);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int I2C_ReadBuffer(void *pBuffer, uint8_t Size)
|
||||
{
|
||||
uint8_t *pData = (uint8_t *)pBuffer;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < Size - 1; i++) {
|
||||
SYSTICK_DelayUs(1);
|
||||
pData[i] = I2C_Read(false);
|
||||
}
|
||||
|
||||
SYSTICK_DelayUs(1);
|
||||
pData[i] = I2C_Read(true);
|
||||
|
||||
return Size;
|
||||
}
|
||||
|
||||
int I2C_WriteBuffer(const void *pBuffer, uint8_t Size)
|
||||
{
|
||||
const uint8_t *pData = (const uint8_t *)pBuffer;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < Size; i++) {
|
||||
if (I2C_Write(*pData++) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
38
driver/i2c.h
Normal file
38
driver/i2c.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_I2C_H
|
||||
#define DRIVER_I2C_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum {
|
||||
I2C_WRITE = 0U,
|
||||
I2C_READ = 1U,
|
||||
};
|
||||
|
||||
void I2C_Start(void);
|
||||
void I2C_Stop(void);
|
||||
|
||||
uint8_t I2C_Read(bool bFinal);
|
||||
int I2C_Write(uint8_t Data);
|
||||
|
||||
int I2C_ReadBuffer(void *pBuffer, uint8_t Size);
|
||||
int I2C_WriteBuffer(const void *pBuffer, uint8_t Size);
|
||||
|
||||
#endif
|
||||
|
||||
153
driver/keyboard.c
Normal file
153
driver/keyboard.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/* Copyright 2023 Manuel Jinger
|
||||
* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/keyboard.h"
|
||||
#include "driver/systick.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "misc.h"
|
||||
|
||||
KEY_Code_t gKeyReading0 = KEY_INVALID;
|
||||
KEY_Code_t gKeyReading1 = KEY_INVALID;
|
||||
uint16_t gDebounceCounter = 0;
|
||||
bool gWasFKeyPressed = false;
|
||||
|
||||
static const struct {
|
||||
|
||||
// Using a 16 bit pre-calculated shift and invert is cheaper
|
||||
// than using 8 bit and doing shift and invert in code.
|
||||
uint16_t set_to_zero_mask;
|
||||
|
||||
// We are very fortunate.
|
||||
// The key and pin defines fit together in a single u8, making this very efficient
|
||||
struct {
|
||||
KEY_Code_t key : 5;
|
||||
uint8_t pin : 3; // Pin 6 is highest
|
||||
} pins[4];
|
||||
|
||||
} keyboard[] = {
|
||||
|
||||
{ // Zero row
|
||||
// Set to zero to handle special case of nothing pulled down
|
||||
.set_to_zero_mask = 0xffff,
|
||||
.pins = {
|
||||
{ .key = KEY_SIDE1, .pin = GPIOA_PIN_KEYBOARD_0},
|
||||
{ .key = KEY_SIDE2, .pin = GPIOA_PIN_KEYBOARD_1},
|
||||
|
||||
// Duplicate to fill the array with valid values
|
||||
{ .key = KEY_INVALID, .pin = GPIOA_PIN_KEYBOARD_1},
|
||||
{ .key = KEY_INVALID, .pin = GPIOA_PIN_KEYBOARD_1}
|
||||
}
|
||||
},
|
||||
{ // First row
|
||||
.set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_4) & 0xffff,
|
||||
.pins = {
|
||||
{ .key = KEY_MENU, .pin = GPIOA_PIN_KEYBOARD_0},
|
||||
{ .key = KEY_1, .pin = GPIOA_PIN_KEYBOARD_1},
|
||||
{ .key = KEY_4, .pin = GPIOA_PIN_KEYBOARD_2},
|
||||
{ .key = KEY_7, .pin = GPIOA_PIN_KEYBOARD_3}
|
||||
}
|
||||
},
|
||||
{ // Second row
|
||||
.set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_5) & 0xffff,
|
||||
.pins = {
|
||||
{ .key = KEY_UP, .pin = GPIOA_PIN_KEYBOARD_0},
|
||||
{ .key = KEY_2 , .pin = GPIOA_PIN_KEYBOARD_1},
|
||||
{ .key = KEY_5 , .pin = GPIOA_PIN_KEYBOARD_2},
|
||||
{ .key = KEY_8 , .pin = GPIOA_PIN_KEYBOARD_3}
|
||||
}
|
||||
},
|
||||
{ // Third row
|
||||
.set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_6) & 0xffff,
|
||||
.pins = {
|
||||
{ .key = KEY_DOWN, .pin = GPIOA_PIN_KEYBOARD_0},
|
||||
{ .key = KEY_3 , .pin = GPIOA_PIN_KEYBOARD_1},
|
||||
{ .key = KEY_6 , .pin = GPIOA_PIN_KEYBOARD_2},
|
||||
{ .key = KEY_9 , .pin = GPIOA_PIN_KEYBOARD_3}
|
||||
}
|
||||
},
|
||||
{ // Fourth row
|
||||
.set_to_zero_mask = ~(1u << GPIOA_PIN_KEYBOARD_7) & 0xffff,
|
||||
.pins = {
|
||||
{ .key = KEY_EXIT, .pin = GPIOA_PIN_KEYBOARD_0},
|
||||
{ .key = KEY_STAR, .pin = GPIOA_PIN_KEYBOARD_1},
|
||||
{ .key = KEY_0 , .pin = GPIOA_PIN_KEYBOARD_2},
|
||||
{ .key = KEY_F , .pin = GPIOA_PIN_KEYBOARD_3}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
KEY_Code_t KEYBOARD_Poll(void)
|
||||
{
|
||||
KEY_Code_t Key = KEY_INVALID;
|
||||
|
||||
// if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT))
|
||||
// return KEY_PTT;
|
||||
|
||||
// *****************
|
||||
|
||||
for (unsigned int j = 0; j < ARRAY_SIZE(keyboard); j++)
|
||||
{
|
||||
uint16_t reg;
|
||||
unsigned int i;
|
||||
unsigned int k;
|
||||
|
||||
// Set all high
|
||||
GPIOA->DATA |= 1u << GPIOA_PIN_KEYBOARD_4 |
|
||||
1u << GPIOA_PIN_KEYBOARD_5 |
|
||||
1u << GPIOA_PIN_KEYBOARD_6 |
|
||||
1u << GPIOA_PIN_KEYBOARD_7;
|
||||
|
||||
// Clear the pin we are selecting
|
||||
GPIOA->DATA &= keyboard[j].set_to_zero_mask;
|
||||
|
||||
// Read all 4 GPIO pins at once .. with de-noise, max of 8 sample loops
|
||||
for (i = 0, k = 0, reg = 0; i < 3 && k < 8; i++, k++) {
|
||||
SYSTICK_DelayUs(1);
|
||||
uint16_t reg2 = GPIOA->DATA;
|
||||
i *= reg == reg2;
|
||||
reg = reg2;
|
||||
}
|
||||
|
||||
if (i < 3)
|
||||
break; // noise is too bad
|
||||
|
||||
for (unsigned int i = 0; i < ARRAY_SIZE(keyboard[j].pins); i++)
|
||||
{
|
||||
const uint16_t mask = 1u << keyboard[j].pins[i].pin;
|
||||
if (!(reg & mask))
|
||||
{
|
||||
Key = keyboard[j].pins[i].key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Key != KEY_INVALID)
|
||||
break;
|
||||
}
|
||||
|
||||
// Create I2C stop condition since we might have toggled I2C pins
|
||||
// This leaves GPIOA_PIN_KEYBOARD_4 and GPIOA_PIN_KEYBOARD_5 high
|
||||
I2C_Stop();
|
||||
|
||||
// Reset VOICE pins
|
||||
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_6);
|
||||
GPIO_SetBit( &GPIOA->DATA, GPIOA_PIN_KEYBOARD_7);
|
||||
|
||||
return Key;
|
||||
}
|
||||
56
driver/keyboard.h
Normal file
56
driver/keyboard.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* Copyright 2023 Manuel Jinger
|
||||
* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_KEYBOARD_H
|
||||
#define DRIVER_KEYBOARD_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum KEY_Code_e {
|
||||
KEY_0 = 0, // 0
|
||||
KEY_1, // 1
|
||||
KEY_2, // 2
|
||||
KEY_3, // 3
|
||||
KEY_4, // 4
|
||||
KEY_5, // 5
|
||||
KEY_6, // 6
|
||||
KEY_7, // 7
|
||||
KEY_8, // 8
|
||||
KEY_9, // 9
|
||||
KEY_MENU, // A
|
||||
KEY_UP, // B
|
||||
KEY_DOWN, // C
|
||||
KEY_EXIT, // D
|
||||
KEY_STAR, // *
|
||||
KEY_F, // #
|
||||
KEY_PTT, //
|
||||
KEY_SIDE2, //
|
||||
KEY_SIDE1, //
|
||||
KEY_INVALID //
|
||||
};
|
||||
typedef enum KEY_Code_e KEY_Code_t;
|
||||
|
||||
extern KEY_Code_t gKeyReading0;
|
||||
extern KEY_Code_t gKeyReading1;
|
||||
extern uint16_t gDebounceCounter;
|
||||
extern bool gWasFKeyPressed;
|
||||
|
||||
KEY_Code_t KEYBOARD_Poll(void);
|
||||
|
||||
#endif
|
||||
|
||||
116
driver/spi.c
Normal file
116
driver/spi.c
Normal file
@@ -0,0 +1,116 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ARMCM0.h"
|
||||
#include "bsp/dp32g030/spi.h"
|
||||
#include "bsp/dp32g030/syscon.h"
|
||||
#include "bsp/dp32g030/irq.h"
|
||||
#include "driver/spi.h"
|
||||
|
||||
void SPI0_Init(void)
|
||||
{
|
||||
SPI_Config_t Config;
|
||||
|
||||
SPI_Disable(&SPI0->CR);
|
||||
|
||||
Config.TXFIFO_EMPTY = 0;
|
||||
Config.RXFIFO_HFULL = 0;
|
||||
Config.RXFIFO_FULL = 0;
|
||||
Config.RXFIFO_OVF = 0;
|
||||
Config.MSTR = 1;
|
||||
Config.SPR = 2;
|
||||
Config.CPHA = 1;
|
||||
Config.CPOL = 1;
|
||||
Config.LSB = 0;
|
||||
Config.TF_CLR = 0;
|
||||
Config.RF_CLR = 0;
|
||||
Config.TXFIFO_HFULL = 0;
|
||||
SPI_Configure(SPI0, &Config);
|
||||
|
||||
SPI_Enable(&SPI0->CR);
|
||||
}
|
||||
|
||||
void SPI_WaitForUndocumentedTxFifoStatusBit(void)
|
||||
{
|
||||
uint32_t Timeout;
|
||||
|
||||
Timeout = 0;
|
||||
do {
|
||||
// Undocumented bit!
|
||||
if ((SPI0->IF & 0x20) == 0) {
|
||||
break;
|
||||
}
|
||||
Timeout++;
|
||||
} while (Timeout <= 100000);
|
||||
}
|
||||
|
||||
void SPI_Disable(volatile uint32_t *pCR)
|
||||
{
|
||||
*pCR = (*pCR & ~SPI_CR_SPE_MASK) | SPI_CR_SPE_BITS_DISABLE;
|
||||
}
|
||||
|
||||
void SPI_Configure(volatile SPI_Port_t *pPort, SPI_Config_t *pConfig)
|
||||
{
|
||||
if (pPort == SPI0) {
|
||||
SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SPI0_MASK) | SYSCON_DEV_CLK_GATE_SPI0_BITS_ENABLE;
|
||||
} else if (pPort == SPI1) {
|
||||
SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SPI1_MASK) | SYSCON_DEV_CLK_GATE_SPI1_BITS_ENABLE;
|
||||
}
|
||||
|
||||
SPI_Disable(&pPort->CR);
|
||||
|
||||
pPort->CR = 0
|
||||
| (pPort->CR & ~(SPI_CR_SPR_MASK | SPI_CR_CPHA_MASK | SPI_CR_CPOL_MASK | SPI_CR_MSTR_MASK | SPI_CR_LSB_MASK | SPI_CR_RF_CLR_MASK))
|
||||
| ((pConfig->SPR << SPI_CR_SPR_SHIFT) & SPI_CR_SPR_MASK)
|
||||
| ((pConfig->CPHA << SPI_CR_CPHA_SHIFT) & SPI_CR_CPHA_MASK)
|
||||
| ((pConfig->CPOL << SPI_CR_CPOL_SHIFT) & SPI_CR_CPOL_MASK)
|
||||
| ((pConfig->MSTR << SPI_CR_MSTR_SHIFT) & SPI_CR_MSTR_MASK)
|
||||
| ((pConfig->LSB << SPI_CR_LSB_SHIFT) & SPI_CR_LSB_MASK)
|
||||
| ((pConfig->RF_CLR << SPI_CR_RF_CLR_SHIFT) & SPI_CR_RF_CLR_MASK)
|
||||
| ((pConfig->TF_CLR << SPI_CR_TF_CLR_SHIFT) & SPI_CR_TF_CLR_MASK)
|
||||
;
|
||||
|
||||
pPort->IE = 0
|
||||
| ((pConfig->RXFIFO_OVF << SPI_IE_RXFIFO_OVF_SHIFT) & SPI_IE_RXFIFO_OVF_MASK)
|
||||
| ((pConfig->RXFIFO_FULL << SPI_IE_RXFIFO_FULL_SHIFT) & SPI_IE_RXFIFO_FULL_MASK)
|
||||
| ((pConfig->RXFIFO_HFULL << SPI_IE_RXFIFO_HFULL_SHIFT) & SPI_IE_RXFIFO_HFULL_MASK)
|
||||
| ((pConfig->TXFIFO_EMPTY << SPI_IE_TXFIFO_EMPTY_SHIFT) & SPI_IE_TXFIFO_EMPTY_MASK)
|
||||
| ((pConfig->TXFIFO_HFULL << SPI_IE_TXFIFO_HFULL_SHIFT) & SPI_IE_TXFIFO_HFULL_MASK)
|
||||
;
|
||||
|
||||
if (pPort->IE) {
|
||||
if (pPort == SPI0) {
|
||||
NVIC_EnableIRQ((IRQn_Type)DP32_SPI0_IRQn);
|
||||
} else if (pPort == SPI1) {
|
||||
NVIC_EnableIRQ((IRQn_Type)DP32_SPI1_IRQn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SPI_ToggleMasterMode(volatile uint32_t *pCR, bool bIsMaster)
|
||||
{
|
||||
if (bIsMaster) {
|
||||
*pCR = (*pCR & ~SPI_CR_MSR_SSN_MASK) | SPI_CR_MSR_SSN_BITS_ENABLE;
|
||||
} else {
|
||||
*pCR = (*pCR & ~SPI_CR_MSR_SSN_MASK) | SPI_CR_MSR_SSN_BITS_DISABLE;
|
||||
}
|
||||
}
|
||||
|
||||
void SPI_Enable(volatile uint32_t *pCR)
|
||||
{
|
||||
*pCR = (*pCR & ~SPI_CR_SPE_MASK) | SPI_CR_SPE_BITS_ENABLE;
|
||||
}
|
||||
|
||||
47
driver/spi.h
Normal file
47
driver/spi.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_SPI_H
|
||||
#define DRIVER_SPI_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t MSTR;
|
||||
uint8_t SPR;
|
||||
uint8_t CPHA;
|
||||
uint8_t CPOL;
|
||||
uint8_t LSB;
|
||||
uint8_t TF_CLR;
|
||||
uint8_t RF_CLR;
|
||||
uint8_t TXFIFO_HFULL;
|
||||
uint8_t TXFIFO_EMPTY;
|
||||
uint8_t RXFIFO_HFULL;
|
||||
uint8_t RXFIFO_FULL;
|
||||
uint8_t RXFIFO_OVF;
|
||||
} SPI_Config_t;
|
||||
|
||||
void SPI0_Init(void);
|
||||
void SPI_WaitForUndocumentedTxFifoStatusBit(void);
|
||||
|
||||
void SPI_Disable(volatile uint32_t *pCR);
|
||||
void SPI_Configure(volatile SPI_Port_t *pPort, SPI_Config_t *pConfig);
|
||||
void SPI_ToggleMasterMode(volatile uint32_t *pCr, bool bIsMaster);
|
||||
void SPI_Enable(volatile uint32_t *pCR);
|
||||
|
||||
#endif
|
||||
|
||||
214
driver/st7565.c
Normal file
214
driver/st7565.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h> // NULL
|
||||
|
||||
#include "bsp/dp32g030/gpio.h"
|
||||
#include "bsp/dp32g030/spi.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi.h"
|
||||
#include "driver/st7565.h"
|
||||
#include "driver/system.h"
|
||||
#include "misc.h"
|
||||
|
||||
uint8_t gStatusLine[LCD_WIDTH];
|
||||
uint8_t gFrameBuffer[FRAME_LINES][LCD_WIDTH];
|
||||
|
||||
static void DrawLine(uint8_t column, uint8_t line, const uint8_t * lineBuffer, unsigned size_defVal)
|
||||
{
|
||||
ST7565_SelectColumnAndLine(column + 4, line);
|
||||
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0);
|
||||
for (unsigned i = 0; i < size_defVal; i++) {
|
||||
while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {}
|
||||
SPI0->WDR = lineBuffer ? lineBuffer[i] : size_defVal;
|
||||
}
|
||||
SPI_WaitForUndocumentedTxFifoStatusBit();
|
||||
}
|
||||
|
||||
void ST7565_DrawLine(const unsigned int Column, const unsigned int Line, const uint8_t *pBitmap, const unsigned int Size)
|
||||
{
|
||||
SPI_ToggleMasterMode(&SPI0->CR, false);
|
||||
DrawLine(Column, Line, pBitmap, Size);
|
||||
SPI_ToggleMasterMode(&SPI0->CR, true);
|
||||
}
|
||||
|
||||
void ST7565_BlitFullScreen(void)
|
||||
{
|
||||
SPI_ToggleMasterMode(&SPI0->CR, false);
|
||||
ST7565_WriteByte(0x40);
|
||||
for (unsigned line = 0; line < FRAME_LINES; line++) {
|
||||
DrawLine(0, line+1, gFrameBuffer[line], LCD_WIDTH);
|
||||
}
|
||||
SPI_ToggleMasterMode(&SPI0->CR, true);
|
||||
}
|
||||
|
||||
void ST7565_BlitLine(unsigned line)
|
||||
{
|
||||
SPI_ToggleMasterMode(&SPI0->CR, false);
|
||||
ST7565_WriteByte(0x40); // start line ?
|
||||
DrawLine(0, line+1, gFrameBuffer[line], LCD_WIDTH);
|
||||
SPI_ToggleMasterMode(&SPI0->CR, true);
|
||||
}
|
||||
|
||||
void ST7565_BlitStatusLine(void)
|
||||
{ // the top small text line on the display
|
||||
SPI_ToggleMasterMode(&SPI0->CR, false);
|
||||
ST7565_WriteByte(0x40); // start line ?
|
||||
DrawLine(0, 0, gStatusLine, LCD_WIDTH);
|
||||
SPI_ToggleMasterMode(&SPI0->CR, true);
|
||||
}
|
||||
|
||||
void ST7565_FillScreen(uint8_t value)
|
||||
{
|
||||
SPI_ToggleMasterMode(&SPI0->CR, false);
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
DrawLine(0, i, NULL, value);
|
||||
}
|
||||
SPI_ToggleMasterMode(&SPI0->CR, true);
|
||||
}
|
||||
|
||||
// Software reset
|
||||
const uint8_t ST7565_CMD_SOFTWARE_RESET = 0xE2;
|
||||
// Bias Select
|
||||
// 1 0 1 0 0 0 1 BS
|
||||
// Select bias setting 0=1/9; 1=1/7 (at 1/65 duty)
|
||||
const uint8_t ST7565_CMD_BIAS_SELECT = 0xA2;
|
||||
// COM Direction
|
||||
// 1 1 0 0 MY - - -
|
||||
// Set output direction of COM
|
||||
// MY=1, reverse direction
|
||||
// MY=0, normal direction
|
||||
const uint8_t ST7565_CMD_COM_DIRECTION = 0xC0;
|
||||
// SEG Direction
|
||||
// 1 0 1 0 0 0 0 MX
|
||||
// Set scan direction of SEG
|
||||
// MX=1, reverse direction
|
||||
// MX=0, normal direction
|
||||
const uint8_t ST7565_CMD_SEG_DIRECTION = 0xA0;
|
||||
// Inverse Display
|
||||
// 1 0 1 0 0 1 1 INV
|
||||
// INV =1, inverse display
|
||||
// INV =0, normal display
|
||||
const uint8_t ST7565_CMD_INVERSE_DISPLAY = 0xA6;
|
||||
// All Pixel ON
|
||||
// 1 0 1 0 0 1 0 AP
|
||||
// AP=1, set all pixel ON
|
||||
// AP=0, normal display
|
||||
const uint8_t ST7565_CMD_ALL_PIXEL_ON = 0xA4;
|
||||
// Regulation Ratio
|
||||
// 0 0 1 0 0 RR2 RR1 RR0
|
||||
// This instruction controls the regulation ratio of the built-in regulator
|
||||
const uint8_t ST7565_CMD_REGULATION_RATIO = 0x20;
|
||||
// Double command!! Set electronic volume (EV) level
|
||||
// Send next: 0 0 EV5 EV4 EV3 EV2 EV1 EV0 contrast 0-63
|
||||
const uint8_t ST7565_CMD_SET_EV = 0x81;
|
||||
// Control built-in power circuit ON/OFF - 0 0 1 0 1 VB VR VF
|
||||
// VB: Built-in Booster
|
||||
// VR: Built-in Regulator
|
||||
// VF: Built-in Follower
|
||||
const uint8_t ST7565_CMD_POWER_CIRCUIT = 0x28;
|
||||
// Set display start line 0-63
|
||||
// 0 0 0 1 S5 S4 S3 S2 S1 S0
|
||||
const uint8_t ST7565_CMD_SET_START_LINE = 0x40;
|
||||
// Display ON/OFF
|
||||
// 0 0 1 0 1 0 1 1 1 D
|
||||
// D=1, display ON
|
||||
// D=0, display OFF
|
||||
const uint8_t ST7565_CMD_DISPLAY_ON_OFF = 0xAE;
|
||||
|
||||
uint8_t cmds[] = {
|
||||
ST7565_CMD_BIAS_SELECT | 0, // Select bias setting: 1/9
|
||||
ST7565_CMD_COM_DIRECTION | (0 << 3), // Set output direction of COM: normal
|
||||
ST7565_CMD_SEG_DIRECTION | 1, // Set scan direction of SEG: reverse
|
||||
ST7565_CMD_INVERSE_DISPLAY | 0, // Inverse Display: false
|
||||
ST7565_CMD_ALL_PIXEL_ON | 0, // All Pixel ON: false - normal display
|
||||
ST7565_CMD_REGULATION_RATIO | (4 << 0), // Regulation Ratio 5.0
|
||||
|
||||
ST7565_CMD_SET_EV, // Set contrast
|
||||
31,
|
||||
|
||||
ST7565_CMD_POWER_CIRCUIT | 0b111, // Built-in power circuit ON/OFF: VB=1 VR=1 VF=1
|
||||
ST7565_CMD_SET_START_LINE | 0, // Set Start Line: 0
|
||||
ST7565_CMD_DISPLAY_ON_OFF | 1, // Display ON/OFF: ON
|
||||
};
|
||||
|
||||
void ST7565_Init(void)
|
||||
{
|
||||
SPI0_Init();
|
||||
ST7565_HardwareReset();
|
||||
SPI_ToggleMasterMode(&SPI0->CR, false);
|
||||
ST7565_WriteByte(ST7565_CMD_SOFTWARE_RESET); // software reset
|
||||
SYSTEM_DelayMs(120);
|
||||
|
||||
for(uint8_t i = 0; i < 8; i++)
|
||||
ST7565_WriteByte(cmds[i]);
|
||||
|
||||
ST7565_WriteByte(ST7565_CMD_POWER_CIRCUIT | 0b011); // VB=0 VR=1 VF=1
|
||||
SYSTEM_DelayMs(1);
|
||||
ST7565_WriteByte(ST7565_CMD_POWER_CIRCUIT | 0b110); // VB=1 VR=1 VF=0
|
||||
SYSTEM_DelayMs(1);
|
||||
|
||||
for(uint8_t i = 0; i < 4; i++) // why 4 times?
|
||||
ST7565_WriteByte(ST7565_CMD_POWER_CIRCUIT | 0b111); // VB=1 VR=1 VF=1
|
||||
|
||||
SYSTEM_DelayMs(40);
|
||||
|
||||
ST7565_WriteByte(ST7565_CMD_SET_START_LINE | 0); // line 0
|
||||
ST7565_WriteByte(ST7565_CMD_DISPLAY_ON_OFF | 1); // D=1
|
||||
SPI_WaitForUndocumentedTxFifoStatusBit();
|
||||
SPI_ToggleMasterMode(&SPI0->CR, true);
|
||||
|
||||
ST7565_FillScreen(0x00);
|
||||
}
|
||||
|
||||
void ST7565_FixInterfGlitch(void)
|
||||
{
|
||||
SPI_ToggleMasterMode(&SPI0->CR, false);
|
||||
for(uint8_t i = 0; i < ARRAY_SIZE(cmds); i++)
|
||||
ST7565_WriteByte(cmds[i]);
|
||||
SPI_WaitForUndocumentedTxFifoStatusBit();
|
||||
SPI_ToggleMasterMode(&SPI0->CR, true);
|
||||
}
|
||||
|
||||
void ST7565_HardwareReset(void)
|
||||
{
|
||||
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_RES);
|
||||
SYSTEM_DelayMs(1);
|
||||
GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_ST7565_RES);
|
||||
SYSTEM_DelayMs(20);
|
||||
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_RES);
|
||||
SYSTEM_DelayMs(120);
|
||||
}
|
||||
|
||||
void ST7565_SelectColumnAndLine(uint8_t Column, uint8_t Line)
|
||||
{
|
||||
GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0);
|
||||
while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {}
|
||||
SPI0->WDR = Line + 176;
|
||||
while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {}
|
||||
SPI0->WDR = ((Column >> 4) & 0x0F) | 0x10;
|
||||
while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {}
|
||||
SPI0->WDR = ((Column >> 0) & 0x0F);
|
||||
SPI_WaitForUndocumentedTxFifoStatusBit();
|
||||
}
|
||||
|
||||
void ST7565_WriteByte(uint8_t Value)
|
||||
{
|
||||
GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_ST7565_A0);
|
||||
while ((SPI0->FIFOST & SPI_FIFOST_TFF_MASK) != SPI_FIFOST_TFF_BITS_NOT_FULL) {}
|
||||
SPI0->WDR = Value;
|
||||
}
|
||||
42
driver/st7565.h
Normal file
42
driver/st7565.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* Copyright 2023 Dual Tachyon
|
||||
* https://github.com/DualTachyon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_ST7565_H
|
||||
#define DRIVER_ST7565_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define LCD_WIDTH 128
|
||||
#define LCD_HEIGHT 64
|
||||
#define FRAME_LINES 7
|
||||
|
||||
extern uint8_t gStatusLine[LCD_WIDTH];
|
||||
extern uint8_t gFrameBuffer[FRAME_LINES][LCD_WIDTH];
|
||||
|
||||
void ST7565_DrawLine(const unsigned int Column, const unsigned int Line, const uint8_t *pBitmap, const unsigned int Size);
|
||||
void ST7565_BlitFullScreen(void);
|
||||
void ST7565_BlitLine(unsigned line);
|
||||
void ST7565_BlitStatusLine(void);
|
||||
void ST7565_FillScreen(uint8_t Value);
|
||||
void ST7565_Init(void);
|
||||
void ST7565_FixInterfGlitch(void);
|
||||
void ST7565_HardwareReset(void);
|
||||
void ST7565_SelectColumnAndLine(uint8_t Column, uint8_t Line);
|
||||
void ST7565_WriteByte(uint8_t Value);
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user