mirror of
https://github.com/pelgraine/Meck.git
synced 2026-05-12 12:26:00 +02:00
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e589b3eb9 | |||
| b0ad1c4901 | |||
| ceb29ba662 | |||
| 18b9ab6c4d | |||
| 661157e368 | |||
| 5cca0e8e50 | |||
| 3596ad558d | |||
| 6de664ea37 | |||
| 708b96e0e8 | |||
| 4b734f1bac | |||
| 20310018d3 | |||
| 8afe71510e | |||
| 7adc0283b2 | |||
| e72e498db9 | |||
| 468a5ad324 | |||
| 44353fcf9e | |||
| 4ba130ccfa | |||
| c2bfc3c985 | |||
| 00b3f66bc4 | |||
| fb93b4e4ec | |||
| a7b44de613 | |||
| 7ebafc39ee | |||
| 97498e131d | |||
| 95c992d966 | |||
| 9c4c374db8 | |||
| ca16af54cc | |||
| f51d8be290 | |||
| 6c0c77d788 | |||
| 715202849c | |||
| 46ff5229e1 | |||
| 64afdb2829 | |||
| 26d54074c8 | |||
| b5b11a2036 | |||
| 964606a018 | |||
| a8d65aa3ba | |||
| e74aa3b214 | |||
| 36976e0029 | |||
| f461777214 | |||
| 7e1009f31c | |||
| db0ecd3c58 | |||
| 291c42a40e | |||
| 88a56d3ff5 | |||
| 4ec5d17402 |
@@ -0,0 +1,4 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: pelgraine
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
A fork created specifically to focus on enabling BLE & WiFi companion firmware for the LilyGo T-Deck Pro & LilyGo T5 E-Paper S3 Pro. Created wholly with Claude AI using Meshcore v1.11 code. 100% vibecoded.
|
A fork created specifically to focus on enabling BLE & WiFi companion firmware for the LilyGo T-Deck Pro & LilyGo T5 E-Paper S3 Pro. Created wholly with Claude AI using Meshcore v1.11 code. 100% vibecoded.
|
||||||
|
|
||||||
[Check out the Meck discussion channel on the MeshCore Discord](https://discord.com/channels/1343693475589263471/1460136499390447670)
|
[Check out the Meck discussion channel on the MeshCore Discord](https://discord.com/channels/1495203904898728149/1496789639556501614)
|
||||||
|
|
||||||
<img src="https://github.com/user-attachments/assets/b30ce6bd-79af-44d3-93c4-f5e7e21e5621" alt="IMG_1453" width="300" height="650">
|
<img src="https://github.com/user-attachments/assets/b30ce6bd-79af-44d3-93c4-f5e7e21e5621" alt="IMG_1453" width="300" height="650">
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@ A fork created specifically to focus on enabling BLE & WiFi companion firmware f
|
|||||||
- [Sending a Direct Message](#sending-a-direct-message)
|
- [Sending a Direct Message](#sending-a-direct-message)
|
||||||
- [Roomservers](#roomservers)
|
- [Roomservers](#roomservers)
|
||||||
- [Repeater Admin Screen](#repeater-admin-screen)
|
- [Repeater Admin Screen](#repeater-admin-screen)
|
||||||
|
- [Trace Route Screen (v1.9+)](#trace-route-screen-v19)
|
||||||
- [Settings Screen](#settings-screen)
|
- [Settings Screen](#settings-screen)
|
||||||
- [Font Styles](#font-styles)
|
- [Font Styles](#font-styles)
|
||||||
- [Compose Mode](#compose-mode)
|
- [Compose Mode](#compose-mode)
|
||||||
@@ -39,6 +40,7 @@ A fork created specifically to focus on enabling BLE & WiFi companion firmware f
|
|||||||
- [Alarm Clock (Audio only)](#alarm-clock-audio-only)
|
- [Alarm Clock (Audio only)](#alarm-clock-audio-only)
|
||||||
- [Voice Notes Over LoRa (Audio only)](#voice-notes-over-lora-audio-only)
|
- [Voice Notes Over LoRa (Audio only)](#voice-notes-over-lora-audio-only)
|
||||||
- [Lock Screen (T-Deck Pro)](#lock-screen-t-deck-pro)
|
- [Lock Screen (T-Deck Pro)](#lock-screen-t-deck-pro)
|
||||||
|
- [Shutdown (T-Deck Pro)](#shutdown-t-deck-pro)
|
||||||
- [Remote Repeater (T-Deck Pro 4G)](#remote-repeater-t-deck-pro-4g)
|
- [Remote Repeater (T-Deck Pro 4G)](#remote-repeater-t-deck-pro-4g)
|
||||||
- [WiFi Repeater](#wifi-repeater)
|
- [WiFi Repeater](#wifi-repeater)
|
||||||
- [T5S3 E-Paper Pro](#t5s3-e-paper-pro)
|
- [T5S3 E-Paper Pro](#t5s3-e-paper-pro)
|
||||||
@@ -120,7 +122,7 @@ On macOS the port is typically `/dev/cu.usbmodem*`. On Windows it will be a COM
|
|||||||
|
|
||||||
**Using the MeshCore Flasher (web-based, T-Deck Pro only):**
|
**Using the MeshCore Flasher (web-based, T-Deck Pro only):**
|
||||||
|
|
||||||
1. Go to https://flasher.meshcore.co.uk
|
1. Go to https://flasher.meshcore.io
|
||||||
2. Select **Custom Firmware**
|
2. Select **Custom Firmware**
|
||||||
3. Select the **merged** `.bin` file you downloaded
|
3. Select the **merged** `.bin` file you downloaded
|
||||||
4. Click **Flash**, select your device in the popup, and click **Connect**
|
4. Click **Flash**, select your device in the popup, and click **Connect**
|
||||||
@@ -140,6 +142,8 @@ esptool.py --chip esp32s3 --port /dev/ttyACM0 --baud 921600 \
|
|||||||
|
|
||||||
> **Tip:** If you're unsure whether the device already has a bootloader, it's always safe to use the merged file and flash at `0x0` — it will overwrite everything cleanly.
|
> **Tip:** If you're unsure whether the device already has a bootloader, it's always safe to use the merged file and flash at `0x0` — it will overwrite everything cleanly.
|
||||||
|
|
||||||
|
> **First boot:** On a fresh flash, the device will format its internal storage partition. The display shows "Formatting storage... First boot - please wait" — this takes 1-2 minutes and only happens once. If the device was previously running different firmware (e.g. stock LilyGo or Meshtastic), the partition is automatically erased and reformatted to ensure a clean start.
|
||||||
|
|
||||||
### Launcher
|
### Launcher
|
||||||
|
|
||||||
If you're loading firmware from an SD card via the LilyGo Launcher firmware, use the **non-merged** `.bin` file. The Launcher provides its own bootloader and only needs the application image.
|
If you're loading firmware from an SD card via the LilyGo Launcher firmware, use the **non-merged** `.bin` file. The Launcher provides its own bootloader and only needs the application image.
|
||||||
@@ -240,6 +244,7 @@ The T-Deck Pro firmware includes full keyboard support for standalone messaging
|
|||||||
| K | Open alarm clock (audio variant only) |
|
| K | Open alarm clock (audio variant only) |
|
||||||
| F | Open node discovery (search for nearby repeaters/nodes) |
|
| F | Open node discovery (search for nearby repeaters/nodes) |
|
||||||
| H | Open last heard list (passive advert history) |
|
| H | Open last heard list (passive advert history) |
|
||||||
|
| R | Open trace route screen (v1.9+) — see [Trace Route Screen](#trace-route-screen-v19) |
|
||||||
| G | Open map screen (shows contacts with GPS positions) |
|
| G | Open map screen (shows contacts with GPS positions) |
|
||||||
| Mic | Open voice messages (audio variant only) |
|
| Mic | Open voice messages (audio variant only) |
|
||||||
| Q | Back to home screen |
|
| Q | Back to home screen |
|
||||||
@@ -343,6 +348,7 @@ Flood-based hop estimates (`~D`, `~N`) are drawn from a cache of up to 1,000 rec
|
|||||||
| Key | Action |
|
| Key | Action |
|
||||||
|-----|--------|
|
|-----|--------|
|
||||||
| W / S | Scroll up / down through contacts |
|
| W / S | Scroll up / down through contacts |
|
||||||
|
| Shift+W / Shift+S | Page up / page down |
|
||||||
| A / D | Cycle filter: All → Chat → Rptr → Room → Sens → Fav |
|
| A / D | Cycle filter: All → Chat → Rptr → Room → Sens → Fav |
|
||||||
| Enter | Enter select mode (highlights current contact, enables batch operations) |
|
| Enter | Enter select mode (highlights current contact, enables batch operations) |
|
||||||
| P | Open path editor for the highlighted contact |
|
| P | Open path editor for the highlighted contact |
|
||||||
@@ -426,6 +432,58 @@ After a successful login, you'll see a menu with the following remote administra
|
|||||||
|
|
||||||
Command responses are displayed in a scrollable view. Use **W / S** to scroll long responses and **Q** to return to the menu.
|
Command responses are displayed in a scrollable view. Use **W / S** to scroll long responses and **Q** to return to the menu.
|
||||||
|
|
||||||
|
### Trace Route Screen (v1.9+)
|
||||||
|
|
||||||
|
The trace route screen lets you build a chain of repeaters and run a trace through them — the same feature available in the MeshCore companion app, but on-device. Each repeater in the chain that recognises its hash appends its receive SNR before forwarding the packet, giving you per-hop signal quality data for the whole route.
|
||||||
|
|
||||||
|
Press **R** from the home screen to open the trace screen. T5S3 users with a CardKB attached can use **R** as well.
|
||||||
|
|
||||||
|
**Building the path**
|
||||||
|
|
||||||
|
There are two ways to add hops to the path:
|
||||||
|
|
||||||
|
- **+ Add repeater** — opens a picker showing all known Repeater contacts. Press W/S to scroll, Enter to append the highlighted repeater to the path. The contact picker uses the repeater's stored public key bytes directly, so the hash is always correct regardless of mode.
|
||||||
|
- **Type Path** — opens an inline text editor for comma-separated decimal hash values, matching the format the companion app uses (e.g. `3601,2198,1244,2198,3601`). Useful when the repeater isn't in your contacts but you know its hash from the app or a community listing.
|
||||||
|
|
||||||
|
The path is shown as a numbered list below the menu. Individual hops can be edited or removed, and the whole path can be cleared if you need to start over.
|
||||||
|
|
||||||
|
**Hash mode**
|
||||||
|
|
||||||
|
Meck supports both 1-byte and 2-byte hash modes. The screen defaults to your device's `path.hash.mode` setting but can be toggled on the fly:
|
||||||
|
|
||||||
|
- 1-byte mode (`Mode: 1-byte`) — older networks, more collision-prone but smaller packets
|
||||||
|
- 2-byte mode (`Mode: 2-byte`) — current MeshCore default in most regions, fewer hash collisions
|
||||||
|
|
||||||
|
Use **A / D** on the mode row to toggle, or Enter to cycle.
|
||||||
|
|
||||||
|
**Running a trace**
|
||||||
|
|
||||||
|
Once at least one hop is in the path, scroll to **Run Trace** and press Enter. Meck creates a `PAYLOAD_TYPE_TRACE` packet and sends it direct-routed through the chain. The screen switches to a "Tracing..." state with an elapsed-time counter while waiting for the response.
|
||||||
|
|
||||||
|
When the trace completes, the screen shows:
|
||||||
|
|
||||||
|
- Each hop in order with its receive SNR (in dB)
|
||||||
|
- The final SNR of the response packet arriving back at your device
|
||||||
|
- Total round-trip time in milliseconds
|
||||||
|
|
||||||
|
If 30 seconds pass without a response, the trace times out and the screen returns to the build view so you can adjust the path and try again.
|
||||||
|
|
||||||
|
**Symmetric paths and direct visibility**
|
||||||
|
|
||||||
|
For a round-trip trace, the path needs to be symmetric. To trace through repeaters A → B → C and back, type `A,B,C,B,A`. The trace packet travels out through A→B→C, and the response comes back C→B→A.
|
||||||
|
|
||||||
|
You also need to be able to **hear the last repeater in the chain directly** — that's the one that sends the response back to your device. If the last hop is too far away to hear, the trace will time out even though the outbound leg succeeded.
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| W / S | Navigate menu items |
|
||||||
|
| A / D | Toggle hash mode (1-byte / 2-byte) on the mode row |
|
||||||
|
| Enter | Select / confirm / open editor |
|
||||||
|
| 0–9 , | Path values (when the inline text editor is open) |
|
||||||
|
| Q | Cancel edit / back to home screen |
|
||||||
|
|
||||||
|
The screen supports up to **16 hops** per trace.
|
||||||
|
|
||||||
### Settings Screen
|
### Settings Screen
|
||||||
|
|
||||||
Press **S** from the home screen to open settings. On first boot (when the device name is still the default hex ID), the settings screen launches automatically as an onboarding wizard to set your device name and radio preset.
|
Press **S** from the home screen to open settings. On first boot (when the device name is still the default hex ID), the settings screen launches automatically as an onboarding wizard to set your device name and radio preset.
|
||||||
@@ -433,6 +491,7 @@ Press **S** from the home screen to open settings. On first boot (when the devic
|
|||||||
| Key | Action |
|
| Key | Action |
|
||||||
|-----|--------|
|
|-----|--------|
|
||||||
| W / S | Navigate up / down through settings |
|
| W / S | Navigate up / down through settings |
|
||||||
|
| Shift+W / Shift+S | Page up / page down |
|
||||||
| Enter | Edit selected setting, or enter a sub-screen |
|
| Enter | Edit selected setting, or enter a sub-screen |
|
||||||
| Q | Back one level (sub-screen → top level → home screen) |
|
| Q | Back one level (sub-screen → top level → home screen) |
|
||||||
|
|
||||||
@@ -491,6 +550,8 @@ Change the font in **Settings → Font** — use A/D to cycle with a live previe
|
|||||||
|
|
||||||
Font styles are available in both Tiny and Larger text size modes. Custom fonts at Tiny size use 7pt glyphs; at Larger size, 9pt — matching the existing FreeSans layout. The font preference is saved and persists across reboots.
|
Font styles are available in both Tiny and Larger text size modes. Custom fonts at Tiny size use 7pt glyphs; at Larger size, 9pt — matching the existing FreeSans layout. The font preference is saved and persists across reboots.
|
||||||
|
|
||||||
|
**Accented character support (v1.8+):** All three font styles now display accented and diacritical characters (Czech, Polish, French, German, etc.) instead of dropping them. **Noto Sans at Larger text size** renders diacritical marks natively (carons, accents, cedillas). All other font and size combinations fold accented characters to their ASCII base letter (ě→e, ž→z, ñ→n) — the letter is always visible, just without the diacritic mark.
|
||||||
|
|
||||||
### Compose Mode
|
### Compose Mode
|
||||||
|
|
||||||
| Key | Action |
|
| Key | Action |
|
||||||
@@ -527,7 +588,7 @@ Press the **Sym** key then the letter key to enter numbers and symbols:
|
|||||||
|
|
||||||
### Emoji Picker
|
### Emoji Picker
|
||||||
|
|
||||||
While in compose mode, press the **$** key to open the emoji picker. A scrollable grid of 76 emoji is displayed in a 5-column layout, with faces and emotions grouped first. Scrolling wraps around — pressing W on the first row goes to the last row and vice versa.
|
While in compose mode, press the **$** key to open the emoji picker. A scrollable grid of 77 emoji is displayed in a 5-column layout, with faces and emotions grouped first. Scrolling wraps around — pressing W on the first row goes to the last row and vice versa.
|
||||||
|
|
||||||
| Key | Action |
|
| Key | Action |
|
||||||
|-----|--------|
|
|-----|--------|
|
||||||
@@ -641,6 +702,10 @@ Double-click the Boot button again to unlock and return to whatever screen you w
|
|||||||
|
|
||||||
An auto-lock timer can be configured in **Settings → Auto Lock** (None / 2 / 5 / 10 / 15 / 30 minutes of idle time).
|
An auto-lock timer can be configured in **Settings → Auto Lock** (None / 2 / 5 / 10 / 15 / 30 minutes of idle time).
|
||||||
|
|
||||||
|
### Shutdown (T-Deck Pro)
|
||||||
|
|
||||||
|
The home screen includes a **Shutdown** page. Selecting it powers the device off completely — the ESP32-S3 enters deep sleep with no wake sources, peripheral power is cut, and the LoRa module is powered down. Only a hardware reset (reset button) or USB power-on will wake the device. This is distinct from the auto-lock hibernate, which maintains wake-on-LoRa capability.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Remote Repeater (T-Deck Pro 4G)
|
## Remote Repeater (T-Deck Pro 4G)
|
||||||
@@ -762,7 +827,7 @@ The virtual keyboard supports:
|
|||||||
- QWERTY letter layout with a symbol/number layer (tap the **123** key to switch)
|
- QWERTY letter layout with a symbol/number layer (tap the **123** key to switch)
|
||||||
- Shift toggle for uppercase
|
- Shift toggle for uppercase
|
||||||
- Backspace (UTF-8 aware — correctly deletes multi-byte emoji) and Enter keys
|
- Backspace (UTF-8 aware — correctly deletes multi-byte emoji) and Enter keys
|
||||||
- **Emoji picker** — tap the **$** key to open a scrollable 8-column grid of 76 emoji sprites with page indicators. Tap an emoji to insert it inline in your message. Tap **Back** to return to the keyboard. Faces and emotions are grouped first for quick access.
|
- **Emoji picker** — tap the **$** key to open a scrollable 8-column grid of 77 emoji sprites with page indicators. Tap an emoji to insert it inline in your message. Tap **Back** to return to the keyboard. Faces and emotions are grouped first for quick access.
|
||||||
- Inline emoji rendering — emoji appear as pixel sprites in the text field as you type
|
- Inline emoji rendering — emoji appear as pixel sprites in the text field as you type
|
||||||
- Phantom keystroke prevention (a brief cooldown after the keyboard opens prevents accidental taps)
|
- Phantom keystroke prevention (a brief cooldown after the keyboard opens prevents accidental taps)
|
||||||
|
|
||||||
@@ -1021,7 +1086,7 @@ The companion firmware can be connected to via BLE (T-Deck Pro and T5S3 BLE vari
|
|||||||
|
|
||||||
## 🛠 Hardware Compatibility
|
## 🛠 Hardware Compatibility
|
||||||
|
|
||||||
MeshCore is designed for devices listed in the [MeshCore Flasher](https://flasher.meshcore.co.uk). Meck specifically targets the LilyGo T-Deck Pro, LilyGo T5S3 E-Paper Pro, Heltec V3 (remote repeater only), and Heltec V4 (remote repeater only).
|
MeshCore is designed for devices listed in the [MeshCore Flasher](https://flasher.meshcore.io). Meck specifically targets the LilyGo T-Deck Pro, LilyGo T5S3 E-Paper Pro, Heltec V3 (remote repeater only), and Heltec V4 (remote repeater only).
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
@@ -1068,8 +1133,14 @@ There are a number of fairly major features in the pipeline, with no particular
|
|||||||
- [X] Channel picker screen with unread badges
|
- [X] Channel picker screen with unread badges
|
||||||
- [X] Region scope (MeshCore v1.15+ compatibility)
|
- [X] Region scope (MeshCore v1.15+ compatibility)
|
||||||
- [X] Selectable font styles (Classic, Noto Sans, Montserrat)
|
- [X] Selectable font styles (Classic, Noto Sans, Montserrat)
|
||||||
- [X] Expanded emoji picker (76 emoji, reordered, wrap scrolling)
|
- [X] Expanded emoji picker (77 emoji, reordered, wrap scrolling)
|
||||||
- [X] 1,000-entry advert path cache (PSRAM)
|
- [X] 1,000-entry advert path cache (PSRAM)
|
||||||
|
- [X] Accented character / diacritics support (Czech, Polish, French, German, Latin Extended)
|
||||||
|
- [X] Page scroll (Shift+W/S) on all list screens
|
||||||
|
- [X] True power off (deep sleep, no wake sources)
|
||||||
|
- [X] BLE 2M PHY, DLE, and faster write interval
|
||||||
|
- [X] Trace route screen with contact picker and typed-path entry (v1.9)
|
||||||
|
- [X] DM message persistence across reboots (v1.9)
|
||||||
- [ ] Fix M4B rendering to enable chaptered audiobook playback
|
- [ ] Fix M4B rendering to enable chaptered audiobook playback
|
||||||
- [ ] Better JPEG and PNG decoding
|
- [ ] Better JPEG and PNG decoding
|
||||||
- [ ] Improve EPUB rendering and EPUB format handling
|
- [ ] Improve EPUB rendering and EPUB format handling
|
||||||
@@ -1103,6 +1174,8 @@ There are a number of fairly major features in the pipeline, with no particular
|
|||||||
- [X] Region scope (MeshCore v1.15+ compatibility)
|
- [X] Region scope (MeshCore v1.15+ compatibility)
|
||||||
- [X] Selectable font styles (Classic, Noto Sans, Montserrat)
|
- [X] Selectable font styles (Classic, Noto Sans, Montserrat)
|
||||||
- [X] Virtual keyboard emoji grid with scrollable pages
|
- [X] Virtual keyboard emoji grid with scrollable pages
|
||||||
|
- [X] Accented character / diacritics support (Czech, Polish, French, German, Latin Extended)
|
||||||
|
- [X] DM message persistence across reboots (v1.9)
|
||||||
- [ ] Improve EPUB rendering and EPUB format handling
|
- [ ] Improve EPUB rendering and EPUB format handling
|
||||||
|
|
||||||
**Heltec V4:**
|
**Heltec V4:**
|
||||||
@@ -1118,7 +1191,7 @@ There are a number of fairly major features in the pipeline, with no particular
|
|||||||
|
|
||||||
## 📞 Get Support
|
## 📞 Get Support
|
||||||
|
|
||||||
- Join [MeshCore Discord](https://discord.gg/BMwCtwHj5V) to chat with the developers and get help from the community.
|
- Join [MeshCore Discord](https://discord.gg/KWFeY45sN) to chat with the developers and get help from the community.
|
||||||
|
|
||||||
## 📜 License
|
## 📜 License
|
||||||
|
|
||||||
|
|||||||
@@ -5,26 +5,29 @@
|
|||||||
},
|
},
|
||||||
"core": "nRF5",
|
"core": "nRF5",
|
||||||
"cpu": "cortex-m4",
|
"cpu": "cortex-m4",
|
||||||
"extra_flags": [
|
"extra_flags": "-DNRF52840_XXAA",
|
||||||
"-DARDUINO_NRF52840_TECHO_CARD",
|
|
||||||
"-DNRF52840_XXAA",
|
|
||||||
"-DNRF52_SERIES"
|
|
||||||
],
|
|
||||||
"f_cpu": "64000000L",
|
"f_cpu": "64000000L",
|
||||||
"hwids": [["0x239A", "0x8029"]],
|
"hwids": [
|
||||||
|
["0x239A", "0x8029"]
|
||||||
|
],
|
||||||
|
"usb_product": "T-Echo Card",
|
||||||
"mcu": "nrf52840",
|
"mcu": "nrf52840",
|
||||||
"variant": "lilygo_techo_card",
|
"variant": "lilygo_techo_card",
|
||||||
|
"variants_dir": "variants_bsp",
|
||||||
"bsp": {
|
"bsp": {
|
||||||
"name": "adafruit"
|
"name": "adafruit"
|
||||||
},
|
},
|
||||||
"softdevice": {
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS140",
|
||||||
"sd_name": "s140",
|
"sd_name": "s140",
|
||||||
"sd_version": "6.1.1",
|
"sd_version": "6.1.1",
|
||||||
"sd_fwid": "0x00B6"
|
"sd_fwid": "0x00B6"
|
||||||
},
|
},
|
||||||
"usb_product": "T-Echo Card"
|
"bootloader": {
|
||||||
|
"settings_addr": "0xFF000"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"connectivity": ["bluetooth", "lora"],
|
"connectivity": ["bluetooth"],
|
||||||
"debug": {
|
"debug": {
|
||||||
"jlink_device": "nRF52840_xxAA",
|
"jlink_device": "nRF52840_xxAA",
|
||||||
"openocd_target": "nrf52840"
|
"openocd_target": "nrf52840"
|
||||||
@@ -32,17 +35,16 @@
|
|||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino"],
|
||||||
"name": "LilyGo T-Echo Card (nRF52840, SX1262, 4MB Flash)",
|
"name": "LilyGo T-Echo Card (nRF52840, SX1262, 4MB Flash)",
|
||||||
"upload": {
|
"upload": {
|
||||||
"flash_size": "796KB",
|
|
||||||
"maximum_ram_size": 248832,
|
"maximum_ram_size": 248832,
|
||||||
"maximum_size": 815104,
|
"maximum_size": 815104,
|
||||||
"native_usb": true,
|
"speed": 115200,
|
||||||
"protocol": "nrfutil",
|
"protocol": "nrfutil",
|
||||||
"protocols": ["nrfutil", "jlink", "cmsis-dap"],
|
"protocols": ["nrfutil", "jlink", "cmsis-dap"],
|
||||||
"require_upload_port": true,
|
"native_usb": true,
|
||||||
"speed": 115200,
|
|
||||||
"use_1200bps_touch": true,
|
"use_1200bps_touch": true,
|
||||||
|
"require_upload_port": true,
|
||||||
"wait_for_upload_port": true
|
"wait_for_upload_port": true
|
||||||
},
|
},
|
||||||
"url": "https://github.com/Xinyuan-LilyGO/T-Echo-Card",
|
"url": "https://github.com/Xinyuan-LilyGO/T-Echo-Card",
|
||||||
"vendor": "LILYGO"
|
"vendor": "LILYGO"
|
||||||
}
|
}
|
||||||
@@ -36,6 +36,7 @@ public:
|
|||||||
void setHasConnection(bool connected) { _connected = connected; }
|
void setHasConnection(bool connected) { _connected = connected; }
|
||||||
bool hasConnection() const { return _connected; }
|
bool hasConnection() const { return _connected; }
|
||||||
uint16_t getBattMilliVolts() const { return _board->getBattMilliVolts(); }
|
uint16_t getBattMilliVolts() const { return _board->getBattMilliVolts(); }
|
||||||
|
uint8_t getBatteryPercent() const { return _board->getBatteryPercent(); }
|
||||||
bool isSerialEnabled() const { return _serial->isEnabled(); }
|
bool isSerialEnabled() const { return _serial->isEnabled(); }
|
||||||
void enableSerial() { _serial->enable(); }
|
void enableSerial() { _serial->enable(); }
|
||||||
void disableSerial() { _serial->disable(); }
|
void disableSerial() { _serial->disable(); }
|
||||||
@@ -50,9 +51,14 @@ public:
|
|||||||
|
|
||||||
// Mark a channel as read when BLE companion app syncs a message
|
// Mark a channel as read when BLE companion app syncs a message
|
||||||
virtual void markChannelReadFromBLE(uint8_t channel_idx) {}
|
virtual void markChannelReadFromBLE(uint8_t channel_idx) {}
|
||||||
|
virtual void markAllChannelsRead() {} // Companion builds: zero all unread on app connect
|
||||||
|
|
||||||
// Repeater admin callbacks (from MyMesh)
|
// Repeater admin callbacks (from MyMesh)
|
||||||
virtual void onAdminLoginResult(bool success, uint8_t permissions, uint32_t server_time) {}
|
virtual void onAdminLoginResult(bool success, uint8_t permissions, uint32_t server_time) {}
|
||||||
virtual void onAdminCliResponse(const char* from_name, const char* text) {}
|
virtual void onAdminCliResponse(const char* from_name, const char* text) {}
|
||||||
virtual void onAdminTelemetryResult(const uint8_t* data, uint8_t len) {}
|
virtual void onAdminTelemetryResult(const uint8_t* data, uint8_t len) {}
|
||||||
|
|
||||||
|
// Trace path callback (from MyMesh::onTraceRecv)
|
||||||
|
virtual void onTraceResult(uint32_t tag, uint8_t flags, const uint8_t* path_snrs,
|
||||||
|
const uint8_t* path_hashes, uint8_t path_len, int8_t final_snr) {}
|
||||||
};
|
};
|
||||||
@@ -274,22 +274,23 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
|
|||||||
if (file.read((uint8_t *)&_prefs.large_font, sizeof(_prefs.large_font)) != sizeof(_prefs.large_font)) {
|
if (file.read((uint8_t *)&_prefs.large_font, sizeof(_prefs.large_font)) != sizeof(_prefs.large_font)) {
|
||||||
_prefs.large_font = 0; // default: tiny font
|
_prefs.large_font = 0; // default: tiny font
|
||||||
}
|
}
|
||||||
if (file.read((uint8_t *)&_prefs.ui_font_style, sizeof(_prefs.ui_font_style)) != sizeof(_prefs.ui_font_style)) {
|
|
||||||
_prefs.ui_font_style = 0; // default: Classic (FreeSans)
|
|
||||||
}
|
|
||||||
if (file.read((uint8_t *)&_prefs.tx_fail_reset_threshold, sizeof(_prefs.tx_fail_reset_threshold)) != sizeof(_prefs.tx_fail_reset_threshold)) {
|
if (file.read((uint8_t *)&_prefs.tx_fail_reset_threshold, sizeof(_prefs.tx_fail_reset_threshold)) != sizeof(_prefs.tx_fail_reset_threshold)) {
|
||||||
_prefs.tx_fail_reset_threshold = 3; // default: 3
|
_prefs.tx_fail_reset_threshold = 3; // default: 3
|
||||||
}
|
}
|
||||||
if (file.read((uint8_t *)&_prefs.rx_fail_reboot_threshold, sizeof(_prefs.rx_fail_reboot_threshold)) != sizeof(_prefs.rx_fail_reboot_threshold)) {
|
if (file.read((uint8_t *)&_prefs.rx_fail_reboot_threshold, sizeof(_prefs.rx_fail_reboot_threshold)) != sizeof(_prefs.rx_fail_reboot_threshold)) {
|
||||||
_prefs.rx_fail_reboot_threshold = 3; // default: 3
|
_prefs.rx_fail_reboot_threshold = 3; // default: 3
|
||||||
}
|
}
|
||||||
|
if (file.read((uint8_t *)&_prefs.ui_font_style, sizeof(_prefs.ui_font_style)) != sizeof(_prefs.ui_font_style)) {
|
||||||
// v1.7+ Meck region scope fields — may not exist in older prefs files
|
_prefs.ui_font_style = 0; // default: Classic (FreeSans)
|
||||||
|
}
|
||||||
if (file.read((uint8_t *)_prefs.default_scope_name, sizeof(_prefs.default_scope_name)) != sizeof(_prefs.default_scope_name)) {
|
if (file.read((uint8_t *)_prefs.default_scope_name, sizeof(_prefs.default_scope_name)) != sizeof(_prefs.default_scope_name)) {
|
||||||
memset(_prefs.default_scope_name, 0, sizeof(_prefs.default_scope_name)); // default: unscoped
|
memset(_prefs.default_scope_name, 0, sizeof(_prefs.default_scope_name));
|
||||||
}
|
}
|
||||||
if (file.read((uint8_t *)_prefs.default_scope_key, sizeof(_prefs.default_scope_key)) != sizeof(_prefs.default_scope_key)) {
|
if (file.read((uint8_t *)_prefs.default_scope_key, sizeof(_prefs.default_scope_key)) != sizeof(_prefs.default_scope_key)) {
|
||||||
memset(_prefs.default_scope_key, 0, sizeof(_prefs.default_scope_key)); // default: null key
|
memset(_prefs.default_scope_key, 0, sizeof(_prefs.default_scope_key));
|
||||||
|
}
|
||||||
|
if (file.read((uint8_t *)_prefs.channel_notif, sizeof(_prefs.channel_notif)) != sizeof(_prefs.channel_notif)) {
|
||||||
|
memset(_prefs.channel_notif, 0, sizeof(_prefs.channel_notif)); // default: NOTIF_ALL
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clamp to valid ranges
|
// Clamp to valid ranges
|
||||||
@@ -297,9 +298,13 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
|
|||||||
if (_prefs.portrait_mode > 1) _prefs.portrait_mode = 0;
|
if (_prefs.portrait_mode > 1) _prefs.portrait_mode = 0;
|
||||||
if (_prefs.hint_shown > 1) _prefs.hint_shown = 0;
|
if (_prefs.hint_shown > 1) _prefs.hint_shown = 0;
|
||||||
if (_prefs.large_font > 1) _prefs.large_font = 0;
|
if (_prefs.large_font > 1) _prefs.large_font = 0;
|
||||||
if (_prefs.ui_font_style >= 3) _prefs.ui_font_style = 0;
|
if (_prefs.ui_font_style > 2) _prefs.ui_font_style = 0;
|
||||||
if (_prefs.tx_fail_reset_threshold > 10) _prefs.tx_fail_reset_threshold = 3;
|
if (_prefs.tx_fail_reset_threshold > 10) _prefs.tx_fail_reset_threshold = 3;
|
||||||
if (_prefs.rx_fail_reboot_threshold > 10) _prefs.rx_fail_reboot_threshold = 3;
|
if (_prefs.rx_fail_reboot_threshold > 10) _prefs.rx_fail_reboot_threshold = 3;
|
||||||
|
// Clamp channel notification preferences to valid range
|
||||||
|
for (int i = 0; i < (int)sizeof(_prefs.channel_notif); i++) {
|
||||||
|
if (_prefs.channel_notif[i] > 2) _prefs.channel_notif[i] = 0;
|
||||||
|
}
|
||||||
// auto_lock_minutes: only accept known options (0, 2, 5, 10, 15, 30)
|
// auto_lock_minutes: only accept known options (0, 2, 5, 10, 15, 30)
|
||||||
{
|
{
|
||||||
uint8_t alm = _prefs.auto_lock_minutes;
|
uint8_t alm = _prefs.auto_lock_minutes;
|
||||||
@@ -354,11 +359,12 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_
|
|||||||
file.write((uint8_t *)&_prefs.auto_lock_minutes, sizeof(_prefs.auto_lock_minutes)); // 100
|
file.write((uint8_t *)&_prefs.auto_lock_minutes, sizeof(_prefs.auto_lock_minutes)); // 100
|
||||||
file.write((uint8_t *)&_prefs.hint_shown, sizeof(_prefs.hint_shown)); // 101
|
file.write((uint8_t *)&_prefs.hint_shown, sizeof(_prefs.hint_shown)); // 101
|
||||||
file.write((uint8_t *)&_prefs.large_font, sizeof(_prefs.large_font)); // 102
|
file.write((uint8_t *)&_prefs.large_font, sizeof(_prefs.large_font)); // 102
|
||||||
file.write((uint8_t *)&_prefs.ui_font_style, sizeof(_prefs.ui_font_style)); // 103
|
file.write((uint8_t *)&_prefs.tx_fail_reset_threshold, sizeof(_prefs.tx_fail_reset_threshold)); // 103
|
||||||
file.write((uint8_t *)&_prefs.tx_fail_reset_threshold, sizeof(_prefs.tx_fail_reset_threshold)); // 104
|
file.write((uint8_t *)&_prefs.rx_fail_reboot_threshold, sizeof(_prefs.rx_fail_reboot_threshold)); // 104
|
||||||
file.write((uint8_t *)&_prefs.rx_fail_reboot_threshold, sizeof(_prefs.rx_fail_reboot_threshold)); // 105
|
file.write((uint8_t *)&_prefs.ui_font_style, sizeof(_prefs.ui_font_style)); // 105
|
||||||
file.write((uint8_t *)_prefs.default_scope_name, sizeof(_prefs.default_scope_name)); // 106
|
file.write((uint8_t *)_prefs.default_scope_name, sizeof(_prefs.default_scope_name)); // 106
|
||||||
file.write((uint8_t *)_prefs.default_scope_key, sizeof(_prefs.default_scope_key)); // 137
|
file.write((uint8_t *)_prefs.default_scope_key, sizeof(_prefs.default_scope_key)); // 137
|
||||||
|
file.write((uint8_t *)_prefs.channel_notif, sizeof(_prefs.channel_notif)); // 153
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
@@ -445,10 +451,42 @@ void DataStore::loadContacts(DataStoreHost* host) {
|
|||||||
|
|
||||||
void DataStore::saveContacts(DataStoreHost* host) {
|
void DataStore::saveContacts(DataStoreHost* host) {
|
||||||
FILESYSTEM* fs = _getContactsChannelsFS();
|
FILESYSTEM* fs = _getContactsChannelsFS();
|
||||||
|
|
||||||
|
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||||
|
// nRF52/STM32: direct write (no tmp+rename — InternalFS doesn't need atomic pattern)
|
||||||
|
File file = openWrite(fs, "/contacts3");
|
||||||
|
if (file) {
|
||||||
|
uint32_t idx = 0;
|
||||||
|
ContactInfo c;
|
||||||
|
uint8_t unused = 0;
|
||||||
|
uint32_t recordsWritten = 0;
|
||||||
|
|
||||||
|
while (host->getContactForSave(idx, c)) {
|
||||||
|
bool success = (file.write(c.id.pub_key, 32) == 32);
|
||||||
|
success = success && (file.write((uint8_t *)&c.name, 32) == 32);
|
||||||
|
success = success && (file.write(&c.type, 1) == 1);
|
||||||
|
success = success && (file.write(&c.flags, 1) == 1);
|
||||||
|
success = success && (file.write(&unused, 1) == 1);
|
||||||
|
success = success && (file.write((uint8_t *)&c.sync_since, 4) == 4);
|
||||||
|
success = success && (file.write((uint8_t *)&c.out_path_len, 1) == 1);
|
||||||
|
success = success && (file.write((uint8_t *)&c.last_advert_timestamp, 4) == 4);
|
||||||
|
success = success && (file.write(c.out_path, 64) == 64);
|
||||||
|
success = success && (file.write((uint8_t *)&c.lastmod, 4) == 4);
|
||||||
|
success = success && (file.write((uint8_t *)&c.gps_lat, 4) == 4);
|
||||||
|
success = success && (file.write((uint8_t *)&c.gps_lon, 4) == 4);
|
||||||
|
|
||||||
|
if (!success) break;
|
||||||
|
recordsWritten++;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
Serial.printf("DataStore: saved %d contacts\n", recordsWritten);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// ESP32: atomic tmp+rename pattern (protects against SD card corruption on power loss)
|
||||||
const char* finalPath = "/contacts3";
|
const char* finalPath = "/contacts3";
|
||||||
const char* tmpPath = "/contacts3.tmp";
|
const char* tmpPath = "/contacts3.tmp";
|
||||||
|
|
||||||
// --- Step 1: Write all contacts to a temporary file ---
|
|
||||||
File file = openWrite(fs, tmpPath);
|
File file = openWrite(fs, tmpPath);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
Serial.println("DataStore: saveContacts FAILED — cannot open tmp file");
|
Serial.println("DataStore: saveContacts FAILED — cannot open tmp file");
|
||||||
@@ -487,9 +525,8 @@ void DataStore::saveContacts(DataStoreHost* host) {
|
|||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
// --- Step 2: Verify the write completed ---
|
// Verify the write completed
|
||||||
// Reopen read-only to get true on-disk size (SPIFFS file.size() is unreliable before close)
|
size_t expectedBytes = recordsWritten * 152;
|
||||||
size_t expectedBytes = recordsWritten * 152; // 152 bytes per contact record
|
|
||||||
File verify = openRead(fs, tmpPath);
|
File verify = openRead(fs, tmpPath);
|
||||||
size_t bytesWritten = verify ? verify.size() : 0;
|
size_t bytesWritten = verify ? verify.size() : 0;
|
||||||
if (verify) verify.close();
|
if (verify) verify.close();
|
||||||
@@ -497,23 +534,25 @@ void DataStore::saveContacts(DataStoreHost* host) {
|
|||||||
if (!writeOk || bytesWritten != expectedBytes) {
|
if (!writeOk || bytesWritten != expectedBytes) {
|
||||||
Serial.printf("DataStore: saveContacts ABORTED — wrote %d bytes, expected %d (%d records)\n",
|
Serial.printf("DataStore: saveContacts ABORTED — wrote %d bytes, expected %d (%d records)\n",
|
||||||
(int)bytesWritten, (int)expectedBytes, recordsWritten);
|
(int)bytesWritten, (int)expectedBytes, recordsWritten);
|
||||||
fs->remove(tmpPath); // Clean up failed tmp file
|
fs->remove(tmpPath);
|
||||||
return; // Original /contacts3 is untouched
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Step 3: Replace original with verified temp file ---
|
// Replace original with verified temp file
|
||||||
fs->remove(finalPath);
|
fs->remove(finalPath);
|
||||||
if (fs->rename(tmpPath, finalPath)) {
|
if (fs->rename(tmpPath, finalPath)) {
|
||||||
Serial.printf("DataStore: saved %d contacts (%d bytes)\n", recordsWritten, (int)bytesWritten);
|
Serial.printf("DataStore: saved %d contacts (%d bytes)\n", recordsWritten, (int)bytesWritten);
|
||||||
} else {
|
} else {
|
||||||
// Rename failed — tmp file still has the good data
|
|
||||||
Serial.println("DataStore: rename failed, tmp file preserved");
|
Serial.println("DataStore: rename failed, tmp file preserved");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Chunked contact save — non-blocking across multiple loop iterations
|
// Chunked contact save — non-blocking across multiple loop iterations
|
||||||
|
// Only for ESP32 with SD card — nRF52 uses blocking saveContacts() above
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
#if !defined(NRF52_PLATFORM) && !defined(STM32_PLATFORM)
|
||||||
|
|
||||||
bool DataStore::beginSaveContacts(DataStoreHost* host) {
|
bool DataStore::beginSaveContacts(DataStoreHost* host) {
|
||||||
if (_saveInProgress) return false; // Already saving
|
if (_saveInProgress) return false; // Already saving
|
||||||
@@ -605,62 +644,14 @@ void DataStore::finishSaveContacts() {
|
|||||||
Serial.println("DataStore: rename failed, tmp file preserved");
|
Serial.println("DataStore: rename failed, tmp file preserved");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // !NRF52_PLATFORM && !STM32_PLATFORM
|
||||||
|
|
||||||
void DataStore::loadChannels(DataStoreHost* host) {
|
void DataStore::loadChannels(DataStoreHost* host) {
|
||||||
FILESYSTEM* fs = _getContactsChannelsFS();
|
FILESYSTEM* fs = _getContactsChannelsFS();
|
||||||
|
|
||||||
// Crash recovery (same pattern as contacts)
|
// Crash recovery (same pattern as contacts)
|
||||||
if (!fs->exists("/channels3") && fs->exists("/channels3.tmp")) {
|
|
||||||
Serial.println("DataStore: recovering channels3 from .tmp file");
|
|
||||||
fs->rename("/channels3.tmp", "/channels3");
|
|
||||||
}
|
|
||||||
if (fs->exists("/channels3.tmp")) {
|
|
||||||
fs->remove("/channels3.tmp");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try channels3 (new format with scope_name) first
|
|
||||||
if (fs->exists("/channels3")) {
|
|
||||||
File file = openRead(fs, "/channels3");
|
|
||||||
if (file) {
|
|
||||||
bool full = false;
|
|
||||||
uint8_t channel_idx = 0;
|
|
||||||
while (!full) {
|
|
||||||
ChannelDetails ch;
|
|
||||||
memset(ch.scope_name, 0, sizeof(ch.scope_name));
|
|
||||||
uint8_t unused[4];
|
|
||||||
|
|
||||||
bool success = (file.read(unused, 4) == 4);
|
|
||||||
success = success && (file.read((uint8_t *)ch.name, 32) == 32);
|
|
||||||
success = success && (file.read((uint8_t *)ch.channel.secret, 32) == 32);
|
|
||||||
success = success && (file.read((uint8_t *)ch.scope_name, 31) == 31);
|
|
||||||
|
|
||||||
if (!success) break; // EOF
|
|
||||||
|
|
||||||
// Sanitize scope_name — reject if it contains non-region characters
|
|
||||||
// (catches garbage from uninitialised memory in early channels3 files)
|
|
||||||
ch.scope_name[30] = '\0'; // force null-terminate
|
|
||||||
for (int s = 0; ch.scope_name[s]; s++) {
|
|
||||||
char sc = ch.scope_name[s];
|
|
||||||
if (!((sc >= 'a' && sc <= 'z') || (sc >= '0' && sc <= '9') || sc == '-')) {
|
|
||||||
memset(ch.scope_name, 0, sizeof(ch.scope_name)); // invalid — clear
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (host->onChannelLoaded(channel_idx, ch)) {
|
|
||||||
channel_idx++;
|
|
||||||
} else {
|
|
||||||
full = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
return; // channels3 loaded successfully
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fall back to channels2 (legacy format without scope_name)
|
|
||||||
if (!fs->exists("/channels2") && fs->exists("/channels2.tmp")) {
|
if (!fs->exists("/channels2") && fs->exists("/channels2.tmp")) {
|
||||||
Serial.println("DataStore: recovering channels2 from .tmp file");
|
Serial.println("DataStore: recovering channels from .tmp file");
|
||||||
fs->rename("/channels2.tmp", "/channels2");
|
fs->rename("/channels2.tmp", "/channels2");
|
||||||
}
|
}
|
||||||
if (fs->exists("/channels2.tmp")) {
|
if (fs->exists("/channels2.tmp")) {
|
||||||
@@ -673,7 +664,6 @@ void DataStore::loadChannels(DataStoreHost* host) {
|
|||||||
uint8_t channel_idx = 0;
|
uint8_t channel_idx = 0;
|
||||||
while (!full) {
|
while (!full) {
|
||||||
ChannelDetails ch;
|
ChannelDetails ch;
|
||||||
memset(ch.scope_name, 0, sizeof(ch.scope_name)); // default: no scope
|
|
||||||
uint8_t unused[4];
|
uint8_t unused[4];
|
||||||
|
|
||||||
bool success = (file.read(unused, 4) == 4);
|
bool success = (file.read(unused, 4) == 4);
|
||||||
@@ -689,18 +679,13 @@ void DataStore::loadChannels(DataStoreHost* host) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
// Migrate: save as channels3 and remove channels2
|
|
||||||
Serial.println("DataStore: migrating channels2 → channels3");
|
|
||||||
saveChannels(host);
|
|
||||||
fs->remove("/channels2");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataStore::saveChannels(DataStoreHost* host) {
|
void DataStore::saveChannels(DataStoreHost* host) {
|
||||||
FILESYSTEM* fs = _getContactsChannelsFS();
|
FILESYSTEM* fs = _getContactsChannelsFS();
|
||||||
const char* finalPath = "/channels3";
|
const char* finalPath = "/channels2";
|
||||||
const char* tmpPath = "/channels3.tmp";
|
const char* tmpPath = "/channels2.tmp";
|
||||||
|
|
||||||
File file = openWrite(fs, tmpPath);
|
File file = openWrite(fs, tmpPath);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
@@ -718,7 +703,6 @@ void DataStore::saveChannels(DataStoreHost* host) {
|
|||||||
bool success = (file.write(unused, 4) == 4);
|
bool success = (file.write(unused, 4) == 4);
|
||||||
success = success && (file.write((uint8_t *)ch.name, 32) == 32);
|
success = success && (file.write((uint8_t *)ch.name, 32) == 32);
|
||||||
success = success && (file.write((uint8_t *)ch.channel.secret, 32) == 32);
|
success = success && (file.write((uint8_t *)ch.channel.secret, 32) == 32);
|
||||||
success = success && (file.write((uint8_t *)ch.scope_name, 31) == 31);
|
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
writeOk = false;
|
writeOk = false;
|
||||||
@@ -731,7 +715,7 @@ void DataStore::saveChannels(DataStoreHost* host) {
|
|||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
// Reopen read-only to get true on-disk size (SPIFFS file.size() is unreliable before close)
|
// Reopen read-only to get true on-disk size (SPIFFS file.size() is unreliable before close)
|
||||||
size_t expectedBytes = channel_idx * 99; // 4 + 32 + 32 + 31 = 99 bytes per channel
|
size_t expectedBytes = channel_idx * 68; // 4 + 32 + 32 = 68 bytes per channel
|
||||||
File verify = openRead(fs, tmpPath);
|
File verify = openRead(fs, tmpPath);
|
||||||
size_t bytesWritten = verify ? verify.size() : 0;
|
size_t bytesWritten = verify ? verify.size() : 0;
|
||||||
if (verify) verify.close();
|
if (verify) verify.close();
|
||||||
@@ -776,7 +760,7 @@ void DataStore::checkAdvBlobFile() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DataStore::migrateToSecondaryFS() {
|
void DataStore::migrateToSecondaryFS() {
|
||||||
// migrate old adv_blobs, contacts3 and channels3/channels2 files to secondary FS if they don't already exist
|
// migrate old adv_blobs, contacts3 and channels2 files to secondary FS if they don't already exist
|
||||||
if (!_fsExtra->exists("/adv_blobs")) {
|
if (!_fsExtra->exists("/adv_blobs")) {
|
||||||
if (_fs->exists("/adv_blobs")) {
|
if (_fs->exists("/adv_blobs")) {
|
||||||
File oldAdvBlobs = openRead(_fs, "/adv_blobs");
|
File oldAdvBlobs = openRead(_fs, "/adv_blobs");
|
||||||
@@ -815,14 +799,10 @@ void DataStore::migrateToSecondaryFS() {
|
|||||||
_fs->remove("/contacts3");
|
_fs->remove("/contacts3");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!_fsExtra->exists("/channels3") && !_fsExtra->exists("/channels2")) {
|
if (!_fsExtra->exists("/channels2")) {
|
||||||
// Migrate channels3 (preferred) or channels2 (legacy) to secondary FS
|
if (_fs->exists("/channels2")) {
|
||||||
const char* srcName = _fs->exists("/channels3") ? "/channels3"
|
File oldFile = openRead(_fs, "/channels2");
|
||||||
: _fs->exists("/channels2") ? "/channels2"
|
File newFile = openWrite(_fsExtra, "/channels2");
|
||||||
: nullptr;
|
|
||||||
if (srcName) {
|
|
||||||
File oldFile = openRead(_fs, srcName);
|
|
||||||
File newFile = openWrite(_fsExtra, srcName);
|
|
||||||
|
|
||||||
if (oldFile && newFile) {
|
if (oldFile && newFile) {
|
||||||
uint8_t buf[64];
|
uint8_t buf[64];
|
||||||
@@ -833,7 +813,7 @@ void DataStore::migrateToSecondaryFS() {
|
|||||||
}
|
}
|
||||||
if (oldFile) oldFile.close();
|
if (oldFile) oldFile.close();
|
||||||
if (newFile) newFile.close();
|
if (newFile) newFile.close();
|
||||||
_fs->remove(srcName);
|
_fs->remove("/channels2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// cleanup nodes which have been testing the extra fs, copy _main.id and new_prefs back to primary
|
// cleanup nodes which have been testing the extra fs, copy _main.id and new_prefs back to primary
|
||||||
@@ -876,9 +856,6 @@ void DataStore::migrateToSecondaryFS() {
|
|||||||
if (_fs->exists("/contacts3")) {
|
if (_fs->exists("/contacts3")) {
|
||||||
_fs->remove("/contacts3");
|
_fs->remove("/contacts3");
|
||||||
}
|
}
|
||||||
if (_fs->exists("/channels3")) {
|
|
||||||
_fs->remove("/channels3");
|
|
||||||
}
|
|
||||||
if (_fs->exists("/channels2")) {
|
if (_fs->exists("/channels2")) {
|
||||||
_fs->remove("/channels2");
|
_fs->remove("/channels2");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,13 +24,15 @@ class DataStore {
|
|||||||
void checkAdvBlobFile();
|
void checkAdvBlobFile();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Chunked save state
|
#if !defined(NRF52_PLATFORM) && !defined(STM32_PLATFORM)
|
||||||
|
// Chunked save state (ESP32 with SD card only)
|
||||||
File _saveFile;
|
File _saveFile;
|
||||||
DataStoreHost* _saveHost = nullptr;
|
DataStoreHost* _saveHost = nullptr;
|
||||||
uint32_t _saveIdx = 0;
|
uint32_t _saveIdx = 0;
|
||||||
uint32_t _saveRecordsWritten = 0;
|
uint32_t _saveRecordsWritten = 0;
|
||||||
bool _saveInProgress = false;
|
bool _saveInProgress = false;
|
||||||
bool _saveWriteOk = true;
|
bool _saveWriteOk = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DataStore(FILESYSTEM& fs, mesh::RTCClock& clock);
|
DataStore(FILESYSTEM& fs, mesh::RTCClock& clock);
|
||||||
@@ -45,14 +47,13 @@ public:
|
|||||||
void savePrefs(const NodePrefs& prefs, double node_lat, double node_lon);
|
void savePrefs(const NodePrefs& prefs, double node_lat, double node_lon);
|
||||||
void loadContacts(DataStoreHost* host);
|
void loadContacts(DataStoreHost* host);
|
||||||
void saveContacts(DataStoreHost* host);
|
void saveContacts(DataStoreHost* host);
|
||||||
|
#if !defined(NRF52_PLATFORM) && !defined(STM32_PLATFORM)
|
||||||
// Chunked save — splits contact write across multiple loop iterations
|
// Chunked save — splits contact write across multiple loop iterations
|
||||||
// to prevent blocking the main loop for 500ms+ on large contact lists.
|
|
||||||
// Call beginSaveContacts(), then saveContactsChunk() each loop until it
|
|
||||||
// returns false (done), then finishSaveContacts() to verify and commit.
|
|
||||||
bool beginSaveContacts(DataStoreHost* host);
|
bool beginSaveContacts(DataStoreHost* host);
|
||||||
bool saveContactsChunk(int batchSize = 20); // returns true if more to write
|
bool saveContactsChunk(int batchSize = 20);
|
||||||
void finishSaveContacts();
|
void finishSaveContacts();
|
||||||
bool isSaveInProgress() const { return _saveInProgress; }
|
bool isSaveInProgress() const { return _saveInProgress; }
|
||||||
|
#endif
|
||||||
void loadChannels(DataStoreHost* host);
|
void loadChannels(DataStoreHost* host);
|
||||||
void saveChannels(DataStoreHost* host);
|
void saveChannels(DataStoreHost* host);
|
||||||
void migrateToSecondaryFS();
|
void migrateToSecondaryFS();
|
||||||
|
|||||||
@@ -114,6 +114,7 @@
|
|||||||
#define DIRECT_SEND_PERHOP_FACTOR 6.0f
|
#define DIRECT_SEND_PERHOP_FACTOR 6.0f
|
||||||
#define DIRECT_SEND_PERHOP_EXTRA_MILLIS 250
|
#define DIRECT_SEND_PERHOP_EXTRA_MILLIS 250
|
||||||
#define LAZY_CONTACTS_WRITE_DELAY 5000
|
#define LAZY_CONTACTS_WRITE_DELAY 5000
|
||||||
|
#define USER_IDLE_SAVE_THRESHOLD 15000 // Defer saves until 15s after last keypress
|
||||||
|
|
||||||
#define PUBLIC_GROUP_PSK "izOH6cXN6mrJ5e26oRXNcg=="
|
#define PUBLIC_GROUP_PSK "izOH6cXN6mrJ5e26oRXNcg=="
|
||||||
|
|
||||||
@@ -154,6 +155,10 @@
|
|||||||
#define AUTO_ADD_ROOM_SERVER (1 << 3) // 0x08 - auto-add Room Server (ADV_TYPE_ROOM)
|
#define AUTO_ADD_ROOM_SERVER (1 << 3) // 0x08 - auto-add Room Server (ADV_TYPE_ROOM)
|
||||||
#define AUTO_ADD_SENSOR (1 << 4) // 0x10 - auto-add Sensor (ADV_TYPE_SENSOR)
|
#define AUTO_ADD_SENSOR (1 << 4) // 0x10 - auto-add Sensor (ADV_TYPE_SENSOR)
|
||||||
|
|
||||||
|
// All type bits combined (excludes overwrite flag)
|
||||||
|
#define AUTO_ADD_ALL_TYPES (AUTO_ADD_CHAT | AUTO_ADD_REPEATER | \
|
||||||
|
AUTO_ADD_ROOM_SERVER | AUTO_ADD_SENSOR)
|
||||||
|
|
||||||
void MyMesh::writeOKFrame() {
|
void MyMesh::writeOKFrame() {
|
||||||
uint8_t buf[1];
|
uint8_t buf[1];
|
||||||
buf[0] = RESP_CODE_OK;
|
buf[0] = RESP_CODE_OK;
|
||||||
@@ -1285,6 +1290,14 @@ void MyMesh::onTraceRecv(mesh::Packet *packet, uint32_t tag, uint32_t auth_code,
|
|||||||
} else {
|
} else {
|
||||||
MESH_DEBUG_PRINTLN("onTraceRecv(), data received while app offline");
|
MESH_DEBUG_PRINTLN("onTraceRecv(), data received while app offline");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Route trace result to standalone UI (TraceScreen)
|
||||||
|
#ifdef DISPLAY_CLASS
|
||||||
|
if (_ui) {
|
||||||
|
_ui->onTraceResult(tag, flags, path_snrs, path_hashes, path_len,
|
||||||
|
(int8_t)(packet->getSNR() * 4));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t MyMesh::calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const {
|
uint32_t MyMesh::calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const {
|
||||||
@@ -1472,6 +1485,11 @@ void MyMesh::handleCmdFrame(size_t len) {
|
|||||||
MESH_DEBUG_PRINTLN("App %s connected", app_name);
|
MESH_DEBUG_PRINTLN("App %s connected", app_name);
|
||||||
|
|
||||||
_iter_started = false; // stop any left-over ContactsIterator
|
_iter_started = false; // stop any left-over ContactsIterator
|
||||||
|
|
||||||
|
#if defined(BLE_PIN_CODE) || defined(MECK_WIFI_COMPANION)
|
||||||
|
// Companion builds: mark all channels/DMs as read on app connect
|
||||||
|
if (_ui) _ui->markAllChannelsRead();
|
||||||
|
#endif
|
||||||
int i = 0;
|
int i = 0;
|
||||||
out_frame[i++] = RESP_CODE_SELF_INFO;
|
out_frame[i++] = RESP_CODE_SELF_INFO;
|
||||||
out_frame[i++] = ADV_TYPE_CHAT; // what this node Advert identifies as (maybe node's pronouns too?? :-)
|
out_frame[i++] = ADV_TYPE_CHAT; // what this node Advert identifies as (maybe node's pronouns too?? :-)
|
||||||
@@ -2163,6 +2181,9 @@ void MyMesh::handleCmdFrame(size_t len) {
|
|||||||
memcpy(&auth, &cmd_frame[5], 4);
|
memcpy(&auth, &cmd_frame[5], 4);
|
||||||
auto pkt = createTrace(tag, auth, flags);
|
auto pkt = createTrace(tag, auth, flags);
|
||||||
if (pkt) {
|
if (pkt) {
|
||||||
|
Serial.printf("[BLE Trace] flags=%d, path_len=%d, path hex:", flags, path_len);
|
||||||
|
for (int pi = 0; pi < path_len; pi++) Serial.printf(" %02X", cmd_frame[10 + pi]);
|
||||||
|
Serial.println();
|
||||||
sendDirect(pkt, &cmd_frame[10], path_len);
|
sendDirect(pkt, &cmd_frame[10], path_len);
|
||||||
|
|
||||||
uint32_t t = _radio->getEstAirtimeFor(pkt->payload_len + pkt->path_len + 2);
|
uint32_t t = _radio->getEstAirtimeFor(pkt->payload_len + pkt->path_len + 2);
|
||||||
@@ -2550,6 +2571,20 @@ void MyMesh::checkCLIRescueCmd() {
|
|||||||
Serial.printf(" apn: %s\n", modemManager.getAPN());
|
Serial.printf(" apn: %s\n", modemManager.getAPN());
|
||||||
Serial.printf(" imei: %s\n", modemManager.getIMEI());
|
Serial.printf(" imei: %s\n", modemManager.getIMEI());
|
||||||
#endif
|
#endif
|
||||||
|
// Contact auto-add
|
||||||
|
{
|
||||||
|
const char* mode = (_prefs.manual_add_contacts & 1) == 0 ? "auto" :
|
||||||
|
(_prefs.autoadd_config & AUTO_ADD_ALL_TYPES) == 0 ? "manual" : "custom";
|
||||||
|
Serial.printf(" contacts: %s", mode);
|
||||||
|
if ((_prefs.manual_add_contacts & 1) != 0 && (_prefs.autoadd_config & AUTO_ADD_ALL_TYPES) != 0) {
|
||||||
|
Serial.printf(" [%s%s%s%s]",
|
||||||
|
(_prefs.autoadd_config & AUTO_ADD_CHAT) ? "C" : "",
|
||||||
|
(_prefs.autoadd_config & AUTO_ADD_REPEATER) ? "R" : "",
|
||||||
|
(_prefs.autoadd_config & AUTO_ADD_ROOM_SERVER) ? "S" : "",
|
||||||
|
(_prefs.autoadd_config & AUTO_ADD_SENSOR) ? "N" : "");
|
||||||
|
}
|
||||||
|
Serial.printf(" maxhops:%d\n", _prefs.autoadd_max_hops);
|
||||||
|
}
|
||||||
// Detect current preset
|
// Detect current preset
|
||||||
bool presetFound = false;
|
bool presetFound = false;
|
||||||
for (int i = 0; i < (int)NUM_RADIO_PRESETS; i++) {
|
for (int i = 0; i < (int)NUM_RADIO_PRESETS; i++) {
|
||||||
@@ -2590,6 +2625,30 @@ void MyMesh::checkCLIRescueCmd() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!chFound) Serial.println(" (none)");
|
if (!chFound) Serial.println(" (none)");
|
||||||
|
|
||||||
|
// --- Contact auto-add settings ---
|
||||||
|
} else if (strcmp(key, "contact.mode") == 0) {
|
||||||
|
if ((_prefs.manual_add_contacts & 1) == 0) {
|
||||||
|
Serial.println(" > auto");
|
||||||
|
} else if ((_prefs.autoadd_config & AUTO_ADD_ALL_TYPES) == 0) {
|
||||||
|
Serial.println(" > manual");
|
||||||
|
} else {
|
||||||
|
Serial.println(" > custom");
|
||||||
|
}
|
||||||
|
} else if (strcmp(key, "contact.autoadd") == 0) {
|
||||||
|
Serial.printf(" > chat:%s rptr:%s room:%s sensor:%s overwrite:%s\n",
|
||||||
|
(_prefs.autoadd_config & AUTO_ADD_CHAT) ? "on" : "off",
|
||||||
|
(_prefs.autoadd_config & AUTO_ADD_REPEATER) ? "on" : "off",
|
||||||
|
(_prefs.autoadd_config & AUTO_ADD_ROOM_SERVER) ? "on" : "off",
|
||||||
|
(_prefs.autoadd_config & AUTO_ADD_SENSOR) ? "on" : "off",
|
||||||
|
(_prefs.autoadd_config & AUTO_ADD_OVERWRITE_OLDEST) ? "on" : "off");
|
||||||
|
} else if (strcmp(key, "contact.maxhops") == 0) {
|
||||||
|
if (_prefs.autoadd_max_hops == 0) {
|
||||||
|
Serial.println(" > 0 (no limit)");
|
||||||
|
} else {
|
||||||
|
Serial.printf(" > %d\n", _prefs.autoadd_max_hops);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Serial.printf(" Error: unknown key '%s' (try 'help')\n", key);
|
Serial.printf(" Error: unknown key '%s' (try 'help')\n", key);
|
||||||
}
|
}
|
||||||
@@ -3049,6 +3108,60 @@ void MyMesh::checkCLIRescueCmd() {
|
|||||||
Serial.println(" Error: backlight not available on this device");
|
Serial.println(" Error: backlight not available on this device");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// --- Contact auto-add settings ---
|
||||||
|
} else if (memcmp(config, "contact.mode ", 13) == 0) {
|
||||||
|
const char* val = &config[13];
|
||||||
|
if (strcmp(val, "auto") == 0) {
|
||||||
|
_prefs.manual_add_contacts &= ~1;
|
||||||
|
savePrefs();
|
||||||
|
Serial.println(" > auto-add all");
|
||||||
|
} else if (strcmp(val, "custom") == 0) {
|
||||||
|
_prefs.manual_add_contacts |= 1;
|
||||||
|
if ((_prefs.autoadd_config & AUTO_ADD_ALL_TYPES) == 0) {
|
||||||
|
_prefs.autoadd_config |= AUTO_ADD_ALL_TYPES;
|
||||||
|
}
|
||||||
|
savePrefs();
|
||||||
|
Serial.println(" > custom (use contact.autoadd to configure)");
|
||||||
|
} else if (strcmp(val, "manual") == 0) {
|
||||||
|
_prefs.manual_add_contacts |= 1;
|
||||||
|
_prefs.autoadd_config &= ~AUTO_ADD_ALL_TYPES;
|
||||||
|
savePrefs();
|
||||||
|
Serial.println(" > manual only (no auto-add)");
|
||||||
|
} else if (strcmp(val, "repeater-only") == 0) {
|
||||||
|
_prefs.manual_add_contacts |= 1;
|
||||||
|
_prefs.autoadd_config = (_prefs.autoadd_config & AUTO_ADD_OVERWRITE_OLDEST) | AUTO_ADD_REPEATER;
|
||||||
|
savePrefs();
|
||||||
|
Serial.println(" > auto-add repeaters only");
|
||||||
|
} else {
|
||||||
|
Serial.println(" Error: auto|custom|manual|repeater-only");
|
||||||
|
}
|
||||||
|
} else if (memcmp(config, "contact.autoadd ", 16) == 0) {
|
||||||
|
const char* rest = &config[16];
|
||||||
|
uint8_t bit = 0;
|
||||||
|
const char* val = NULL;
|
||||||
|
if (memcmp(rest, "chat ", 5) == 0) { bit = AUTO_ADD_CHAT; val = &rest[5]; }
|
||||||
|
else if (memcmp(rest, "repeater ", 9) == 0) { bit = AUTO_ADD_REPEATER; val = &rest[9]; }
|
||||||
|
else if (memcmp(rest, "room ", 5) == 0) { bit = AUTO_ADD_ROOM_SERVER; val = &rest[5]; }
|
||||||
|
else if (memcmp(rest, "sensor ", 7) == 0) { bit = AUTO_ADD_SENSOR; val = &rest[7]; }
|
||||||
|
else if (memcmp(rest, "overwrite ", 10) == 0) { bit = AUTO_ADD_OVERWRITE_OLDEST; val = &rest[10]; }
|
||||||
|
|
||||||
|
if (bit && val) {
|
||||||
|
if (strcmp(val, "on") == 0) { _prefs.autoadd_config |= bit; savePrefs(); Serial.println(" > OK"); }
|
||||||
|
else if (strcmp(val, "off") == 0) { _prefs.autoadd_config &= ~bit; savePrefs(); Serial.println(" > OK"); }
|
||||||
|
else { Serial.println(" Error: on|off"); }
|
||||||
|
} else {
|
||||||
|
Serial.println(" Error: chat|repeater|room|sensor|overwrite on|off");
|
||||||
|
}
|
||||||
|
} else if (memcmp(config, "contact.maxhops ", 16) == 0) {
|
||||||
|
int h = atoi(&config[16]);
|
||||||
|
if (h >= 0 && h <= 64) {
|
||||||
|
_prefs.autoadd_max_hops = (uint8_t)h;
|
||||||
|
savePrefs();
|
||||||
|
Serial.printf(" > maxhops = %d%s\n", h, h == 0 ? " (no limit)" : "");
|
||||||
|
} else {
|
||||||
|
Serial.println(" Error: 0-64 (0=no limit)");
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Serial.printf(" Error: unknown setting '%s' (try 'help')\n", config);
|
Serial.printf(" Error: unknown setting '%s' (try 'help')\n", config);
|
||||||
}
|
}
|
||||||
@@ -3146,6 +3259,12 @@ void MyMesh::checkCLIRescueCmd() {
|
|||||||
Serial.println(" set region none Clear default region (unscoped)");
|
Serial.println(" set region none Clear default region (unscoped)");
|
||||||
Serial.println(" get channel.scope <i> Show scope for channel i");
|
Serial.println(" get channel.scope <i> Show scope for channel i");
|
||||||
Serial.println(" set channel.scope <i> <name|none>");
|
Serial.println(" set channel.scope <i> <name|none>");
|
||||||
|
Serial.println("");
|
||||||
|
Serial.println(" Contact auto-add:");
|
||||||
|
Serial.println(" contact.mode auto|custom|manual|repeater-only");
|
||||||
|
Serial.println(" contact.autoadd Show type toggles");
|
||||||
|
Serial.println(" contact.autoadd <type> on|off chat|repeater|room|sensor|overwrite");
|
||||||
|
Serial.println(" contact.maxhops <0-64> Max hops for auto-add (0=no limit)");
|
||||||
#ifdef HAS_4G_MODEM
|
#ifdef HAS_4G_MODEM
|
||||||
Serial.println("");
|
Serial.println("");
|
||||||
Serial.println(" 4G modem:");
|
Serial.println(" 4G modem:");
|
||||||
@@ -3360,22 +3479,36 @@ void MyMesh::loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// is there are pending dirty contacts write needed?
|
// is there are pending dirty contacts write needed?
|
||||||
|
bool userActive = _lastUserInput && (millis() - _lastUserInput) < USER_IDLE_SAVE_THRESHOLD;
|
||||||
if (dirty_contacts_expiry && millisHasNowPassed(dirty_contacts_expiry)) {
|
if (dirty_contacts_expiry && millisHasNowPassed(dirty_contacts_expiry)) {
|
||||||
if (_deferSaves) {
|
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||||
// Voice session receiving — push save forward to avoid SPI contention
|
// nRF52/STM32: blocking save (fast on internal flash, no chunking needed)
|
||||||
|
if (!_deferSaves && !userActive) {
|
||||||
|
_store->saveContacts(this);
|
||||||
|
dirty_contacts_expiry = 0;
|
||||||
|
} else {
|
||||||
|
dirty_contacts_expiry = futureMillis(2000);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (_deferSaves || userActive) {
|
||||||
|
// Voice session or active keyboard use -- push save forward
|
||||||
dirty_contacts_expiry = futureMillis(2000);
|
dirty_contacts_expiry = futureMillis(2000);
|
||||||
} else if (!_store->isSaveInProgress()) {
|
} else if (!_store->isSaveInProgress()) {
|
||||||
_store->beginSaveContacts(this);
|
_store->beginSaveContacts(this);
|
||||||
dirty_contacts_expiry = 0;
|
dirty_contacts_expiry = 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drive chunked contact save — write a batch each loop iteration
|
#if !defined(NRF52_PLATFORM) && !defined(STM32_PLATFORM)
|
||||||
if (_store->isSaveInProgress() && !_deferSaves) {
|
// Drive chunked contact save -- write a batch each loop iteration
|
||||||
|
// Paused while user is actively pressing keys or voice session is receiving
|
||||||
|
if (_store->isSaveInProgress() && !_deferSaves && !userActive) {
|
||||||
if (!_store->saveContactsChunk(20)) { // 20 contacts per chunk (~3KB, ~30ms)
|
if (!_store->saveContactsChunk(20)) { // 20 contacts per chunk (~3KB, ~30ms)
|
||||||
_store->finishSaveContacts(); // Done or error — verify and commit
|
_store->finishSaveContacts(); // Done or error -- verify and commit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Discovery scan timeout
|
// Discovery scan timeout
|
||||||
if (_discoveryActive && millisHasNowPassed(_discoveryTimeout)) {
|
if (_discoveryActive && millisHasNowPassed(_discoveryTimeout)) {
|
||||||
|
|||||||
@@ -8,11 +8,11 @@
|
|||||||
#define FIRMWARE_VER_CODE 11
|
#define FIRMWARE_VER_CODE 11
|
||||||
|
|
||||||
#ifndef FIRMWARE_BUILD_DATE
|
#ifndef FIRMWARE_BUILD_DATE
|
||||||
#define FIRMWARE_BUILD_DATE "19 April 2026"
|
#define FIRMWARE_BUILD_DATE "12 May 2026"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef FIRMWARE_VERSION
|
#ifndef FIRMWARE_VERSION
|
||||||
#define FIRMWARE_VERSION "Meck v1.7"
|
#define FIRMWARE_VERSION "Meck v1.10"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||||
@@ -160,6 +160,10 @@ public:
|
|||||||
void setDeferSaves(bool defer) { _deferSaves = defer; }
|
void setDeferSaves(bool defer) { _deferSaves = defer; }
|
||||||
bool isDeferSaves() const { return _deferSaves; }
|
bool isDeferSaves() const { return _deferSaves; }
|
||||||
|
|
||||||
|
// Notify that the user pressed a key — defers contact saves until idle.
|
||||||
|
// Call from main.cpp keyboard handler on every keypress.
|
||||||
|
void notifyUserInput() { _lastUserInput = millis(); }
|
||||||
|
|
||||||
// Repeater admin - UI-initiated operations
|
// Repeater admin - UI-initiated operations
|
||||||
bool uiLoginToRepeater(uint32_t contact_idx, const char* password, uint32_t& est_timeout_ms);
|
bool uiLoginToRepeater(uint32_t contact_idx, const char* password, uint32_t& est_timeout_ms);
|
||||||
bool uiSendCliCommand(uint32_t contact_idx, const char* command);
|
bool uiSendCliCommand(uint32_t contact_idx, const char* command);
|
||||||
@@ -274,6 +278,7 @@ private:
|
|||||||
VoiceEnvelopeHandler _voiceEnvHandler = nullptr;
|
VoiceEnvelopeHandler _voiceEnvHandler = nullptr;
|
||||||
mutable bool _forceNextImport = false;
|
mutable bool _forceNextImport = false;
|
||||||
bool _deferSaves = false;
|
bool _deferSaves = false;
|
||||||
|
unsigned long _lastUserInput = 0; // millis() of last keypress -- defer saves until idle
|
||||||
uint32_t pending_login;
|
uint32_t pending_login;
|
||||||
uint32_t pending_status;
|
uint32_t pending_status;
|
||||||
uint32_t pending_telemetry, pending_discovery; // pending _TELEMETRY_REQ
|
uint32_t pending_telemetry, pending_discovery; // pending _TELEMETRY_REQ
|
||||||
@@ -317,7 +322,9 @@ private:
|
|||||||
AckTableEntry expected_ack_table[EXPECTED_ACK_TABLE_SIZE]; // circular table
|
AckTableEntry expected_ack_table[EXPECTED_ACK_TABLE_SIZE]; // circular table
|
||||||
int next_ack_idx;
|
int next_ack_idx;
|
||||||
|
|
||||||
#define ADVERT_PATH_TABLE_SIZE 1000
|
#ifndef ADVERT_PATH_TABLE_SIZE
|
||||||
|
#define ADVERT_PATH_TABLE_SIZE 1000
|
||||||
|
#endif
|
||||||
AdvertPath* advert_paths; // PSRAM-allocated in begin(), size = ADVERT_PATH_TABLE_SIZE
|
AdvertPath* advert_paths; // PSRAM-allocated in begin(), size = ADVERT_PATH_TABLE_SIZE
|
||||||
|
|
||||||
// Sent message repeat tracking
|
// Sent message repeat tracking
|
||||||
|
|||||||
@@ -8,6 +8,11 @@
|
|||||||
#define ADVERT_LOC_NONE 0
|
#define ADVERT_LOC_NONE 0
|
||||||
#define ADVERT_LOC_SHARE 1
|
#define ADVERT_LOC_SHARE 1
|
||||||
|
|
||||||
|
// Per-channel notification preferences (stored in channel_notif[])
|
||||||
|
#define NOTIF_ALL 0 // Notify on all messages (default)
|
||||||
|
#define NOTIF_MENTIONS 1 // Notify only when @nodename appears in message
|
||||||
|
#define NOTIF_NONE 2 // No notifications (muted)
|
||||||
|
|
||||||
struct NodePrefs { // persisted to file
|
struct NodePrefs { // persisted to file
|
||||||
float airtime_factor;
|
float airtime_factor;
|
||||||
char node_name[32];
|
char node_name[32];
|
||||||
@@ -53,6 +58,12 @@ struct NodePrefs { // persisted to file
|
|||||||
char default_scope_name[31]; // e.g. "au-nsw", empty = unscoped
|
char default_scope_name[31]; // e.g. "au-nsw", empty = unscoped
|
||||||
uint8_t default_scope_key[16]; // TransportKey derived from "#" + name
|
uint8_t default_scope_key[16]; // TransportKey derived from "#" + name
|
||||||
|
|
||||||
|
// --- Per-channel notification preferences ---
|
||||||
|
// Index 0..MAX_GROUP_CHANNELS-1 for group channels, index MAX_GROUP_CHANNELS for DMs.
|
||||||
|
// Values: NOTIF_ALL (0), NOTIF_MENTIONS (1), NOTIF_NONE (2).
|
||||||
|
// Defaults to NOTIF_ALL for all channels.
|
||||||
|
uint8_t channel_notif[21]; // 20 group channels + 1 DM slot
|
||||||
|
|
||||||
// --- Font helpers (inline, no overhead) ---
|
// --- Font helpers (inline, no overhead) ---
|
||||||
// Returns the DisplayDriver text-size index for "small/body" text.
|
// Returns the DisplayDriver text-size index for "small/body" text.
|
||||||
// T-Deck Pro: 0 = built-in 6×8 (or 7pt with custom fonts), 1 = 9pt.
|
// T-Deck Pro: 0 = built-in 6×8 (or 7pt with custom fonts), 1 = 9pt.
|
||||||
@@ -86,8 +97,10 @@ struct NodePrefs { // persisted to file
|
|||||||
#if defined(LilyGo_T5S3_EPaper_Pro)
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
// Custom 7pt fonts at textSize 0 use GFXfont (baseline rendering), not built-in
|
// Custom 7pt fonts at textSize 0 use GFXfont (baseline rendering), not built-in.
|
||||||
if (ui_font_style > 0 && !large_font) return -2;
|
// Offset 0: highlight starts at row top, covers 7pt ascenders without
|
||||||
|
// bleeding into the row above (-2 was calibrated for taller 9pt ascenders).
|
||||||
|
if (ui_font_style > 0 && !large_font) return 0;
|
||||||
return large_font ? -2 : 5;
|
return large_font ? -2 : 5;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -5,19 +5,22 @@
|
|||||||
// Polls 0x5F on the shared I2C bus via QWIIC connector.
|
// Polls 0x5F on the shared I2C bus via QWIIC connector.
|
||||||
// Maps CardKB special key codes to Meck key constants.
|
// Maps CardKB special key codes to Meck key constants.
|
||||||
//
|
//
|
||||||
|
// Platform support:
|
||||||
|
// - ESP32/ESP32-S3 (T5S3, T-Deck Pro): Wire.begin(SDA, SCL)
|
||||||
|
// - nRF52840 (T-Echo Lite): Wire.begin() uses variant.h pins
|
||||||
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// CardKBKeyboard cardkb;
|
// CardKBKeyboard cardkb;
|
||||||
// if (cardkb.begin()) { /* detected */ }
|
// if (cardkb.begin()) { /* detected */ }
|
||||||
// char key = cardkb.readKey(); // returns 0 if no key
|
// char key = cardkb.readKey(); // returns 0 if no key
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
#if defined(LilyGo_T5S3_EPaper_Pro) && defined(MECK_CARDKB)
|
#if defined(MECK_CARDKB)
|
||||||
#ifndef CARDKB_KEYBOARD_H
|
#ifndef CARDKB_KEYBOARD_H
|
||||||
#define CARDKB_KEYBOARD_H
|
#define CARDKB_KEYBOARD_H
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include "variant.h" // For I2C_SDA, I2C_SCL (bus recovery)
|
|
||||||
|
|
||||||
// I2C address (defined in variant.h, fallback here)
|
// I2C address (defined in variant.h, fallback here)
|
||||||
#ifndef CARDKB_I2C_ADDR
|
#ifndef CARDKB_I2C_ADDR
|
||||||
@@ -75,7 +78,13 @@ public:
|
|||||||
_errorCount++;
|
_errorCount++;
|
||||||
if (_errorCount >= 3) {
|
if (_errorCount >= 3) {
|
||||||
// I2C bus may be stuck — re-init to recover
|
// I2C bus may be stuck — re-init to recover
|
||||||
|
#if defined(ESP32)
|
||||||
|
// ESP32: Wire.begin() accepts explicit SDA/SCL pins
|
||||||
Wire.begin(I2C_SDA, I2C_SCL);
|
Wire.begin(I2C_SDA, I2C_SCL);
|
||||||
|
#else
|
||||||
|
// nRF52: Wire.begin() uses PIN_WIRE_SDA/SCL from variant.h
|
||||||
|
Wire.begin();
|
||||||
|
#endif
|
||||||
Wire.setClock(100000);
|
Wire.setClock(100000);
|
||||||
_pollInterval = 500; // Back off for 500ms
|
_pollInterval = 500; // Back off for 500ms
|
||||||
_errorCount = 0;
|
_errorCount = 0;
|
||||||
@@ -119,4 +128,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif // CARDKB_KEYBOARD_H
|
#endif // CARDKB_KEYBOARD_H
|
||||||
#endif // LilyGo_T5S3_EPaper_Pro && MECK_CARDKB
|
#endif // MECK_CARDKB
|
||||||
@@ -13,8 +13,12 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Maximum messages to store in history
|
// Maximum messages to store in history
|
||||||
|
#ifndef CHANNEL_MSG_HISTORY_SIZE
|
||||||
#define CHANNEL_MSG_HISTORY_SIZE 300
|
#define CHANNEL_MSG_HISTORY_SIZE 300
|
||||||
|
#endif
|
||||||
|
#ifndef CHANNEL_MSG_TEXT_LEN
|
||||||
#define CHANNEL_MSG_TEXT_LEN 160
|
#define CHANNEL_MSG_TEXT_LEN 160
|
||||||
|
#endif
|
||||||
#define MSG_PATH_MAX 20 // Max repeater hops stored per message
|
#define MSG_PATH_MAX 20 // Max repeater hops stored per message
|
||||||
|
|
||||||
#ifndef MAX_GROUP_CHANNELS
|
#ifndef MAX_GROUP_CHANNELS
|
||||||
@@ -25,7 +29,7 @@
|
|||||||
// On-disk format for message persistence (SD card)
|
// On-disk format for message persistence (SD card)
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
#define MSG_FILE_MAGIC 0x4D434853 // "MCHS" - MeshCore History Store
|
#define MSG_FILE_MAGIC 0x4D434853 // "MCHS" - MeshCore History Store
|
||||||
#define MSG_FILE_VERSION 3 // v3: MSG_PATH_MAX=20, reserved→snr field
|
#define MSG_FILE_VERSION 4 // v4: added dm_peer_hash for DM persistence
|
||||||
#define MSG_FILE_PATH "/meshcore/messages.bin"
|
#define MSG_FILE_PATH "/meshcore/messages.bin"
|
||||||
|
|
||||||
struct __attribute__((packed)) MsgFileHeader {
|
struct __attribute__((packed)) MsgFileHeader {
|
||||||
@@ -42,10 +46,11 @@ struct __attribute__((packed)) MsgFileRecord {
|
|||||||
uint8_t path_len;
|
uint8_t path_len;
|
||||||
uint8_t channel_idx;
|
uint8_t channel_idx;
|
||||||
uint8_t valid;
|
uint8_t valid;
|
||||||
int8_t snr; // Receive SNR × 4 (was reserved; 0 = unknown)
|
int8_t snr; // Receive SNR x 4 (was reserved; 0 = unknown)
|
||||||
|
uint32_t dm_peer_hash; // DM peer name hash (v4+, for conversation filtering)
|
||||||
uint8_t path[MSG_PATH_MAX]; // Repeater hop hashes (first byte of pub key)
|
uint8_t path[MSG_PATH_MAX]; // Repeater hop hashes (first byte of pub key)
|
||||||
char text[CHANNEL_MSG_TEXT_LEN];
|
char text[CHANNEL_MSG_TEXT_LEN];
|
||||||
// 188 bytes total
|
// 192 bytes total
|
||||||
};
|
};
|
||||||
|
|
||||||
class UITask; // Forward declaration
|
class UITask; // Forward declaration
|
||||||
@@ -143,8 +148,10 @@ public:
|
|||||||
|
|
||||||
// Add a new message to the history
|
// Add a new message to the history
|
||||||
// peer_name: for DMs, the contact this message belongs to (sender for received, recipient for sent)
|
// peer_name: for DMs, the contact this message belongs to (sender for received, recipient for sent)
|
||||||
|
// suppressUnread: if true, do not increment the unread counter for this message
|
||||||
void addMessage(uint8_t channel_idx, uint8_t path_len, const char* sender, const char* text,
|
void addMessage(uint8_t channel_idx, uint8_t path_len, const char* sender, const char* text,
|
||||||
const uint8_t* path_bytes = nullptr, int8_t snr = 0, const char* peer_name = nullptr) {
|
const uint8_t* path_bytes = nullptr, int8_t snr = 0, const char* peer_name = nullptr,
|
||||||
|
bool suppressUnread = false) {
|
||||||
// Move to next slot in circular buffer
|
// Move to next slot in circular buffer
|
||||||
_newestIdx = (_newestIdx + 1) % CHANNEL_MSG_HISTORY_SIZE;
|
_newestIdx = (_newestIdx + 1) % CHANNEL_MSG_HISTORY_SIZE;
|
||||||
|
|
||||||
@@ -186,8 +193,9 @@ public:
|
|||||||
_replySelectPos = -1;
|
_replySelectPos = -1;
|
||||||
|
|
||||||
// Track unread count for this channel (only for received messages, not sent)
|
// Track unread count for this channel (only for received messages, not sent)
|
||||||
// path_len == 0 means locally sent
|
// path_len == 0 means locally sent.
|
||||||
if (path_len != 0) {
|
// suppressUnread: per-channel notification preference says not to count this message.
|
||||||
|
if (path_len != 0 && !suppressUnread) {
|
||||||
int unreadSlot = (channel_idx == 0xFF) ? MAX_GROUP_CHANNELS : channel_idx;
|
int unreadSlot = (channel_idx == 0xFF) ? MAX_GROUP_CHANNELS : channel_idx;
|
||||||
if (unreadSlot >= 0 && unreadSlot <= MAX_GROUP_CHANNELS) {
|
if (unreadSlot >= 0 && unreadSlot <= MAX_GROUP_CHANNELS) {
|
||||||
_unread[unreadSlot]++;
|
_unread[unreadSlot]++;
|
||||||
@@ -332,6 +340,11 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark all channels + DMs as read (companion app connected)
|
||||||
|
void markAllRead() {
|
||||||
|
memset(_unread, 0, sizeof(_unread));
|
||||||
|
}
|
||||||
|
|
||||||
// Get unread count for a specific channel
|
// Get unread count for a specific channel
|
||||||
int getUnreadForChannel(uint8_t channel_idx) const {
|
int getUnreadForChannel(uint8_t channel_idx) const {
|
||||||
int slot = (channel_idx == 0xFF) ? MAX_GROUP_CHANNELS : channel_idx;
|
int slot = (channel_idx == 0xFF) ? MAX_GROUP_CHANNELS : channel_idx;
|
||||||
@@ -387,6 +400,42 @@ public:
|
|||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// Per-channel history deletion
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Clear all stored messages for a specific channel (or all DMs if 0xFF).
|
||||||
|
// Invalidates matching slots in the circular buffer and persists to SD.
|
||||||
|
// Does NOT alter _newestIdx -- gaps are naturally overwritten as new
|
||||||
|
// messages arrive.
|
||||||
|
int clearHistoryForChannel(uint8_t channel_idx) {
|
||||||
|
int cleared = 0;
|
||||||
|
for (int i = 0; i < CHANNEL_MSG_HISTORY_SIZE; i++) {
|
||||||
|
if (_messages[i].valid && _messages[i].channel_idx == channel_idx) {
|
||||||
|
_messages[i].valid = false;
|
||||||
|
cleared++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cleared > 0) {
|
||||||
|
// Reset unread counter for the cleared channel
|
||||||
|
markChannelRead(channel_idx);
|
||||||
|
// Reset scroll if we're viewing the cleared channel
|
||||||
|
if (_viewChannelIdx == channel_idx) {
|
||||||
|
_scrollPos = 0;
|
||||||
|
}
|
||||||
|
// Reset DM inbox state if clearing DMs
|
||||||
|
if (channel_idx == 0xFF) {
|
||||||
|
_dmInboxScroll = 0;
|
||||||
|
_dmFilterName[0] = '\0';
|
||||||
|
_dmInboxMode = true;
|
||||||
|
}
|
||||||
|
saveToSD();
|
||||||
|
Serial.printf("ChannelScreen: Cleared %d messages for channel %d\n",
|
||||||
|
cleared, (int)channel_idx);
|
||||||
|
}
|
||||||
|
return cleared;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// SD card persistence
|
// SD card persistence
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
@@ -425,6 +474,7 @@ public:
|
|||||||
rec.channel_idx = _messages[i].channel_idx;
|
rec.channel_idx = _messages[i].channel_idx;
|
||||||
rec.valid = _messages[i].valid ? 1 : 0;
|
rec.valid = _messages[i].valid ? 1 : 0;
|
||||||
rec.snr = _messages[i].snr;
|
rec.snr = _messages[i].snr;
|
||||||
|
rec.dm_peer_hash = _messages[i].dm_peer_hash;
|
||||||
memcpy(rec.path, _messages[i].path, MSG_PATH_MAX);
|
memcpy(rec.path, _messages[i].path, MSG_PATH_MAX);
|
||||||
memcpy(rec.text, _messages[i].text, CHANNEL_MSG_TEXT_LEN);
|
memcpy(rec.text, _messages[i].text, CHANNEL_MSG_TEXT_LEN);
|
||||||
f.write((uint8_t*)&rec, sizeof(rec));
|
f.write((uint8_t*)&rec, sizeof(rec));
|
||||||
@@ -492,6 +542,7 @@ public:
|
|||||||
_messages[i].channel_idx = rec.channel_idx;
|
_messages[i].channel_idx = rec.channel_idx;
|
||||||
_messages[i].valid = (rec.valid != 0);
|
_messages[i].valid = (rec.valid != 0);
|
||||||
_messages[i].snr = rec.snr;
|
_messages[i].snr = rec.snr;
|
||||||
|
_messages[i].dm_peer_hash = rec.dm_peer_hash;
|
||||||
memcpy(_messages[i].path, rec.path, MSG_PATH_MAX);
|
memcpy(_messages[i].path, rec.path, MSG_PATH_MAX);
|
||||||
memcpy(_messages[i].text, rec.text, CHANNEL_MSG_TEXT_LEN);
|
memcpy(_messages[i].text, rec.text, CHANNEL_MSG_TEXT_LEN);
|
||||||
if (_messages[i].valid) loaded++;
|
if (_messages[i].valid) loaded++;
|
||||||
@@ -728,6 +779,12 @@ public:
|
|||||||
const char* rtInbox = "Hold:Open";
|
const char* rtInbox = "Hold:Open";
|
||||||
display.setCursor(display.width() - display.getTextWidth(rtInbox) - 2, footerY);
|
display.setCursor(display.width() - display.getTextWidth(rtInbox) - 2, footerY);
|
||||||
display.print(rtInbox);
|
display.print(rtInbox);
|
||||||
|
#elif defined(LILYGO_TECHO_LITE)
|
||||||
|
display.setCursor(0, footerY);
|
||||||
|
display.print("Q:Bk");
|
||||||
|
const char* rtInbox = "Ent:Open";
|
||||||
|
display.setCursor(display.width() - display.getTextWidth(rtInbox) - 2, footerY);
|
||||||
|
display.print(rtInbox);
|
||||||
#else
|
#else
|
||||||
display.setCursor(0, footerY);
|
display.setCursor(0, footerY);
|
||||||
display.print("Q:Bck A/D:Ch");
|
display.print("Q:Bck A/D:Ch");
|
||||||
@@ -964,6 +1021,10 @@ public:
|
|||||||
display.print("Swipe: Switch channel");
|
display.print("Swipe: Switch channel");
|
||||||
display.setCursor(0, 40);
|
display.setCursor(0, 40);
|
||||||
display.print("Long press: Compose");
|
display.print("Long press: Compose");
|
||||||
|
#elif defined(LILYGO_TECHO_LITE)
|
||||||
|
display.print("Arrows: Switch channel");
|
||||||
|
display.setCursor(0, 40);
|
||||||
|
display.print("Ent: Compose message");
|
||||||
#else
|
#else
|
||||||
display.print("A/D: Switch channel");
|
display.print("A/D: Switch channel");
|
||||||
display.setCursor(0, 40);
|
display.setCursor(0, 40);
|
||||||
@@ -1216,9 +1277,16 @@ public:
|
|||||||
uint8_t b = (uint8_t)msg->text[pos];
|
uint8_t b = (uint8_t)msg->text[pos];
|
||||||
|
|
||||||
if (b == EMOJI_PAD_BYTE) { pos++; continue; }
|
if (b == EMOJI_PAD_BYTE) { pos++; continue; }
|
||||||
|
|
||||||
|
// --- UTF-8 lead byte detection ---
|
||||||
|
// Must check BEFORE isEmojiEscape() because lead bytes 0xC2-0xCC
|
||||||
|
// overlap the emoji escape range (0x80-0xCC). A byte >= 0xC2
|
||||||
|
// followed by a continuation byte (0x80-0xBF) is always UTF-8.
|
||||||
|
bool isUtf8 = (b >= 0xC2 && pos + 1 < textLen &&
|
||||||
|
((uint8_t)msg->text[pos + 1] & 0xC0) == 0x80);
|
||||||
|
|
||||||
// Word wrap: when starting a new text word, check if it fits
|
// Word wrap: when starting a new text word, check if it fits
|
||||||
if (b != ' ' && !isEmojiEscape(b) && px > 0) {
|
if (b != ' ' && (isUtf8 || !isEmojiEscape(b)) && px > 0) {
|
||||||
bool boundary = (pos == 0);
|
bool boundary = (pos == 0);
|
||||||
if (!boundary) {
|
if (!boundary) {
|
||||||
for (int bp = pos - 1; bp >= 0; bp--) {
|
for (int bp = pos - 1; bp >= 0; bp--) {
|
||||||
@@ -1230,15 +1298,31 @@ public:
|
|||||||
}
|
}
|
||||||
if (boundary) {
|
if (boundary) {
|
||||||
int wordW = 0;
|
int wordW = 0;
|
||||||
for (int j = pos; j < textLen; j++) {
|
for (int j = pos; j < textLen; ) {
|
||||||
uint8_t wb = (uint8_t)msg->text[j];
|
uint8_t wb = (uint8_t)msg->text[j];
|
||||||
if (wb == EMOJI_PAD_BYTE) continue;
|
if (wb == EMOJI_PAD_BYTE) { j++; continue; }
|
||||||
if (wb == ' ' || isEmojiEscape(wb)) break;
|
if (wb == ' ') break;
|
||||||
charStr[0] = (char)wb;
|
// Check for UTF-8 lead byte in word scan
|
||||||
dblStr[0] = dblStr[1] = (char)wb;
|
bool wbUtf8 = (wb >= 0xC2 && j + 1 < textLen &&
|
||||||
int charAdv = display.getTextWidth(dblStr) - display.getTextWidth(charStr);
|
((uint8_t)msg->text[j + 1] & 0xC0) == 0x80);
|
||||||
if (charAdv < 1) charAdv = 1;
|
if (!wbUtf8 && isEmojiEscape(wb)) break;
|
||||||
wordW += charAdv;
|
if (wbUtf8) {
|
||||||
|
int clen = (wb < 0xE0) ? 2 : (wb < 0xF0) ? 3 : 4;
|
||||||
|
int actual = (j + clen <= textLen) ? clen : textLen - j;
|
||||||
|
char mbuf[5] = {0};
|
||||||
|
memcpy(mbuf, &msg->text[j], actual);
|
||||||
|
int charAdv = display.getTextWidth(mbuf);
|
||||||
|
if (charAdv < 1) charAdv = 1;
|
||||||
|
wordW += charAdv;
|
||||||
|
j += actual;
|
||||||
|
} else {
|
||||||
|
charStr[0] = (char)wb;
|
||||||
|
dblStr[0] = dblStr[1] = (char)wb;
|
||||||
|
int charAdv = display.getTextWidth(dblStr) - display.getTextWidth(charStr);
|
||||||
|
if (charAdv < 1) charAdv = 1;
|
||||||
|
wordW += charAdv;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (px + wordW > lineW) {
|
if (px + wordW > lineW) {
|
||||||
px = 0;
|
px = 0;
|
||||||
@@ -1249,7 +1333,25 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isEmojiEscape(b)) {
|
// --- Render: UTF-8 multi-byte character ---
|
||||||
|
if (isUtf8) {
|
||||||
|
int clen = (b < 0xE0) ? 2 : (b < 0xF0) ? 3 : 4;
|
||||||
|
int actual = (pos + clen <= textLen) ? clen : textLen - pos;
|
||||||
|
char mbuf[5] = {0};
|
||||||
|
memcpy(mbuf, &msg->text[pos], actual);
|
||||||
|
int adv = display.getTextWidth(mbuf);
|
||||||
|
if (adv < 1) adv = 1;
|
||||||
|
if (px + adv > lineW) {
|
||||||
|
px = 0;
|
||||||
|
linesForThisMsg++;
|
||||||
|
y += lineHeight;
|
||||||
|
if (linesForThisMsg >= maxLinesPerMsg || y + lineHeight > maxY) break;
|
||||||
|
}
|
||||||
|
display.setCursor(px, y);
|
||||||
|
display.print(mbuf);
|
||||||
|
px += adv;
|
||||||
|
pos += actual;
|
||||||
|
} else if (isEmojiEscape(b)) {
|
||||||
if (px + EMOJI_SM_W > lineW) {
|
if (px + EMOJI_SM_W > lineW) {
|
||||||
px = 0;
|
px = 0;
|
||||||
linesForThisMsg++;
|
linesForThisMsg++;
|
||||||
@@ -1388,7 +1490,7 @@ public:
|
|||||||
display.setCursor(display.width() - display.getTextWidth(rtCh) - 2, footerY);
|
display.setCursor(display.width() - display.getTextWidth(rtCh) - 2, footerY);
|
||||||
display.print(rtCh);
|
display.print(rtCh);
|
||||||
} else {
|
} else {
|
||||||
display.print("Swipe:List/Scroll");
|
display.print("Swipe:Ch/Scroll");
|
||||||
const char* midCh = "Tap:Path";
|
const char* midCh = "Tap:Path";
|
||||||
display.setCursor((display.width() - display.getTextWidth(midCh)) / 2, footerY);
|
display.setCursor((display.width() - display.getTextWidth(midCh)) / 2, footerY);
|
||||||
display.print(midCh);
|
display.print(midCh);
|
||||||
@@ -1396,6 +1498,19 @@ public:
|
|||||||
display.setCursor(display.width() - display.getTextWidth(rtCh) - 2, footerY);
|
display.setCursor(display.width() - display.getTextWidth(rtCh) - 2, footerY);
|
||||||
display.print(rtCh);
|
display.print(rtCh);
|
||||||
}
|
}
|
||||||
|
#elif defined(LILYGO_TECHO_LITE)
|
||||||
|
// T-Echo Lite: minimal footer for narrow display
|
||||||
|
if (_viewChannelIdx == 0xFF) {
|
||||||
|
display.print("Q:Bk");
|
||||||
|
const char* rightText = "Ent:Reply";
|
||||||
|
display.setCursor(display.width() - display.getTextWidth(rightText) - 2, footerY);
|
||||||
|
display.print(rightText);
|
||||||
|
} else {
|
||||||
|
display.print("Q:Bk");
|
||||||
|
const char* rightText = "Ent:New";
|
||||||
|
display.setCursor(display.width() - display.getTextWidth(rightText) - 2, footerY);
|
||||||
|
display.print(rightText);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
// Left side: abbreviated controls
|
// Left side: abbreviated controls
|
||||||
if (_replySelectMode) {
|
if (_replySelectMode) {
|
||||||
@@ -1413,14 +1528,10 @@ public:
|
|||||||
display.setCursor(display.width() - display.getTextWidth(rightText) - 2, footerY);
|
display.setCursor(display.width() - display.getTextWidth(rightText) - 2, footerY);
|
||||||
display.print(rightText);
|
display.print(rightText);
|
||||||
} else {
|
} else {
|
||||||
display.print("Q:Bk A/D:List R:Rply");
|
display.print("Q:Bck A/D:Ch R:Rply");
|
||||||
// "Ent:New" only fits with Classic+TINY — wider fonts cause overlap
|
const char* rightText = "Ent:New";
|
||||||
NodePrefs* _fp = the_mesh.getNodePrefs();
|
display.setCursor(display.width() - display.getTextWidth(rightText) - 2, footerY);
|
||||||
if (_fp->ui_font_style == 0 && !_fp->large_font) {
|
display.print(rightText);
|
||||||
const char* rightText = " Ent:New";
|
|
||||||
display.setCursor(display.width() - display.getTextWidth(rightText) - 2, footerY);
|
|
||||||
display.print(rightText);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1636,11 +1747,81 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A/D - open channel picker (handled by main.cpp — return false to pass through)
|
// A - previous channel (includes DM tab at 0xFF)
|
||||||
if (c == 'a' || c == 'A' || c == 'd' || c == 'D') {
|
if (c == 'a' || c == 'A') {
|
||||||
_replySelectMode = false;
|
_replySelectMode = false;
|
||||||
_replySelectPos = -1;
|
_replySelectPos = -1;
|
||||||
return false; // Let main.cpp open the channel picker
|
if (_viewChannelIdx == 0xFF) {
|
||||||
|
// DM tab → go to last valid group channel
|
||||||
|
for (uint8_t i = MAX_GROUP_CHANNELS - 1; i > 0; i--) {
|
||||||
|
ChannelDetails ch;
|
||||||
|
if (the_mesh.getChannel(i, ch) && ch.name[0] != '\0') {
|
||||||
|
_viewChannelIdx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (_viewChannelIdx > 0) {
|
||||||
|
// Skip backwards over any empty/gap slots
|
||||||
|
uint8_t prev = _viewChannelIdx - 1;
|
||||||
|
bool found = false;
|
||||||
|
while (true) {
|
||||||
|
ChannelDetails ch;
|
||||||
|
if (the_mesh.getChannel(prev, ch) && ch.name[0] != '\0') {
|
||||||
|
_viewChannelIdx = prev;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (prev == 0) break;
|
||||||
|
prev--;
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
// No valid channel below → wrap to DM tab
|
||||||
|
_viewChannelIdx = 0xFF;
|
||||||
|
_dmInboxMode = true;
|
||||||
|
_dmInboxScroll = 0;
|
||||||
|
_dmFilterName[0] = '\0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Channel 0 → wrap to DM tab
|
||||||
|
_viewChannelIdx = 0xFF;
|
||||||
|
_dmInboxMode = true;
|
||||||
|
_dmInboxScroll = 0;
|
||||||
|
_dmFilterName[0] = '\0';
|
||||||
|
}
|
||||||
|
_scrollPos = 0;
|
||||||
|
markChannelRead(_viewChannelIdx);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// D - next channel (includes DM tab at 0xFF)
|
||||||
|
if (c == 'd' || c == 'D') {
|
||||||
|
_replySelectMode = false;
|
||||||
|
_replySelectPos = -1;
|
||||||
|
if (_viewChannelIdx == 0xFF) {
|
||||||
|
// DM tab → wrap to channel 0
|
||||||
|
_viewChannelIdx = 0;
|
||||||
|
} else {
|
||||||
|
// Skip forward over any empty/gap slots
|
||||||
|
bool found = false;
|
||||||
|
for (uint8_t next = _viewChannelIdx + 1; next < MAX_GROUP_CHANNELS; next++) {
|
||||||
|
ChannelDetails ch;
|
||||||
|
if (the_mesh.getChannel(next, ch) && ch.name[0] != '\0') {
|
||||||
|
_viewChannelIdx = next;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
// Past last channel → go to DM tab
|
||||||
|
_viewChannelIdx = 0xFF;
|
||||||
|
_dmInboxMode = true;
|
||||||
|
_dmInboxScroll = 0;
|
||||||
|
_dmFilterName[0] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_scrollPos = 0;
|
||||||
|
markChannelRead(_viewChannelIdx);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -32,7 +32,13 @@ extern MyMesh the_mesh;
|
|||||||
// T-Deck Pro / MAX : vertical list with "> " cursor, unread badge, right-
|
// T-Deck Pro / MAX : vertical list with "> " cursor, unread badge, right-
|
||||||
// aligned. Same highlight/tap convention as Contacts.
|
// aligned. Same highlight/tap convention as Contacts.
|
||||||
//
|
//
|
||||||
// Navigation signals use a wantsExit() flag (same pattern as PathEditor) —
|
// Delete history:
|
||||||
|
// Press X on a highlighted channel to enter delete confirmation mode.
|
||||||
|
// Confirmation overlay asks the user to press Enter to confirm or Q to
|
||||||
|
// cancel. On confirm, all messages for that channel are invalidated in
|
||||||
|
// the circular buffer and persisted to SD.
|
||||||
|
//
|
||||||
|
// Navigation signals use a wantsExit() flag (same pattern as PathEditor) --
|
||||||
// UITask is only forward-declared, so the picker cannot call UITask methods
|
// UITask is only forward-declared, so the picker cannot call UITask methods
|
||||||
// directly. main.cpp / UITask.cpp check the flag after injectKey().
|
// directly. main.cpp / UITask.cpp check the flag after injectKey().
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -50,12 +56,15 @@ class ChannelPickerScreen : public UIScreen {
|
|||||||
int _cursor;
|
int _cursor;
|
||||||
int _scrollTop; // Scroll offset (T-Deck Pro list only)
|
int _scrollTop; // Scroll offset (T-Deck Pro list only)
|
||||||
|
|
||||||
// Grid layout cache (T5S3) — set in render(), consumed by touch hit test
|
// Grid layout cache (T5S3) -- set in render(), consumed by touch hit test
|
||||||
int _cellW;
|
int _cellW;
|
||||||
int _cellH;
|
int _cellH;
|
||||||
int _gridTop;
|
int _gridTop;
|
||||||
int _gridCols;
|
int _gridCols;
|
||||||
|
|
||||||
|
// Delete confirmation sub-menu
|
||||||
|
bool _confirmDelete; // True when showing "Delete history?" overlay
|
||||||
|
|
||||||
// Rebuild the items list from MyMesh. O(20), safe every render.
|
// Rebuild the items list from MyMesh. O(20), safe every render.
|
||||||
void rebuildItems() {
|
void rebuildItems() {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
@@ -100,13 +109,14 @@ public:
|
|||||||
: _task(task), _channelScreen(nullptr),
|
: _task(task), _channelScreen(nullptr),
|
||||||
_itemCount(0), _cursor(0), _scrollTop(0),
|
_itemCount(0), _cursor(0), _scrollTop(0),
|
||||||
_cellW(40), _cellH(12), _gridTop(14), _gridCols(3),
|
_cellW(40), _cellH(12), _gridTop(14), _gridCols(3),
|
||||||
|
_confirmDelete(false),
|
||||||
_wantExit(false) {
|
_wantExit(false) {
|
||||||
_items[0] = 0xFF;
|
_items[0] = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setChannelScreen(ChannelScreen* cs) { _channelScreen = cs; }
|
void setChannelScreen(ChannelScreen* cs) { _channelScreen = cs; }
|
||||||
|
|
||||||
// --- wantsExit flag — checked by main.cpp / UITask after injectKey() ---
|
// --- wantsExit flag -- checked by main.cpp / UITask after injectKey() ---
|
||||||
bool _wantExit;
|
bool _wantExit;
|
||||||
bool wantsExit() const { return _wantExit; }
|
bool wantsExit() const { return _wantExit; }
|
||||||
|
|
||||||
@@ -118,6 +128,7 @@ public:
|
|||||||
if (_items[i] == currentChannelIdx) { _cursor = i; break; }
|
if (_items[i] == currentChannelIdx) { _cursor = i; break; }
|
||||||
}
|
}
|
||||||
_scrollTop = 0;
|
_scrollTop = 0;
|
||||||
|
_confirmDelete = false;
|
||||||
_wantExit = false;
|
_wantExit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +182,7 @@ public:
|
|||||||
_cellW = bubbleW;
|
_cellW = bubbleW;
|
||||||
_cellH = bubbleH + gap;
|
_cellH = bubbleH + gap;
|
||||||
_gridTop = headerH;
|
_gridTop = headerH;
|
||||||
_gridCols = 1; // Single column — list mode
|
_gridCols = 1; // Single column -- list mode
|
||||||
|
|
||||||
// Centre scroll window on cursor
|
// Centre scroll window on cursor
|
||||||
_scrollTop = max(0, min(_cursor - maxVisible / 2, _itemCount - maxVisible));
|
_scrollTop = max(0, min(_cursor - maxVisible / 2, _itemCount - maxVisible));
|
||||||
@@ -200,7 +211,7 @@ public:
|
|||||||
display.drawRect(x + 1, y + 1, w - 2, h - 2);
|
display.drawRect(x + 1, y + 1, w - 2, h - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Channel name — left-aligned with inner padding
|
// Channel name -- left-aligned with inner padding
|
||||||
char name[32];
|
char name[32];
|
||||||
getItemName(i, name, sizeof(name));
|
getItemName(i, name, sizeof(name));
|
||||||
char filtered[32];
|
char filtered[32];
|
||||||
@@ -229,7 +240,7 @@ public:
|
|||||||
display.drawTextEllipsized(textX, textY, nameMaxW, filtered);
|
display.drawTextEllipsized(textX, textY, nameMaxW, filtered);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unread badge — right-aligned inside bubble
|
// Unread badge -- right-aligned inside bubble
|
||||||
if (unread > 0) {
|
if (unread > 0) {
|
||||||
int bx = x + w - badgeW;
|
int bx = x + w - badgeW;
|
||||||
display.setCursor(bx, textY);
|
display.setCursor(bx, textY);
|
||||||
@@ -329,6 +340,47 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// =================================================================
|
||||||
|
// Delete confirmation overlay
|
||||||
|
// Drawn on top of the list when _confirmDelete is active.
|
||||||
|
// =================================================================
|
||||||
|
if (_confirmDelete) {
|
||||||
|
// Clear a centred box and draw a border
|
||||||
|
int boxW = display.width() - 16;
|
||||||
|
int boxH = 42;
|
||||||
|
int boxX = 8;
|
||||||
|
int boxY = (display.height() - boxH) / 2;
|
||||||
|
|
||||||
|
// Clear the box area
|
||||||
|
display.setColor(DisplayDriver::DARK);
|
||||||
|
display.fillRect(boxX, boxY, boxW, boxH);
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
display.drawRect(boxX, boxY, boxW, boxH);
|
||||||
|
display.drawRect(boxX + 1, boxY + 1, boxW - 2, boxH - 2);
|
||||||
|
|
||||||
|
// Channel name
|
||||||
|
display.setTextSize(1);
|
||||||
|
char name[32];
|
||||||
|
getItemName(_cursor, name, sizeof(name));
|
||||||
|
char filtered[32];
|
||||||
|
display.translateUTF8ToBlocks(filtered, name, sizeof(filtered));
|
||||||
|
|
||||||
|
display.setColor(DisplayDriver::GREEN);
|
||||||
|
display.drawTextEllipsized(boxX + 4, boxY + 5, boxW - 8, filtered);
|
||||||
|
|
||||||
|
// "Delete history?" prompt
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
const char* prompt = "Delete message history?";
|
||||||
|
display.setCursor(boxX + 4, boxY + 17);
|
||||||
|
display.print(prompt);
|
||||||
|
|
||||||
|
// Key hints
|
||||||
|
display.setColor(DisplayDriver::YELLOW);
|
||||||
|
const char* hints = "Enter:Yes Q:Cancel";
|
||||||
|
display.setCursor(boxX + 4, boxY + 29);
|
||||||
|
display.print(hints);
|
||||||
|
}
|
||||||
|
|
||||||
// === Footer ===
|
// === Footer ===
|
||||||
display.setTextSize(1);
|
display.setTextSize(1);
|
||||||
int footerY = display.height() - 12;
|
int footerY = display.height() - 12;
|
||||||
@@ -337,15 +389,31 @@ public:
|
|||||||
display.setCursor(0, footerY);
|
display.setCursor(0, footerY);
|
||||||
|
|
||||||
#if defined(LilyGo_T5S3_EPaper_Pro)
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
display.print("Tap:Open");
|
if (_confirmDelete) {
|
||||||
const char* rt = "Boot:Back";
|
display.print("Tap:Yes");
|
||||||
display.setCursor(display.width() - display.getTextWidth(rt) - 2, footerY);
|
const char* rt = "Boot:Cancel";
|
||||||
display.print(rt);
|
display.setCursor(display.width() - display.getTextWidth(rt) - 2, footerY);
|
||||||
#else
|
display.print(rt);
|
||||||
display.print("W/S:Nav Q:Back");
|
} else {
|
||||||
|
display.print("Tap:Open");
|
||||||
|
const char* rt = "Hold:Del Boot:Back";
|
||||||
|
display.setCursor(display.width() - display.getTextWidth(rt) - 2, footerY);
|
||||||
|
display.print(rt);
|
||||||
|
}
|
||||||
|
#elif defined(LILYGO_TECHO_LITE)
|
||||||
|
display.print("Q:Bk");
|
||||||
const char* rt = "Ent:Open";
|
const char* rt = "Ent:Open";
|
||||||
display.setCursor(display.width() - display.getTextWidth(rt) - 2, footerY);
|
display.setCursor(display.width() - display.getTextWidth(rt) - 2, footerY);
|
||||||
display.print(rt);
|
display.print(rt);
|
||||||
|
#else
|
||||||
|
if (_confirmDelete) {
|
||||||
|
display.print("Enter:Yes Q:Cancel");
|
||||||
|
} else {
|
||||||
|
display.print("W/S:Nav Q:Back");
|
||||||
|
const char* rt = "Ent:Open";
|
||||||
|
display.setCursor(display.width() - display.getTextWidth(rt) - 2, footerY);
|
||||||
|
display.print(rt);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_EINK
|
#ifdef USE_EINK
|
||||||
@@ -359,6 +427,30 @@ public:
|
|||||||
// Input
|
// Input
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
bool handleInput(char c) override {
|
bool handleInput(char c) override {
|
||||||
|
// --- Delete confirmation mode ---
|
||||||
|
if (_confirmDelete) {
|
||||||
|
// Enter -- confirm deletion
|
||||||
|
if (c == '\r' || c == 13 || c == KEY_ENTER || c == KEY_SELECT) {
|
||||||
|
if (_channelScreen && _cursor >= 0 && _cursor < _itemCount) {
|
||||||
|
int cleared = _channelScreen->clearHistoryForChannel(_items[_cursor]);
|
||||||
|
char name[32];
|
||||||
|
getItemName(_cursor, name, sizeof(name));
|
||||||
|
Serial.printf("ChannelPicker: Deleted %d messages for '%s'\n", cleared, name);
|
||||||
|
}
|
||||||
|
_confirmDelete = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Q / backspace -- cancel
|
||||||
|
if (c == 'q' || c == 'Q' || c == '\b' || c == KEY_CANCEL) {
|
||||||
|
_confirmDelete = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Consume all other keys while confirmation is showing
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Normal picker mode ---
|
||||||
|
|
||||||
// W / UP
|
// W / UP
|
||||||
if (c == 'w' || c == 'W' || c == 0xF2 || c == KEY_UP) {
|
if (c == 'w' || c == 'W' || c == 0xF2 || c == KEY_UP) {
|
||||||
if (_cursor > 0) { _cursor--; return true; }
|
if (_cursor > 0) { _cursor--; return true; }
|
||||||
@@ -371,7 +463,7 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A / D — consumed (no channel cycling from picker)
|
// A / D -- consumed (no channel cycling from picker)
|
||||||
if (c == 'a' || c == 'A' || c == KEY_LEFT) {
|
if (c == 'a' || c == 'A' || c == KEY_LEFT) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -379,16 +471,24 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enter — select the highlighted channel and signal exit
|
// X -- delete message history for highlighted channel
|
||||||
|
if (c == 'x' || c == 'X') {
|
||||||
|
if (_cursor >= 0 && _cursor < _itemCount) {
|
||||||
|
_confirmDelete = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enter -- select the highlighted channel and signal exit
|
||||||
if (c == '\r' || c == 13 || c == KEY_ENTER || c == KEY_SELECT) {
|
if (c == '\r' || c == 13 || c == KEY_ENTER || c == KEY_SELECT) {
|
||||||
if (_channelScreen && _cursor >= 0 && _cursor < _itemCount) {
|
if (_channelScreen && _cursor >= 0 && _cursor < _itemCount) {
|
||||||
_channelScreen->setViewChannelIdx(_items[_cursor]);
|
_channelScreen->setViewChannelIdx(_items[_cursor]);
|
||||||
}
|
}
|
||||||
_wantExit = true;
|
_wantExit = true;
|
||||||
return true; // Consumed — caller checks wantsExit() and navigates
|
return true; // Consumed -- caller checks wantsExit() and navigates
|
||||||
}
|
}
|
||||||
|
|
||||||
// Q / backspace — cancel without changing channel, signal exit
|
// Q / backspace -- cancel without changing channel, signal exit
|
||||||
if (c == 'q' || c == 'Q' || c == '\b' || c == KEY_CANCEL) {
|
if (c == 'q' || c == 'Q' || c == '\b' || c == KEY_CANCEL) {
|
||||||
_wantExit = true;
|
_wantExit = true;
|
||||||
return true;
|
return true;
|
||||||
@@ -400,10 +500,22 @@ public:
|
|||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// Touch hit test (virtual coordinates)
|
// Touch hit test (virtual coordinates)
|
||||||
// Returns: 0=miss, 1=cursor moved, 2=activate.
|
// Returns: 0=miss, 1=cursor moved, 2=activate.
|
||||||
// T5S3 bubbles: any tap on a bubble → 2 (direct open).
|
// T5S3 bubbles: any tap on a bubble -> 2 (direct open).
|
||||||
// T-Deck Pro list: 1st tap → 1 (highlight), 2nd tap same row → 2.
|
// T-Deck Pro list: 1st tap -> 1 (highlight), 2nd tap same row -> 2.
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
int selectAtVxVy(int vx, int vy) {
|
int selectAtVxVy(int vx, int vy) {
|
||||||
|
// If delete confirmation is showing:
|
||||||
|
// T5S3: tap = confirm (return 2 → KEY_ENTER → handleInput confirms)
|
||||||
|
// T-Deck Pro: tap = cancel (dismiss overlay, stay on picker)
|
||||||
|
if (_confirmDelete) {
|
||||||
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
|
return 2; // Confirm — maps to KEY_ENTER in mapTouchTap
|
||||||
|
#else
|
||||||
|
_confirmDelete = false;
|
||||||
|
return 1; // Cancel — redraw without activating
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(LilyGo_T5S3_EPaper_Pro)
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
// Vertical bubble list hit test
|
// Vertical bubble list hit test
|
||||||
if (vy < _gridTop || _cellH == 0) return 0;
|
if (vy < _gridTop || _cellH == 0) return 0;
|
||||||
@@ -415,7 +527,7 @@ public:
|
|||||||
_cursor = idx;
|
_cursor = idx;
|
||||||
return 2; // Direct open on tap
|
return 2; // Direct open on tap
|
||||||
#else
|
#else
|
||||||
// T-Deck Pro / MAX list hit test — uses NodePrefs for large_font compatibility
|
// T-Deck Pro / MAX list hit test -- uses NodePrefs for large_font compatibility
|
||||||
NodePrefs* prefs = the_mesh.getNodePrefs();
|
NodePrefs* prefs = the_mesh.getNodePrefs();
|
||||||
int lineH = prefs->smallLineH();
|
int lineH = prefs->smallLineH();
|
||||||
const int headerH = 14;
|
const int headerH = 14;
|
||||||
|
|||||||
@@ -466,6 +466,16 @@ public:
|
|||||||
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
|
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
|
||||||
display.print(right);
|
display.print(right);
|
||||||
}
|
}
|
||||||
|
#elif defined(LILYGO_TECHO_LITE)
|
||||||
|
display.setCursor(0, footerY);
|
||||||
|
if (_selectMode) {
|
||||||
|
display.print("Q:Done");
|
||||||
|
} else {
|
||||||
|
display.print("Q:Bk");
|
||||||
|
const char* right = "Ent:Sel";
|
||||||
|
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
|
||||||
|
display.print(right);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
display.setCursor(0, footerY);
|
display.setCursor(0, footerY);
|
||||||
if (_selectMode) {
|
if (_selectMode) {
|
||||||
@@ -485,16 +495,30 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool handleInput(char c) override {
|
bool handleInput(char c) override {
|
||||||
|
// Shift+W: page up
|
||||||
|
if (c == 'W') {
|
||||||
|
int pageSize = (128 - 14 - 14) / the_mesh.getNodePrefs()->smallLineH();
|
||||||
|
if (pageSize < 3) pageSize = 3;
|
||||||
|
_scrollPos = max(0, _scrollPos - pageSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// W - scroll up (previous contact)
|
// W - scroll up (previous contact)
|
||||||
if (c == 'w' || c == 'W' || c == 0xF2) {
|
if (c == 'w' || c == 0xF2) {
|
||||||
if (_scrollPos > 0) {
|
if (_scrollPos > 0) {
|
||||||
_scrollPos--;
|
_scrollPos--;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shift+S: page down
|
||||||
|
if (c == 'S') {
|
||||||
|
int pageSize = (128 - 14 - 14) / the_mesh.getNodePrefs()->smallLineH();
|
||||||
|
if (pageSize < 3) pageSize = 3;
|
||||||
|
_scrollPos = min(_filteredCount - 1, _scrollPos + pageSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// S - scroll down (next contact)
|
// S - scroll down (next contact)
|
||||||
if (c == 's' || c == 'S' || c == 0xF1) {
|
if (c == 's' || c == 0xF1) {
|
||||||
if (_scrollPos < _filteredCount - 1) {
|
if (_scrollPos < _filteredCount - 1) {
|
||||||
_scrollPos++;
|
_scrollPos++;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -217,16 +217,30 @@ public:
|
|||||||
bool handleInput(char c) override {
|
bool handleInput(char c) override {
|
||||||
int count = the_mesh.getDiscoveredCount();
|
int count = the_mesh.getDiscoveredCount();
|
||||||
|
|
||||||
|
// Shift+W: page up
|
||||||
|
if (c == 'W') {
|
||||||
|
int pageSize = (128 - 14 - 14) / the_mesh.getNodePrefs()->smallLineH();
|
||||||
|
if (pageSize < 3) pageSize = 3;
|
||||||
|
_scrollPos = max(0, _scrollPos - pageSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// W - scroll up
|
// W - scroll up
|
||||||
if (c == 'w' || c == 'W' || c == 0xF2) {
|
if (c == 'w' || c == 0xF2) {
|
||||||
if (_scrollPos > 0) {
|
if (_scrollPos > 0) {
|
||||||
_scrollPos--;
|
_scrollPos--;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shift+S: page down
|
||||||
|
if (c == 'S') {
|
||||||
|
int pageSize = (128 - 14 - 14) / the_mesh.getNodePrefs()->smallLineH();
|
||||||
|
if (pageSize < 3) pageSize = 3;
|
||||||
|
_scrollPos = min(count - 1, _scrollPos + pageSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// S - scroll down
|
// S - scroll down
|
||||||
if (c == 's' || c == 'S' || c == 0xF1) {
|
if (c == 's' || c == 0xF1) {
|
||||||
if (_scrollPos < count - 1) {
|
if (_scrollPos < count - 1) {
|
||||||
_scrollPos++;
|
_scrollPos++;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// Emoji sprites for e-ink display - dual size
|
// Emoji sprites for e-ink display - dual size
|
||||||
// Large (12x12) for compose/picker, Small (10x10) for channel view
|
// Large (12x12) for compose/picker, Small (10x10) for channel view
|
||||||
// MSB-first, 2 bytes per row
|
// MSB-first, 2 bytes per row
|
||||||
// 76 total emoji: joy/thumbsup/frown first, then 43 original, then 19 new, then 11 newest
|
// 77 total emoji: joy/thumbsup/frown first, then 43 original, then 19 new, then 11 newest, then 1 latest
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
@@ -15,11 +15,11 @@
|
|||||||
#define EMOJI_SM_W 10
|
#define EMOJI_SM_W 10
|
||||||
#define EMOJI_SM_H 10
|
#define EMOJI_SM_H 10
|
||||||
|
|
||||||
#define EMOJI_COUNT 76
|
#define EMOJI_COUNT 77
|
||||||
|
|
||||||
// Escape codes in 0x80+ range - safe from keyboard ASCII (32-126)
|
// Escape codes in 0x80+ range - safe from keyboard ASCII (32-126)
|
||||||
#define EMOJI_ESCAPE_START 0x80
|
#define EMOJI_ESCAPE_START 0x80
|
||||||
#define EMOJI_ESCAPE_END 0xCB // 0x80 + 75
|
#define EMOJI_ESCAPE_END 0xCC // 0x80 + 76
|
||||||
#define EMOJI_PAD_BYTE 0x7F // DEL, not typeable (key < 127 guard)
|
#define EMOJI_PAD_BYTE 0x7F // DEL, not typeable (key < 127 guard)
|
||||||
|
|
||||||
// ======== LARGE 12x12 SPRITES ========
|
// ======== LARGE 12x12 SPRITES ========
|
||||||
@@ -328,6 +328,10 @@ static const uint8_t emoji_lg_eight_spoked_asterisk[] PROGMEM = {
|
|||||||
static const uint8_t emoji_lg_signal_strength[] PROGMEM = {
|
static const uint8_t emoji_lg_signal_strength[] PROGMEM = {
|
||||||
0x00,0x20, 0x00,0x20, 0x00,0xA0, 0x00,0xA0, 0x02,0xA0, 0x02,0xA0, 0x0A,0xA0, 0x0A,0xA0, 0x2A,0xA0, 0x2A,0xA0, 0xAA,0xA0, 0xAA,0xA0,
|
0x00,0x20, 0x00,0x20, 0x00,0xA0, 0x00,0xA0, 0x02,0xA0, 0x02,0xA0, 0x0A,0xA0, 0x0A,0xA0, 0x2A,0xA0, 0x2A,0xA0, 0xAA,0xA0, 0xAA,0xA0,
|
||||||
};
|
};
|
||||||
|
// [76] beer 🍺
|
||||||
|
static const uint8_t emoji_lg_beer[] PROGMEM = {
|
||||||
|
0x24,0x80, 0x77,0x60, 0xFF,0x80, 0x7F,0xC0, 0x40,0x70, 0x5F,0x50, 0x5F,0x50, 0x5F,0x50, 0x40,0x70, 0x7F,0xC0, 0xFF,0xE0, 0x00,0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static const uint8_t* const EMOJI_SPRITES_LG[] PROGMEM = {
|
static const uint8_t* const EMOJI_SPRITES_LG[] PROGMEM = {
|
||||||
@@ -354,6 +358,7 @@ static const uint8_t* const EMOJI_SPRITES_LG[] PROGMEM = {
|
|||||||
emoji_lg_diamond_suit, emoji_lg_spade_suit, emoji_lg_pizza, emoji_lg_four_leaf_clover,
|
emoji_lg_diamond_suit, emoji_lg_spade_suit, emoji_lg_pizza, emoji_lg_four_leaf_clover,
|
||||||
emoji_lg_cloud, emoji_lg_rocket, emoji_lg_passport_control,
|
emoji_lg_cloud, emoji_lg_rocket, emoji_lg_passport_control,
|
||||||
emoji_lg_eight_spoked_asterisk, emoji_lg_signal_strength,
|
emoji_lg_eight_spoked_asterisk, emoji_lg_signal_strength,
|
||||||
|
emoji_lg_beer,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ======== SMALL 10x10 SPRITES ========
|
// ======== SMALL 10x10 SPRITES ========
|
||||||
@@ -616,6 +621,10 @@ static const uint8_t emoji_sm_eight_spoked_asterisk[] PROGMEM = {
|
|||||||
static const uint8_t emoji_sm_signal_strength[] PROGMEM = {
|
static const uint8_t emoji_sm_signal_strength[] PROGMEM = {
|
||||||
0x00,0x80, 0x00,0x80, 0x02,0x80, 0x02,0x80, 0x0A,0x80, 0x0A,0x80, 0x2A,0x80, 0x2A,0x80, 0xAA,0x80, 0xAA,0x80,
|
0x00,0x80, 0x00,0x80, 0x02,0x80, 0x02,0x80, 0x0A,0x80, 0x0A,0x80, 0x2A,0x80, 0x2A,0x80, 0xAA,0x80, 0xAA,0x80,
|
||||||
};
|
};
|
||||||
|
// [76] beer 🍺
|
||||||
|
static const uint8_t emoji_sm_beer[] PROGMEM = {
|
||||||
|
0x54,0x00, 0x6E,0xC0, 0xFF,0x80, 0x80,0xC0, 0xBE,0x40, 0xBE,0x40, 0x80,0xC0, 0xFF,0x80, 0x00,0x00, 0xFF,0x80,
|
||||||
|
};
|
||||||
|
|
||||||
static const uint8_t* const EMOJI_SPRITES_SM[] PROGMEM = {
|
static const uint8_t* const EMOJI_SPRITES_SM[] PROGMEM = {
|
||||||
// Faces/emotion first
|
// Faces/emotion first
|
||||||
@@ -641,6 +650,7 @@ static const uint8_t* const EMOJI_SPRITES_SM[] PROGMEM = {
|
|||||||
emoji_sm_diamond_suit, emoji_sm_spade_suit, emoji_sm_pizza, emoji_sm_four_leaf_clover,
|
emoji_sm_diamond_suit, emoji_sm_spade_suit, emoji_sm_pizza, emoji_sm_four_leaf_clover,
|
||||||
emoji_sm_cloud, emoji_sm_rocket, emoji_sm_passport_control,
|
emoji_sm_cloud, emoji_sm_rocket, emoji_sm_passport_control,
|
||||||
emoji_sm_eight_spoked_asterisk, emoji_sm_signal_strength,
|
emoji_sm_eight_spoked_asterisk, emoji_sm_signal_strength,
|
||||||
|
emoji_sm_beer,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- Codepoint lookup for UTF-8 conversion ----
|
// ---- Codepoint lookup for UTF-8 conversion ----
|
||||||
@@ -726,6 +736,7 @@ static const EmojiCodepoint EMOJI_CODEPOINTS[EMOJI_COUNT] = {
|
|||||||
{ 0x1F6C2, 0x0000, 0xC9 }, // passport_control
|
{ 0x1F6C2, 0x0000, 0xC9 }, // passport_control
|
||||||
{ 0x2733, 0x0000, 0xCA }, // eight_spoked_asterisk
|
{ 0x2733, 0x0000, 0xCA }, // eight_spoked_asterisk
|
||||||
{ 0x1F4F6, 0x0000, 0xCB }, // signal_strength
|
{ 0x1F4F6, 0x0000, 0xCB }, // signal_strength
|
||||||
|
{ 0x1F37A, 0x0000, 0xCC }, // beer
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- Helper functions ----
|
// ---- Helper functions ----
|
||||||
@@ -769,6 +780,7 @@ static void emojiSanitize(const char* src, char* dst, int dstLen) {
|
|||||||
int consumed;
|
int consumed;
|
||||||
uint32_t cp = emojiDecodeUtf8(s + si, srcLen - si, &consumed);
|
uint32_t cp = emojiDecodeUtf8(s + si, srcLen - si, &consumed);
|
||||||
if (cp == 0xFE0F) { si += consumed; continue; }
|
if (cp == 0xFE0F) { si += consumed; continue; }
|
||||||
|
if (cp == 0xFFFD) { si += consumed; continue; } // Invalid UTF-8 — skip stray bytes safely
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (int e = 0; e < EMOJI_COUNT; e++) {
|
for (int e = 0; e < EMOJI_COUNT; e++) {
|
||||||
if (EMOJI_CODEPOINTS[e].cp == cp) {
|
if (EMOJI_CODEPOINTS[e].cp == cp) {
|
||||||
@@ -803,7 +815,20 @@ static void emojiSanitize(const char* src, char* dst, int dstLen) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) si += consumed; // Skip unknown multi-byte chars
|
if (!found) {
|
||||||
|
// Preserve non-emoji UTF-8 (accented letters, Cyrillic, Greek, etc.) by
|
||||||
|
// copying original bytes through to dst. UTF-8-aware render paths handle
|
||||||
|
// them downstream. Emoji-escape disambiguation remains unambiguous because
|
||||||
|
// emoji escapes (0x80-0xCC) only appear standalone — never as a continuation
|
||||||
|
// byte following a UTF-8 lead byte (0xC2-0xF7), so the decoder can tell them
|
||||||
|
// apart by tracking lead-byte state.
|
||||||
|
if (di + consumed < dstLen) {
|
||||||
|
for (int k = 0; k < consumed; k++) dst[di++] = (char)s[si + k];
|
||||||
|
si += consumed;
|
||||||
|
} else {
|
||||||
|
break; // Not enough room for full UTF-8 sequence — stop cleanly
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
dst[di++] = (char)b;
|
dst[di++] = (char)b;
|
||||||
si++;
|
si++;
|
||||||
|
|||||||
@@ -223,14 +223,28 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool handleInput(char c) override {
|
bool handleInput(char c) override {
|
||||||
|
// Shift+W: page up
|
||||||
|
if (c == 'W') {
|
||||||
|
int pageSize = (128 - 14 - 14) / the_mesh.getNodePrefs()->smallLineH();
|
||||||
|
if (pageSize < 3) pageSize = 3;
|
||||||
|
_scrollPos = max(0, _scrollPos - pageSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// Scroll up
|
// Scroll up
|
||||||
if (c == 'w' || c == 'W' || c == 0xF2) {
|
if (c == 'w' || c == 0xF2) {
|
||||||
if (_scrollPos > 0) { _scrollPos--; return true; }
|
if (_scrollPos > 0) { _scrollPos--; return true; }
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shift+S: page down
|
||||||
|
if (c == 'S') {
|
||||||
|
int pageSize = (128 - 14 - 14) / the_mesh.getNodePrefs()->smallLineH();
|
||||||
|
if (pageSize < 3) pageSize = 3;
|
||||||
|
_scrollPos = min(_count - 1, _scrollPos + pageSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// Scroll down
|
// Scroll down
|
||||||
if (c == 's' || c == 'S' || c == 0xF1) {
|
if (c == 's' || c == 0xF1) {
|
||||||
if (_scrollPos < _count - 1) { _scrollPos++; return true; }
|
if (_scrollPos < _count - 1) { _scrollPos++; return true; }
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ static inline const char* meckFontStyleName(uint8_t style) {
|
|||||||
// Font includes — Noto Sans family
|
// Font includes — Noto Sans family
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
#include "fonts/NotoSans7pt7b.h"
|
#include "fonts/NotoSans7pt7b.h"
|
||||||
#include "fonts/NotoSans9pt7b.h"
|
#include "fonts/NotoSans9pt8b.h"
|
||||||
#include "fonts/NotoSans12pt7b.h"
|
#include "fonts/NotoSans12pt8b.h"
|
||||||
#include "fonts/NotoSansBold7pt7b.h"
|
#include "fonts/NotoSansBold7pt7b.h"
|
||||||
#include "fonts/NotoSansBold9pt7b.h"
|
#include "fonts/NotoSansBold9pt7b.h"
|
||||||
#include "fonts/NotoSansBold12pt7b.h"
|
#include "fonts/NotoSansBold12pt7b.h"
|
||||||
@@ -52,8 +52,8 @@ static inline const char* meckFontStyleName(uint8_t style) {
|
|||||||
#include "fonts/Montserrat9pt7b.h"
|
#include "fonts/Montserrat9pt7b.h"
|
||||||
#include "fonts/Montserrat12pt7b.h"
|
#include "fonts/Montserrat12pt7b.h"
|
||||||
#include "fonts/MontserratBold7pt7b.h"
|
#include "fonts/MontserratBold7pt7b.h"
|
||||||
#include "fonts/MontserratBold9pt7b.h"
|
#include "fonts/MontserratBold9pt8b.h"
|
||||||
#include "fonts/MontserratBold12pt7b.h"
|
#include "fonts/MontserratBold12pt8b.h"
|
||||||
#include "fonts/MontserratBold18pt7b.h"
|
#include "fonts/MontserratBold18pt7b.h"
|
||||||
#include "fonts/MontserratBold24pt7b.h"
|
#include "fonts/MontserratBold24pt7b.h"
|
||||||
|
|
||||||
@@ -83,11 +83,11 @@ static inline const GFXfont* meckGetFont_TDeckPro(uint8_t style, int textSize) {
|
|||||||
if (style == MECK_FONT_NOTO) {
|
if (style == MECK_FONT_NOTO) {
|
||||||
switch (textSize) {
|
switch (textSize) {
|
||||||
case 0: return &NotoSans_Regular7pt7b;
|
case 0: return &NotoSans_Regular7pt7b;
|
||||||
case 1: return &NotoSans_Regular9pt7b;
|
case 1: return &NotoSans9pt8b;
|
||||||
case 2: return &NotoSans_Regular9pt7b;
|
case 2: return &NotoSans9pt8b;
|
||||||
case 3: return &NotoSans_Bold12pt7b;
|
case 3: return &NotoSans_Bold12pt7b;
|
||||||
case 5: return &NotoSans_Bold12pt7b; // caller applies ×2 scale
|
case 5: return &NotoSans_Bold12pt7b; // caller applies x2 scale
|
||||||
default: return &NotoSans_Regular9pt7b;
|
default: return &NotoSans9pt8b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +96,8 @@ static inline const GFXfont* meckGetFont_TDeckPro(uint8_t style, int textSize) {
|
|||||||
case 0: return &Montserrat_Regular7pt7b;
|
case 0: return &Montserrat_Regular7pt7b;
|
||||||
case 1: return &Montserrat_Regular9pt7b;
|
case 1: return &Montserrat_Regular9pt7b;
|
||||||
case 2: return &Montserrat_Regular9pt7b;
|
case 2: return &Montserrat_Regular9pt7b;
|
||||||
case 3: return &Montserrat_Bold12pt7b;
|
case 3: return &MontserratBold12pt8b;
|
||||||
case 5: return &Montserrat_Bold12pt7b; // caller applies ×2 scale
|
case 5: return &MontserratBold12pt8b; // caller applies x2 scale
|
||||||
default: return &Montserrat_Regular9pt7b;
|
default: return &Montserrat_Regular9pt7b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,22 +130,22 @@ static inline const GFXfont* meckGetFont_T5S3(uint8_t style, int textSize) {
|
|||||||
|
|
||||||
if (style == MECK_FONT_NOTO) {
|
if (style == MECK_FONT_NOTO) {
|
||||||
switch (textSize) {
|
switch (textSize) {
|
||||||
case 0: return &NotoSans_Regular12pt7b;
|
case 0: return &NotoSans12pt8b;
|
||||||
case 1: return &NotoSans_Bold12pt7b;
|
case 1: return &NotoSans_Bold12pt7b;
|
||||||
case 2: return &NotoSans_Bold18pt7b;
|
case 2: return &NotoSans_Bold18pt7b;
|
||||||
case 3: return &NotoSans_Bold24pt7b;
|
case 3: return &NotoSans_Bold24pt7b;
|
||||||
case 5: return &NotoSans_Bold24pt7b; // caller applies ×5 scale
|
case 5: return &NotoSans_Bold24pt7b; // caller applies x5 scale
|
||||||
default: return &NotoSans_Regular12pt7b;
|
default: return &NotoSans12pt8b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MECK_FONT_MONTSERRAT
|
// MECK_FONT_MONTSERRAT
|
||||||
switch (textSize) {
|
switch (textSize) {
|
||||||
case 0: return &Montserrat_Regular12pt7b;
|
case 0: return &Montserrat_Regular12pt7b;
|
||||||
case 1: return &Montserrat_Bold12pt7b;
|
case 1: return &MontserratBold12pt8b;
|
||||||
case 2: return &Montserrat_Bold18pt7b;
|
case 2: return &Montserrat_Bold18pt7b;
|
||||||
case 3: return &Montserrat_Bold24pt7b;
|
case 3: return &Montserrat_Bold24pt7b;
|
||||||
case 5: return &Montserrat_Bold24pt7b; // caller applies ×5 scale
|
case 5: return &Montserrat_Bold24pt7b; // caller applies x5 scale
|
||||||
default: return &Montserrat_Regular12pt7b;
|
default: return &Montserrat_Regular12pt7b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -909,12 +909,26 @@ private:
|
|||||||
bool handleFileListInput(char c) {
|
bool handleFileListInput(char c) {
|
||||||
int totalItems = 1 + (int)_fileList.size();
|
int totalItems = 1 + (int)_fileList.size();
|
||||||
|
|
||||||
if (c == 'w' || c == 'W' || c == 0xF2) {
|
// Shift+W: page up
|
||||||
|
if (c == 'W') {
|
||||||
|
int pageSize = (128 - 14 - 14) / _prefs->smallLineH();
|
||||||
|
if (pageSize < 3) pageSize = 3;
|
||||||
|
_selectedFile = max(0, _selectedFile - pageSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (c == 'w' || c == 0xF2) {
|
||||||
if (_selectedFile > 0) { _selectedFile--; return true; }
|
if (_selectedFile > 0) { _selectedFile--; return true; }
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == 's' || c == 'S' || c == 0xF1) {
|
// Shift+S: page down
|
||||||
|
if (c == 'S') {
|
||||||
|
int pageSize = (128 - 14 - 14) / _prefs->smallLineH();
|
||||||
|
if (pageSize < 3) pageSize = 3;
|
||||||
|
_selectedFile = min(totalItems - 1, _selectedFile + pageSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (c == 's' || c == 0xF1) {
|
||||||
if (_selectedFile < totalItems - 1) { _selectedFile++; return true; }
|
if (_selectedFile < totalItems - 1) { _selectedFile++; return true; }
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,223 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// NotifSounds.h -- Per-channel notification sound configuration
|
||||||
|
//
|
||||||
|
// Stores a custom MP3 filename per channel for notification tones.
|
||||||
|
// Config persisted to /meshcore/notif_sounds.cfg on SD card.
|
||||||
|
// Sound files live in /alarms/ (shared with alarm clock sounds).
|
||||||
|
//
|
||||||
|
// Playback is request-based: UITask calls requestPlay() when a message
|
||||||
|
// arrives on a channel with a custom tone. main.cpp loop() polls
|
||||||
|
// hasPendingPlay() and drives the Audio* object.
|
||||||
|
//
|
||||||
|
// Guard: MECK_AUDIO_VARIANT (requires speaker hardware)
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
#ifdef MECK_AUDIO_VARIANT
|
||||||
|
|
||||||
|
#ifndef NOTIF_SOUNDS_H
|
||||||
|
#define NOTIF_SOUNDS_H
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <SD.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "variant.h"
|
||||||
|
|
||||||
|
#ifndef MAX_GROUP_CHANNELS
|
||||||
|
#define MAX_GROUP_CHANNELS 20
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NOTIF_SOUND_NAME_MAX 32
|
||||||
|
#define NOTIF_SOUND_SLOTS (MAX_GROUP_CHANNELS + 1) // +1 for DMs
|
||||||
|
#define NOTIF_SOUND_CONFIG_PATH "/meshcore/notif_sounds.cfg"
|
||||||
|
#define NOTIF_SOUND_MAGIC 0x4E534E44 // "NSND"
|
||||||
|
#define NOTIF_SOUND_VERSION 1
|
||||||
|
#ifndef ALARMS_FOLDER
|
||||||
|
#define ALARMS_FOLDER "/alarms"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct __attribute__((packed)) NotifSoundCfgHeader {
|
||||||
|
uint32_t magic;
|
||||||
|
uint8_t version;
|
||||||
|
uint8_t count; // Number of slots stored
|
||||||
|
uint8_t reserved[2];
|
||||||
|
// Followed by count * NOTIF_SOUND_NAME_MAX bytes
|
||||||
|
};
|
||||||
|
|
||||||
|
class NotifSounds {
|
||||||
|
public:
|
||||||
|
NotifSounds() : _pendingPlay(false) {
|
||||||
|
memset(_sounds, 0, sizeof(_sounds));
|
||||||
|
_pendingFile[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void begin() {
|
||||||
|
loadConfig();
|
||||||
|
Serial.println("NotifSounds: Config loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Config accessors ---
|
||||||
|
|
||||||
|
const char* getSoundForChannel(uint8_t channel_idx) const {
|
||||||
|
int slot = (channel_idx == 0xFF) ? MAX_GROUP_CHANNELS : (int)channel_idx;
|
||||||
|
if (slot < 0 || slot >= NOTIF_SOUND_SLOTS) return "";
|
||||||
|
return _sounds[slot];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasSoundForChannel(uint8_t channel_idx) const {
|
||||||
|
const char* s = getSoundForChannel(channel_idx);
|
||||||
|
return s && s[0] != '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSoundForChannel(uint8_t channel_idx, const char* filename) {
|
||||||
|
int slot = (channel_idx == 0xFF) ? MAX_GROUP_CHANNELS : (int)channel_idx;
|
||||||
|
if (slot < 0 || slot >= NOTIF_SOUND_SLOTS) return;
|
||||||
|
if (filename) {
|
||||||
|
strncpy(_sounds[slot], filename, NOTIF_SOUND_NAME_MAX - 1);
|
||||||
|
_sounds[slot][NOTIF_SOUND_NAME_MAX - 1] = '\0';
|
||||||
|
} else {
|
||||||
|
_sounds[slot][0] = '\0';
|
||||||
|
}
|
||||||
|
saveConfig();
|
||||||
|
Serial.printf("NotifSounds: Channel %d -> '%s'\n", (int)channel_idx,
|
||||||
|
_sounds[slot][0] ? _sounds[slot] : "(default)");
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearSoundForChannel(uint8_t channel_idx) {
|
||||||
|
setSoundForChannel(channel_idx, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Sound file scanning (reuses /alarms/ folder) ---
|
||||||
|
|
||||||
|
void scanSoundFiles() {
|
||||||
|
_soundFiles.clear();
|
||||||
|
if (!SD.exists(ALARMS_FOLDER)) {
|
||||||
|
SD.mkdir(ALARMS_FOLDER);
|
||||||
|
}
|
||||||
|
File root = SD.open(ALARMS_FOLDER);
|
||||||
|
if (!root || !root.isDirectory()) {
|
||||||
|
digitalWrite(SDCARD_CS, HIGH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
File entry = root.openNextFile();
|
||||||
|
while (entry) {
|
||||||
|
if (!entry.isDirectory()) {
|
||||||
|
String name = entry.name();
|
||||||
|
if (name.length() > 0 && name.charAt(0) != '.') {
|
||||||
|
String lower = name;
|
||||||
|
lower.toLowerCase();
|
||||||
|
if (lower.endsWith(".mp3")) {
|
||||||
|
_soundFiles.push_back(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry = root.openNextFile();
|
||||||
|
}
|
||||||
|
root.close();
|
||||||
|
digitalWrite(SDCARD_CS, HIGH);
|
||||||
|
std::sort(_soundFiles.begin(), _soundFiles.end());
|
||||||
|
Serial.printf("NotifSounds: Found %d sound files\n", (int)_soundFiles.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
int getSoundFileCount() const { return (int)_soundFiles.size(); }
|
||||||
|
const String& getSoundFile(int idx) const { return _soundFiles[idx]; }
|
||||||
|
const std::vector<String>& getSoundFiles() const { return _soundFiles; }
|
||||||
|
|
||||||
|
// --- Pending playback request ---
|
||||||
|
|
||||||
|
void requestPlay(const char* fullPath) {
|
||||||
|
strncpy(_pendingFile, fullPath, sizeof(_pendingFile) - 1);
|
||||||
|
_pendingFile[sizeof(_pendingFile) - 1] = '\0';
|
||||||
|
_pendingPlay = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasPendingPlay() const { return _pendingPlay; }
|
||||||
|
|
||||||
|
const char* getPendingFile() const { return _pendingFile; }
|
||||||
|
|
||||||
|
void clearPending() {
|
||||||
|
_pendingPlay = false;
|
||||||
|
_pendingFile[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
char _sounds[NOTIF_SOUND_SLOTS][NOTIF_SOUND_NAME_MAX];
|
||||||
|
std::vector<String> _soundFiles;
|
||||||
|
|
||||||
|
bool _pendingPlay;
|
||||||
|
char _pendingFile[48];
|
||||||
|
|
||||||
|
void loadConfig() {
|
||||||
|
memset(_sounds, 0, sizeof(_sounds));
|
||||||
|
|
||||||
|
if (!SD.exists(NOTIF_SOUND_CONFIG_PATH)) {
|
||||||
|
Serial.println("NotifSounds: No config file, using defaults");
|
||||||
|
digitalWrite(SDCARD_CS, HIGH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File f = SD.open(NOTIF_SOUND_CONFIG_PATH, "r");
|
||||||
|
if (!f) {
|
||||||
|
Serial.println("NotifSounds: Failed to open config");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NotifSoundCfgHeader hdr;
|
||||||
|
if (f.read((uint8_t*)&hdr, sizeof(hdr)) != sizeof(hdr) ||
|
||||||
|
hdr.magic != NOTIF_SOUND_MAGIC || hdr.version != NOTIF_SOUND_VERSION) {
|
||||||
|
Serial.println("NotifSounds: Config invalid or wrong version");
|
||||||
|
f.close();
|
||||||
|
digitalWrite(SDCARD_CS, HIGH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int slotsToRead = hdr.count;
|
||||||
|
if (slotsToRead > NOTIF_SOUND_SLOTS) slotsToRead = NOTIF_SOUND_SLOTS;
|
||||||
|
|
||||||
|
for (int i = 0; i < slotsToRead; i++) {
|
||||||
|
if (f.read((uint8_t*)_sounds[i], NOTIF_SOUND_NAME_MAX) != NOTIF_SOUND_NAME_MAX) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_sounds[i][NOTIF_SOUND_NAME_MAX - 1] = '\0'; // Safety null-terminate
|
||||||
|
}
|
||||||
|
|
||||||
|
f.close();
|
||||||
|
digitalWrite(SDCARD_CS, HIGH);
|
||||||
|
Serial.printf("NotifSounds: Loaded %d slots from config\n", slotsToRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveConfig() {
|
||||||
|
if (!SD.exists("/meshcore")) {
|
||||||
|
SD.mkdir("/meshcore");
|
||||||
|
}
|
||||||
|
|
||||||
|
File f = SD.open(NOTIF_SOUND_CONFIG_PATH, FILE_WRITE);
|
||||||
|
if (!f) {
|
||||||
|
Serial.println("NotifSounds: Failed to save config");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NotifSoundCfgHeader hdr;
|
||||||
|
hdr.magic = NOTIF_SOUND_MAGIC;
|
||||||
|
hdr.version = NOTIF_SOUND_VERSION;
|
||||||
|
hdr.count = NOTIF_SOUND_SLOTS;
|
||||||
|
hdr.reserved[0] = 0;
|
||||||
|
hdr.reserved[1] = 0;
|
||||||
|
f.write((uint8_t*)&hdr, sizeof(hdr));
|
||||||
|
|
||||||
|
for (int i = 0; i < NOTIF_SOUND_SLOTS; i++) {
|
||||||
|
f.write((uint8_t*)_sounds[i], NOTIF_SOUND_NAME_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
f.close();
|
||||||
|
digitalWrite(SDCARD_CS, HIGH);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Global singleton
|
||||||
|
extern NotifSounds notifSounds;
|
||||||
|
|
||||||
|
#endif // NOTIF_SOUNDS_H
|
||||||
|
#endif // MECK_AUDIO_VARIANT
|
||||||
@@ -7,6 +7,9 @@
|
|||||||
#include <MeshCore.h>
|
#include <MeshCore.h>
|
||||||
#include "../NodePrefs.h"
|
#include "../NodePrefs.h"
|
||||||
#include "MeckFonts.h"
|
#include "MeckFonts.h"
|
||||||
|
#ifdef MECK_AUDIO_VARIANT
|
||||||
|
#include "NotifSounds.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// Inline edit hint shown next to values being adjusted
|
// Inline edit hint shown next to values being adjusted
|
||||||
#if defined(LilyGo_T5S3_EPaper_Pro)
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
@@ -170,6 +173,7 @@ enum EditMode : uint8_t {
|
|||||||
EDIT_PICKER, // A/D cycles options (radio preset, contact mode)
|
EDIT_PICKER, // A/D cycles options (radio preset, contact mode)
|
||||||
EDIT_NUMBER, // W/S adjusts value (freq, BW, SF, CR, TX, UTC)
|
EDIT_NUMBER, // W/S adjusts value (freq, BW, SF, CR, TX, UTC)
|
||||||
EDIT_CONFIRM, // Confirmation dialog (delete channel, apply radio)
|
EDIT_CONFIRM, // Confirmation dialog (delete channel, apply radio)
|
||||||
|
EDIT_NOTIF_SOUND, // Sound picker for per-channel notification tone
|
||||||
#ifdef MECK_WIFI_COMPANION
|
#ifdef MECK_WIFI_COMPANION
|
||||||
EDIT_WIFI, // WiFi scan/select/password flow
|
EDIT_WIFI, // WiFi scan/select/password flow
|
||||||
#endif
|
#endif
|
||||||
@@ -252,6 +256,13 @@ private:
|
|||||||
uint8_t _fontPickerOriginal; // font style before edit (for cancel revert)
|
uint8_t _fontPickerOriginal; // font style before edit (for cancel revert)
|
||||||
int _confirmAction; // 0=none, 1=delete channel, 2=apply radio
|
int _confirmAction; // 0=none, 1=delete channel, 2=apply radio
|
||||||
|
|
||||||
|
// Notification sound picker state (audio variant only)
|
||||||
|
#ifdef MECK_AUDIO_VARIANT
|
||||||
|
int _notifSoundSelected; // Cursor in sound picker (0=default/silent, 1+=files)
|
||||||
|
int _notifSoundScroll; // Scroll offset in picker list
|
||||||
|
uint8_t _notifSoundChannel; // Channel index being edited
|
||||||
|
#endif
|
||||||
|
|
||||||
// Onboarding mode
|
// Onboarding mode
|
||||||
bool _onboarding;
|
bool _onboarding;
|
||||||
|
|
||||||
@@ -402,12 +413,16 @@ private:
|
|||||||
addRow(ROW_TX_POWER);
|
addRow(ROW_TX_POWER);
|
||||||
addRow(ROW_UTC_OFFSET);
|
addRow(ROW_UTC_OFFSET);
|
||||||
addRow(ROW_MSG_NOTIFY);
|
addRow(ROW_MSG_NOTIFY);
|
||||||
|
#if HAS_GPS
|
||||||
addRow(ROW_GPS_BAUD);
|
addRow(ROW_GPS_BAUD);
|
||||||
|
#endif
|
||||||
addRow(ROW_PATH_HASH_SIZE);
|
addRow(ROW_PATH_HASH_SIZE);
|
||||||
addRow(ROW_DEFAULT_SCOPE);
|
addRow(ROW_DEFAULT_SCOPE);
|
||||||
addRow(ROW_DARK_MODE);
|
addRow(ROW_DARK_MODE);
|
||||||
|
#if !defined(LILYGO_TECHO_LITE)
|
||||||
addRow(ROW_LARGE_FONT);
|
addRow(ROW_LARGE_FONT);
|
||||||
addRow(ROW_FONT_STYLE);
|
addRow(ROW_FONT_STYLE);
|
||||||
|
#endif
|
||||||
#if defined(LilyGo_T5S3_EPaper_Pro)
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
addRow(ROW_PORTRAIT_MODE);
|
addRow(ROW_PORTRAIT_MODE);
|
||||||
#endif
|
#endif
|
||||||
@@ -591,6 +606,11 @@ public:
|
|||||||
_fmError = nullptr;
|
_fmError = nullptr;
|
||||||
_dnsServer = nullptr;
|
_dnsServer = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MECK_AUDIO_VARIANT
|
||||||
|
_notifSoundSelected = 0;
|
||||||
|
_notifSoundScroll = 0;
|
||||||
|
_notifSoundChannel = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void enter() {
|
void enter() {
|
||||||
@@ -1926,15 +1946,33 @@ public:
|
|||||||
snprintf(tmp, sizeof(tmp), " %s [*]", ch.name);
|
snprintf(tmp, sizeof(tmp), " %s [*]", ch.name);
|
||||||
}
|
}
|
||||||
if (selected) {
|
if (selected) {
|
||||||
// Show edit/delete hints on right
|
// Build hint with notification state + actions
|
||||||
|
uint8_t nPref = _prefs->channel_notif[chIdx];
|
||||||
|
const char* nTag = (nPref == NOTIF_NONE) ? "Off" :
|
||||||
|
(nPref == NOTIF_MENTIONS) ? "@" : "All";
|
||||||
|
char hintBuf[40];
|
||||||
#if defined(LilyGo_T5S3_EPaper_Pro)
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
const char* hint = chIdx > 0 ? "Ent:Region Hold:Del" : "Ent:Region";
|
if (chIdx > 0) {
|
||||||
|
snprintf(hintBuf, sizeof(hintBuf), "Notif:%s Ent:Region Hold:Del", nTag);
|
||||||
|
} else {
|
||||||
|
snprintf(hintBuf, sizeof(hintBuf), "Notif:%s Ent:Region", nTag);
|
||||||
|
}
|
||||||
|
#elif defined(MECK_AUDIO_VARIANT)
|
||||||
|
if (chIdx > 0) {
|
||||||
|
snprintf(hintBuf, sizeof(hintBuf), "N:%s T:Tone X:Del", nTag);
|
||||||
|
} else {
|
||||||
|
snprintf(hintBuf, sizeof(hintBuf), "N:%s T:Tone Ent:Region", nTag);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
const char* hint = chIdx > 0 ? "Ent:Region X:Del" : "Ent:Region";
|
if (chIdx > 0) {
|
||||||
|
snprintf(hintBuf, sizeof(hintBuf), "N:%s Ent:Region X:Del", nTag);
|
||||||
|
} else {
|
||||||
|
snprintf(hintBuf, sizeof(hintBuf), "N:%s Ent:Region", nTag);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
int hintW = display.getTextWidth(hint);
|
int hintW = display.getTextWidth(hintBuf);
|
||||||
display.setCursor(display.width() - hintW - 2, y);
|
display.setCursor(display.width() - hintW - 2, y);
|
||||||
display.print(hint);
|
display.print(hintBuf);
|
||||||
display.setCursor(0, y);
|
display.setCursor(0, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2071,6 +2109,92 @@ public:
|
|||||||
display.setTextSize(1);
|
display.setTextSize(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// === Notification sound picker overlay (audio variant) ===
|
||||||
|
#ifdef MECK_AUDIO_VARIANT
|
||||||
|
if (_editMode == EDIT_NOTIF_SOUND) {
|
||||||
|
int bx = 2, by = 14, bw = display.width() - 4;
|
||||||
|
int bh = display.height() - 28;
|
||||||
|
display.setColor(DisplayDriver::DARK);
|
||||||
|
display.fillRect(bx, by, bw, bh);
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
display.drawRect(bx, by, bw, bh);
|
||||||
|
|
||||||
|
display.setTextSize(_prefs->smallTextSize());
|
||||||
|
int lineH = _prefs->smallLineH();
|
||||||
|
|
||||||
|
// Header
|
||||||
|
display.setColor(DisplayDriver::GREEN);
|
||||||
|
display.setCursor(bx + 4, by + 3);
|
||||||
|
display.print("Notification Tone");
|
||||||
|
|
||||||
|
int listTop = by + 14;
|
||||||
|
int listBot = by + bh - 14;
|
||||||
|
int maxVisible = (listBot - listTop) / lineH;
|
||||||
|
if (maxVisible < 3) maxVisible = 3;
|
||||||
|
|
||||||
|
// Total items: 1 ("Default") + sound file count
|
||||||
|
const auto& files = notifSounds.getSoundFiles();
|
||||||
|
int totalItems = 1 + (int)files.size();
|
||||||
|
|
||||||
|
// Centre scroll on selection
|
||||||
|
_notifSoundScroll = max(0, min(_notifSoundSelected - maxVisible / 2,
|
||||||
|
totalItems - maxVisible));
|
||||||
|
if (_notifSoundScroll < 0) _notifSoundScroll = 0;
|
||||||
|
int endIdx = min(totalItems, _notifSoundScroll + maxVisible);
|
||||||
|
|
||||||
|
int sy = listTop;
|
||||||
|
for (int i = _notifSoundScroll; i < endIdx && sy + lineH <= listBot; i++) {
|
||||||
|
bool isSel = (i == _notifSoundSelected);
|
||||||
|
|
||||||
|
if (isSel) {
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
display.fillRect(bx + 2, sy + _prefs->smallHighlightOff(), bw - 4, lineH);
|
||||||
|
display.setColor(DisplayDriver::DARK);
|
||||||
|
} else {
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
display.setCursor(bx + 6, sy);
|
||||||
|
if (i == 0) {
|
||||||
|
display.print("Default (silent)");
|
||||||
|
} else {
|
||||||
|
// Show MP3 filename without extension
|
||||||
|
String displayName = files[i - 1];
|
||||||
|
int dot = displayName.lastIndexOf('.');
|
||||||
|
if (dot > 0) displayName = displayName.substring(0, dot);
|
||||||
|
if (displayName.length() > 28) displayName = displayName.substring(0, 28);
|
||||||
|
display.print(displayName.c_str());
|
||||||
|
}
|
||||||
|
sy += lineH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Footer
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.setColor(DisplayDriver::YELLOW);
|
||||||
|
int fy = by + bh - 11;
|
||||||
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
|
display.setCursor(bx + 4, fy);
|
||||||
|
display.print("Tap:Pick Boot:Back");
|
||||||
|
#else
|
||||||
|
display.setCursor(bx + 4, fy);
|
||||||
|
display.print("Enter:Pick Q:Back");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Scroll indicator
|
||||||
|
if (totalItems > maxVisible) {
|
||||||
|
int sbX = bx + bw - 4;
|
||||||
|
int sbH = listBot - listTop;
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
display.drawRect(sbX, listTop, 3, sbH);
|
||||||
|
int thumbH = max(4, (maxVisible * sbH) / totalItems);
|
||||||
|
int maxScroll = totalItems - maxVisible;
|
||||||
|
if (maxScroll < 1) maxScroll = 1;
|
||||||
|
int thumbY = listTop + (_notifSoundScroll * (sbH - thumbH)) / maxScroll;
|
||||||
|
display.fillRect(sbX + 1, thumbY + 1, 1, thumbH - 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MECK_WIFI_COMPANION
|
#ifdef MECK_WIFI_COMPANION
|
||||||
// === WiFi setup overlay ===
|
// === WiFi setup overlay ===
|
||||||
if (_editMode == EDIT_WIFI) {
|
if (_editMode == EDIT_WIFI) {
|
||||||
@@ -2404,6 +2528,21 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
display.print("Editing...");
|
display.print("Editing...");
|
||||||
}
|
}
|
||||||
|
#elif defined(LILYGO_TECHO_LITE)
|
||||||
|
if (_editMode == EDIT_TEXT) {
|
||||||
|
display.print("Ent:Ok Q:Cancel");
|
||||||
|
} else if (_editMode == EDIT_PICKER) {
|
||||||
|
display.print("A/D:Pick Ent:Ok");
|
||||||
|
} else if (_editMode == EDIT_NUMBER) {
|
||||||
|
display.print("W/S:Adj Ent:Ok");
|
||||||
|
} else if (_editMode == EDIT_CONFIRM) {
|
||||||
|
// overlay handles it
|
||||||
|
} else {
|
||||||
|
display.print("Q:Bk");
|
||||||
|
const char* r = "Ent:Edit";
|
||||||
|
display.setCursor(display.width() - display.getTextWidth(r) - 2, footerY);
|
||||||
|
display.print(r);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
if (_editMode == EDIT_TEXT) {
|
if (_editMode == EDIT_TEXT) {
|
||||||
display.print("Type, Enter:Ok Q:Cancel");
|
display.print("Type, Enter:Ok Q:Cancel");
|
||||||
@@ -2517,6 +2656,41 @@ public:
|
|||||||
return true; // consume all keys in confirm mode
|
return true; // consume all keys in confirm mode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Notification sound picker (audio variant) ---
|
||||||
|
#ifdef MECK_AUDIO_VARIANT
|
||||||
|
if (_editMode == EDIT_NOTIF_SOUND) {
|
||||||
|
const auto& files = notifSounds.getSoundFiles();
|
||||||
|
int totalItems = 1 + (int)files.size(); // 0=Default, rest=files
|
||||||
|
|
||||||
|
if (c == 'w' || c == 'W' || c == 0xF2 || c == KEY_UP) {
|
||||||
|
if (_notifSoundSelected > 0) _notifSoundSelected--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (c == 's' || c == 'S' || c == 0xF1 || c == KEY_DOWN) {
|
||||||
|
if (_notifSoundSelected < totalItems - 1) _notifSoundSelected++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (c == '\r' || c == 13) {
|
||||||
|
// Select: 0 = clear (default silent), 1+ = file
|
||||||
|
if (_notifSoundSelected == 0) {
|
||||||
|
notifSounds.clearSoundForChannel(_notifSoundChannel);
|
||||||
|
} else {
|
||||||
|
int fileIdx = _notifSoundSelected - 1;
|
||||||
|
if (fileIdx >= 0 && fileIdx < (int)files.size()) {
|
||||||
|
notifSounds.setSoundForChannel(_notifSoundChannel, files[fileIdx].c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_editMode = EDIT_NONE;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (c == 'q' || c == 'Q' || c == '\b') {
|
||||||
|
_editMode = EDIT_NONE;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true; // consume all keys in picker mode
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MECK_OTA_UPDATE
|
#ifdef MECK_OTA_UPDATE
|
||||||
// --- OTA update flow ---
|
// --- OTA update flow ---
|
||||||
if (_editMode == EDIT_OTA) {
|
if (_editMode == EDIT_OTA) {
|
||||||
@@ -2795,9 +2969,11 @@ public:
|
|||||||
} else if (type == ROW_GPS_BAUD) {
|
} else if (type == ROW_GPS_BAUD) {
|
||||||
_editPickerIdx--;
|
_editPickerIdx--;
|
||||||
if (_editPickerIdx < 0) _editPickerIdx = GPS_BAUD_OPTION_COUNT - 1;
|
if (_editPickerIdx < 0) _editPickerIdx = GPS_BAUD_OPTION_COUNT - 1;
|
||||||
|
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LilyGo_TDeck_Pro)
|
||||||
} else if (type == ROW_AUTO_LOCK) {
|
} else if (type == ROW_AUTO_LOCK) {
|
||||||
_editPickerIdx--;
|
_editPickerIdx--;
|
||||||
if (_editPickerIdx < 0) _editPickerIdx = AUTO_LOCK_OPTION_COUNT - 1;
|
if (_editPickerIdx < 0) _editPickerIdx = AUTO_LOCK_OPTION_COUNT - 1;
|
||||||
|
#endif
|
||||||
} else if (type == ROW_FONT_STYLE) {
|
} else if (type == ROW_FONT_STYLE) {
|
||||||
_editPickerIdx--;
|
_editPickerIdx--;
|
||||||
if (_editPickerIdx < 0) _editPickerIdx = MECK_FONT_STYLE_COUNT - 1;
|
if (_editPickerIdx < 0) _editPickerIdx = MECK_FONT_STYLE_COUNT - 1;
|
||||||
@@ -2816,9 +2992,11 @@ public:
|
|||||||
} else if (type == ROW_GPS_BAUD) {
|
} else if (type == ROW_GPS_BAUD) {
|
||||||
_editPickerIdx++;
|
_editPickerIdx++;
|
||||||
if (_editPickerIdx >= GPS_BAUD_OPTION_COUNT) _editPickerIdx = 0;
|
if (_editPickerIdx >= GPS_BAUD_OPTION_COUNT) _editPickerIdx = 0;
|
||||||
|
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LilyGo_TDeck_Pro)
|
||||||
} else if (type == ROW_AUTO_LOCK) {
|
} else if (type == ROW_AUTO_LOCK) {
|
||||||
_editPickerIdx++;
|
_editPickerIdx++;
|
||||||
if (_editPickerIdx >= AUTO_LOCK_OPTION_COUNT) _editPickerIdx = 0;
|
if (_editPickerIdx >= AUTO_LOCK_OPTION_COUNT) _editPickerIdx = 0;
|
||||||
|
#endif
|
||||||
} else if (type == ROW_FONT_STYLE) {
|
} else if (type == ROW_FONT_STYLE) {
|
||||||
_editPickerIdx++;
|
_editPickerIdx++;
|
||||||
if (_editPickerIdx >= MECK_FONT_STYLE_COUNT) _editPickerIdx = 0;
|
if (_editPickerIdx >= MECK_FONT_STYLE_COUNT) _editPickerIdx = 0;
|
||||||
@@ -2840,12 +3018,14 @@ public:
|
|||||||
_editMode = EDIT_NONE;
|
_editMode = EDIT_NONE;
|
||||||
Serial.printf("Settings: GPS baud set to %lu (reboot to apply)\n",
|
Serial.printf("Settings: GPS baud set to %lu (reboot to apply)\n",
|
||||||
(unsigned long)_prefs->gps_baudrate);
|
(unsigned long)_prefs->gps_baudrate);
|
||||||
|
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LilyGo_TDeck_Pro)
|
||||||
} else if (type == ROW_AUTO_LOCK) {
|
} else if (type == ROW_AUTO_LOCK) {
|
||||||
_prefs->auto_lock_minutes = AUTO_LOCK_OPTIONS[_editPickerIdx];
|
_prefs->auto_lock_minutes = AUTO_LOCK_OPTIONS[_editPickerIdx];
|
||||||
the_mesh.savePrefs();
|
the_mesh.savePrefs();
|
||||||
_editMode = EDIT_NONE;
|
_editMode = EDIT_NONE;
|
||||||
Serial.printf("Settings: Auto lock = %s\n",
|
Serial.printf("Settings: Auto lock = %s\n",
|
||||||
autoLockLabel(_prefs->auto_lock_minutes));
|
autoLockLabel(_prefs->auto_lock_minutes));
|
||||||
|
#endif
|
||||||
} else if (type == ROW_FONT_STYLE) {
|
} else if (type == ROW_FONT_STYLE) {
|
||||||
_prefs->ui_font_style = _editPickerIdx;
|
_prefs->ui_font_style = _editPickerIdx;
|
||||||
the_mesh.savePrefs();
|
the_mesh.savePrefs();
|
||||||
@@ -2977,8 +3157,17 @@ public:
|
|||||||
|
|
||||||
// --- Normal browsing mode ---
|
// --- Normal browsing mode ---
|
||||||
|
|
||||||
// W/S: navigate
|
// W/S: navigate, Shift+W/S: page scroll
|
||||||
if (c == 'w' || c == 'W') {
|
if (c == 'W') {
|
||||||
|
// Shift+W: page up
|
||||||
|
int pageSize = (128 - 14 - 14) / _prefs->smallLineH();
|
||||||
|
if (pageSize < 3) pageSize = 3;
|
||||||
|
_cursor = max(0, _cursor - pageSize);
|
||||||
|
skipNonSelectable(-1);
|
||||||
|
Serial.printf("Settings: page up cursor=%d/%d\n", _cursor, _numRows);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (c == 'w') {
|
||||||
if (_cursor > 0) {
|
if (_cursor > 0) {
|
||||||
_cursor--;
|
_cursor--;
|
||||||
skipNonSelectable(-1);
|
skipNonSelectable(-1);
|
||||||
@@ -2986,7 +3175,16 @@ public:
|
|||||||
Serial.printf("Settings: cursor=%d/%d row=%d\n", _cursor, _numRows, _rows[_cursor].type);
|
Serial.printf("Settings: cursor=%d/%d row=%d\n", _cursor, _numRows, _rows[_cursor].type);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (c == 's' || c == 'S') {
|
if (c == 'S') {
|
||||||
|
// Shift+S: page down
|
||||||
|
int pageSize = (128 - 14 - 14) / _prefs->smallLineH();
|
||||||
|
if (pageSize < 3) pageSize = 3;
|
||||||
|
_cursor = min(_numRows - 1, _cursor + pageSize);
|
||||||
|
skipNonSelectable(1);
|
||||||
|
Serial.printf("Settings: page down cursor=%d/%d\n", _cursor, _numRows);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (c == 's') {
|
||||||
if (_cursor < _numRows - 1) {
|
if (_cursor < _numRows - 1) {
|
||||||
_cursor++;
|
_cursor++;
|
||||||
skipNonSelectable(1);
|
skipNonSelectable(1);
|
||||||
@@ -3243,6 +3441,45 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// N: cycle notification preference (All -> Mentions -> None -> All)
|
||||||
|
if (c == 'n' || c == 'N') {
|
||||||
|
if (_rows[_cursor].type == ROW_CHANNEL) {
|
||||||
|
uint8_t chIdx = _rows[_cursor].param;
|
||||||
|
uint8_t cur = _prefs->channel_notif[chIdx];
|
||||||
|
_prefs->channel_notif[chIdx] = (cur + 1) % 3;
|
||||||
|
the_mesh.savePrefs();
|
||||||
|
const char* labels[] = {"All", "Mentions", "Off"};
|
||||||
|
Serial.printf("Settings: Channel %d notif -> %s\n",
|
||||||
|
chIdx, labels[_prefs->channel_notif[chIdx]]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// T: open notification tone picker (audio variant only)
|
||||||
|
#ifdef MECK_AUDIO_VARIANT
|
||||||
|
if (c == 't' || c == 'T') {
|
||||||
|
if (_rows[_cursor].type == ROW_CHANNEL) {
|
||||||
|
_notifSoundChannel = _rows[_cursor].param;
|
||||||
|
notifSounds.scanSoundFiles();
|
||||||
|
_notifSoundSelected = 0; // 0 = "Default (silent)"
|
||||||
|
_notifSoundScroll = 0;
|
||||||
|
// Pre-select current assignment
|
||||||
|
const char* current = notifSounds.getSoundForChannel(_notifSoundChannel);
|
||||||
|
if (current && current[0] != '\0') {
|
||||||
|
const auto& files = notifSounds.getSoundFiles();
|
||||||
|
for (int i = 0; i < (int)files.size(); i++) {
|
||||||
|
if (files[i] == String(current)) {
|
||||||
|
_notifSoundSelected = i + 1; // +1 because 0 is "Default"
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_editMode = EDIT_NOTIF_SOUND;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Q: back -- if in sub-screen, return to top level; else exit settings
|
// Q: back -- if in sub-screen, return to top level; else exit settings
|
||||||
if (c == 'q' || c == 'Q') {
|
if (c == 'q' || c == 'Q') {
|
||||||
if (_subScreen != SUB_NONE) {
|
if (_subScreen != SUB_NONE) {
|
||||||
|
|||||||
@@ -1123,10 +1123,9 @@ private:
|
|||||||
display.fillRect(0, y, display.width(), listLineH);
|
display.fillRect(0, y, display.width(), listLineH);
|
||||||
#else
|
#else
|
||||||
// setCursor adds +5 to y internally, but fillRect does not.
|
// setCursor adds +5 to y internally, but fillRect does not.
|
||||||
// Built-in font: offset by +5 to align with top-left positioned text.
|
// NodePrefs::smallHighlightOff() returns the correct offset for all
|
||||||
// GFX fonts (large_font or custom style): offset by -2 to cover ascenders above baseline.
|
// font combinations (built-in, large_font, custom 7pt styles).
|
||||||
int hlOff = (!_prefs->large_font && display.getFontStyle() > 0) ? -2 : _prefs->smallHighlightOff();
|
display.fillRect(0, y + _prefs->smallHighlightOff(), display.width(), listLineH);
|
||||||
display.fillRect(0, y + hlOff, display.width(), listLineH);
|
|
||||||
#endif
|
#endif
|
||||||
display.setColor(DisplayDriver::DARK);
|
display.setColor(DisplayDriver::DARK);
|
||||||
} else {
|
} else {
|
||||||
@@ -1759,7 +1758,7 @@ public:
|
|||||||
#if defined(LilyGo_T5S3_EPaper_Pro)
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
const int bodyTop = startY;
|
const int bodyTop = startY;
|
||||||
#else
|
#else
|
||||||
const int bodyTop = startY + ((_prefs && !_prefs->large_font && _prefs->ui_font_style > 0) ? -2 : (_prefs ? _prefs->smallHighlightOff() : 5));
|
const int bodyTop = startY + (_prefs ? _prefs->smallHighlightOff() : 5);
|
||||||
#endif
|
#endif
|
||||||
if (vy < bodyTop || vy >= 128 - footerH) return 0;
|
if (vy < bodyTop || vy >= 128 - footerH) return 0;
|
||||||
|
|
||||||
@@ -1812,8 +1811,15 @@ public:
|
|||||||
bool handleFileListInput(char c) {
|
bool handleFileListInput(char c) {
|
||||||
int total = totalListItems();
|
int total = totalListItems();
|
||||||
|
|
||||||
|
// Shift+W: page up
|
||||||
|
if (c == 'W') {
|
||||||
|
int pageSize = (128 - 14 - 14) / _prefs->smallLineH();
|
||||||
|
if (pageSize < 3) pageSize = 3;
|
||||||
|
_selectedFile = max(0, _selectedFile - pageSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// W - scroll up
|
// W - scroll up
|
||||||
if (c == 'w' || c == 'W' || c == 0xF2) {
|
if (c == 'w' || c == 0xF2) {
|
||||||
if (_selectedFile > 0) {
|
if (_selectedFile > 0) {
|
||||||
_selectedFile--;
|
_selectedFile--;
|
||||||
return true;
|
return true;
|
||||||
@@ -1821,8 +1827,15 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shift+S: page down
|
||||||
|
if (c == 'S') {
|
||||||
|
int pageSize = (128 - 14 - 14) / _prefs->smallLineH();
|
||||||
|
if (pageSize < 3) pageSize = 3;
|
||||||
|
_selectedFile = min(total - 1, _selectedFile + pageSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// S - scroll down
|
// S - scroll down
|
||||||
if (c == 's' || c == 'S' || c == 0xF1) {
|
if (c == 's' || c == 0xF1) {
|
||||||
if (_selectedFile < total - 1) {
|
if (_selectedFile < total - 1) {
|
||||||
_selectedFile++;
|
_selectedFile++;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -0,0 +1,988 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <helpers/ui/UIScreen.h>
|
||||||
|
#include <helpers/ui/DisplayDriver.h>
|
||||||
|
#include <MeshCore.h>
|
||||||
|
#include <Packet.h>
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
class UITask;
|
||||||
|
class MyMesh;
|
||||||
|
extern MyMesh the_mesh;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// TraceScreen
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Standalone trace path tool for the T-Deck Pro. The user builds a repeater
|
||||||
|
// chain from the contacts list or by typing comma-separated hash values, sends
|
||||||
|
// a PAYLOAD_TYPE_TRACE packet direct-routed through the chain, and views
|
||||||
|
// per-hop SNR results.
|
||||||
|
//
|
||||||
|
// Path size (1-byte or 2-byte hashes) follows the device's path_hash_mode
|
||||||
|
// setting but can be toggled on this screen.
|
||||||
|
//
|
||||||
|
// The trace packet is created via Mesh::createTrace() and sent via
|
||||||
|
// Mesh::sendDirect(). Each repeater in the chain checks if its pub_key
|
||||||
|
// prefix matches the next hash in the payload; if so, it appends its receive
|
||||||
|
// SNR*4 to the packet's path field and forwards. When the packet reaches
|
||||||
|
// the end of its given path, onTraceRecv() fires on the receiving node.
|
||||||
|
//
|
||||||
|
// For round-trip traces the user should build a symmetric path
|
||||||
|
// (e.g. A,B,C,B,A) and must be able to hear the last repeater directly.
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define TRACE_MAX_HOPS 16
|
||||||
|
#define TRACE_TIMEOUT_MS 30000 // 30 second timeout
|
||||||
|
#define TRACE_EDIT_BUF 80 // Max chars for typed path
|
||||||
|
|
||||||
|
class TraceScreen : public UIScreen {
|
||||||
|
public:
|
||||||
|
enum ScreenState {
|
||||||
|
STATE_BUILD, // Building the path
|
||||||
|
STATE_PICK_HOP, // Picking a repeater from contacts
|
||||||
|
STATE_RUNNING, // Trace sent, waiting for response
|
||||||
|
STATE_RESULTS // Showing results
|
||||||
|
};
|
||||||
|
|
||||||
|
// Trace result data (filled by onTraceResult callback)
|
||||||
|
struct TraceResult {
|
||||||
|
uint8_t hashes[TRACE_MAX_HOPS * 2]; // Hash bytes (1 or 2 per hop)
|
||||||
|
int8_t snrs[TRACE_MAX_HOPS]; // SNR*4 per hop
|
||||||
|
int8_t final_snr; // SNR of the response arriving back
|
||||||
|
int hopCount; // Number of hops that responded
|
||||||
|
int totalHops; // Total hops in the path
|
||||||
|
uint32_t duration_ms; // Round-trip time
|
||||||
|
bool valid;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
UITask* _task;
|
||||||
|
mesh::RTCClock* _rtc;
|
||||||
|
|
||||||
|
ScreenState _state;
|
||||||
|
|
||||||
|
// Path being built
|
||||||
|
uint8_t _pathBuf[TRACE_MAX_HOPS * 2]; // Hash bytes (max 2 bytes per hop)
|
||||||
|
int _hopCount;
|
||||||
|
int _bytesPerHop; // 1 or 2
|
||||||
|
|
||||||
|
// Menu navigation (STATE_BUILD)
|
||||||
|
int _menuSel;
|
||||||
|
|
||||||
|
// Inline text editor (for Type Path)
|
||||||
|
bool _editing;
|
||||||
|
char _editBuf[TRACE_EDIT_BUF];
|
||||||
|
int _editPos;
|
||||||
|
|
||||||
|
// Repeater picker (STATE_PICK_HOP)
|
||||||
|
static const int MAX_REPEATERS = 200;
|
||||||
|
uint16_t* _repIdx; // Indices into contact table (PSRAM)
|
||||||
|
int _repCount;
|
||||||
|
int _repSel;
|
||||||
|
int _repScroll;
|
||||||
|
|
||||||
|
// Trace state (STATE_RUNNING / STATE_RESULTS)
|
||||||
|
uint32_t _traceTag;
|
||||||
|
uint32_t _traceAuth;
|
||||||
|
unsigned long _traceSentAt;
|
||||||
|
TraceResult _result;
|
||||||
|
|
||||||
|
// Results scroll
|
||||||
|
int _resultScroll;
|
||||||
|
|
||||||
|
bool _wantExit;
|
||||||
|
|
||||||
|
// --- Menu helpers (STATE_BUILD) ---
|
||||||
|
// Menu layout:
|
||||||
|
// 0: Mode selector (1-byte / 2-byte)
|
||||||
|
// 1: Type Path (inline text editor)
|
||||||
|
// 2..hopCount+1: each hop
|
||||||
|
// next: + Add repeater (if < TRACE_MAX_HOPS)
|
||||||
|
// next: Remove last (if hopCount > 0)
|
||||||
|
// next: Run Trace (if hopCount > 0)
|
||||||
|
// last: Exit
|
||||||
|
enum MenuItem {
|
||||||
|
MENU_PATH_SIZE = 0,
|
||||||
|
MENU_TYPE_PATH = 1,
|
||||||
|
MENU_HOP_BASE = 2,
|
||||||
|
MENU_ADD_HOP = 200,
|
||||||
|
MENU_REMOVE_LAST,
|
||||||
|
MENU_RUN_TRACE,
|
||||||
|
MENU_EXIT
|
||||||
|
};
|
||||||
|
|
||||||
|
int buildMenuCount() const {
|
||||||
|
int count = 2; // Mode + Type Path
|
||||||
|
count += _hopCount;
|
||||||
|
if (_hopCount < TRACE_MAX_HOPS) count++; // Add hop
|
||||||
|
if (_hopCount > 0) count++; // Remove last
|
||||||
|
if (_hopCount > 0) count++; // Run Trace
|
||||||
|
count++; // Exit
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem menuItemAt(int idx) const {
|
||||||
|
if (idx == 0) return MENU_PATH_SIZE;
|
||||||
|
if (idx == 1) return MENU_TYPE_PATH;
|
||||||
|
int pos = 2;
|
||||||
|
for (int h = 0; h < _hopCount; h++) {
|
||||||
|
if (idx == pos) return (MenuItem)(MENU_HOP_BASE + h);
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
if (_hopCount < TRACE_MAX_HOPS) {
|
||||||
|
if (idx == pos) return MENU_ADD_HOP;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
if (_hopCount > 0) {
|
||||||
|
if (idx == pos) return MENU_REMOVE_LAST;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
if (_hopCount > 0) {
|
||||||
|
if (idx == pos) return MENU_RUN_TRACE;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
return MENU_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build repeater list from contacts
|
||||||
|
void buildRepeaterList() {
|
||||||
|
_repCount = 0;
|
||||||
|
uint32_t numContacts = the_mesh.getNumContacts();
|
||||||
|
ContactInfo c;
|
||||||
|
for (uint32_t i = 0; i < numContacts && _repCount < MAX_REPEATERS; i++) {
|
||||||
|
if (the_mesh.getContactByIdx(i, c)) {
|
||||||
|
if (c.type == ADV_TYPE_REPEATER) {
|
||||||
|
_repIdx[_repCount++] = (uint16_t)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look up contact name from hash prefix
|
||||||
|
bool findNameForHash(const uint8_t* hash, int hashLen, char* name, size_t nameLen) const {
|
||||||
|
uint32_t numContacts = the_mesh.getNumContacts();
|
||||||
|
ContactInfo c;
|
||||||
|
// First pass: repeaters only
|
||||||
|
for (uint32_t i = 0; i < numContacts; i++) {
|
||||||
|
if (the_mesh.getContactByIdx(i, c) && c.type == ADV_TYPE_REPEATER) {
|
||||||
|
if (memcmp(c.id.pub_key, hash, hashLen) == 0) {
|
||||||
|
strncpy(name, c.name, nameLen);
|
||||||
|
name[nameLen - 1] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Second pass: any contact
|
||||||
|
for (uint32_t i = 0; i < numContacts; i++) {
|
||||||
|
if (the_mesh.getContactByIdx(i, c)) {
|
||||||
|
if (memcmp(c.id.pub_key, hash, hashLen) == 0) {
|
||||||
|
strncpy(name, c.name, nameLen);
|
||||||
|
name[nameLen - 1] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse comma-separated decimal values from edit buffer into path
|
||||||
|
// Returns number of hops parsed, or -1 on error
|
||||||
|
int parseTypedPath() {
|
||||||
|
if (_editBuf[0] == '\0') return 0;
|
||||||
|
|
||||||
|
uint8_t tmpPath[TRACE_MAX_HOPS * 2];
|
||||||
|
int hops = 0;
|
||||||
|
const char* p = _editBuf;
|
||||||
|
|
||||||
|
while (*p && hops < TRACE_MAX_HOPS) {
|
||||||
|
// Skip whitespace/commas
|
||||||
|
while (*p == ',' || *p == ' ') p++;
|
||||||
|
if (*p == '\0') break;
|
||||||
|
|
||||||
|
// Parse hex number (companion app uses hex hash values)
|
||||||
|
char* end;
|
||||||
|
long val = strtol(p, &end, 16);
|
||||||
|
if (end == p) return -1; // No digits found
|
||||||
|
p = end;
|
||||||
|
|
||||||
|
if (_bytesPerHop == 1) {
|
||||||
|
if (val < 0 || val > 255) return -1;
|
||||||
|
tmpPath[hops] = (uint8_t)val;
|
||||||
|
} else {
|
||||||
|
if (val < 0 || val > 65535) return -1;
|
||||||
|
// Big-endian storage: hash display = (pub_key[0] << 8) | pub_key[1]
|
||||||
|
// So val >> 8 is pub_key[0], val & 0xFF is pub_key[1]
|
||||||
|
tmpPath[hops * 2] = (uint8_t)((val >> 8) & 0xFF);
|
||||||
|
tmpPath[hops * 2 + 1] = (uint8_t)(val & 0xFF);
|
||||||
|
}
|
||||||
|
hops++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hops > 0) {
|
||||||
|
memcpy(_pathBuf, tmpPath, hops * _bytesPerHop);
|
||||||
|
_hopCount = hops;
|
||||||
|
}
|
||||||
|
return hops;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build display string from current path (for showing in edit field)
|
||||||
|
void pathToEditBuf() {
|
||||||
|
_editBuf[0] = '\0';
|
||||||
|
_editPos = 0;
|
||||||
|
for (int i = 0; i < _hopCount; i++) {
|
||||||
|
char tmp[8];
|
||||||
|
if (_bytesPerHop == 1) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "%02X", _pathBuf[i]);
|
||||||
|
} else {
|
||||||
|
uint16_t val = ((uint16_t)_pathBuf[i * 2] << 8) | _pathBuf[i * 2 + 1];
|
||||||
|
snprintf(tmp, sizeof(tmp), "%04X", val);
|
||||||
|
}
|
||||||
|
if (i > 0) {
|
||||||
|
if (_editPos < TRACE_EDIT_BUF - 1) _editBuf[_editPos++] = ',';
|
||||||
|
}
|
||||||
|
int tlen = strlen(tmp);
|
||||||
|
if (_editPos + tlen < TRACE_EDIT_BUF - 1) {
|
||||||
|
memcpy(&_editBuf[_editPos], tmp, tlen);
|
||||||
|
_editPos += tlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_editBuf[_editPos] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truncate long names to maxLen chars + "..." for display
|
||||||
|
static void truncateName(char* name, int maxLen = 10) {
|
||||||
|
if ((int)strlen(name) > maxLen) {
|
||||||
|
name[maxLen] = '\0';
|
||||||
|
// Remove trailing space before ellipsis
|
||||||
|
while (maxLen > 0 && name[maxLen - 1] == ' ') {
|
||||||
|
name[--maxLen] = '\0';
|
||||||
|
}
|
||||||
|
strcat(name, "...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw signal bars (3 bars) based on SNR
|
||||||
|
void drawSignalBars(DisplayDriver& display, int x, int y, int8_t snr4) {
|
||||||
|
float snr = snr4 / 4.0f;
|
||||||
|
// 3 bars: low >= -5, mid >= 3, high >= 8
|
||||||
|
int bars = 0;
|
||||||
|
if (snr >= -5.0f) bars = 1;
|
||||||
|
if (snr >= 3.0f) bars = 2;
|
||||||
|
if (snr >= 8.0f) bars = 3;
|
||||||
|
|
||||||
|
int barW = 3;
|
||||||
|
int gap = 1;
|
||||||
|
int heights[] = { 4, 7, 10 };
|
||||||
|
for (int b = 0; b < 3; b++) {
|
||||||
|
int bx = x + b * (barW + gap);
|
||||||
|
int by = y + 10 - heights[b];
|
||||||
|
if (b < bars) {
|
||||||
|
display.setColor(DisplayDriver::GREEN);
|
||||||
|
} else {
|
||||||
|
display.setColor(DisplayDriver::DARK);
|
||||||
|
}
|
||||||
|
display.fillRect(bx, by, barW, heights[b]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
TraceScreen(UITask* task, mesh::RTCClock* rtc)
|
||||||
|
: _task(task), _rtc(rtc), _state(STATE_BUILD),
|
||||||
|
_hopCount(0), _bytesPerHop(2),
|
||||||
|
_menuSel(0), _editing(false), _editPos(0),
|
||||||
|
_repCount(0), _repSel(0), _repScroll(0),
|
||||||
|
_traceTag(0), _traceAuth(0), _traceSentAt(0),
|
||||||
|
_resultScroll(0), _wantExit(false) {
|
||||||
|
memset(_pathBuf, 0, sizeof(_pathBuf));
|
||||||
|
memset(_editBuf, 0, sizeof(_editBuf));
|
||||||
|
memset(&_result, 0, sizeof(_result));
|
||||||
|
#if defined(ESP32) && defined(BOARD_HAS_PSRAM)
|
||||||
|
_repIdx = (uint16_t*)ps_calloc(MAX_REPEATERS, sizeof(uint16_t));
|
||||||
|
#else
|
||||||
|
_repIdx = new uint16_t[MAX_REPEATERS]();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wantsExit() const { return _wantExit; }
|
||||||
|
bool isEditing() const { return _editing; }
|
||||||
|
|
||||||
|
// --- Public helpers for T5S3 long-press → virtual keyboard integration ---
|
||||||
|
|
||||||
|
// True if the highlighted menu row is the Type Path entry (STATE_BUILD only).
|
||||||
|
bool isOnTypePathRow() const {
|
||||||
|
return _state == STATE_BUILD && menuItemAt(_menuSel) == MENU_TYPE_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the current path formatted as a comma-separated string, suitable
|
||||||
|
// for pre-populating an external text editor (e.g. the T5S3 virtual keyboard).
|
||||||
|
// The returned pointer references an internal buffer and is valid until the
|
||||||
|
// next call to this method or to setTypedPath()/parseTypedPath().
|
||||||
|
const char* getCurrentPathAsText() {
|
||||||
|
pathToEditBuf();
|
||||||
|
return _editBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply a path typed externally (via virtual keyboard submission).
|
||||||
|
// Replaces the working path buffer with whatever parses out of `text`
|
||||||
|
// and ensures the inline editor flag is cleared so the menu redraws cleanly.
|
||||||
|
void setTypedPath(const char* text) {
|
||||||
|
if (!text) return;
|
||||||
|
strncpy(_editBuf, text, sizeof(_editBuf) - 1);
|
||||||
|
_editBuf[sizeof(_editBuf) - 1] = '\0';
|
||||||
|
parseTypedPath();
|
||||||
|
_editing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void enter(int pathHashMode) {
|
||||||
|
_state = STATE_BUILD;
|
||||||
|
_hopCount = 0;
|
||||||
|
_menuSel = 0;
|
||||||
|
_editing = false;
|
||||||
|
_editPos = 0;
|
||||||
|
memset(_editBuf, 0, sizeof(_editBuf));
|
||||||
|
_repSel = 0;
|
||||||
|
_repScroll = 0;
|
||||||
|
_wantExit = false;
|
||||||
|
_resultScroll = 0;
|
||||||
|
memset(_pathBuf, 0, sizeof(_pathBuf));
|
||||||
|
memset(&_result, 0, sizeof(_result));
|
||||||
|
|
||||||
|
// Default to device path hash mode (clamped to 1 or 2 for trace)
|
||||||
|
_bytesPerHop = (pathHashMode >= 1) ? 2 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by MyMesh::onTraceRecv() via UITask
|
||||||
|
void onTraceResult(uint32_t tag, uint8_t flags,
|
||||||
|
const uint8_t* path_snrs, const uint8_t* path_hashes,
|
||||||
|
uint8_t path_byte_len, int8_t final_snr) {
|
||||||
|
if (_state != STATE_RUNNING) return;
|
||||||
|
if (tag != _traceTag) return; // Not our trace
|
||||||
|
|
||||||
|
uint8_t pathSz = flags & 0x03;
|
||||||
|
int numHops = (pathSz > 0) ? (path_byte_len >> pathSz) : path_byte_len;
|
||||||
|
|
||||||
|
_result.valid = true;
|
||||||
|
_result.totalHops = numHops;
|
||||||
|
_result.final_snr = final_snr;
|
||||||
|
_result.duration_ms = millis() - _traceSentAt;
|
||||||
|
|
||||||
|
// Copy hash data
|
||||||
|
int copyBytes = path_byte_len;
|
||||||
|
if (copyBytes > (int)sizeof(_result.hashes)) copyBytes = sizeof(_result.hashes);
|
||||||
|
memcpy(_result.hashes, path_hashes, copyBytes);
|
||||||
|
|
||||||
|
// Count SNR entries (= number of hops that actually forwarded)
|
||||||
|
int snrCount = numHops;
|
||||||
|
if (snrCount > TRACE_MAX_HOPS) snrCount = TRACE_MAX_HOPS;
|
||||||
|
_result.hopCount = snrCount;
|
||||||
|
for (int i = 0; i < snrCount; i++) {
|
||||||
|
_result.snrs[i] = (int8_t)path_snrs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
_state = STATE_RESULTS;
|
||||||
|
_resultScroll = 0;
|
||||||
|
Serial.printf("[Trace] Result received: %d hops, %dms\n", numHops, _result.duration_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Render ---
|
||||||
|
int render(DisplayDriver& display) override {
|
||||||
|
// Header
|
||||||
|
display.setCursor(0, 0);
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.setColor(DisplayDriver::GREEN);
|
||||||
|
display.print("Trace Path");
|
||||||
|
display.drawRect(0, 11, display.width(), 1);
|
||||||
|
|
||||||
|
if (_state == STATE_BUILD) {
|
||||||
|
return renderBuild(display);
|
||||||
|
} else if (_state == STATE_PICK_HOP) {
|
||||||
|
return renderPicker(display);
|
||||||
|
} else if (_state == STATE_RUNNING) {
|
||||||
|
return renderRunning(display);
|
||||||
|
} else {
|
||||||
|
return renderResults(display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int renderBuild(DisplayDriver& display) {
|
||||||
|
char tmp[TRACE_EDIT_BUF + 16];
|
||||||
|
int y = 14;
|
||||||
|
int lineH = 11;
|
||||||
|
int menuCount = buildMenuCount();
|
||||||
|
int maxVisible = (display.height() - y - 14) / lineH;
|
||||||
|
if (maxVisible < 1) maxVisible = 1;
|
||||||
|
|
||||||
|
// Scroll window
|
||||||
|
int scrollTop = 0;
|
||||||
|
if (_menuSel >= scrollTop + maxVisible) scrollTop = _menuSel - maxVisible + 1;
|
||||||
|
if (_menuSel < scrollTop) scrollTop = _menuSel;
|
||||||
|
|
||||||
|
for (int vi = 0; vi < maxVisible && (scrollTop + vi) < menuCount; vi++) {
|
||||||
|
int idx = scrollTop + vi;
|
||||||
|
MenuItem item = menuItemAt(idx);
|
||||||
|
char prefix = (idx == _menuSel) ? '>' : ' ';
|
||||||
|
|
||||||
|
display.setCursor(0, y);
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
|
||||||
|
switch (item) {
|
||||||
|
case MENU_PATH_SIZE:
|
||||||
|
snprintf(tmp, sizeof(tmp), "%c Mode: %d-byte", prefix, _bytesPerHop);
|
||||||
|
display.print(tmp);
|
||||||
|
if (idx == _menuSel) {
|
||||||
|
const char* hint = "(A/D)";
|
||||||
|
display.setCursor(display.width() - display.getTextWidth(hint) - 4, y);
|
||||||
|
display.print(hint);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MENU_TYPE_PATH:
|
||||||
|
if (_editing) {
|
||||||
|
// Active text editor with cursor
|
||||||
|
display.setColor(DisplayDriver::GREEN);
|
||||||
|
snprintf(tmp, sizeof(tmp), " Path: %s_", _editBuf);
|
||||||
|
display.print(tmp);
|
||||||
|
} else if (_hopCount > 0) {
|
||||||
|
// Show current path as decimal values
|
||||||
|
char pathStr[TRACE_EDIT_BUF];
|
||||||
|
pathStr[0] = '\0';
|
||||||
|
int pos = 0;
|
||||||
|
for (int i = 0; i < _hopCount && pos < (int)sizeof(pathStr) - 8; i++) {
|
||||||
|
if (i > 0) pathStr[pos++] = ',';
|
||||||
|
if (_bytesPerHop == 1) {
|
||||||
|
pos += snprintf(&pathStr[pos], sizeof(pathStr) - pos, "%02X", _pathBuf[i]);
|
||||||
|
} else {
|
||||||
|
uint16_t val = ((uint16_t)_pathBuf[i * 2] << 8) | _pathBuf[i * 2 + 1];
|
||||||
|
pos += snprintf(&pathStr[pos], sizeof(pathStr) - pos, "%04X", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snprintf(tmp, sizeof(tmp), "%c Path: %s", prefix, pathStr);
|
||||||
|
display.print(tmp);
|
||||||
|
} else {
|
||||||
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
|
snprintf(tmp, sizeof(tmp), "%c Type Path: [Long press]", prefix);
|
||||||
|
#else
|
||||||
|
snprintf(tmp, sizeof(tmp), "%c Type Path: [Press Enter]", prefix);
|
||||||
|
#endif
|
||||||
|
display.print(tmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MENU_ADD_HOP:
|
||||||
|
display.setColor(DisplayDriver::GREEN);
|
||||||
|
snprintf(tmp, sizeof(tmp), "%c + Add repeater...", prefix);
|
||||||
|
display.print(tmp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MENU_REMOVE_LAST:
|
||||||
|
snprintf(tmp, sizeof(tmp), "%c - Remove last", prefix);
|
||||||
|
display.print(tmp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MENU_RUN_TRACE:
|
||||||
|
display.setColor(DisplayDriver::YELLOW);
|
||||||
|
snprintf(tmp, sizeof(tmp), "%c Run Trace", prefix);
|
||||||
|
display.print(tmp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MENU_EXIT:
|
||||||
|
snprintf(tmp, sizeof(tmp), "%c Exit", prefix);
|
||||||
|
display.print(tmp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Hop line
|
||||||
|
if (item >= MENU_HOP_BASE && item < MENU_HOP_BASE + TRACE_MAX_HOPS) {
|
||||||
|
int hopIdx = item - MENU_HOP_BASE;
|
||||||
|
int offset = hopIdx * _bytesPerHop;
|
||||||
|
char hopName[24];
|
||||||
|
uint16_t hashVal;
|
||||||
|
if (_bytesPerHop == 1) {
|
||||||
|
hashVal = _pathBuf[offset];
|
||||||
|
} else {
|
||||||
|
hashVal = ((uint16_t)_pathBuf[offset] << 8) | _pathBuf[offset + 1];
|
||||||
|
}
|
||||||
|
if (findNameForHash(&_pathBuf[offset], _bytesPerHop, hopName, sizeof(hopName))) {
|
||||||
|
truncateName(hopName);
|
||||||
|
display.setColor(DisplayDriver::GREEN);
|
||||||
|
snprintf(tmp, sizeof(tmp), "%c%d: %s (%X)", prefix, hopIdx + 1,
|
||||||
|
hopName, hashVal);
|
||||||
|
} else {
|
||||||
|
snprintf(tmp, sizeof(tmp), "%c%d: (%X)", prefix, hopIdx + 1, hashVal);
|
||||||
|
}
|
||||||
|
display.print(tmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
y += lineH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Footer
|
||||||
|
int footerY = display.height() - 12;
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.drawRect(0, footerY - 2, display.width(), 1);
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
display.setCursor(0, footerY);
|
||||||
|
if (_editing) {
|
||||||
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
|
display.print("Boot:Cancel Tap:Apply");
|
||||||
|
#else
|
||||||
|
display.print("Q:Cancel Enter:Apply");
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
|
display.print("Boot:Exit Tap:Sel");
|
||||||
|
#else
|
||||||
|
display.print("Q:Exit W/S:Nav Ent:Sel");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return 5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
int renderPicker(DisplayDriver& display) {
|
||||||
|
char tmp[48];
|
||||||
|
int y = 14;
|
||||||
|
int lineH = 11;
|
||||||
|
int maxVisible = (display.height() - y - 14) / lineH;
|
||||||
|
if (maxVisible < 1) maxVisible = 1;
|
||||||
|
|
||||||
|
if (_repCount == 0) {
|
||||||
|
display.setCursor(0, y);
|
||||||
|
display.setColor(DisplayDriver::RED);
|
||||||
|
display.print("No repeaters in contacts");
|
||||||
|
y += lineH;
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
display.print("Press Q to go back");
|
||||||
|
} else {
|
||||||
|
// Clamp scroll
|
||||||
|
if (_repSel >= _repCount) _repSel = _repCount - 1;
|
||||||
|
if (_repSel < 0) _repSel = 0;
|
||||||
|
if (_repSel < _repScroll) _repScroll = _repSel;
|
||||||
|
if (_repSel >= _repScroll + maxVisible) _repScroll = _repSel - maxVisible + 1;
|
||||||
|
|
||||||
|
for (int vi = 0; vi < maxVisible && (_repScroll + vi) < _repCount; vi++) {
|
||||||
|
int idx = _repScroll + vi;
|
||||||
|
uint16_t contactIdx = _repIdx[idx];
|
||||||
|
ContactInfo c;
|
||||||
|
if (!the_mesh.getContactByIdx(contactIdx, c)) continue;
|
||||||
|
|
||||||
|
char prefix = (idx == _repSel) ? '>' : ' ';
|
||||||
|
display.setCursor(0, y);
|
||||||
|
|
||||||
|
// Show name + decimal hash value
|
||||||
|
char filteredName[24];
|
||||||
|
display.translateUTF8ToBlocks(filteredName, c.name, sizeof(filteredName));
|
||||||
|
truncateName(filteredName, 14); // Picker has more room
|
||||||
|
uint16_t hashVal;
|
||||||
|
if (_bytesPerHop == 1) {
|
||||||
|
hashVal = c.id.pub_key[0];
|
||||||
|
} else {
|
||||||
|
hashVal = ((uint16_t)c.id.pub_key[0] << 8) | c.id.pub_key[1];
|
||||||
|
}
|
||||||
|
snprintf(tmp, sizeof(tmp), "%c %s (%X)", prefix, filteredName, hashVal);
|
||||||
|
display.setColor((idx == _repSel) ? DisplayDriver::GREEN : DisplayDriver::LIGHT);
|
||||||
|
display.print(tmp);
|
||||||
|
y += lineH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Footer
|
||||||
|
int footerY = display.height() - 12;
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.drawRect(0, footerY - 2, display.width(), 1);
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
display.setCursor(0, footerY);
|
||||||
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
|
display.print("Boot:Back Tap:Add");
|
||||||
|
#else
|
||||||
|
display.print("Q:Back W/S:Scroll Ent:Add");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
int renderRunning(DisplayDriver& display) {
|
||||||
|
int y = 14;
|
||||||
|
display.setColor(DisplayDriver::YELLOW);
|
||||||
|
display.setCursor(0, y);
|
||||||
|
display.print("Tracing...");
|
||||||
|
y += 14;
|
||||||
|
|
||||||
|
// Show path summary
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
char tmp[48];
|
||||||
|
snprintf(tmp, sizeof(tmp), "%d hops, %d-byte mode", _hopCount, _bytesPerHop);
|
||||||
|
display.setCursor(0, y);
|
||||||
|
display.print(tmp);
|
||||||
|
y += 14;
|
||||||
|
|
||||||
|
// Elapsed time
|
||||||
|
unsigned long elapsed = millis() - _traceSentAt;
|
||||||
|
snprintf(tmp, sizeof(tmp), "Elapsed: %lu ms", elapsed);
|
||||||
|
display.setCursor(0, y);
|
||||||
|
display.print(tmp);
|
||||||
|
y += 14;
|
||||||
|
|
||||||
|
// Timeout bar
|
||||||
|
int barW = display.width() - 20;
|
||||||
|
int barH = 4;
|
||||||
|
int barX = 10;
|
||||||
|
display.setColor(DisplayDriver::DARK);
|
||||||
|
display.drawRect(barX, y, barW, barH);
|
||||||
|
int fill = (int)((unsigned long)barW * elapsed / TRACE_TIMEOUT_MS);
|
||||||
|
if (fill > barW) fill = barW;
|
||||||
|
display.setColor(DisplayDriver::GREEN);
|
||||||
|
display.fillRect(barX, y, fill, barH);
|
||||||
|
|
||||||
|
// Check timeout
|
||||||
|
if (elapsed >= TRACE_TIMEOUT_MS) {
|
||||||
|
_state = STATE_RESULTS;
|
||||||
|
_result.valid = false;
|
||||||
|
_result.duration_ms = TRACE_TIMEOUT_MS;
|
||||||
|
Serial.println("[Trace] Timeout");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Footer
|
||||||
|
int footerY = display.height() - 12;
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.drawRect(0, footerY - 2, display.width(), 1);
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
display.setCursor(0, footerY);
|
||||||
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
|
display.print("Boot:Cancel");
|
||||||
|
#else
|
||||||
|
display.print("Q:Cancel");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 500; // Fast refresh for elapsed timer
|
||||||
|
}
|
||||||
|
|
||||||
|
int renderResults(DisplayDriver& display) {
|
||||||
|
char tmp[48];
|
||||||
|
int y = 14;
|
||||||
|
int lineH = 12;
|
||||||
|
|
||||||
|
if (!_result.valid) {
|
||||||
|
display.setColor(DisplayDriver::RED);
|
||||||
|
display.setCursor(0, y);
|
||||||
|
display.print("Trace timed out");
|
||||||
|
y += lineH;
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
snprintf(tmp, sizeof(tmp), "No response after %ds", TRACE_TIMEOUT_MS / 1000);
|
||||||
|
display.setCursor(0, y);
|
||||||
|
display.print(tmp);
|
||||||
|
} else {
|
||||||
|
// Duration header
|
||||||
|
display.setColor(DisplayDriver::GREEN);
|
||||||
|
snprintf(tmp, sizeof(tmp), "Complete: %dms", (int)_result.duration_ms);
|
||||||
|
display.setCursor(0, y);
|
||||||
|
display.print(tmp);
|
||||||
|
y += lineH + 2;
|
||||||
|
|
||||||
|
int maxVisible = (display.height() - y - 14) / lineH;
|
||||||
|
if (maxVisible < 1) maxVisible = 1;
|
||||||
|
|
||||||
|
// Clamp scroll
|
||||||
|
int totalItems = _result.hopCount + 1; // hops + final SNR line
|
||||||
|
if (_resultScroll > totalItems - maxVisible) _resultScroll = totalItems - maxVisible;
|
||||||
|
if (_resultScroll < 0) _resultScroll = 0;
|
||||||
|
|
||||||
|
for (int vi = 0; vi < maxVisible && (_resultScroll + vi) < totalItems; vi++) {
|
||||||
|
int idx = _resultScroll + vi;
|
||||||
|
display.setCursor(0, y);
|
||||||
|
|
||||||
|
if (idx < _result.hopCount) {
|
||||||
|
// Hop entry
|
||||||
|
int offset = idx * _bytesPerHop;
|
||||||
|
char hopName[20];
|
||||||
|
bool resolved = findNameForHash(&_result.hashes[offset], _bytesPerHop,
|
||||||
|
hopName, sizeof(hopName));
|
||||||
|
if (resolved) truncateName(hopName);
|
||||||
|
|
||||||
|
float snr = _result.snrs[idx] / 4.0f;
|
||||||
|
|
||||||
|
display.setColor(resolved ? DisplayDriver::GREEN : DisplayDriver::LIGHT);
|
||||||
|
if (resolved) {
|
||||||
|
snprintf(tmp, sizeof(tmp), "%d: %s", idx + 1, hopName);
|
||||||
|
} else {
|
||||||
|
uint16_t hashVal;
|
||||||
|
if (_bytesPerHop == 1) {
|
||||||
|
hashVal = _result.hashes[offset];
|
||||||
|
} else {
|
||||||
|
hashVal = ((uint16_t)_result.hashes[offset] << 8) | _result.hashes[offset + 1];
|
||||||
|
}
|
||||||
|
snprintf(tmp, sizeof(tmp), "%d: (%X)", idx + 1, hashVal);
|
||||||
|
}
|
||||||
|
display.print(tmp);
|
||||||
|
|
||||||
|
// SNR value on right
|
||||||
|
snprintf(tmp, sizeof(tmp), "%.1fdB", snr);
|
||||||
|
int snrW = display.getTextWidth(tmp);
|
||||||
|
int barsW = 14;
|
||||||
|
display.setCursor(display.width() - snrW - barsW - 4, y);
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
display.print(tmp);
|
||||||
|
|
||||||
|
// Signal bars
|
||||||
|
drawSignalBars(display, display.width() - barsW - 1, y, _result.snrs[idx]);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Final SNR (response arriving back at this node)
|
||||||
|
float snr = _result.final_snr / 4.0f;
|
||||||
|
display.setColor(DisplayDriver::YELLOW);
|
||||||
|
snprintf(tmp, sizeof(tmp), "Return SNR: %.1fdB", snr);
|
||||||
|
display.print(tmp);
|
||||||
|
drawSignalBars(display, display.width() - 15, y, _result.final_snr);
|
||||||
|
}
|
||||||
|
y += lineH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Footer
|
||||||
|
int footerY = display.height() - 12;
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.drawRect(0, footerY - 2, display.width(), 1);
|
||||||
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
display.setCursor(0, footerY);
|
||||||
|
#if defined(LilyGo_T5S3_EPaper_Pro)
|
||||||
|
display.print("Boot:Back Tap:New Trace");
|
||||||
|
#else
|
||||||
|
display.print("Q:Back Ent:New Trace");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// --- Input handling ---
|
||||||
|
bool handleInput(char c) override {
|
||||||
|
// Text editing mode consumes all keys
|
||||||
|
if (_editing) {
|
||||||
|
return handleEditInput(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (_state) {
|
||||||
|
case STATE_BUILD: return handleBuildInput(c);
|
||||||
|
case STATE_PICK_HOP: return handlePickerInput(c);
|
||||||
|
case STATE_RUNNING: return handleRunningInput(c);
|
||||||
|
case STATE_RESULTS: return handleResultsInput(c);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// --- Text editor for typed path ---
|
||||||
|
bool handleEditInput(char c) {
|
||||||
|
// Enter: apply typed path
|
||||||
|
if (c == '\r' || c == 13) {
|
||||||
|
int parsed = parseTypedPath();
|
||||||
|
if (parsed < 0) {
|
||||||
|
Serial.println("[Trace] Failed to parse typed path");
|
||||||
|
// Stay in edit mode -- user can fix
|
||||||
|
} else {
|
||||||
|
Serial.printf("[Trace] Parsed %d hops from typed path\n", parsed);
|
||||||
|
_editing = false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Q or Escape: cancel edit
|
||||||
|
if (c == 'q' || c == 'Q' || c == 27) {
|
||||||
|
_editing = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Backspace
|
||||||
|
if (c == '\b') {
|
||||||
|
if (_editPos > 0) {
|
||||||
|
_editPos--;
|
||||||
|
_editBuf[_editPos] = '\0';
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Accept hex digits, commas, spaces
|
||||||
|
if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')
|
||||||
|
|| c == ',' || c == ' ') {
|
||||||
|
if (_editPos < TRACE_EDIT_BUF - 1) {
|
||||||
|
_editBuf[_editPos++] = c;
|
||||||
|
_editBuf[_editPos] = '\0';
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true; // Consume all keys in edit mode
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handleBuildInput(char c) {
|
||||||
|
int menuCount = buildMenuCount();
|
||||||
|
|
||||||
|
// W - up
|
||||||
|
if (c == 'w' || c == 'W' || c == 0xF2) {
|
||||||
|
if (_menuSel > 0) _menuSel--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// S - down
|
||||||
|
if (c == 's' || c == 'S' || c == 0xF1) {
|
||||||
|
if (_menuSel < menuCount - 1) _menuSel++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// A/D - toggle mode on path size row
|
||||||
|
if ((c == 'a' || c == 'A' || c == 'd' || c == 'D') && menuItemAt(_menuSel) == MENU_PATH_SIZE) {
|
||||||
|
_bytesPerHop = (_bytesPerHop == 1) ? 2 : 1;
|
||||||
|
// Changing mode clears path (byte layout is different)
|
||||||
|
_hopCount = 0;
|
||||||
|
memset(_pathBuf, 0, sizeof(_pathBuf));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Q - exit
|
||||||
|
if (c == 'q' || c == 'Q' || c == '\b') {
|
||||||
|
_wantExit = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Enter - select
|
||||||
|
if (c == '\r' || c == 13) {
|
||||||
|
MenuItem item = menuItemAt(_menuSel);
|
||||||
|
switch (item) {
|
||||||
|
case MENU_TYPE_PATH:
|
||||||
|
// Enter edit mode -- pre-fill with current path if any
|
||||||
|
pathToEditBuf();
|
||||||
|
_editing = true;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MENU_ADD_HOP:
|
||||||
|
buildRepeaterList();
|
||||||
|
_repSel = 0;
|
||||||
|
_repScroll = 0;
|
||||||
|
_state = STATE_PICK_HOP;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MENU_REMOVE_LAST:
|
||||||
|
if (_hopCount > 0) {
|
||||||
|
_hopCount--;
|
||||||
|
if (_menuSel >= buildMenuCount()) _menuSel = buildMenuCount() - 1;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MENU_RUN_TRACE:
|
||||||
|
return sendTrace();
|
||||||
|
|
||||||
|
case MENU_EXIT:
|
||||||
|
_wantExit = true;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handlePickerInput(char c) {
|
||||||
|
// W - up
|
||||||
|
if (c == 'w' || c == 'W' || c == 0xF2) {
|
||||||
|
if (_repSel > 0) _repSel--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// S - down
|
||||||
|
if (c == 's' || c == 'S' || c == 0xF1) {
|
||||||
|
if (_repSel < _repCount - 1) _repSel++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Q - back to build
|
||||||
|
if (c == 'q' || c == 'Q' || c == '\b') {
|
||||||
|
_state = STATE_BUILD;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Enter - add selected repeater
|
||||||
|
if (c == '\r' || c == 13) {
|
||||||
|
if (_repCount > 0 && _repSel >= 0 && _repSel < _repCount) {
|
||||||
|
ContactInfo contact;
|
||||||
|
if (the_mesh.getContactByIdx(_repIdx[_repSel], contact)) {
|
||||||
|
int offset = _hopCount * _bytesPerHop;
|
||||||
|
memcpy(&_pathBuf[offset], contact.id.pub_key, _bytesPerHop);
|
||||||
|
_hopCount++;
|
||||||
|
uint16_t hashVal = ((uint16_t)contact.id.pub_key[0] << 8)
|
||||||
|
| contact.id.pub_key[1];
|
||||||
|
Serial.printf("[Trace] Added hop %d: %s (%X)\n",
|
||||||
|
_hopCount, contact.name, hashVal);
|
||||||
|
}
|
||||||
|
_state = STATE_BUILD;
|
||||||
|
_menuSel = _hopCount + 1; // Point to row after last hop
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handleRunningInput(char c) {
|
||||||
|
// Q - cancel
|
||||||
|
if (c == 'q' || c == 'Q' || c == '\b') {
|
||||||
|
_state = STATE_BUILD;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true; // Consume all keys while running
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handleResultsInput(char c) {
|
||||||
|
// W - scroll up
|
||||||
|
if (c == 'w' || c == 'W' || c == 0xF2) {
|
||||||
|
if (_resultScroll > 0) _resultScroll--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// S - scroll down
|
||||||
|
if (c == 's' || c == 'S' || c == 0xF1) {
|
||||||
|
_resultScroll++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Q - back to build screen (keep path)
|
||||||
|
if (c == 'q' || c == 'Q' || c == '\b') {
|
||||||
|
_state = STATE_BUILD;
|
||||||
|
_menuSel = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Enter - new trace (re-run with same path)
|
||||||
|
if (c == '\r' || c == 13) {
|
||||||
|
return sendTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Send trace ---
|
||||||
|
bool sendTrace() {
|
||||||
|
if (_hopCount <= 0) return true;
|
||||||
|
|
||||||
|
// Generate random tag and auth code
|
||||||
|
the_mesh.getRNG()->random((uint8_t*)&_traceTag, 4);
|
||||||
|
the_mesh.getRNG()->random((uint8_t*)&_traceAuth, 4);
|
||||||
|
|
||||||
|
// flags: lower 2 bits = path_sz
|
||||||
|
// path_sz 0 = 1-byte hashes, path_sz 1 = 2-byte hashes
|
||||||
|
uint8_t pathSz = (_bytesPerHop == 2) ? 1 : 0;
|
||||||
|
uint8_t flags = pathSz;
|
||||||
|
|
||||||
|
mesh::Packet* pkt = the_mesh.createTrace(_traceTag, _traceAuth, flags);
|
||||||
|
if (!pkt) {
|
||||||
|
Serial.println("[Trace] Failed to create trace packet (pool empty)");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Path bytes to send
|
||||||
|
uint8_t pathByteLen = _hopCount * _bytesPerHop;
|
||||||
|
|
||||||
|
// sendDirect for TRACE appends path to payload and sets path_len=0
|
||||||
|
the_mesh.sendDirect(pkt, _pathBuf, pathByteLen);
|
||||||
|
|
||||||
|
_traceSentAt = millis();
|
||||||
|
_state = STATE_RUNNING;
|
||||||
|
memset(&_result, 0, sizeof(_result));
|
||||||
|
|
||||||
|
Serial.printf("[Trace] Sent: tag=0x%08X, %d hops, %d-byte, %d path bytes\n",
|
||||||
|
_traceTag, _hopCount, _bytesPerHop, pathByteLen);
|
||||||
|
Serial.printf("[Trace] Path hex:");
|
||||||
|
for (int i = 0; i < pathByteLen; i++) {
|
||||||
|
Serial.printf(" %02X", _pathBuf[i]);
|
||||||
|
}
|
||||||
|
Serial.println();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -66,6 +66,7 @@ class UITask : public AbstractUITask {
|
|||||||
int _msgcount;
|
int _msgcount;
|
||||||
unsigned long ui_started_at, next_batt_chck;
|
unsigned long ui_started_at, next_batt_chck;
|
||||||
uint8_t _low_batt_count = 0; // Consecutive low-voltage readings for debounce
|
uint8_t _low_batt_count = 0; // Consecutive low-voltage readings for debounce
|
||||||
|
bool _full_poweroff = false; // True = BQ25896 BATFET disconnect (USB-C wake only)
|
||||||
int next_backlight_btn_check = 0;
|
int next_backlight_btn_check = 0;
|
||||||
#ifdef PIN_STATUS_LED
|
#ifdef PIN_STATUS_LED
|
||||||
int led_state = 0;
|
int led_state = 0;
|
||||||
@@ -98,6 +99,7 @@ class UITask : public AbstractUITask {
|
|||||||
UIScreen* path_editor; // Custom path editor screen (lazy-init)
|
UIScreen* path_editor; // Custom path editor screen (lazy-init)
|
||||||
UIScreen* discovery_screen; // Node discovery scan screen
|
UIScreen* discovery_screen; // Node discovery scan screen
|
||||||
UIScreen* last_heard_screen; // Last heard passive advert list
|
UIScreen* last_heard_screen; // Last heard passive advert list
|
||||||
|
UIScreen* trace_screen; // Trace path screen (standalone trace tool)
|
||||||
#ifdef MECK_WEB_READER
|
#ifdef MECK_WEB_READER
|
||||||
UIScreen* web_reader; // Web reader screen (lazy-init, WiFi required)
|
UIScreen* web_reader; // Web reader screen (lazy-init, WiFi required)
|
||||||
#endif
|
#endif
|
||||||
@@ -199,6 +201,7 @@ public:
|
|||||||
void gotoPathEditor(int contactIdx); // Navigate to custom path editor
|
void gotoPathEditor(int contactIdx); // Navigate to custom path editor
|
||||||
void gotoDiscoveryScreen(); // Navigate to node discovery scan
|
void gotoDiscoveryScreen(); // Navigate to node discovery scan
|
||||||
void gotoLastHeardScreen(); // Navigate to last heard passive list
|
void gotoLastHeardScreen(); // Navigate to last heard passive list
|
||||||
|
void gotoTraceScreen(); // Navigate to trace path screen
|
||||||
#if HAS_GPS
|
#if HAS_GPS
|
||||||
void gotoMapScreen(); // Navigate to map tile screen
|
void gotoMapScreen(); // Navigate to map tile screen
|
||||||
#endif
|
#endif
|
||||||
@@ -215,6 +218,8 @@ public:
|
|||||||
void showBootHint(bool immediate = false); // Show navigation hint overlay on first boot
|
void showBootHint(bool immediate = false); // Show navigation hint overlay on first boot
|
||||||
void dismissBootHint(); // Dismiss hint and save preference
|
void dismissBootHint(); // Dismiss hint and save preference
|
||||||
bool isHintActive() const { return _hintActive; }
|
bool isHintActive() const { return _hintActive; }
|
||||||
|
// BQ25896 BATFET disconnect -- true power off, USB-C required to wake
|
||||||
|
void setFullPowerOff(bool v) { _full_poweroff = v; }
|
||||||
// Wake display and extend auto-off timer. Call this when handling keys
|
// Wake display and extend auto-off timer. Call this when handling keys
|
||||||
// outside of injectKey() to prevent display auto-off during direct input.
|
// outside of injectKey() to prevent display auto-off during direct input.
|
||||||
void keepAlive() {
|
void keepAlive() {
|
||||||
@@ -253,6 +258,7 @@ public:
|
|||||||
bool isOnPathEditor() const { return curr == path_editor; }
|
bool isOnPathEditor() const { return curr == path_editor; }
|
||||||
bool isOnDiscoveryScreen() const { return curr == discovery_screen; }
|
bool isOnDiscoveryScreen() const { return curr == discovery_screen; }
|
||||||
bool isOnLastHeardScreen() const { return curr == last_heard_screen; }
|
bool isOnLastHeardScreen() const { return curr == last_heard_screen; }
|
||||||
|
bool isOnTraceScreen() const { return curr == trace_screen; }
|
||||||
bool isOnMapScreen() const { return curr == map_screen; }
|
bool isOnMapScreen() const { return curr == map_screen; }
|
||||||
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LilyGo_TDeck_Pro)
|
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LilyGo_TDeck_Pro)
|
||||||
bool isLocked() const { return _locked; }
|
bool isLocked() const { return _locked; }
|
||||||
@@ -291,6 +297,7 @@ public:
|
|||||||
bool isEditingHomeScreen() const;
|
bool isEditingHomeScreen() const;
|
||||||
// Check if home screen is showing the Recent Adverts page
|
// Check if home screen is showing the Recent Adverts page
|
||||||
bool isHomeOnRecentPage() const;
|
bool isHomeOnRecentPage() const;
|
||||||
|
bool isHomeOnShutdownPage() const;
|
||||||
|
|
||||||
// Inject a key press from external source (e.g., keyboard)
|
// Inject a key press from external source (e.g., keyboard)
|
||||||
void injectKey(char c);
|
void injectKey(char c);
|
||||||
@@ -301,11 +308,17 @@ public:
|
|||||||
|
|
||||||
// Mark channel as read when BLE companion app syncs messages
|
// Mark channel as read when BLE companion app syncs messages
|
||||||
void markChannelReadFromBLE(uint8_t channel_idx) override;
|
void markChannelReadFromBLE(uint8_t channel_idx) override;
|
||||||
|
// Mark all channels + DMs as read (companion app connected)
|
||||||
|
void markAllChannelsRead() override;
|
||||||
|
|
||||||
// Repeater admin callbacks
|
// Repeater admin callbacks
|
||||||
void onAdminLoginResult(bool success, uint8_t permissions, uint32_t server_time) override;
|
void onAdminLoginResult(bool success, uint8_t permissions, uint32_t server_time) override;
|
||||||
void onAdminCliResponse(const char* from_name, const char* text) override;
|
void onAdminCliResponse(const char* from_name, const char* text) override;
|
||||||
void onAdminTelemetryResult(const uint8_t* data, uint8_t len) override;
|
void onAdminTelemetryResult(const uint8_t* data, uint8_t len) override;
|
||||||
|
|
||||||
|
// Trace path callback (from MyMesh::onTraceRecv)
|
||||||
|
void onTraceResult(uint32_t tag, uint8_t flags, const uint8_t* path_snrs,
|
||||||
|
const uint8_t* path_hashes, uint8_t path_len, int8_t final_snr) override;
|
||||||
|
|
||||||
// Get current screen for checking state
|
// Get current screen for checking state
|
||||||
UIScreen* getCurrentScreen() const { return curr; }
|
UIScreen* getCurrentScreen() const { return curr; }
|
||||||
@@ -319,6 +332,7 @@ public:
|
|||||||
NodePrefs* getNodePrefs() const { return _node_prefs; }
|
NodePrefs* getNodePrefs() const { return _node_prefs; }
|
||||||
UIScreen* getAudiobookScreen() const { return audiobook_screen; }
|
UIScreen* getAudiobookScreen() const { return audiobook_screen; }
|
||||||
void setAudiobookScreen(UIScreen* s) { audiobook_screen = s; }
|
void setAudiobookScreen(UIScreen* s) { audiobook_screen = s; }
|
||||||
|
void setHomeScreen(UIScreen* s) { if (home) delete home; home = s; }
|
||||||
#ifdef MECK_AUDIO_VARIANT
|
#ifdef MECK_AUDIO_VARIANT
|
||||||
UIScreen* getAlarmScreen() const { return alarm_screen; }
|
UIScreen* getAlarmScreen() const { return alarm_screen; }
|
||||||
void setAlarmScreen(UIScreen* s) { alarm_screen = s; }
|
void setAlarmScreen(UIScreen* s) { alarm_screen = s; }
|
||||||
@@ -329,6 +343,7 @@ public:
|
|||||||
UIScreen* getPathEditorScreen() const { return path_editor; }
|
UIScreen* getPathEditorScreen() const { return path_editor; }
|
||||||
UIScreen* getDiscoveryScreen() const { return discovery_screen; }
|
UIScreen* getDiscoveryScreen() const { return discovery_screen; }
|
||||||
UIScreen* getLastHeardScreen() const { return last_heard_screen; }
|
UIScreen* getLastHeardScreen() const { return last_heard_screen; }
|
||||||
|
UIScreen* getTraceScreen() const { return trace_screen; }
|
||||||
UIScreen* getMapScreen() const { return map_screen; }
|
UIScreen* getMapScreen() const { return map_screen; }
|
||||||
#ifdef MECK_WEB_READER
|
#ifdef MECK_WEB_READER
|
||||||
UIScreen* getWebReaderScreen() const { return web_reader; }
|
UIScreen* getWebReaderScreen() const { return web_reader; }
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ static const char* EMOJI_LABELS[EMOJI_COUNT] = {
|
|||||||
"HFC", // 73 passport_control
|
"HFC", // 73 passport_control
|
||||||
"Star", // 74 eight_spoked_asterisk
|
"Star", // 74 eight_spoked_asterisk
|
||||||
"Sig", // 75 signal_strength
|
"Sig", // 75 signal_strength
|
||||||
|
"Beer", // 76 beer
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EmojiPicker {
|
struct EmojiPicker {
|
||||||
|
|||||||
@@ -1,310 +0,0 @@
|
|||||||
#ifndef MONTSERRATBOLD12PT7B_H
|
|
||||||
#define MONTSERRATBOLD12PT7B_H
|
|
||||||
const uint8_t Montserrat_Bold12pt7bBitmaps[] PROGMEM = {
|
|
||||||
0x00, 0xFF, 0xFF, 0xF7, 0x39, 0xCE, 0x73, 0x9C, 0x00, 0x3B, 0xFF, 0x70,
|
|
||||||
0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x07, 0x1C, 0x03, 0x8E, 0x01,
|
|
||||||
0xC7, 0x00, 0xE3, 0x87, 0xFF, 0xFB, 0xFF, 0xFD, 0xFF, 0xFE, 0x1C, 0x30,
|
|
||||||
0x0E, 0x38, 0x07, 0x1C, 0x03, 0x8E, 0x1F, 0xFF, 0xEF, 0xFF, 0xF0, 0x61,
|
|
||||||
0xC0, 0x70, 0xC0, 0x38, 0x60, 0x1C, 0x70, 0x00, 0x03, 0x00, 0x0C, 0x00,
|
|
||||||
0x30, 0x07, 0xF8, 0x3F, 0xF9, 0xFF, 0xCF, 0xB3, 0x3C, 0xC0, 0xF3, 0x03,
|
|
||||||
0xEC, 0x07, 0xF8, 0x0F, 0xFC, 0x1F, 0xF8, 0x0F, 0xE0, 0x37, 0xC0, 0xCF,
|
|
||||||
0xE3, 0x7B, 0xFF, 0xEF, 0xFF, 0x0F, 0xF8, 0x03, 0x00, 0x0C, 0x00, 0x30,
|
|
||||||
0x00, 0x3C, 0x03, 0x0F, 0xC0, 0xE3, 0x9C, 0x38, 0x63, 0x86, 0x0C, 0x31,
|
|
||||||
0xC1, 0x8E, 0x70, 0x31, 0xCC, 0x07, 0xF3, 0x80, 0x7C, 0xE7, 0x80, 0x39,
|
|
||||||
0xF8, 0x07, 0x73, 0x81, 0xCE, 0x30, 0x71, 0x86, 0x0E, 0x38, 0xC3, 0x87,
|
|
||||||
0x38, 0xE0, 0x7F, 0x1C, 0x07, 0xC0, 0x0F, 0xC0, 0x1F, 0xE0, 0x3F, 0xF0,
|
|
||||||
0x38, 0x70, 0x38, 0x70, 0x3C, 0xF0, 0x1F, 0xE0, 0x1F, 0xC0, 0x3F, 0x88,
|
|
||||||
0x7F, 0xCE, 0xF1, 0xEE, 0xF0, 0xFE, 0xF0, 0x7C, 0xF0, 0x7C, 0xFF, 0xFE,
|
|
||||||
0x7F, 0xFE, 0x1F, 0xC6, 0xFF, 0xFF, 0xF8, 0x1C, 0xF7, 0x9E, 0x73, 0xCF,
|
|
||||||
0x3C, 0xF3, 0x8E, 0x38, 0xE3, 0x8F, 0x3C, 0xF3, 0xC7, 0x1E, 0x38, 0xF1,
|
|
||||||
0xC0, 0xF0, 0xF1, 0xE1, 0xE3, 0xC7, 0x87, 0x0F, 0x1E, 0x3C, 0x78, 0xF1,
|
|
||||||
0xE3, 0xC7, 0x8F, 0x1C, 0x78, 0xF1, 0xC7, 0x8F, 0x3C, 0x00, 0x0C, 0x03,
|
|
||||||
0x06, 0xDF, 0xFF, 0x3F, 0x0F, 0xEF, 0xFD, 0xB2, 0x0C, 0x03, 0x00, 0x07,
|
|
||||||
0x00, 0x70, 0x07, 0x00, 0x70, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x70, 0x07,
|
|
||||||
0x00, 0x70, 0x07, 0x00, 0xFF, 0xFF, 0x76, 0xEE, 0xFF, 0xFF, 0xF8, 0xFF,
|
|
||||||
0xFF, 0x00, 0xE0, 0x1C, 0x07, 0x80, 0xE0, 0x3C, 0x07, 0x00, 0xE0, 0x3C,
|
|
||||||
0x07, 0x00, 0xE0, 0x3C, 0x07, 0x00, 0xE0, 0x3C, 0x07, 0x00, 0xE0, 0x3C,
|
|
||||||
0x07, 0x00, 0xE0, 0x3C, 0x07, 0x00, 0xE0, 0x00, 0x0F, 0xC0, 0x7F, 0xC3,
|
|
||||||
0xFF, 0x9F, 0x3E, 0x78, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F,
|
|
||||||
0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0x78, 0x3D, 0xF1, 0xE3, 0xFF, 0x8F, 0xFC,
|
|
||||||
0x0F, 0xC0, 0xFF, 0xFF, 0xF8, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38,
|
|
||||||
0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x1F, 0xC3, 0xFF, 0x3F, 0xFC, 0xF1, 0xF2,
|
|
||||||
0x07, 0x80, 0x3C, 0x01, 0xE0, 0x1E, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F,
|
|
||||||
0x01, 0xF0, 0x1F, 0x01, 0xFF, 0xEF, 0xFF, 0x7F, 0xF8, 0x7F, 0xFB, 0xFF,
|
|
||||||
0xDF, 0xFE, 0x01, 0xE0, 0x1E, 0x01, 0xE0, 0x1E, 0x00, 0xF8, 0x07, 0xF0,
|
|
||||||
0x3F, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0xB0, 0x7F, 0xFF, 0xFF, 0xFE, 0x3F,
|
|
||||||
0xC0, 0x01, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF8, 0x01, 0xE0,
|
|
||||||
0x07, 0x80, 0x1E, 0x3C, 0x7C, 0x78, 0xF0, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xE0, 0x0F, 0x00, 0x1E, 0x00, 0x3C, 0x00, 0x78, 0x3F, 0xF8, 0xFF,
|
|
||||||
0xE3, 0xFF, 0x8F, 0x00, 0x3C, 0x00, 0xE0, 0x03, 0x80, 0x0F, 0xF8, 0x3F,
|
|
||||||
0xF9, 0xFF, 0xE0, 0x07, 0x80, 0x0F, 0x00, 0x3D, 0xC1, 0xE7, 0xFF, 0xBF,
|
|
||||||
0xFC, 0x3F, 0xE0, 0x07, 0xF0, 0x7F, 0xE3, 0xFF, 0x1F, 0x04, 0x78, 0x03,
|
|
||||||
0xC0, 0x0F, 0x10, 0x3F, 0xFC, 0xFF, 0xFB, 0xFB, 0xEF, 0x83, 0xFC, 0x0F,
|
|
||||||
0xF0, 0x3D, 0xE1, 0xF7, 0xFF, 0x8F, 0xFC, 0x0F, 0xE0, 0xFF, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xFF, 0xC0, 0xFE, 0x0F, 0x70, 0x78, 0x07, 0x80, 0x3C, 0x03, 0xE0,
|
|
||||||
0x1E, 0x01, 0xF0, 0x0F, 0x00, 0x78, 0x07, 0x80, 0x3C, 0x03, 0xE0, 0x1E,
|
|
||||||
0x00, 0x0F, 0xC0, 0xFF, 0xC7, 0xFF, 0x9E, 0x1E, 0xF0, 0x7B, 0xC1, 0xE7,
|
|
||||||
0x87, 0x8F, 0xFC, 0x3F, 0xF1, 0xFF, 0xEF, 0x07, 0xFC, 0x0F, 0xF0, 0x3F,
|
|
||||||
0xC1, 0xFF, 0xFF, 0x9F, 0xFC, 0x1F, 0xE0, 0x0F, 0xC0, 0xFF, 0xC7, 0xFF,
|
|
||||||
0x9E, 0x1E, 0x70, 0x3F, 0xC0, 0xF7, 0x83, 0xDF, 0x1F, 0x7F, 0xFC, 0xFF,
|
|
||||||
0xF0, 0xF3, 0xC0, 0x0F, 0x00, 0x7C, 0x83, 0xE3, 0xFF, 0x1F, 0xF8, 0x3F,
|
|
||||||
0xC0, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0xFF, 0xFF, 0x00, 0x00,
|
|
||||||
0x0F, 0xFF, 0xF7, 0x6E, 0xE0, 0x00, 0x30, 0x1F, 0x07, 0xF3, 0xFC, 0xFE,
|
|
||||||
0x0F, 0x00, 0xFC, 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0x00, 0x70, 0x00, 0xFF,
|
|
||||||
0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
||||||
0xF0, 0xE0, 0x0F, 0x80, 0xFF, 0x01, 0xFE, 0x07, 0xF0, 0x0F, 0x03, 0xF1,
|
|
||||||
0xFE, 0xFF, 0x0F, 0xC0, 0xE0, 0x00, 0x00, 0x1F, 0xC3, 0xFF, 0xBF, 0xFC,
|
|
||||||
0xE1, 0xF2, 0x07, 0x80, 0x3C, 0x03, 0xC0, 0x3E, 0x03, 0xE0, 0x1E, 0x01,
|
|
||||||
0xE0, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x00,
|
|
||||||
0xFE, 0x00, 0x0F, 0xFF, 0x80, 0x3E, 0x0F, 0x80, 0xF0, 0x03, 0x83, 0x80,
|
|
||||||
0x03, 0x8E, 0x1F, 0x7B, 0x9C, 0x7F, 0xF3, 0x71, 0xFF, 0xE6, 0xE7, 0x87,
|
|
||||||
0xCF, 0xCF, 0x07, 0x9F, 0x9C, 0x0F, 0x3F, 0x38, 0x1E, 0x7E, 0x78, 0x3C,
|
|
||||||
0xFC, 0xF0, 0xF9, 0xB8, 0xFF, 0xFF, 0x38, 0xFE, 0xFC, 0x70, 0xF8, 0xF0,
|
|
||||||
0x70, 0x00, 0x00, 0x78, 0x00, 0x00, 0x7E, 0x3C, 0x00, 0x7F, 0xF8, 0x00,
|
|
||||||
0x1F, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x3E, 0x00, 0x0F, 0xC0, 0x01, 0xFC,
|
|
||||||
0x00, 0x7F, 0x80, 0x0F, 0x70, 0x03, 0xCF, 0x00, 0x78, 0xE0, 0x0E, 0x1E,
|
|
||||||
0x03, 0xC3, 0xC0, 0x7F, 0xFC, 0x1F, 0xFF, 0x83, 0xFF, 0xF8, 0xF0, 0x0F,
|
|
||||||
0x1E, 0x00, 0xF7, 0x80, 0x1E, 0xF0, 0x03, 0xC0, 0xFF, 0xE1, 0xFF, 0xF3,
|
|
||||||
0xFF, 0xF7, 0x81, 0xEF, 0x01, 0xFE, 0x03, 0xBC, 0x0F, 0x7F, 0xFC, 0xFF,
|
|
||||||
0xF9, 0xFF, 0xFB, 0xC0, 0x7F, 0x80, 0xFF, 0x01, 0xFE, 0x03, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xFE, 0xFF, 0xF0, 0x03, 0xF8, 0x0F, 0xFC, 0x3F, 0xFF, 0x3F, 0x1E,
|
|
||||||
0x7C, 0x04, 0xF8, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00,
|
|
||||||
0xF0, 0x00, 0xF8, 0x00, 0x78, 0x04, 0x7E, 0x1E, 0x3F, 0xFF, 0x1F, 0xFE,
|
|
||||||
0x07, 0xF8, 0xFF, 0xC0, 0x7F, 0xFC, 0x3F, 0xFF, 0x1E, 0x1F, 0xCF, 0x01,
|
|
||||||
0xF7, 0x80, 0x7B, 0xC0, 0x1F, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x03, 0xFC,
|
|
||||||
0x01, 0xFE, 0x01, 0xEF, 0x01, 0xF7, 0x83, 0xF3, 0xFF, 0xF9, 0xFF, 0xF0,
|
|
||||||
0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x0F, 0x00, 0x78,
|
|
||||||
0x03, 0xC0, 0x1F, 0xFE, 0xFF, 0xF7, 0xFF, 0xBC, 0x01, 0xE0, 0x0F, 0x00,
|
|
||||||
0x78, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
||||||
0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xFF, 0xF7, 0xFF, 0xBF,
|
|
||||||
0xFD, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x00, 0x03,
|
|
||||||
0xF8, 0x0F, 0xFE, 0x3F, 0xFF, 0x3F, 0x1E, 0x7C, 0x04, 0xF8, 0x00, 0xF0,
|
|
||||||
0x00, 0xF0, 0x00, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF8, 0x0F, 0x78,
|
|
||||||
0x0F, 0x7E, 0x0F, 0x3F, 0xFF, 0x1F, 0xFE, 0x07, 0xF8, 0xF0, 0x0F, 0xE0,
|
|
||||||
0x1F, 0xC0, 0x3F, 0x80, 0x7F, 0x00, 0xFE, 0x01, 0xFC, 0x03, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x3F, 0x80, 0x7F, 0x00, 0xFE, 0x01, 0xFC,
|
|
||||||
0x03, 0xF8, 0x07, 0xF0, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xF0, 0x7F, 0xEF, 0xFD, 0xFF, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78,
|
|
||||||
0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0xC3, 0xFF, 0xF7, 0xFE,
|
|
||||||
0x3F, 0x80, 0xF0, 0x1E, 0xF0, 0x3C, 0xF0, 0x78, 0xF0, 0xF8, 0xF1, 0xF0,
|
|
||||||
0xF3, 0xE0, 0xF7, 0xC0, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xE0,
|
|
||||||
0xF9, 0xF0, 0xF0, 0xF0, 0xF0, 0x78, 0xF0, 0x7C, 0xF0, 0x3E, 0xF0, 0x1F,
|
|
||||||
0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00,
|
|
||||||
0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xFF, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xF0, 0xE0, 0x01, 0xFE, 0x00, 0x3F, 0xE0, 0x0F, 0xFC, 0x01, 0xFF,
|
|
||||||
0xC0, 0x7F, 0xF8, 0x0F, 0xFF, 0x83, 0xFF, 0xF8, 0xFF, 0xFF, 0x1D, 0xFE,
|
|
||||||
0xF7, 0xBF, 0xCE, 0xE7, 0xF9, 0xFC, 0xFF, 0x1F, 0x1F, 0xE1, 0xC3, 0xFC,
|
|
||||||
0x38, 0x7F, 0x80, 0x0F, 0xF0, 0x01, 0xE0, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0,
|
|
||||||
0x3F, 0xE0, 0x7F, 0xE0, 0xFF, 0xE1, 0xFF, 0xC3, 0xFF, 0xC7, 0xF7, 0xCF,
|
|
||||||
0xE7, 0xDF, 0xC7, 0xFF, 0x87, 0xFF, 0x0F, 0xFE, 0x0F, 0xFC, 0x0F, 0xF8,
|
|
||||||
0x0F, 0xF0, 0x0E, 0x03, 0xF8, 0x03, 0xFF, 0x83, 0xFF, 0xF0, 0xFC, 0x7E,
|
|
||||||
0x7C, 0x07, 0xBE, 0x01, 0xFF, 0x00, 0x3F, 0xC0, 0x0F, 0xF0, 0x03, 0xFC,
|
|
||||||
0x00, 0xFF, 0x00, 0x3F, 0xE0, 0x0F, 0x78, 0x07, 0x9F, 0x87, 0xE3, 0xFF,
|
|
||||||
0xF0, 0x7F, 0xF8, 0x07, 0xF8, 0x00, 0xFF, 0xC1, 0xFF, 0xE3, 0xFF, 0xE7,
|
|
||||||
0x87, 0xEF, 0x03, 0xDE, 0x03, 0xFC, 0x07, 0xF8, 0x1E, 0xF0, 0x3D, 0xFF,
|
|
||||||
0xFB, 0xFF, 0xE7, 0xFF, 0x0F, 0x00, 0x1E, 0x00, 0x3C, 0x00, 0x78, 0x00,
|
|
||||||
0xF0, 0x00, 0x03, 0xF8, 0x01, 0xFF, 0xC0, 0xFF, 0xFC, 0x1F, 0x8F, 0xC7,
|
|
||||||
0xC0, 0x79, 0xF0, 0x0F, 0xBC, 0x00, 0xF7, 0x80, 0x1E, 0xF0, 0x03, 0xDE,
|
|
||||||
0x00, 0x7B, 0xC0, 0x0F, 0x7C, 0x01, 0xE7, 0x80, 0x78, 0xFC, 0x3F, 0x0F,
|
|
||||||
0xFF, 0xC0, 0xFF, 0xF0, 0x07, 0xF8, 0x00, 0x1F, 0x18, 0x01, 0xFF, 0x80,
|
|
||||||
0x1F, 0xE0, 0x00, 0xF8, 0xFF, 0x81, 0xFF, 0xE3, 0xFF, 0xE7, 0x87, 0xEF,
|
|
||||||
0x03, 0xDE, 0x03, 0xFC, 0x07, 0xF8, 0x1E, 0xF0, 0x3D, 0xFF, 0xFB, 0xFF,
|
|
||||||
0xE7, 0xFF, 0x0F, 0x0F, 0x1E, 0x1E, 0x3C, 0x1E, 0x78, 0x1E, 0xF0, 0x3E,
|
|
||||||
0x1F, 0xE0, 0xFF, 0xE7, 0xFF, 0x3E, 0x0C, 0xF0, 0x03, 0xC0, 0x0F, 0x80,
|
|
||||||
0x1F, 0xE0, 0x3F, 0xF0, 0x7F, 0xE0, 0x1F, 0x80, 0x1F, 0x00, 0x3F, 0x81,
|
|
||||||
0xEF, 0xFF, 0xBF, 0xFC, 0x3F, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8,
|
|
||||||
0x3C, 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0x80, 0x0F,
|
|
||||||
0x00, 0x1E, 0x00, 0x3C, 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0,
|
|
||||||
0x07, 0x80, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80, 0xFF, 0x01, 0xFE,
|
|
||||||
0x03, 0xFC, 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80,
|
|
||||||
0xFF, 0x01, 0xEF, 0x0F, 0x9F, 0xFF, 0x1F, 0xFC, 0x0F, 0xE0, 0xF0, 0x03,
|
|
||||||
0xFE, 0x00, 0xF7, 0x80, 0x79, 0xE0, 0x1E, 0x3C, 0x0F, 0x0F, 0x03, 0xC3,
|
|
||||||
0xE0, 0xE0, 0x78, 0x78, 0x1F, 0x1E, 0x03, 0xCF, 0x00, 0xF3, 0xC0, 0x1F,
|
|
||||||
0xE0, 0x07, 0xF8, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xC0, 0x01, 0xE0,
|
|
||||||
0x00, 0xF0, 0x1E, 0x01, 0xFC, 0x07, 0x80, 0xFF, 0x01, 0xF0, 0x3D, 0xE0,
|
|
||||||
0xFC, 0x0E, 0x78, 0x3F, 0x07, 0x9E, 0x0F, 0xE1, 0xE3, 0xC7, 0xF8, 0x70,
|
|
||||||
0xF1, 0xCE, 0x3C, 0x3C, 0x73, 0xCF, 0x07, 0xBC, 0xF3, 0x81, 0xEE, 0x1D,
|
|
||||||
0xE0, 0x7F, 0x87, 0xF8, 0x0F, 0xE1, 0xFC, 0x03, 0xF0, 0x3F, 0x00, 0xFC,
|
|
||||||
0x0F, 0xC0, 0x1F, 0x03, 0xE0, 0x07, 0x80, 0x78, 0x00, 0x78, 0x0F, 0x3E,
|
|
||||||
0x07, 0x8F, 0x07, 0x83, 0xC7, 0x81, 0xF7, 0xC0, 0x7F, 0xC0, 0x1F, 0xC0,
|
|
||||||
0x07, 0xC0, 0x03, 0xE0, 0x03, 0xF8, 0x01, 0xFC, 0x01, 0xEF, 0x01, 0xF7,
|
|
||||||
0xC0, 0xF1, 0xF0, 0xF0, 0x78, 0xF8, 0x1E, 0xF8, 0x0F, 0x80, 0xF0, 0x07,
|
|
||||||
0x7C, 0x07, 0x9E, 0x07, 0x87, 0x83, 0xC3, 0xC3, 0xC0, 0xF1, 0xC0, 0x7D,
|
|
||||||
0xE0, 0x1F, 0xE0, 0x07, 0xF0, 0x03, 0xF0, 0x00, 0xF0, 0x00, 0x78, 0x00,
|
|
||||||
0x3C, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x00, 0xFF,
|
|
||||||
0xFD, 0xFF, 0xFB, 0xFF, 0xF0, 0x03, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0x78,
|
|
||||||
0x01, 0xE0, 0x07, 0x80, 0x1F, 0x00, 0x7C, 0x01, 0xF0, 0x03, 0xC0, 0x0F,
|
|
||||||
0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x8F, 0x1E,
|
|
||||||
0x3C, 0x78, 0xF1, 0xE3, 0xC7, 0x8F, 0x1E, 0x3C, 0x78, 0xF1, 0xE3, 0xC7,
|
|
||||||
0x8F, 0xFF, 0xFF, 0x80, 0xF0, 0x0E, 0x01, 0xC0, 0x3C, 0x03, 0x80, 0x70,
|
|
||||||
0x0F, 0x00, 0xE0, 0x1C, 0x03, 0xC0, 0x38, 0x07, 0x00, 0xF0, 0x0E, 0x01,
|
|
||||||
0xC0, 0x3C, 0x03, 0x80, 0x78, 0x07, 0x00, 0xE0, 0x1E, 0x01, 0xC0, 0xFF,
|
|
||||||
0xFF, 0xF8, 0xF1, 0xE3, 0xC7, 0x8F, 0x1E, 0x3C, 0x78, 0xF1, 0xE3, 0xC7,
|
|
||||||
0x8F, 0x1E, 0x3C, 0x78, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0x00, 0xF8, 0x1F,
|
|
||||||
0x81, 0xD8, 0x19, 0xC3, 0x9C, 0x38, 0xE7, 0x0E, 0x70, 0x7E, 0x07, 0xFF,
|
|
||||||
0xFF, 0xFF, 0x78, 0x78, 0x78, 0x3F, 0x8F, 0xFE, 0x7F, 0xE6, 0x0F, 0x00,
|
|
||||||
0xF0, 0xFF, 0x7F, 0xFF, 0xFF, 0xF0, 0xFF, 0x0F, 0xFB, 0xF7, 0xFF, 0x3F,
|
|
||||||
0x70, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x9F, 0x0F,
|
|
||||||
0xFF, 0x3F, 0xFE, 0xF8, 0xFB, 0xC1, 0xFF, 0x03, 0xF8, 0x0F, 0xF0, 0x3F,
|
|
||||||
0xC0, 0xFF, 0x87, 0xBF, 0xFE, 0xFF, 0xF3, 0xBF, 0x00, 0x0F, 0xC1, 0xFF,
|
|
||||||
0x9F, 0xFD, 0xF0, 0xEF, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07,
|
|
||||||
0xC3, 0x9F, 0xFC, 0x7F, 0xE0, 0xFC, 0x00, 0x00, 0x3C, 0x00, 0xF0, 0x03,
|
|
||||||
0xC0, 0x0F, 0x00, 0x3C, 0x7E, 0xF3, 0xFF, 0xDF, 0xFF, 0xF8, 0x7F, 0xC0,
|
|
||||||
0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x87, 0xDF, 0xFF, 0x3F,
|
|
||||||
0xFC, 0x7E, 0xF0, 0x0F, 0xC1, 0xFF, 0x1F, 0xFD, 0xF0, 0xFF, 0x03, 0xFF,
|
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xC1, 0x1F, 0xFC, 0x7F, 0xE0, 0xFE,
|
|
||||||
0x00, 0x07, 0xC7, 0xF1, 0xF8, 0xF0, 0x3C, 0x3F, 0xEF, 0xFB, 0xFE, 0x3C,
|
|
||||||
0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x00,
|
|
||||||
0x1F, 0xBC, 0xFF, 0xF7, 0xFF, 0xFE, 0x1F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03,
|
|
||||||
0xFC, 0x0F, 0xF8, 0x7D, 0xFF, 0xF7, 0xFF, 0xC7, 0xEF, 0x00, 0x3C, 0x00,
|
|
||||||
0xF7, 0x07, 0x9F, 0xFE, 0x7F, 0xF0, 0x3E, 0x00, 0xE0, 0x07, 0x00, 0x38,
|
|
||||||
0x01, 0xC0, 0x0E, 0x00, 0x73, 0xE3, 0xFF, 0xDF, 0xFE, 0xF8, 0xFF, 0x83,
|
|
||||||
0xFC, 0x1F, 0xC0, 0xFE, 0x07, 0xF0, 0x3F, 0x81, 0xFC, 0x0F, 0xE0, 0x7F,
|
|
||||||
0x03, 0xC0, 0x77, 0xBF, 0xE0, 0x01, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCE,
|
|
||||||
0x73, 0x9C, 0x07, 0x07, 0x83, 0xE1, 0xE0, 0x00, 0x00, 0x3C, 0x1E, 0x0F,
|
|
||||||
0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1,
|
|
||||||
0xE1, 0xE7, 0xF3, 0xF0, 0xF0, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00,
|
|
||||||
0xE0, 0x03, 0x83, 0xEE, 0x1F, 0x38, 0xF8, 0xE7, 0xC3, 0xBE, 0x0F, 0xF0,
|
|
||||||
0x3F, 0xE0, 0xFF, 0xC3, 0xEF, 0x0F, 0x1E, 0x38, 0x7C, 0xE0, 0xFB, 0x81,
|
|
||||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xE7, 0xC3, 0xE3, 0xFF,
|
|
||||||
0xBF, 0xCF, 0xFF, 0xFF, 0xBE, 0x3F, 0x1E, 0xF0, 0xF8, 0x7B, 0xC1, 0xE0,
|
|
||||||
0xFE, 0x07, 0x83, 0xF8, 0x1E, 0x0F, 0xE0, 0x78, 0x3F, 0x81, 0xE0, 0xFE,
|
|
||||||
0x07, 0x83, 0xF8, 0x1E, 0x0F, 0xE0, 0x78, 0x3C, 0xE7, 0xC7, 0xFF, 0xBF,
|
|
||||||
0xFD, 0xF1, 0xFF, 0x07, 0xF8, 0x3F, 0x81, 0xFC, 0x0F, 0xE0, 0x7F, 0x03,
|
|
||||||
0xF8, 0x1F, 0xC0, 0xFE, 0x07, 0x80, 0x0F, 0xC0, 0xFF, 0xC7, 0xFF, 0xBE,
|
|
||||||
0x1E, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xE1, 0xE7,
|
|
||||||
0xFF, 0x8F, 0xFC, 0x0F, 0xC0, 0xE7, 0xC3, 0xFF, 0xCF, 0xFF, 0xBE, 0x3E,
|
|
||||||
0xF0, 0x7F, 0xC0, 0xFE, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xE1, 0xEF, 0xFF,
|
|
||||||
0xBF, 0xFC, 0xE7, 0xC3, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80,
|
|
||||||
0x00, 0x1F, 0xBC, 0xFF, 0xF7, 0xFF, 0xFE, 0x1F, 0xF0, 0x3F, 0xC0, 0xFF,
|
|
||||||
0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xE1, 0xF7, 0xFF, 0xCF, 0xFF, 0x1F, 0xBC,
|
|
||||||
0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0xE7, 0xEF, 0xFF,
|
|
||||||
0xFC, 0xF0, 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x1F, 0xE3,
|
|
||||||
0xFF, 0x7F, 0xE7, 0x82, 0x78, 0x07, 0xF8, 0x3F, 0xE1, 0xFF, 0x00, 0xF0,
|
|
||||||
0x07, 0x7F, 0xF7, 0xFE, 0x3F, 0xC0, 0x3C, 0x0F, 0x03, 0xC3, 0xFE, 0xFF,
|
|
||||||
0xBF, 0xE3, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0xE1,
|
|
||||||
0xFC, 0x3F, 0xE0, 0x7F, 0x03, 0xF8, 0x1F, 0xC0, 0xFE, 0x07, 0xF0, 0x3F,
|
|
||||||
0x81, 0xFC, 0x0F, 0xF0, 0x7F, 0x87, 0xFF, 0xFE, 0xFF, 0xF3, 0xF7, 0x80,
|
|
||||||
0xF0, 0x1D, 0xE0, 0x79, 0xE0, 0xF3, 0xC3, 0xC3, 0x87, 0x87, 0x8E, 0x0F,
|
|
||||||
0x3C, 0x0F, 0x70, 0x1F, 0xE0, 0x1F, 0xC0, 0x3F, 0x00, 0x3E, 0x00, 0x78,
|
|
||||||
0x00, 0xF0, 0x38, 0x1D, 0xC1, 0xE0, 0x77, 0x07, 0xC3, 0xDE, 0x1F, 0x0E,
|
|
||||||
0x38, 0xFC, 0x38, 0xE3, 0xF9, 0xE3, 0xDE, 0xE7, 0x07, 0x73, 0xFC, 0x1D,
|
|
||||||
0xC7, 0xE0, 0x7F, 0x1F, 0x80, 0xF8, 0x7E, 0x03, 0xE0, 0xF0, 0x0F, 0x03,
|
|
||||||
0xC0, 0x78, 0x3D, 0xE1, 0xE3, 0xCF, 0x07, 0xF8, 0x0F, 0xE0, 0x3F, 0x00,
|
|
||||||
0x78, 0x03, 0xF0, 0x0F, 0xE0, 0x7F, 0xC3, 0xCF, 0x1E, 0x1E, 0xF8, 0x3C,
|
|
||||||
0xF0, 0x1D, 0xE0, 0x79, 0xE0, 0xF3, 0xC1, 0xC3, 0xC7, 0x87, 0x8E, 0x07,
|
|
||||||
0x3C, 0x0F, 0x70, 0x1F, 0xE0, 0x1F, 0xC0, 0x3F, 0x00, 0x3E, 0x00, 0x78,
|
|
||||||
0x00, 0xF0, 0x13, 0xC0, 0x7F, 0x80, 0xFE, 0x00, 0xF0, 0x00, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xFF, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0xC0, 0xF0, 0x3C, 0x0F, 0x03,
|
|
||||||
0xFF, 0xFF, 0xFF, 0xFE, 0x07, 0x1F, 0x3F, 0x3E, 0x3C, 0x3C, 0x3C, 0x3C,
|
|
||||||
0x3C, 0x3C, 0xF8, 0xF0, 0xFC, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3E,
|
|
||||||
0x3F, 0x1F, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8,
|
|
||||||
0xF0, 0xF8, 0xFC, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1F, 0x0F,
|
|
||||||
0x1F, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, 0x7C, 0xFC, 0xF8, 0xE0, 0x38,
|
|
||||||
0x37, 0xE3, 0x7F, 0xFE, 0x7E, 0xE1, 0xC0 };
|
|
||||||
|
|
||||||
const GFXglyph Montserrat_Bold12pt7bGlyphs[] PROGMEM = {
|
|
||||||
{ 0, 1, 1, 7, 0, 0 }, // 0x20 ' '
|
|
||||||
{ 1, 5, 17, 7, 1, -16 }, // 0x21 '!'
|
|
||||||
{ 12, 8, 7, 10, 1, -16 }, // 0x22 '"'
|
|
||||||
{ 19, 17, 17, 17, 0, -16 }, // 0x23 '#'
|
|
||||||
{ 56, 14, 23, 15, 1, -19 }, // 0x24 '$'
|
|
||||||
{ 97, 19, 17, 21, 1, -16 }, // 0x25 '%'
|
|
||||||
{ 138, 16, 17, 17, 1, -16 }, // 0x26 '&'
|
|
||||||
{ 172, 3, 7, 6, 1, -16 }, // 0x27 '''
|
|
||||||
{ 175, 6, 23, 9, 2, -17 }, // 0x28 '('
|
|
||||||
{ 193, 7, 23, 9, 0, -17 }, // 0x29 ')'
|
|
||||||
{ 214, 10, 10, 10, 0, -17 }, // 0x2A '*'
|
|
||||||
{ 227, 12, 11, 14, 1, -13 }, // 0x2B '+'
|
|
||||||
{ 244, 4, 8, 6, 1, -3 }, // 0x2C ','
|
|
||||||
{ 248, 7, 3, 9, 1, -7 }, // 0x2D '-'
|
|
||||||
{ 251, 4, 4, 6, 1, -3 }, // 0x2E '.'
|
|
||||||
{ 253, 11, 22, 9, -1, -19 }, // 0x2F '/'
|
|
||||||
{ 284, 14, 17, 16, 1, -16 }, // 0x30 '0'
|
|
||||||
{ 314, 7, 17, 9, 0, -16 }, // 0x31 '1'
|
|
||||||
{ 329, 13, 17, 14, 0, -16 }, // 0x32 '2'
|
|
||||||
{ 357, 13, 17, 14, 0, -16 }, // 0x33 '3'
|
|
||||||
{ 385, 15, 17, 17, 1, -16 }, // 0x34 '4'
|
|
||||||
{ 417, 14, 17, 14, 0, -16 }, // 0x35 '5'
|
|
||||||
{ 447, 14, 17, 15, 1, -16 }, // 0x36 '6'
|
|
||||||
{ 477, 13, 17, 15, 1, -16 }, // 0x37 '7'
|
|
||||||
{ 505, 14, 17, 16, 1, -16 }, // 0x38 '8'
|
|
||||||
{ 535, 14, 17, 15, 0, -16 }, // 0x39 '9'
|
|
||||||
{ 565, 4, 13, 6, 1, -12 }, // 0x3A ':'
|
|
||||||
{ 572, 4, 17, 6, 1, -12 }, // 0x3B ';'
|
|
||||||
{ 581, 12, 12, 14, 1, -13 }, // 0x3C '<'
|
|
||||||
{ 599, 12, 9, 14, 1, -12 }, // 0x3D '='
|
|
||||||
{ 613, 12, 12, 14, 1, -13 }, // 0x3E '>'
|
|
||||||
{ 631, 13, 17, 14, 0, -16 }, // 0x3F '?'
|
|
||||||
{ 659, 23, 22, 25, 1, -16 }, // 0x40 '@'
|
|
||||||
{ 723, 19, 17, 18, 0, -16 }, // 0x41 'A'
|
|
||||||
{ 764, 15, 17, 18, 2, -16 }, // 0x42 'B'
|
|
||||||
{ 796, 16, 17, 17, 1, -16 }, // 0x43 'C'
|
|
||||||
{ 830, 17, 17, 20, 2, -16 }, // 0x44 'D'
|
|
||||||
{ 867, 13, 17, 16, 2, -16 }, // 0x45 'E'
|
|
||||||
{ 895, 13, 17, 15, 2, -16 }, // 0x46 'F'
|
|
||||||
{ 923, 16, 17, 19, 1, -16 }, // 0x47 'G'
|
|
||||||
{ 957, 15, 17, 19, 2, -16 }, // 0x48 'H'
|
|
||||||
{ 989, 4, 17, 8, 2, -16 }, // 0x49 'I'
|
|
||||||
{ 998, 11, 17, 13, 0, -16 }, // 0x4A 'J'
|
|
||||||
{ 1022, 16, 17, 18, 2, -16 }, // 0x4B 'K'
|
|
||||||
{ 1056, 12, 17, 15, 2, -16 }, // 0x4C 'L'
|
|
||||||
{ 1082, 19, 17, 23, 2, -16 }, // 0x4D 'M'
|
|
||||||
{ 1123, 15, 17, 19, 2, -16 }, // 0x4E 'N'
|
|
||||||
{ 1155, 18, 17, 20, 1, -16 }, // 0x4F 'O'
|
|
||||||
{ 1194, 15, 17, 18, 2, -16 }, // 0x50 'P'
|
|
||||||
{ 1226, 19, 21, 20, 1, -16 }, // 0x51 'Q'
|
|
||||||
{ 1276, 15, 17, 18, 2, -16 }, // 0x52 'R'
|
|
||||||
{ 1308, 14, 17, 15, 1, -16 }, // 0x53 'S'
|
|
||||||
{ 1338, 15, 17, 15, 0, -16 }, // 0x54 'T'
|
|
||||||
{ 1370, 15, 17, 19, 2, -16 }, // 0x55 'U'
|
|
||||||
{ 1402, 18, 17, 18, 0, -16 }, // 0x56 'V'
|
|
||||||
{ 1441, 26, 17, 28, 1, -16 }, // 0x57 'W'
|
|
||||||
{ 1497, 17, 17, 17, 0, -16 }, // 0x58 'X'
|
|
||||||
{ 1534, 17, 17, 16, 0, -16 }, // 0x59 'Y'
|
|
||||||
{ 1571, 15, 17, 16, 1, -16 }, // 0x5A 'Z'
|
|
||||||
{ 1603, 7, 23, 9, 2, -17 }, // 0x5B '['
|
|
||||||
{ 1624, 11, 22, 9, -1, -19 }, // 0x5C '\'
|
|
||||||
{ 1655, 7, 23, 9, 0, -17 }, // 0x5D ']'
|
|
||||||
{ 1676, 12, 10, 14, 1, -12 }, // 0x5E '^'
|
|
||||||
{ 1691, 12, 2, 12, 0, 1 }, // 0x5F '_'
|
|
||||||
{ 1694, 7, 3, 14, 2, -17 }, // 0x60 '`'
|
|
||||||
{ 1697, 12, 13, 15, 1, -12 }, // 0x61 'a'
|
|
||||||
{ 1717, 14, 18, 17, 2, -17 }, // 0x62 'b'
|
|
||||||
{ 1749, 13, 13, 14, 1, -12 }, // 0x63 'c'
|
|
||||||
{ 1771, 14, 18, 17, 1, -17 }, // 0x64 'd'
|
|
||||||
{ 1803, 13, 13, 15, 1, -12 }, // 0x65 'e'
|
|
||||||
{ 1825, 10, 18, 9, 0, -17 }, // 0x66 'f'
|
|
||||||
{ 1848, 14, 18, 17, 1, -12 }, // 0x67 'g'
|
|
||||||
{ 1880, 13, 18, 17, 2, -17 }, // 0x68 'h'
|
|
||||||
{ 1910, 5, 19, 7, 1, -18 }, // 0x69 'i'
|
|
||||||
{ 1922, 9, 24, 7, -2, -18 }, // 0x6A 'j'
|
|
||||||
{ 1949, 14, 18, 16, 2, -17 }, // 0x6B 'k'
|
|
||||||
{ 1981, 3, 18, 7, 2, -17 }, // 0x6C 'l'
|
|
||||||
{ 1988, 22, 13, 25, 2, -12 }, // 0x6D 'm'
|
|
||||||
{ 2024, 13, 13, 17, 2, -12 }, // 0x6E 'n'
|
|
||||||
{ 2046, 14, 13, 16, 1, -12 }, // 0x6F 'o'
|
|
||||||
{ 2069, 14, 18, 17, 2, -12 }, // 0x70 'p'
|
|
||||||
{ 2101, 14, 18, 17, 1, -12 }, // 0x71 'q'
|
|
||||||
{ 2133, 8, 13, 10, 2, -12 }, // 0x72 'r'
|
|
||||||
{ 2146, 12, 13, 13, 0, -12 }, // 0x73 's'
|
|
||||||
{ 2166, 10, 16, 10, 0, -15 }, // 0x74 't'
|
|
||||||
{ 2186, 13, 13, 16, 2, -12 }, // 0x75 'u'
|
|
||||||
{ 2208, 15, 13, 14, 0, -12 }, // 0x76 'v'
|
|
||||||
{ 2233, 22, 13, 22, 0, -12 }, // 0x77 'w'
|
|
||||||
{ 2269, 14, 13, 14, 0, -12 }, // 0x78 'x'
|
|
||||||
{ 2292, 15, 18, 14, 0, -12 }, // 0x79 'y'
|
|
||||||
{ 2326, 11, 13, 13, 1, -12 }, // 0x7A 'z'
|
|
||||||
{ 2344, 8, 23, 9, 1, -17 }, // 0x7B '{'
|
|
||||||
{ 2367, 3, 23, 7, 2, -17 }, // 0x7C '|'
|
|
||||||
{ 2376, 8, 23, 9, 0, -17 }, // 0x7D '}'
|
|
||||||
{ 2399, 12, 5, 14, 1, -10 } }; // 0x7E '~'
|
|
||||||
|
|
||||||
const GFXfont Montserrat_Bold12pt7b PROGMEM = {
|
|
||||||
(uint8_t *)Montserrat_Bold12pt7bBitmaps,
|
|
||||||
(GFXglyph *)Montserrat_Bold12pt7bGlyphs,
|
|
||||||
0x20, 0x7E, 29 };
|
|
||||||
|
|
||||||
// Approx. 3079 bytes
|
|
||||||
|
|
||||||
#endif // MONTSERRATBOLD12PT7B_H
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,227 +0,0 @@
|
|||||||
#ifndef MONTSERRATBOLD9PT7B_H
|
|
||||||
#define MONTSERRATBOLD9PT7B_H
|
|
||||||
const uint8_t Montserrat_Bold9pt7bBitmaps[] PROGMEM = {
|
|
||||||
0x00, 0xFF, 0xFF, 0xFF, 0xE3, 0xFE, 0xCF, 0x3C, 0xF3, 0xCF, 0x30, 0x0C,
|
|
||||||
0x60, 0x66, 0x03, 0x30, 0xFF, 0xF7, 0xFF, 0x8C, 0x60, 0x63, 0x03, 0x18,
|
|
||||||
0xFF, 0xF7, 0xFF, 0x86, 0x60, 0x33, 0x03, 0x18, 0x00, 0x06, 0x00, 0xC0,
|
|
||||||
0x3E, 0x1F, 0xE7, 0xFC, 0xEC, 0x1D, 0x83, 0xF0, 0x3F, 0x81, 0xF8, 0x1F,
|
|
||||||
0x83, 0x76, 0x6E, 0xFF, 0x8F, 0xE0, 0x30, 0x06, 0x00, 0x38, 0x18, 0xF8,
|
|
||||||
0x71, 0x98, 0xC6, 0x33, 0x04, 0x6C, 0x0D, 0x98, 0x0F, 0x67, 0x01, 0x9F,
|
|
||||||
0x03, 0x66, 0x0C, 0xCC, 0x31, 0x98, 0x63, 0xB1, 0x83, 0xC0, 0x1E, 0x03,
|
|
||||||
0xF0, 0x73, 0x87, 0x38, 0x77, 0x03, 0xE0, 0x3C, 0x0F, 0xE6, 0xE7, 0xEC,
|
|
||||||
0x3E, 0xE1, 0xEF, 0xFF, 0x7F, 0x60, 0xFF, 0xF0, 0x39, 0x9C, 0xE6, 0x73,
|
|
||||||
0x9C, 0xE7, 0x38, 0xC7, 0x38, 0xC7, 0x63, 0x9C, 0x73, 0x9C, 0xE7, 0x39,
|
|
||||||
0xCE, 0x73, 0x99, 0xCC, 0x18, 0x5E, 0x7E, 0x3C, 0xFE, 0x5A, 0x18, 0x1C,
|
|
||||||
0x0E, 0x07, 0x1F, 0xFF, 0xF8, 0xE0, 0x70, 0x38, 0xFF, 0xFD, 0x80, 0xFF,
|
|
||||||
0xC0, 0xFF, 0x80, 0x03, 0x81, 0x81, 0xC0, 0xE0, 0x60, 0x70, 0x38, 0x18,
|
|
||||||
0x1C, 0x0C, 0x06, 0x07, 0x03, 0x01, 0x81, 0xC0, 0xC0, 0x60, 0x00, 0x1E,
|
|
||||||
0x07, 0xF1, 0xFE, 0x70, 0xEE, 0x1D, 0xC3, 0xB8, 0x37, 0x06, 0xE1, 0xDC,
|
|
||||||
0x39, 0xCF, 0x3F, 0xC3, 0xF0, 0xFF, 0xFF, 0xC7, 0x1C, 0x71, 0xC7, 0x1C,
|
|
||||||
0x71, 0xC7, 0x1C, 0x1E, 0x1F, 0xEF, 0xF8, 0x07, 0x01, 0xC0, 0xE0, 0x78,
|
|
||||||
0x3C, 0x1E, 0x0F, 0x07, 0x81, 0xFF, 0x7F, 0xC0, 0x7F, 0x9F, 0xE7, 0xF8,
|
|
||||||
0x1C, 0x0E, 0x03, 0x81, 0xF8, 0x7F, 0x01, 0xC0, 0x76, 0x3F, 0xFE, 0x7F,
|
|
||||||
0x00, 0x07, 0x00, 0xE0, 0x38, 0x0E, 0x03, 0xC0, 0x70, 0x1C, 0xE7, 0x1C,
|
|
||||||
0xFF, 0xFF, 0xFC, 0x0E, 0x01, 0xC0, 0x38, 0x3F, 0x8F, 0xE3, 0xF9, 0xC0,
|
|
||||||
0x70, 0x1F, 0xC7, 0xF8, 0x1F, 0x01, 0xC0, 0x76, 0x3F, 0xFE, 0x7F, 0x00,
|
|
||||||
0x0F, 0x0F, 0xE7, 0xFB, 0xC0, 0xE0, 0x3B, 0xCF, 0xFB, 0xCF, 0xE1, 0xF8,
|
|
||||||
0x7F, 0x1D, 0xFE, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x70, 0xEE, 0x3C,
|
|
||||||
0x07, 0x00, 0xE0, 0x38, 0x07, 0x01, 0xC0, 0x38, 0x0F, 0x01, 0xC0, 0x1E,
|
|
||||||
0x1F, 0xEF, 0x3F, 0x87, 0xE1, 0xDF, 0xE7, 0xFB, 0xCF, 0xE1, 0xF8, 0x7E,
|
|
||||||
0x1F, 0xFE, 0x3F, 0x00, 0x1E, 0x07, 0xF1, 0xCF, 0x70, 0xEE, 0x1E, 0xE3,
|
|
||||||
0xDF, 0xF9, 0xF7, 0x00, 0xE0, 0x38, 0x0F, 0x3F, 0xC7, 0xF0, 0xFF, 0x80,
|
|
||||||
0x3F, 0xE0, 0xFF, 0x80, 0x3F, 0xFF, 0x60, 0x00, 0x83, 0xC7, 0xFF, 0x8E,
|
|
||||||
0x07, 0xC0, 0xFC, 0x1F, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x07,
|
|
||||||
0xFF, 0xFE, 0x80, 0x70, 0x3F, 0x03, 0xF0, 0x38, 0x7D, 0xF9, 0xE0, 0xC0,
|
|
||||||
0x00, 0x1E, 0x1F, 0xEF, 0xF8, 0x07, 0x01, 0xC0, 0xE0, 0x70, 0x38, 0x0E,
|
|
||||||
0x00, 0x00, 0xE0, 0x38, 0x0E, 0x00, 0x03, 0xE0, 0x0F, 0xFC, 0x0E, 0x07,
|
|
||||||
0x8E, 0x00, 0xC6, 0x3F, 0xB6, 0x3F, 0xCF, 0x38, 0xE7, 0x98, 0x73, 0xCC,
|
|
||||||
0x39, 0xE6, 0x1C, 0xF3, 0x8E, 0x79, 0xFF, 0xE6, 0x3D, 0xE3, 0x80, 0x00,
|
|
||||||
0xF0, 0x40, 0x1F, 0xE0, 0x03, 0xC0, 0x00, 0x07, 0x00, 0x1E, 0x00, 0x78,
|
|
||||||
0x03, 0xF0, 0x0D, 0xC0, 0x73, 0x81, 0xCE, 0x0E, 0x1C, 0x3F, 0xF1, 0xFF,
|
|
||||||
0xC7, 0x03, 0x98, 0x0E, 0xE0, 0x1C, 0xFF, 0x0F, 0xFC, 0xFF, 0xEE, 0x0E,
|
|
||||||
0xE0, 0xEE, 0x1E, 0xFF, 0xCF, 0xFE, 0xE0, 0x7E, 0x07, 0xE0, 0xFF, 0xFE,
|
|
||||||
0xFF, 0xC0, 0x0F, 0x83, 0xFE, 0x7F, 0xF7, 0x06, 0xE0, 0x0E, 0x00, 0xE0,
|
|
||||||
0x0E, 0x00, 0xE0, 0x0F, 0x00, 0x78, 0xE3, 0xFE, 0x1F, 0xC0, 0xFF, 0x07,
|
|
||||||
0xFE, 0x3F, 0xFD, 0xC0, 0xEE, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0,
|
|
||||||
0x3F, 0x03, 0xF8, 0x7D, 0xFF, 0xCF, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
||||||
0x80, 0xE0, 0x3F, 0xEF, 0xFB, 0xFE, 0xE0, 0x38, 0x0E, 0x03, 0xFF, 0xFF,
|
|
||||||
0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xE0, 0x38, 0x0F, 0xFB, 0xFE, 0xE0,
|
|
||||||
0x38, 0x0E, 0x03, 0x80, 0xE0, 0x00, 0x0F, 0x83, 0xFE, 0x7F, 0xF7, 0x06,
|
|
||||||
0xE0, 0x0E, 0x00, 0xE0, 0x7E, 0x07, 0xE0, 0x7F, 0x07, 0x78, 0xF3, 0xFF,
|
|
||||||
0x1F, 0xC0, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7F, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xFF, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x70, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xFF, 0xFE, 0x7F, 0x7F, 0x7F, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
||||||
0x07, 0xC7, 0xFF, 0x7E, 0xE0, 0x77, 0x07, 0x38, 0x71, 0xC7, 0x0E, 0x70,
|
|
||||||
0x77, 0x03, 0xF8, 0x1F, 0xE0, 0xFF, 0x87, 0x9E, 0x38, 0x79, 0xC1, 0xCE,
|
|
||||||
0x07, 0x00, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80,
|
|
||||||
0xE0, 0x38, 0x0E, 0x03, 0xFF, 0xFF, 0xC0, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0,
|
|
||||||
0x7F, 0xC1, 0xFF, 0x83, 0xFF, 0x8F, 0xFB, 0x9B, 0xF7, 0x77, 0xE7, 0xCF,
|
|
||||||
0xC7, 0x9F, 0x8E, 0x3F, 0x08, 0x7E, 0x00, 0xE0, 0xE0, 0x7F, 0x07, 0xF8,
|
|
||||||
0x7F, 0x87, 0xFC, 0x7F, 0xE7, 0xEF, 0x7E, 0x7F, 0xE3, 0xFE, 0x1F, 0xE0,
|
|
||||||
0xFE, 0x0F, 0xE0, 0x70, 0x0F, 0x81, 0xFF, 0x1F, 0xFC, 0xE0, 0xFE, 0x03,
|
|
||||||
0xF0, 0x1F, 0x80, 0x7C, 0x07, 0xE0, 0x3F, 0x81, 0xDE, 0x3C, 0x7F, 0xC1,
|
|
||||||
0xFC, 0x00, 0xFE, 0x1F, 0xFB, 0xFF, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F,
|
|
||||||
0xFF, 0xFF, 0xDF, 0xC3, 0x80, 0x70, 0x0E, 0x00, 0x0F, 0x80, 0xFF, 0x87,
|
|
||||||
0xFF, 0x1C, 0x1E, 0xE0, 0x3B, 0x80, 0xEE, 0x01, 0xB8, 0x0E, 0xE0, 0x3B,
|
|
||||||
0xC0, 0xE7, 0x8F, 0x0F, 0xF8, 0x1F, 0xC0, 0x0F, 0x20, 0x1F, 0xC0, 0x1E,
|
|
||||||
0xFE, 0x0F, 0xFC, 0xFF, 0xEE, 0x0E, 0xE0, 0xEE, 0x0E, 0xE0, 0xEF, 0xFE,
|
|
||||||
0xFF, 0xCE, 0x38, 0xE1, 0xCE, 0x1E, 0xE0, 0xE0, 0x0F, 0x87, 0xF9, 0xFF,
|
|
||||||
0x38, 0x07, 0x00, 0xF8, 0x0F, 0xE0, 0x7E, 0x01, 0xE0, 0x1D, 0x83, 0xBF,
|
|
||||||
0xE3, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0xE0, 0x1C, 0x03, 0x80,
|
|
||||||
0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xE0, 0xE0, 0x7E, 0x07, 0xE0,
|
|
||||||
0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x77, 0x0F, 0x79,
|
|
||||||
0xE3, 0xFE, 0x1F, 0x80, 0xE0, 0x1F, 0x80, 0xE7, 0x03, 0x9C, 0x1C, 0x38,
|
|
||||||
0x70, 0xE1, 0x83, 0xCE, 0x07, 0x38, 0x1D, 0xC0, 0x3F, 0x00, 0xF8, 0x01,
|
|
||||||
0xE0, 0x07, 0x00, 0xE0, 0x70, 0x3B, 0x83, 0x83, 0x9C, 0x1E, 0x1C, 0xE1,
|
|
||||||
0xF0, 0xE3, 0x8D, 0x8E, 0x1C, 0x6E, 0x70, 0xE7, 0x73, 0x83, 0xB3, 0xB8,
|
|
||||||
0x1D, 0x8F, 0xC0, 0xFC, 0x7E, 0x03, 0xC3, 0xE0, 0x1E, 0x0F, 0x00, 0xF0,
|
|
||||||
0x78, 0x00, 0xF0, 0x73, 0x83, 0x8E, 0x38, 0x7B, 0x81, 0xFC, 0x07, 0xC0,
|
|
||||||
0x1C, 0x01, 0xF0, 0x1F, 0xC0, 0xEE, 0x0E, 0x38, 0xE1, 0xEF, 0x07, 0x00,
|
|
||||||
0xE0, 0x3F, 0x07, 0x70, 0xE3, 0x8E, 0x39, 0xC1, 0xD8, 0x1F, 0x80, 0xF0,
|
|
||||||
0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00, 0xFF, 0xDF, 0xFB, 0xFF,
|
|
||||||
0x01, 0xC0, 0x78, 0x1E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0xC0, 0x7F,
|
|
||||||
0xFF, 0xFE, 0xFF, 0xF9, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0xFF,
|
|
||||||
0xE0, 0x30, 0x1C, 0x06, 0x03, 0x01, 0xC0, 0x60, 0x30, 0x1C, 0x06, 0x03,
|
|
||||||
0x01, 0xC0, 0x60, 0x38, 0x1C, 0x06, 0x03, 0x80, 0xFF, 0xCE, 0x73, 0x9C,
|
|
||||||
0xE7, 0x39, 0xCE, 0x73, 0x9F, 0xFF, 0x1C, 0x0E, 0x0D, 0x86, 0xC6, 0x73,
|
|
||||||
0x1B, 0x8C, 0xFF, 0xFF, 0xC0, 0xE3, 0x8E, 0x3C, 0x7F, 0x99, 0xE0, 0x73,
|
|
||||||
0xFF, 0xFF, 0x8F, 0x87, 0xFF, 0xBF, 0xC0, 0xE0, 0x1C, 0x03, 0x80, 0x77,
|
|
||||||
0x8F, 0xF9, 0xF7, 0xBC, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0xC7, 0x7F, 0xEE,
|
|
||||||
0xF8, 0x1E, 0x3F, 0xFF, 0xFC, 0x2C, 0x06, 0x03, 0x81, 0xE7, 0x7F, 0x9F,
|
|
||||||
0x80, 0x01, 0xC0, 0x70, 0x1C, 0x77, 0x7F, 0xFF, 0xFE, 0x1F, 0x87, 0xC1,
|
|
||||||
0xF8, 0x7F, 0x3D, 0xFF, 0x3F, 0xC0, 0x1E, 0x1F, 0xCF, 0x3B, 0x87, 0xFF,
|
|
||||||
0xFF, 0xFE, 0x03, 0xC4, 0x7F, 0x8F, 0xC0, 0x00, 0x1E, 0x3E, 0x30, 0x30,
|
|
||||||
0xFE, 0xFE, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1C, 0xDF, 0xFF,
|
|
||||||
0xFF, 0x87, 0xC1, 0xF8, 0x7E, 0x1F, 0xFF, 0x7F, 0xC2, 0x74, 0x1D, 0xFF,
|
|
||||||
0xFF, 0x87, 0x00, 0xE0, 0x38, 0x0E, 0x03, 0xBC, 0xFF, 0xBF, 0xFF, 0x1F,
|
|
||||||
0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xC0, 0xFF, 0x8F, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xC0, 0x1C, 0x71, 0xC0, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C,
|
|
||||||
0x71, 0xDF, 0x79, 0xC0, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0xEE, 0x39, 0xCE,
|
|
||||||
0x3B, 0x87, 0xF0, 0xFE, 0x1E, 0xE3, 0x9E, 0x71, 0xEE, 0x1E, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xFF, 0xFE, 0xEF, 0x1C, 0x7F, 0xFF, 0xBF, 0xFF, 0xDC, 0x38, 0x7E,
|
|
||||||
0x1C, 0x3F, 0x0E, 0x1F, 0x87, 0x0F, 0xC3, 0x87, 0xE1, 0xC3, 0xF0, 0xE1,
|
|
||||||
0xC0, 0xEF, 0x3F, 0xEF, 0xFF, 0xC7, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1,
|
|
||||||
0xF8, 0x70, 0x1E, 0x1F, 0xEF, 0xFB, 0x87, 0xC1, 0xF0, 0x7E, 0x1F, 0xCF,
|
|
||||||
0x7F, 0x8F, 0xC0, 0xEF, 0x1F, 0xF3, 0xEF, 0x78, 0x7E, 0x0F, 0xC1, 0xF8,
|
|
||||||
0x3F, 0x8E, 0xFF, 0xDD, 0xF3, 0x80, 0x70, 0x0E, 0x00, 0x1D, 0xDF, 0xFF,
|
|
||||||
0xFF, 0x87, 0xC1, 0xF0, 0x7E, 0x1F, 0xCF, 0x7F, 0xCF, 0xF0, 0x1C, 0x07,
|
|
||||||
0x01, 0xC0, 0xEF, 0xFF, 0xFC, 0xE3, 0x8E, 0x38, 0xE3, 0x80, 0x1F, 0x3F,
|
|
||||||
0xDC, 0x4C, 0x07, 0xE1, 0xFC, 0x0E, 0x87, 0x7F, 0xBF, 0x80, 0x30, 0x30,
|
|
||||||
0xFE, 0xFE, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x3E, 0x1F, 0xE1, 0xF8,
|
|
||||||
0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0xCF, 0x7F, 0xCF, 0xF0, 0xE0,
|
|
||||||
0xFC, 0x19, 0xC7, 0x38, 0xE3, 0x38, 0x77, 0x0E, 0xC0, 0xF8, 0x1E, 0x01,
|
|
||||||
0xC0, 0xE1, 0xC3, 0xF0, 0xE1, 0x98, 0x70, 0xCE, 0x7C, 0xE3, 0x36, 0x61,
|
|
||||||
0xBB, 0xB0, 0xFD, 0xF8, 0x3C, 0x78, 0x1E, 0x3C, 0x0E, 0x1E, 0x00, 0xE1,
|
|
||||||
0xCE, 0x38, 0xEE, 0x0F, 0x81, 0xE0, 0x1C, 0x07, 0xC1, 0xDC, 0x73, 0xDC,
|
|
||||||
0x38, 0xE0, 0xFC, 0x19, 0xC7, 0x38, 0xE3, 0x38, 0x77, 0x06, 0xC0, 0xF8,
|
|
||||||
0x1E, 0x01, 0xC0, 0x38, 0x7E, 0x0F, 0x80, 0xE0, 0x00, 0xFF, 0xFF, 0x07,
|
|
||||||
0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xFF, 0xFF, 0x3C, 0xF7, 0x1C, 0x71, 0xC7,
|
|
||||||
0x3C, 0xF1, 0xC7, 0x1C, 0x71, 0xC7, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xF3, 0xE3, 0x8E, 0x38, 0xE3, 0x8F, 0x3C, 0xE3, 0x8E, 0x38, 0xEF,
|
|
||||||
0xBC, 0x71, 0xFF, 0xF3, 0xC0 };
|
|
||||||
|
|
||||||
const GFXglyph Montserrat_Bold9pt7bGlyphs[] PROGMEM = {
|
|
||||||
{ 0, 1, 1, 5, 0, 0 }, // 0x20 ' '
|
|
||||||
{ 1, 3, 13, 5, 1, -12 }, // 0x21 '!'
|
|
||||||
{ 6, 6, 6, 8, 1, -12 }, // 0x22 '"'
|
|
||||||
{ 11, 13, 13, 13, 0, -12 }, // 0x23 '#'
|
|
||||||
{ 33, 11, 17, 11, 0, -14 }, // 0x24 '$'
|
|
||||||
{ 57, 15, 13, 16, 0, -12 }, // 0x25 '%'
|
|
||||||
{ 82, 12, 13, 13, 1, -12 }, // 0x26 '&'
|
|
||||||
{ 102, 2, 6, 4, 1, -12 }, // 0x27 '''
|
|
||||||
{ 104, 5, 16, 6, 1, -12 }, // 0x28 '('
|
|
||||||
{ 114, 5, 16, 6, 0, -12 }, // 0x29 ')'
|
|
||||||
{ 124, 8, 7, 8, 0, -12 }, // 0x2A '*'
|
|
||||||
{ 131, 9, 8, 11, 1, -9 }, // 0x2B '+'
|
|
||||||
{ 140, 3, 6, 5, 1, -2 }, // 0x2C ','
|
|
||||||
{ 143, 5, 2, 7, 1, -5 }, // 0x2D '-'
|
|
||||||
{ 145, 3, 3, 5, 1, -2 }, // 0x2E '.'
|
|
||||||
{ 147, 9, 17, 7, -1, -14 }, // 0x2F '/'
|
|
||||||
{ 167, 11, 13, 12, 1, -12 }, // 0x30 '0'
|
|
||||||
{ 185, 6, 13, 7, 0, -12 }, // 0x31 '1'
|
|
||||||
{ 195, 10, 13, 11, 0, -12 }, // 0x32 '2'
|
|
||||||
{ 212, 10, 13, 11, 0, -12 }, // 0x33 '3'
|
|
||||||
{ 229, 11, 13, 12, 1, -12 }, // 0x34 '4'
|
|
||||||
{ 247, 10, 13, 11, 0, -12 }, // 0x35 '5'
|
|
||||||
{ 264, 10, 13, 11, 1, -12 }, // 0x36 '6'
|
|
||||||
{ 281, 11, 13, 11, 0, -12 }, // 0x37 '7'
|
|
||||||
{ 299, 10, 13, 12, 1, -12 }, // 0x38 '8'
|
|
||||||
{ 316, 11, 13, 11, 0, -12 }, // 0x39 '9'
|
|
||||||
{ 334, 3, 9, 5, 1, -8 }, // 0x3A ':'
|
|
||||||
{ 338, 3, 12, 5, 1, -8 }, // 0x3B ';'
|
|
||||||
{ 343, 9, 9, 11, 1, -10 }, // 0x3C '<'
|
|
||||||
{ 354, 9, 7, 11, 1, -9 }, // 0x3D '='
|
|
||||||
{ 362, 9, 9, 11, 1, -10 }, // 0x3E '>'
|
|
||||||
{ 373, 10, 13, 11, 0, -12 }, // 0x3F '?'
|
|
||||||
{ 390, 17, 17, 19, 1, -12 }, // 0x40 '@'
|
|
||||||
{ 427, 14, 13, 14, 0, -12 }, // 0x41 'A'
|
|
||||||
{ 450, 12, 13, 14, 1, -12 }, // 0x42 'B'
|
|
||||||
{ 470, 12, 13, 13, 1, -12 }, // 0x43 'C'
|
|
||||||
{ 490, 13, 13, 15, 1, -12 }, // 0x44 'D'
|
|
||||||
{ 512, 10, 13, 12, 1, -12 }, // 0x45 'E'
|
|
||||||
{ 529, 10, 13, 12, 1, -12 }, // 0x46 'F'
|
|
||||||
{ 546, 12, 13, 14, 1, -12 }, // 0x47 'G'
|
|
||||||
{ 566, 12, 13, 15, 1, -12 }, // 0x48 'H'
|
|
||||||
{ 586, 3, 13, 6, 1, -12 }, // 0x49 'I'
|
|
||||||
{ 591, 8, 13, 10, 0, -12 }, // 0x4A 'J'
|
|
||||||
{ 604, 13, 13, 13, 1, -12 }, // 0x4B 'K'
|
|
||||||
{ 626, 10, 13, 11, 1, -12 }, // 0x4C 'L'
|
|
||||||
{ 643, 15, 13, 17, 1, -12 }, // 0x4D 'M'
|
|
||||||
{ 668, 12, 13, 15, 1, -12 }, // 0x4E 'N'
|
|
||||||
{ 688, 13, 13, 15, 1, -12 }, // 0x4F 'O'
|
|
||||||
{ 710, 11, 13, 13, 1, -12 }, // 0x50 'P'
|
|
||||||
{ 728, 14, 16, 15, 1, -12 }, // 0x51 'Q'
|
|
||||||
{ 756, 12, 13, 13, 1, -12 }, // 0x52 'R'
|
|
||||||
{ 776, 11, 13, 11, 0, -12 }, // 0x53 'S'
|
|
||||||
{ 794, 11, 13, 11, 0, -12 }, // 0x54 'T'
|
|
||||||
{ 812, 12, 13, 14, 1, -12 }, // 0x55 'U'
|
|
||||||
{ 832, 14, 13, 13, 0, -12 }, // 0x56 'V'
|
|
||||||
{ 855, 21, 13, 21, 0, -12 }, // 0x57 'W'
|
|
||||||
{ 890, 13, 13, 13, 0, -12 }, // 0x58 'X'
|
|
||||||
{ 912, 12, 13, 12, 0, -12 }, // 0x59 'Y'
|
|
||||||
{ 932, 11, 13, 12, 1, -12 }, // 0x5A 'Z'
|
|
||||||
{ 950, 5, 16, 7, 1, -12 }, // 0x5B '['
|
|
||||||
{ 960, 9, 17, 7, -1, -14 }, // 0x5C '\'
|
|
||||||
{ 980, 5, 16, 7, 0, -12 }, // 0x5D ']'
|
|
||||||
{ 990, 9, 7, 11, 1, -9 }, // 0x5E '^'
|
|
||||||
{ 998, 9, 2, 9, 0, 1 }, // 0x5F '_'
|
|
||||||
{ 1001, 5, 3, 11, 2, -13 }, // 0x60 '`'
|
|
||||||
{ 1003, 9, 10, 11, 1, -9 }, // 0x61 'a'
|
|
||||||
{ 1015, 11, 13, 12, 1, -12 }, // 0x62 'b'
|
|
||||||
{ 1033, 9, 10, 11, 1, -9 }, // 0x63 'c'
|
|
||||||
{ 1045, 10, 13, 12, 1, -12 }, // 0x64 'd'
|
|
||||||
{ 1062, 10, 10, 11, 1, -9 }, // 0x65 'e'
|
|
||||||
{ 1075, 8, 14, 7, 0, -13 }, // 0x66 'f'
|
|
||||||
{ 1089, 10, 14, 13, 1, -9 }, // 0x67 'g'
|
|
||||||
{ 1107, 10, 13, 12, 1, -12 }, // 0x68 'h'
|
|
||||||
{ 1124, 3, 14, 5, 1, -13 }, // 0x69 'i'
|
|
||||||
{ 1130, 6, 18, 6, -2, -13 }, // 0x6A 'j'
|
|
||||||
{ 1144, 11, 13, 12, 1, -12 }, // 0x6B 'k'
|
|
||||||
{ 1162, 3, 13, 5, 1, -12 }, // 0x6C 'l'
|
|
||||||
{ 1167, 17, 10, 19, 1, -9 }, // 0x6D 'm'
|
|
||||||
{ 1189, 10, 10, 12, 1, -9 }, // 0x6E 'n'
|
|
||||||
{ 1202, 10, 10, 12, 1, -9 }, // 0x6F 'o'
|
|
||||||
{ 1215, 11, 13, 12, 1, -9 }, // 0x70 'p'
|
|
||||||
{ 1233, 10, 13, 12, 1, -9 }, // 0x71 'q'
|
|
||||||
{ 1250, 6, 10, 8, 1, -9 }, // 0x72 'r'
|
|
||||||
{ 1258, 9, 10, 10, 0, -9 }, // 0x73 's'
|
|
||||||
{ 1270, 8, 12, 8, 0, -11 }, // 0x74 't'
|
|
||||||
{ 1282, 10, 10, 12, 1, -9 }, // 0x75 'u'
|
|
||||||
{ 1295, 11, 10, 11, 0, -9 }, // 0x76 'v'
|
|
||||||
{ 1309, 17, 10, 17, 0, -9 }, // 0x77 'w'
|
|
||||||
{ 1331, 11, 10, 11, 0, -9 }, // 0x78 'x'
|
|
||||||
{ 1345, 11, 14, 11, 0, -9 }, // 0x79 'y'
|
|
||||||
{ 1365, 8, 10, 10, 1, -9 }, // 0x7A 'z'
|
|
||||||
{ 1375, 6, 16, 7, 1, -12 }, // 0x7B '{'
|
|
||||||
{ 1387, 3, 16, 6, 1, -12 }, // 0x7C '|'
|
|
||||||
{ 1393, 6, 16, 7, 0, -12 }, // 0x7D '}'
|
|
||||||
{ 1405, 9, 3, 11, 1, -7 } }; // 0x7E '~'
|
|
||||||
|
|
||||||
const GFXfont Montserrat_Bold9pt7b PROGMEM = {
|
|
||||||
(uint8_t *)Montserrat_Bold9pt7bBitmaps,
|
|
||||||
(GFXglyph *)Montserrat_Bold9pt7bGlyphs,
|
|
||||||
0x20, 0x7E, 21 };
|
|
||||||
|
|
||||||
// Approx. 2081 bytes
|
|
||||||
|
|
||||||
#endif // MONTSERRATBOLD9PT7B_H
|
|
||||||
@@ -0,0 +1,899 @@
|
|||||||
|
// MontserratBold9pt8b.h
|
||||||
|
//
|
||||||
|
// Adafruit GFX font header — Latin Extended-A coverage (U+0020 to U+017F).
|
||||||
|
// Source: Montserrat Bold at 9pt.
|
||||||
|
// 352 glyphs covering ASCII, Latin-1 Supplement, and Latin Extended-A.
|
||||||
|
// Supports Czech, Polish, German, French, Spanish, Italian, Croatian,
|
||||||
|
// Hungarian, Slovak, Romanian, and other European languages.
|
||||||
|
//
|
||||||
|
// Codepoints 0x7F-0x9F (C0/C1 control codes) are present as empty glyphs.
|
||||||
|
// They are never rendered in normal use because UTF-8 decoding does not
|
||||||
|
// produce them as standalone codepoints.
|
||||||
|
//
|
||||||
|
// To render glyphs above 0x7F, use a drawCodepoint(font, x, y, cp) helper
|
||||||
|
// that walks the glyph table directly. Adafruit GFX's print() / write() /
|
||||||
|
// drawChar() are byte-oriented (uint8_t) and cannot address indices > 255.
|
||||||
|
|
||||||
|
#ifndef MONTSERRATBOLD9PT8B_H
|
||||||
|
#define MONTSERRATBOLD9PT8B_H
|
||||||
|
|
||||||
|
const uint8_t MontserratBold9pt8bBitmaps[] PROGMEM = {
|
||||||
|
0x00, 0xFF, 0xFF, 0xFF, 0xE3, 0xFE, 0xCF, 0x3C, 0xF3, 0xCF, 0x30, 0x0C,
|
||||||
|
0x60, 0x66, 0x03, 0x30, 0xFF, 0xF7, 0xFF, 0x8C, 0x60, 0x63, 0x03, 0x18,
|
||||||
|
0xFF, 0xF7, 0xFF, 0x86, 0x60, 0x33, 0x03, 0x18, 0x00, 0x06, 0x00, 0xC0,
|
||||||
|
0x3E, 0x1F, 0xE7, 0xFC, 0xEC, 0x1D, 0x83, 0xF0, 0x3F, 0x81, 0xF8, 0x1F,
|
||||||
|
0x83, 0x76, 0x6E, 0xFF, 0x8F, 0xE0, 0x30, 0x06, 0x00, 0x38, 0x18, 0xF8,
|
||||||
|
0x71, 0x98, 0xC6, 0x33, 0x04, 0x6C, 0x0D, 0x98, 0x0F, 0x67, 0x01, 0x9F,
|
||||||
|
0x03, 0x66, 0x0C, 0xCC, 0x31, 0x98, 0x63, 0xB1, 0x83, 0xC0, 0x1E, 0x03,
|
||||||
|
0xF0, 0x73, 0x87, 0x38, 0x77, 0x03, 0xE0, 0x3C, 0x0F, 0xE6, 0xE7, 0xEC,
|
||||||
|
0x3E, 0xE1, 0xEF, 0xFF, 0x7F, 0x60, 0xFF, 0xF0, 0x39, 0x9C, 0xE6, 0x73,
|
||||||
|
0x9C, 0xE7, 0x38, 0xC7, 0x38, 0xC7, 0x63, 0x9C, 0x73, 0x9C, 0xE7, 0x39,
|
||||||
|
0xCE, 0x73, 0x99, 0xCC, 0x18, 0x5E, 0x7E, 0x3C, 0xFE, 0x5A, 0x18, 0x1C,
|
||||||
|
0x0E, 0x07, 0x1F, 0xFF, 0xF8, 0xE0, 0x70, 0x38, 0xFF, 0xFD, 0x80, 0xFF,
|
||||||
|
0xC0, 0xFF, 0x80, 0x03, 0x81, 0x81, 0xC0, 0xE0, 0x60, 0x70, 0x38, 0x18,
|
||||||
|
0x1C, 0x0C, 0x06, 0x07, 0x03, 0x01, 0x81, 0xC0, 0xC0, 0x60, 0x00, 0x1E,
|
||||||
|
0x07, 0xF1, 0xFE, 0x70, 0xEE, 0x1D, 0xC3, 0xB8, 0x37, 0x06, 0xE1, 0xDC,
|
||||||
|
0x39, 0xCF, 0x3F, 0xC3, 0xF0, 0xFF, 0xFF, 0xC7, 0x1C, 0x71, 0xC7, 0x1C,
|
||||||
|
0x71, 0xC7, 0x1C, 0x1E, 0x1F, 0xEF, 0xF8, 0x07, 0x01, 0xC0, 0xE0, 0x78,
|
||||||
|
0x3C, 0x1E, 0x0F, 0x07, 0x81, 0xFF, 0x7F, 0xC0, 0x7F, 0x9F, 0xE7, 0xF8,
|
||||||
|
0x1C, 0x0E, 0x03, 0x81, 0xF8, 0x7F, 0x01, 0xC0, 0x76, 0x3F, 0xFE, 0x7F,
|
||||||
|
0x00, 0x07, 0x00, 0xE0, 0x38, 0x0E, 0x03, 0xC0, 0x70, 0x1C, 0xE7, 0x1C,
|
||||||
|
0xFF, 0xFF, 0xFC, 0x0E, 0x01, 0xC0, 0x38, 0x3F, 0x8F, 0xE3, 0xF9, 0xC0,
|
||||||
|
0x70, 0x1F, 0xC7, 0xF8, 0x1F, 0x01, 0xC0, 0x76, 0x3F, 0xFE, 0x7F, 0x00,
|
||||||
|
0x0F, 0x0F, 0xE7, 0xFB, 0xC0, 0xE0, 0x3B, 0xCF, 0xFB, 0xCF, 0xE1, 0xF8,
|
||||||
|
0x7F, 0x1D, 0xFE, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x70, 0xEE, 0x3C,
|
||||||
|
0x07, 0x00, 0xE0, 0x38, 0x07, 0x01, 0xC0, 0x38, 0x0F, 0x01, 0xC0, 0x1E,
|
||||||
|
0x1F, 0xEF, 0x3F, 0x87, 0xE1, 0xDF, 0xE7, 0xFB, 0xCF, 0xE1, 0xF8, 0x7E,
|
||||||
|
0x1F, 0xFE, 0x3F, 0x00, 0x1E, 0x07, 0xF1, 0xCF, 0x70, 0xEE, 0x1E, 0xE3,
|
||||||
|
0xDF, 0xF9, 0xF7, 0x00, 0xE0, 0x38, 0x0F, 0x3F, 0xC7, 0xF0, 0xFF, 0x80,
|
||||||
|
0x3F, 0xE0, 0xFF, 0x80, 0x3F, 0xFF, 0x60, 0x00, 0x83, 0xC7, 0xFF, 0x8E,
|
||||||
|
0x07, 0xC0, 0xFC, 0x1F, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x07,
|
||||||
|
0xFF, 0xFE, 0x80, 0x70, 0x3F, 0x03, 0xF0, 0x38, 0x7D, 0xF9, 0xE0, 0xC0,
|
||||||
|
0x00, 0x1E, 0x1F, 0xEF, 0xF8, 0x07, 0x01, 0xC0, 0xE0, 0x70, 0x38, 0x0E,
|
||||||
|
0x00, 0x00, 0xE0, 0x38, 0x0E, 0x00, 0x03, 0xE0, 0x0F, 0xFC, 0x0E, 0x07,
|
||||||
|
0x8E, 0x00, 0xC6, 0x3F, 0xB6, 0x3F, 0xCF, 0x38, 0xE7, 0x98, 0x73, 0xCC,
|
||||||
|
0x39, 0xE6, 0x1C, 0xF3, 0x8E, 0x79, 0xFF, 0xE6, 0x3D, 0xE3, 0x80, 0x00,
|
||||||
|
0xF0, 0x40, 0x1F, 0xE0, 0x03, 0xC0, 0x00, 0x07, 0x00, 0x1E, 0x00, 0x78,
|
||||||
|
0x03, 0xF0, 0x0D, 0xC0, 0x73, 0x81, 0xCE, 0x0E, 0x1C, 0x3F, 0xF1, 0xFF,
|
||||||
|
0xC7, 0x03, 0x98, 0x0E, 0xE0, 0x1C, 0xFF, 0x0F, 0xFC, 0xFF, 0xEE, 0x0E,
|
||||||
|
0xE0, 0xEE, 0x1E, 0xFF, 0xCF, 0xFE, 0xE0, 0x7E, 0x07, 0xE0, 0xFF, 0xFE,
|
||||||
|
0xFF, 0xC0, 0x0F, 0x83, 0xFE, 0x7F, 0xF7, 0x06, 0xE0, 0x0E, 0x00, 0xE0,
|
||||||
|
0x0E, 0x00, 0xE0, 0x0F, 0x00, 0x78, 0xE3, 0xFE, 0x1F, 0xC0, 0xFF, 0x07,
|
||||||
|
0xFE, 0x3F, 0xFD, 0xC0, 0xEE, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0,
|
||||||
|
0x3F, 0x03, 0xF8, 0x7D, 0xFF, 0xCF, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0x80, 0xE0, 0x3F, 0xEF, 0xFB, 0xFE, 0xE0, 0x38, 0x0E, 0x03, 0xFF, 0xFF,
|
||||||
|
0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xE0, 0x38, 0x0F, 0xFB, 0xFE, 0xE0,
|
||||||
|
0x38, 0x0E, 0x03, 0x80, 0xE0, 0x00, 0x0F, 0x83, 0xFE, 0x7F, 0xF7, 0x06,
|
||||||
|
0xE0, 0x0E, 0x00, 0xE0, 0x7E, 0x07, 0xE0, 0x7F, 0x07, 0x78, 0xF3, 0xFF,
|
||||||
|
0x1F, 0xC0, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7F, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x70, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFE, 0x7F, 0x7F, 0x7F, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||||
|
0x07, 0xC7, 0xFF, 0x7E, 0xE0, 0x77, 0x07, 0x38, 0x71, 0xC7, 0x0E, 0x70,
|
||||||
|
0x77, 0x03, 0xF8, 0x1F, 0xE0, 0xFF, 0x87, 0x9E, 0x38, 0x79, 0xC1, 0xCE,
|
||||||
|
0x07, 0x00, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80,
|
||||||
|
0xE0, 0x38, 0x0E, 0x03, 0xFF, 0xFF, 0xC0, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0,
|
||||||
|
0x7F, 0xC1, 0xFF, 0x83, 0xFF, 0x8F, 0xFB, 0x9B, 0xF7, 0x77, 0xE7, 0xCF,
|
||||||
|
0xC7, 0x9F, 0x8E, 0x3F, 0x08, 0x7E, 0x00, 0xE0, 0xE0, 0x7F, 0x07, 0xF8,
|
||||||
|
0x7F, 0x87, 0xFC, 0x7F, 0xE7, 0xEF, 0x7E, 0x7F, 0xE3, 0xFE, 0x1F, 0xE0,
|
||||||
|
0xFE, 0x0F, 0xE0, 0x70, 0x0F, 0x81, 0xFF, 0x1F, 0xFC, 0xE0, 0xFE, 0x03,
|
||||||
|
0xF0, 0x1F, 0x80, 0x7C, 0x07, 0xE0, 0x3F, 0x81, 0xDE, 0x3C, 0x7F, 0xC1,
|
||||||
|
0xFC, 0x00, 0xFE, 0x1F, 0xFB, 0xFF, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F,
|
||||||
|
0xFF, 0xFF, 0xDF, 0xC3, 0x80, 0x70, 0x0E, 0x00, 0x0F, 0x80, 0xFF, 0x87,
|
||||||
|
0xFF, 0x1C, 0x1E, 0xE0, 0x3B, 0x80, 0xEE, 0x01, 0xB8, 0x0E, 0xE0, 0x3B,
|
||||||
|
0xC0, 0xE7, 0x8F, 0x0F, 0xF8, 0x1F, 0xC0, 0x0F, 0x20, 0x1F, 0xC0, 0x1E,
|
||||||
|
0xFE, 0x0F, 0xFC, 0xFF, 0xEE, 0x0E, 0xE0, 0xEE, 0x0E, 0xE0, 0xEF, 0xFE,
|
||||||
|
0xFF, 0xCE, 0x38, 0xE1, 0xCE, 0x1E, 0xE0, 0xE0, 0x0F, 0x87, 0xF9, 0xFF,
|
||||||
|
0x38, 0x07, 0x00, 0xF8, 0x0F, 0xE0, 0x7E, 0x01, 0xE0, 0x1D, 0x83, 0xBF,
|
||||||
|
0xE3, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0xE0, 0x1C, 0x03, 0x80,
|
||||||
|
0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xE0, 0xE0, 0x7E, 0x07, 0xE0,
|
||||||
|
0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x77, 0x0F, 0x79,
|
||||||
|
0xE3, 0xFE, 0x1F, 0x80, 0xE0, 0x1F, 0x80, 0xE7, 0x03, 0x9C, 0x1C, 0x38,
|
||||||
|
0x70, 0xE1, 0x83, 0xCE, 0x07, 0x38, 0x1D, 0xC0, 0x3F, 0x00, 0xF8, 0x01,
|
||||||
|
0xE0, 0x07, 0x00, 0xE0, 0x70, 0x3B, 0x83, 0x83, 0x9C, 0x1E, 0x1C, 0xE1,
|
||||||
|
0xF0, 0xE3, 0x8D, 0x8E, 0x1C, 0x6E, 0x70, 0xE7, 0x73, 0x83, 0xB3, 0xB8,
|
||||||
|
0x1D, 0x8F, 0xC0, 0xFC, 0x7E, 0x03, 0xC3, 0xE0, 0x1E, 0x0F, 0x00, 0xF0,
|
||||||
|
0x78, 0x00, 0xF0, 0x73, 0x83, 0x8E, 0x38, 0x7B, 0x81, 0xFC, 0x07, 0xC0,
|
||||||
|
0x1C, 0x01, 0xF0, 0x1F, 0xC0, 0xEE, 0x0E, 0x38, 0xE1, 0xEF, 0x07, 0x00,
|
||||||
|
0xE0, 0x3F, 0x07, 0x70, 0xE3, 0x8E, 0x39, 0xC1, 0xD8, 0x1F, 0x80, 0xF0,
|
||||||
|
0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00, 0xFF, 0xDF, 0xFB, 0xFF,
|
||||||
|
0x01, 0xC0, 0x78, 0x1E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0xC0, 0x7F,
|
||||||
|
0xFF, 0xFE, 0xFF, 0xF9, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0xFF,
|
||||||
|
0xE0, 0x30, 0x1C, 0x06, 0x03, 0x01, 0xC0, 0x60, 0x30, 0x1C, 0x06, 0x03,
|
||||||
|
0x01, 0xC0, 0x60, 0x38, 0x1C, 0x06, 0x03, 0x80, 0xFF, 0xCE, 0x73, 0x9C,
|
||||||
|
0xE7, 0x39, 0xCE, 0x73, 0x9F, 0xFF, 0x1C, 0x0E, 0x0D, 0x86, 0xC6, 0x73,
|
||||||
|
0x1B, 0x8C, 0xFF, 0xFF, 0xC0, 0xE3, 0x8E, 0x3C, 0x7F, 0x99, 0xE0, 0x73,
|
||||||
|
0xFF, 0xFF, 0x8F, 0x87, 0xFF, 0xBF, 0xC0, 0xE0, 0x1C, 0x03, 0x80, 0x77,
|
||||||
|
0x8F, 0xF9, 0xF7, 0xBC, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0xC7, 0x7F, 0xEE,
|
||||||
|
0xF8, 0x1E, 0x3F, 0xFF, 0xFC, 0x2C, 0x06, 0x03, 0x81, 0xE7, 0x7F, 0x9F,
|
||||||
|
0x80, 0x01, 0xC0, 0x70, 0x1C, 0x77, 0x7F, 0xFF, 0xFE, 0x1F, 0x87, 0xC1,
|
||||||
|
0xF8, 0x7F, 0x3D, 0xFF, 0x3F, 0xC0, 0x1E, 0x1F, 0xCF, 0x3B, 0x87, 0xFF,
|
||||||
|
0xFF, 0xFE, 0x03, 0xC4, 0x7F, 0x8F, 0xC0, 0x00, 0x1E, 0x3E, 0x30, 0x30,
|
||||||
|
0xFE, 0xFE, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1C, 0xDF, 0xFF,
|
||||||
|
0xFF, 0x87, 0xC1, 0xF8, 0x7E, 0x1F, 0xFF, 0x7F, 0xC2, 0x74, 0x1D, 0xFF,
|
||||||
|
0xFF, 0x87, 0x00, 0xE0, 0x38, 0x0E, 0x03, 0xBC, 0xFF, 0xBF, 0xFF, 0x1F,
|
||||||
|
0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xC0, 0xFF, 0x8F, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xC0, 0x1C, 0x71, 0xC0, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C,
|
||||||
|
0x71, 0xDF, 0x79, 0xC0, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0xEE, 0x39, 0xCE,
|
||||||
|
0x3B, 0x87, 0xF0, 0xFE, 0x1E, 0xE3, 0x9E, 0x71, 0xEE, 0x1E, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFE, 0xEF, 0x1C, 0x7F, 0xFF, 0xBF, 0xFF, 0xDC, 0x38, 0x7E,
|
||||||
|
0x1C, 0x3F, 0x0E, 0x1F, 0x87, 0x0F, 0xC3, 0x87, 0xE1, 0xC3, 0xF0, 0xE1,
|
||||||
|
0xC0, 0xEF, 0x3F, 0xEF, 0xFF, 0xC7, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1,
|
||||||
|
0xF8, 0x70, 0x1E, 0x1F, 0xEF, 0xFB, 0x87, 0xC1, 0xF0, 0x7E, 0x1F, 0xCF,
|
||||||
|
0x7F, 0x8F, 0xC0, 0xEF, 0x1F, 0xF3, 0xEF, 0x78, 0x7E, 0x0F, 0xC1, 0xF8,
|
||||||
|
0x3F, 0x8E, 0xFF, 0xDD, 0xF3, 0x80, 0x70, 0x0E, 0x00, 0x1D, 0xDF, 0xFF,
|
||||||
|
0xFF, 0x87, 0xC1, 0xF0, 0x7E, 0x1F, 0xCF, 0x7F, 0xCF, 0xF0, 0x1C, 0x07,
|
||||||
|
0x01, 0xC0, 0xEF, 0xFF, 0xFC, 0xE3, 0x8E, 0x38, 0xE3, 0x80, 0x1F, 0x3F,
|
||||||
|
0xDC, 0x4C, 0x07, 0xE1, 0xFC, 0x0E, 0x87, 0x7F, 0xBF, 0x80, 0x30, 0x30,
|
||||||
|
0xFE, 0xFE, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x3E, 0x1F, 0xE1, 0xF8,
|
||||||
|
0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0xCF, 0x7F, 0xCF, 0xF0, 0xE0,
|
||||||
|
0xFC, 0x19, 0xC7, 0x38, 0xE3, 0x38, 0x77, 0x0E, 0xC0, 0xF8, 0x1E, 0x01,
|
||||||
|
0xC0, 0xE1, 0xC3, 0xF0, 0xE1, 0x98, 0x70, 0xCE, 0x7C, 0xE3, 0x36, 0x61,
|
||||||
|
0xBB, 0xB0, 0xFD, 0xF8, 0x3C, 0x78, 0x1E, 0x3C, 0x0E, 0x1E, 0x00, 0xE1,
|
||||||
|
0xCE, 0x38, 0xEE, 0x0F, 0x81, 0xE0, 0x1C, 0x07, 0xC1, 0xDC, 0x73, 0xDC,
|
||||||
|
0x38, 0xE0, 0xFC, 0x19, 0xC7, 0x38, 0xE3, 0x38, 0x77, 0x06, 0xC0, 0xF8,
|
||||||
|
0x1E, 0x01, 0xC0, 0x38, 0x7E, 0x0F, 0x80, 0xE0, 0x00, 0xFF, 0xFF, 0x07,
|
||||||
|
0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xFF, 0xFF, 0x3C, 0xF7, 0x1C, 0x71, 0xC7,
|
||||||
|
0x3C, 0xF1, 0xC7, 0x1C, 0x71, 0xC7, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xF3, 0xE3, 0x8E, 0x38, 0xE3, 0x8F, 0x3C, 0xE3, 0x8E, 0x38, 0xEF,
|
||||||
|
0xBC, 0x71, 0xFF, 0xF3, 0xC0, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E,
|
||||||
|
0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70,
|
||||||
|
0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF,
|
||||||
|
0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70,
|
||||||
|
0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81,
|
||||||
|
0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E,
|
||||||
|
0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70,
|
||||||
|
0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF,
|
||||||
|
0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70,
|
||||||
|
0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81,
|
||||||
|
0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E,
|
||||||
|
0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70,
|
||||||
|
0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF,
|
||||||
|
0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70,
|
||||||
|
0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81,
|
||||||
|
0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E,
|
||||||
|
0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70,
|
||||||
|
0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF,
|
||||||
|
0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70,
|
||||||
|
0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81,
|
||||||
|
0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E,
|
||||||
|
0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70,
|
||||||
|
0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF,
|
||||||
|
0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70,
|
||||||
|
0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81,
|
||||||
|
0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E,
|
||||||
|
0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70,
|
||||||
|
0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF,
|
||||||
|
0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70,
|
||||||
|
0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81,
|
||||||
|
0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E,
|
||||||
|
0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70,
|
||||||
|
0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF,
|
||||||
|
0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70,
|
||||||
|
0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81,
|
||||||
|
0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E,
|
||||||
|
0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70,
|
||||||
|
0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF,
|
||||||
|
0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70,
|
||||||
|
0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81,
|
||||||
|
0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E,
|
||||||
|
0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xF8, 0x00, 0x7F, 0x81, 0xFF,
|
||||||
|
0xFF, 0xFE, 0x0C, 0x06, 0x07, 0x8F, 0xFF, 0xFF, 0x6B, 0x31, 0x98, 0xEC,
|
||||||
|
0x7F, 0xDF, 0xE7, 0xE0, 0xC0, 0x60, 0x07, 0xC3, 0xFC, 0xFF, 0x1C, 0x07,
|
||||||
|
0x00, 0xE0, 0x3F, 0xE7, 0xFC, 0x70, 0x0E, 0x01, 0xC0, 0x7F, 0xEF, 0xFC,
|
||||||
|
0x00, 0x26, 0x07, 0x7F, 0xF3, 0xFE, 0x38, 0xE3, 0x06, 0x30, 0x63, 0x0E,
|
||||||
|
0x39, 0xC7, 0xFE, 0xFF, 0x76, 0x02, 0xE0, 0x1B, 0xC0, 0xE7, 0x07, 0x0E,
|
||||||
|
0x38, 0x1C, 0xE0, 0x77, 0x00, 0xF8, 0x0F, 0xF8, 0x3F, 0xE0, 0x1C, 0x03,
|
||||||
|
0xFE, 0x01, 0xC0, 0x07, 0x00, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x1E,
|
||||||
|
0x1F, 0xDC, 0x4C, 0x07, 0x83, 0xF9, 0x9E, 0xC7, 0x73, 0xBF, 0x87, 0xC0,
|
||||||
|
0x74, 0x33, 0xF8, 0xF8, 0x03, 0xB6, 0xC0, 0x07, 0x03, 0xFC, 0x60, 0x64,
|
||||||
|
0xF3, 0x9F, 0x99, 0x81, 0xB8, 0x19, 0x81, 0x9F, 0x9C, 0xFB, 0x40, 0x23,
|
||||||
|
0x0C, 0x1F, 0x80, 0x00, 0xF8, 0x33, 0xF4, 0x6F, 0xC0, 0x33, 0x33, 0x3B,
|
||||||
|
0x99, 0x86, 0x63, 0xB8, 0xEE, 0xFF, 0xFF, 0xC0, 0xE0, 0x70, 0x38, 0xFF,
|
||||||
|
0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70,
|
||||||
|
0x3F, 0xF8, 0x07, 0x03, 0xFC, 0x60, 0x65, 0xF3, 0x9F, 0x99, 0x89, 0x99,
|
||||||
|
0x99, 0xF9, 0x99, 0x9D, 0x9B, 0x40, 0x23, 0x0C, 0x1F, 0x80, 0xFF, 0xFC,
|
||||||
|
0x73, 0xE8, 0xE3, 0xCF, 0xE0, 0x1C, 0x0E, 0x07, 0x1F, 0xFF, 0xF8, 0xE0,
|
||||||
|
0x70, 0x38, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x38, 0xF9, 0x18, 0x71, 0xC7,
|
||||||
|
0x1F, 0xBF, 0x7E, 0x18, 0x60, 0xF0, 0x6D, 0xDF, 0x00, 0x3B, 0xB8, 0xE1,
|
||||||
|
0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0xCF, 0xFF, 0xFF, 0xBE,
|
||||||
|
0x03, 0x80, 0xE0, 0x00, 0x3F, 0xEF, 0xFF, 0xF1, 0xFE, 0x37, 0xC6, 0xF8,
|
||||||
|
0xC3, 0x18, 0x63, 0x0C, 0x61, 0x8C, 0x31, 0x86, 0x30, 0xC6, 0x18, 0xC3,
|
||||||
|
0x18, 0x7F, 0xB0, 0x67, 0x1F, 0xF0, 0xC3, 0x0C, 0x33, 0xFF, 0xC0, 0x00,
|
||||||
|
0xF9, 0x9E, 0x36, 0x6F, 0x80, 0x77, 0x0C, 0xC3, 0xB8, 0x66, 0x3B, 0x9D,
|
||||||
|
0xC6, 0x60, 0x00, 0x0C, 0x78, 0x0C, 0x0C, 0x0E, 0x06, 0x06, 0x03, 0x06,
|
||||||
|
0x01, 0x87, 0x03, 0xF3, 0x19, 0xFB, 0x18, 0x03, 0x9C, 0x01, 0x8D, 0x81,
|
||||||
|
0x8F, 0xE1, 0x80, 0x60, 0xC0, 0x30, 0x00, 0x0C, 0x78, 0x0C, 0x0C, 0x0E,
|
||||||
|
0x06, 0x06, 0x03, 0x06, 0x01, 0x87, 0x73, 0xF3, 0x7D, 0xFB, 0x23, 0x03,
|
||||||
|
0x83, 0x81, 0x83, 0x81, 0x83, 0x81, 0x83, 0xF0, 0xC1, 0xF8, 0x00, 0x06,
|
||||||
|
0x1F, 0x83, 0x00, 0xC1, 0xC0, 0x60, 0x60, 0x1E, 0x30, 0x01, 0x9C, 0x06,
|
||||||
|
0xE6, 0x31, 0xF3, 0x18, 0x01, 0xCE, 0x00, 0x63, 0x60, 0x31, 0xFC, 0x18,
|
||||||
|
0x06, 0x06, 0x01, 0x80, 0x18, 0x07, 0x01, 0xC0, 0x00, 0x00, 0x07, 0x03,
|
||||||
|
0x81, 0xC0, 0xE0, 0x38, 0x4F, 0x3D, 0xFE, 0x3E, 0x00, 0x0E, 0x00, 0x1C,
|
||||||
|
0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x1E, 0x00, 0x78, 0x03, 0xF0, 0x0D,
|
||||||
|
0xC0, 0x73, 0x81, 0xCE, 0x0E, 0x1C, 0x3F, 0xF1, 0xFF, 0xC7, 0x03, 0x98,
|
||||||
|
0x0E, 0xE0, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00,
|
||||||
|
0x1E, 0x00, 0x78, 0x03, 0xF0, 0x0D, 0xC0, 0x73, 0x81, 0xCE, 0x0E, 0x1C,
|
||||||
|
0x3F, 0xF1, 0xFF, 0xC7, 0x03, 0x98, 0x0E, 0xE0, 0x1C, 0x03, 0x80, 0x1F,
|
||||||
|
0x00, 0xCE, 0x00, 0x00, 0x07, 0x00, 0x1E, 0x00, 0x78, 0x03, 0xF0, 0x0D,
|
||||||
|
0xC0, 0x73, 0x81, 0xCE, 0x0E, 0x1C, 0x3F, 0xF1, 0xFF, 0xC7, 0x03, 0x98,
|
||||||
|
0x0E, 0xE0, 0x1C, 0x0F, 0x60, 0x37, 0x80, 0x00, 0x01, 0xC0, 0x07, 0x80,
|
||||||
|
0x1E, 0x00, 0xFC, 0x03, 0x70, 0x1C, 0xE0, 0x73, 0x83, 0x87, 0x0F, 0xFC,
|
||||||
|
0x7F, 0xF1, 0xC0, 0xE6, 0x03, 0xB8, 0x07, 0x00, 0x00, 0x3B, 0x00, 0x6C,
|
||||||
|
0x00, 0x00, 0x07, 0x00, 0x1E, 0x00, 0x78, 0x03, 0xF0, 0x0D, 0xC0, 0x73,
|
||||||
|
0x81, 0xCE, 0x0E, 0x1C, 0x3F, 0xF1, 0xFF, 0xC7, 0x03, 0x98, 0x0E, 0xE0,
|
||||||
|
0x1C, 0x03, 0x80, 0x1B, 0x00, 0x4C, 0x00, 0xE0, 0x00, 0x00, 0x1C, 0x00,
|
||||||
|
0x78, 0x01, 0xE0, 0x0F, 0xC0, 0x37, 0x01, 0xCE, 0x07, 0x38, 0x38, 0x70,
|
||||||
|
0xFF, 0xC7, 0xFF, 0x1C, 0x0E, 0x60, 0x3B, 0x80, 0x70, 0x01, 0xFF, 0xC0,
|
||||||
|
0x7F, 0xF8, 0x0F, 0xFF, 0x03, 0xB8, 0x00, 0x67, 0x00, 0x1C, 0xFF, 0x83,
|
||||||
|
0x1F, 0xF0, 0xE3, 0xFE, 0x3F, 0xF0, 0x07, 0xFE, 0x01, 0xC1, 0xC0, 0x38,
|
||||||
|
0x3F, 0xFE, 0x07, 0xFE, 0x0F, 0x83, 0xFE, 0x7F, 0xF7, 0x06, 0xE0, 0x0E,
|
||||||
|
0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0F, 0x00, 0x78, 0xE3, 0xFE, 0x1F, 0xC0,
|
||||||
|
0x60, 0x07, 0x00, 0x10, 0x0F, 0x00, 0x38, 0x07, 0x00, 0xE0, 0x00, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0x80, 0xE0, 0x3F, 0xEF, 0xFB, 0xFE, 0xE0, 0x38, 0x0E,
|
||||||
|
0x03, 0xFF, 0xFF, 0xC0, 0x03, 0x81, 0xC0, 0xE0, 0x00, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0x80, 0xE0, 0x3F, 0xEF, 0xFB, 0xFE, 0xE0, 0x38, 0x0E, 0x03, 0xFF,
|
||||||
|
0xFF, 0xC0, 0x0E, 0x07, 0xC3, 0x38, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
|
||||||
|
0xE0, 0x3F, 0xEF, 0xFB, 0xFE, 0xE0, 0x38, 0x0E, 0x03, 0xFF, 0xFF, 0xC0,
|
||||||
|
0x00, 0x0E, 0xC1, 0xB0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xE0, 0x3F,
|
||||||
|
0xEF, 0xFB, 0xFE, 0xE0, 0x38, 0x0E, 0x03, 0xFF, 0xFF, 0xC0, 0xE3, 0x8E,
|
||||||
|
0x07, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x70, 0x1C, 0xE7, 0x00,
|
||||||
|
0xE3, 0x8E, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0x8E, 0x38, 0xE0, 0x38, 0xFB,
|
||||||
|
0x38, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38,
|
||||||
|
0x70, 0x03, 0xB6, 0xC0, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7,
|
||||||
|
0x1C, 0x70, 0xFF, 0x07, 0xFE, 0x3F, 0xFD, 0xC0, 0xEE, 0x03, 0xF0, 0x1F,
|
||||||
|
0xF8, 0xFF, 0xC7, 0xE0, 0x3F, 0x03, 0xF8, 0x7D, 0xFF, 0xCF, 0xF8, 0x00,
|
||||||
|
0x1E, 0xC1, 0xBC, 0x00, 0x0E, 0x07, 0xF0, 0x7F, 0x87, 0xF8, 0x7F, 0xC7,
|
||||||
|
0xFE, 0x7E, 0xF7, 0xE7, 0xFE, 0x3F, 0xE1, 0xFE, 0x0F, 0xE0, 0xFE, 0x07,
|
||||||
|
0x1C, 0x00, 0x70, 0x01, 0xC0, 0x00, 0x00, 0xF8, 0x1F, 0xF1, 0xFF, 0xCE,
|
||||||
|
0x0F, 0xE0, 0x3F, 0x01, 0xF8, 0x07, 0xC0, 0x7E, 0x03, 0xF8, 0x1D, 0xE3,
|
||||||
|
0xC7, 0xFC, 0x1F, 0xC0, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x00, 0x00, 0xF8,
|
||||||
|
0x1F, 0xF1, 0xFF, 0xCE, 0x0F, 0xE0, 0x3F, 0x01, 0xF8, 0x07, 0xC0, 0x7E,
|
||||||
|
0x03, 0xF8, 0x1D, 0xE3, 0xC7, 0xFC, 0x1F, 0xC0, 0x07, 0x00, 0x7C, 0x06,
|
||||||
|
0x70, 0x00, 0x00, 0xF8, 0x1F, 0xF1, 0xFF, 0xCE, 0x0F, 0xE0, 0x3F, 0x01,
|
||||||
|
0xF8, 0x07, 0xC0, 0x7E, 0x03, 0xF8, 0x1D, 0xE3, 0xC7, 0xFC, 0x1F, 0xC0,
|
||||||
|
0x1E, 0xC0, 0xDE, 0x00, 0x00, 0x1F, 0x03, 0xFE, 0x3F, 0xF9, 0xC1, 0xFC,
|
||||||
|
0x07, 0xE0, 0x3F, 0x00, 0xF8, 0x0F, 0xC0, 0x7F, 0x03, 0xBC, 0x78, 0xFF,
|
||||||
|
0x83, 0xF8, 0x00, 0x00, 0xEC, 0x03, 0x60, 0x00, 0x00, 0xF8, 0x1F, 0xF1,
|
||||||
|
0xFF, 0xCE, 0x0F, 0xE0, 0x3F, 0x01, 0xF8, 0x07, 0xC0, 0x7E, 0x03, 0xF8,
|
||||||
|
0x1D, 0xE3, 0xC7, 0xFC, 0x1F, 0xC0, 0x45, 0xDD, 0xF1, 0xC7, 0xDD, 0xF1,
|
||||||
|
0x80, 0x00, 0x60, 0x7F, 0x0F, 0xF8, 0xFF, 0xE7, 0x1F, 0xF1, 0x9F, 0x8C,
|
||||||
|
0xFC, 0xC3, 0xE6, 0x3F, 0x61, 0xFF, 0x0E, 0xF1, 0xE3, 0xFE, 0x1F, 0xE0,
|
||||||
|
0x80, 0x00, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x00, 0xE0, 0x7E, 0x07, 0xE0,
|
||||||
|
0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x77, 0x0F, 0x79,
|
||||||
|
0xE3, 0xFE, 0x1F, 0x80, 0x01, 0xC0, 0x38, 0x07, 0x00, 0x00, 0xE0, 0x7E,
|
||||||
|
0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x77,
|
||||||
|
0x0F, 0x79, 0xE3, 0xFE, 0x1F, 0x80, 0x07, 0x00, 0xF8, 0x19, 0xC0, 0x00,
|
||||||
|
0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07,
|
||||||
|
0xE0, 0x77, 0x0F, 0x79, 0xE3, 0xFE, 0x1F, 0x80, 0x00, 0x01, 0xD8, 0x0D,
|
||||||
|
0x80, 0x00, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0,
|
||||||
|
0x7E, 0x07, 0xE0, 0x77, 0x0F, 0x79, 0xE3, 0xFE, 0x1F, 0x80, 0x01, 0xC0,
|
||||||
|
0x38, 0x07, 0x00, 0x00, 0xE0, 0x3F, 0x07, 0x70, 0xE3, 0x8E, 0x39, 0xC1,
|
||||||
|
0xD8, 0x1F, 0x80, 0xF0, 0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00,
|
||||||
|
0xE0, 0x1C, 0x03, 0xFE, 0x7F, 0xEE, 0x1F, 0xC1, 0xF8, 0x3F, 0x07, 0xE3,
|
||||||
|
0xFF, 0xFB, 0xFE, 0x70, 0x0E, 0x00, 0x00, 0x07, 0xE1, 0xFE, 0x38, 0xEE,
|
||||||
|
0x1D, 0xC3, 0xB9, 0xE7, 0x3E, 0xE7, 0xDC, 0x1F, 0x83, 0xF0, 0xFE, 0xFD,
|
||||||
|
0xDF, 0x00, 0x70, 0x1C, 0x07, 0x00, 0x03, 0xC7, 0xF9, 0x9E, 0x07, 0x3F,
|
||||||
|
0xFF, 0xF8, 0xF8, 0x7F, 0xFB, 0xFC, 0x07, 0x07, 0x07, 0x00, 0x03, 0xC7,
|
||||||
|
0xF9, 0x9E, 0x07, 0x3F, 0xFF, 0xF8, 0xF8, 0x7F, 0xFB, 0xFC, 0x1C, 0x1F,
|
||||||
|
0x19, 0xC0, 0x03, 0xC7, 0xF9, 0x9E, 0x07, 0x3F, 0xFF, 0xF8, 0xF8, 0x7F,
|
||||||
|
0xFB, 0xFC, 0x30, 0x3D, 0x93, 0x80, 0x03, 0xC7, 0xF9, 0x9E, 0x07, 0x3F,
|
||||||
|
0xFF, 0xF8, 0xF8, 0x7F, 0xFB, 0xFC, 0x00, 0x3B, 0x0D, 0x80, 0x03, 0xC7,
|
||||||
|
0xF9, 0x9E, 0x07, 0x3F, 0xFF, 0xF8, 0xF8, 0x7F, 0xFB, 0xFC, 0x1C, 0x1B,
|
||||||
|
0x09, 0x83, 0x80, 0x01, 0xE3, 0xFC, 0xCF, 0x03, 0x9F, 0xFF, 0xFC, 0x7C,
|
||||||
|
0x3F, 0xFD, 0xFE, 0x3C, 0x78, 0xFF, 0xFE, 0x67, 0xCF, 0x03, 0x87, 0x3F,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xE3, 0x80, 0xC3, 0xC6, 0xFF, 0xFF, 0x7C, 0x7C, 0x1E,
|
||||||
|
0x3F, 0xFF, 0xFC, 0x2C, 0x06, 0x03, 0x81, 0xE7, 0x7F, 0x9F, 0x86, 0x03,
|
||||||
|
0x80, 0x41, 0xE0, 0x70, 0x0E, 0x01, 0xC0, 0x00, 0x1E, 0x1F, 0xCF, 0x3B,
|
||||||
|
0x87, 0xFF, 0xFF, 0xFE, 0x03, 0xC4, 0x7F, 0x8F, 0xC0, 0x07, 0x03, 0x81,
|
||||||
|
0xC0, 0x00, 0x1E, 0x1F, 0xCF, 0x3B, 0x87, 0xFF, 0xFF, 0xFE, 0x03, 0xC4,
|
||||||
|
0x7F, 0x8F, 0xC0, 0x1C, 0x0F, 0x86, 0x70, 0x00, 0x1E, 0x1F, 0xCF, 0x3B,
|
||||||
|
0x87, 0xFF, 0xFF, 0xFE, 0x03, 0xC4, 0x7F, 0x8F, 0xC0, 0x00, 0x1D, 0x83,
|
||||||
|
0x60, 0x00, 0x1E, 0x1F, 0xCF, 0x3B, 0x87, 0xFF, 0xFF, 0xFE, 0x03, 0xC4,
|
||||||
|
0x7F, 0x8F, 0xC0, 0xE3, 0x8E, 0x03, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9C,
|
||||||
|
0x3B, 0xB8, 0x0E, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x70, 0x38, 0xF1, 0xB0,
|
||||||
|
0x03, 0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x00, 0xDE, 0xC0,
|
||||||
|
0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x00, 0x3D, 0x83, 0xC1, 0xF0, 0xCE,
|
||||||
|
0x01, 0x8F, 0xF7, 0xFD, 0xC7, 0xE1, 0xF8, 0x77, 0x1D, 0xFE, 0x3F, 0x00,
|
||||||
|
0x18, 0x0F, 0x62, 0x70, 0x00, 0xEF, 0x3F, 0xEF, 0xFF, 0xC7, 0xE1, 0xF8,
|
||||||
|
0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x70, 0x70, 0x0E, 0x01, 0xC0, 0x00, 0x1E,
|
||||||
|
0x1F, 0xEF, 0xFB, 0x87, 0xC1, 0xF0, 0x7E, 0x1F, 0xCF, 0x7F, 0x8F, 0xC0,
|
||||||
|
0x07, 0x03, 0x81, 0xC0, 0x00, 0x1E, 0x1F, 0xEF, 0xFB, 0x87, 0xC1, 0xF0,
|
||||||
|
0x7E, 0x1F, 0xCF, 0x7F, 0x8F, 0xC0, 0x1C, 0x0F, 0x86, 0x70, 0x00, 0x1E,
|
||||||
|
0x1F, 0xEF, 0xFB, 0x87, 0xC1, 0xF0, 0x7E, 0x1F, 0xCF, 0x7F, 0x8F, 0xC0,
|
||||||
|
0x30, 0x1E, 0xC4, 0xE0, 0x00, 0x1E, 0x1F, 0xEF, 0xFB, 0x87, 0xC1, 0xF0,
|
||||||
|
0x7E, 0x1F, 0xCF, 0x7F, 0x8F, 0xC0, 0x00, 0x1D, 0x83, 0x60, 0x00, 0x1E,
|
||||||
|
0x1F, 0xEF, 0xFB, 0x87, 0xC1, 0xF0, 0x7E, 0x1F, 0xCF, 0x7F, 0x8F, 0xC0,
|
||||||
|
0x08, 0x0E, 0x07, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x1C, 0x0E, 0x06,
|
||||||
|
0x00, 0x01, 0x07, 0xC7, 0xFB, 0xFE, 0xE5, 0xF3, 0x7C, 0x9F, 0xE7, 0xF3,
|
||||||
|
0xDF, 0xE3, 0xF1, 0x80, 0x38, 0x07, 0x00, 0xE0, 0x00, 0xE1, 0xF8, 0x7E,
|
||||||
|
0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0xCF, 0x7F, 0xCF, 0xF0, 0x03, 0x81,
|
||||||
|
0xC0, 0xE0, 0x00, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F,
|
||||||
|
0xCF, 0x7F, 0xCF, 0xF0, 0x0E, 0x07, 0xC3, 0x38, 0x00, 0xE1, 0xF8, 0x7E,
|
||||||
|
0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0xCF, 0x7F, 0xCF, 0xF0, 0x00, 0x0E,
|
||||||
|
0xC1, 0xB0, 0x00, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F,
|
||||||
|
0xCF, 0x7F, 0xCF, 0xF0, 0x03, 0x80, 0xE0, 0x38, 0x00, 0x0E, 0x0F, 0xC1,
|
||||||
|
0x9C, 0x73, 0x8E, 0x33, 0x87, 0x70, 0x6C, 0x0F, 0x81, 0xE0, 0x1C, 0x03,
|
||||||
|
0x87, 0xE0, 0xF8, 0x0E, 0x00, 0xE0, 0x1C, 0x03, 0x80, 0x77, 0x8F, 0xF9,
|
||||||
|
0xF7, 0xBC, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0xC7, 0x7F, 0xEE, 0xF9, 0xC0,
|
||||||
|
0x38, 0x07, 0x00, 0x00, 0x07, 0x60, 0x6C, 0x00, 0x0E, 0x0F, 0xC1, 0x9C,
|
||||||
|
0x73, 0x8E, 0x33, 0x87, 0x70, 0x6C, 0x0F, 0x81, 0xE0, 0x1C, 0x03, 0x87,
|
||||||
|
0xE0, 0xF8, 0x0E, 0x00, 0x0F, 0xE0, 0x3F, 0x80, 0x00, 0x01, 0xC0, 0x07,
|
||||||
|
0x80, 0x1E, 0x00, 0xFC, 0x03, 0x70, 0x1C, 0xE0, 0x73, 0x83, 0x87, 0x0F,
|
||||||
|
0xFC, 0x7F, 0xF1, 0xC0, 0xE6, 0x03, 0xB8, 0x07, 0x7F, 0x3F, 0x80, 0x07,
|
||||||
|
0x8F, 0xF3, 0x3C, 0x0E, 0x7F, 0xFF, 0xF1, 0xF0, 0xFF, 0xF7, 0xF8, 0x0C,
|
||||||
|
0x60, 0x33, 0x00, 0x7C, 0x00, 0x00, 0x07, 0x00, 0x1E, 0x00, 0x78, 0x03,
|
||||||
|
0xF0, 0x0D, 0xC0, 0x73, 0x81, 0xCE, 0x0E, 0x1C, 0x3F, 0xF1, 0xFF, 0xC7,
|
||||||
|
0x03, 0x98, 0x0E, 0xE0, 0x1C, 0x63, 0x33, 0x0F, 0x80, 0x03, 0xC7, 0xF9,
|
||||||
|
0x9E, 0x07, 0x3F, 0xFF, 0xF8, 0xF8, 0x7F, 0xFB, 0xFC, 0x07, 0x00, 0x1E,
|
||||||
|
0x00, 0x78, 0x03, 0xF0, 0x0D, 0xC0, 0x73, 0x81, 0xCE, 0x0E, 0x1C, 0x3F,
|
||||||
|
0xF1, 0xFF, 0xC7, 0x03, 0x98, 0x0E, 0xE0, 0x1C, 0x00, 0xE0, 0x03, 0x00,
|
||||||
|
0x0C, 0x00, 0x3C, 0x3C, 0x7F, 0x99, 0xE0, 0x73, 0xFF, 0xFF, 0x8F, 0x87,
|
||||||
|
0xFF, 0xBF, 0xC1, 0xC0, 0xC0, 0x60, 0x3C, 0x01, 0xC0, 0x38, 0x07, 0x00,
|
||||||
|
0x00, 0x0F, 0x83, 0xFE, 0x7F, 0xF7, 0x06, 0xE0, 0x0E, 0x00, 0xE0, 0x0E,
|
||||||
|
0x00, 0xE0, 0x0F, 0x00, 0x78, 0xE3, 0xFE, 0x1F, 0xC0, 0x07, 0x07, 0x07,
|
||||||
|
0x00, 0x01, 0xE3, 0xFF, 0xFF, 0xC2, 0xC0, 0x60, 0x38, 0x1E, 0x77, 0xF9,
|
||||||
|
0xF8, 0x07, 0x00, 0xF8, 0x19, 0xC0, 0x00, 0x0F, 0x83, 0xFE, 0x7F, 0xF7,
|
||||||
|
0x06, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0F, 0x00, 0x78, 0xE3,
|
||||||
|
0xFE, 0x1F, 0xC0, 0x1C, 0x1F, 0x19, 0xC0, 0x01, 0xE3, 0xFF, 0xFF, 0xC2,
|
||||||
|
0xC0, 0x60, 0x38, 0x1E, 0x77, 0xF9, 0xF8, 0x07, 0x00, 0x70, 0x07, 0x00,
|
||||||
|
0x00, 0x0F, 0x83, 0xFE, 0x7F, 0xF7, 0x06, 0xE0, 0x0E, 0x00, 0xE0, 0x0E,
|
||||||
|
0x00, 0xE0, 0x0F, 0x00, 0x78, 0xE3, 0xFE, 0x1F, 0xC0, 0x1C, 0x0E, 0x07,
|
||||||
|
0x00, 0x01, 0xE3, 0xFF, 0xFF, 0xC2, 0xC0, 0x60, 0x38, 0x1E, 0x77, 0xF9,
|
||||||
|
0xF8, 0x18, 0xC0, 0xD8, 0x07, 0x00, 0x00, 0x0F, 0x83, 0xFE, 0x7F, 0xF7,
|
||||||
|
0x06, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0F, 0x00, 0x78, 0xE3,
|
||||||
|
0xFE, 0x1F, 0xC0, 0x63, 0x1B, 0x07, 0x00, 0x01, 0xE3, 0xFF, 0xFF, 0xC2,
|
||||||
|
0xC0, 0x60, 0x38, 0x1E, 0x77, 0xF9, 0xF8, 0x31, 0x80, 0xD8, 0x03, 0x80,
|
||||||
|
0x00, 0x0F, 0xF0, 0x7F, 0xE3, 0xFF, 0xDC, 0x0E, 0xE0, 0x3F, 0x01, 0xF8,
|
||||||
|
0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x3F, 0x87, 0xDF, 0xFC, 0xFF, 0x80, 0x00,
|
||||||
|
0x18, 0x07, 0x60, 0x1D, 0x80, 0x70, 0x1D, 0xC1, 0xFF, 0x0F, 0xFC, 0x38,
|
||||||
|
0x70, 0xE1, 0xC3, 0x07, 0x0E, 0x1C, 0x3C, 0xF0, 0x7F, 0xC0, 0xFF, 0x00,
|
||||||
|
0xFF, 0x07, 0xFE, 0x3F, 0xFD, 0xC0, 0xEE, 0x03, 0xF0, 0x1F, 0xF8, 0xFF,
|
||||||
|
0xC7, 0xE0, 0x3F, 0x03, 0xF8, 0x7D, 0xFF, 0xCF, 0xF8, 0x00, 0x0F, 0xE1,
|
||||||
|
0xFC, 0x07, 0x0E, 0xE7, 0xFD, 0xFF, 0xB8, 0x77, 0x0E, 0xC1, 0xDC, 0x3B,
|
||||||
|
0xCF, 0x3F, 0xE3, 0xFC, 0x3F, 0x8F, 0xE0, 0x03, 0xFF, 0xFF, 0xFF, 0xFE,
|
||||||
|
0x03, 0x80, 0xFF, 0xBF, 0xEF, 0xFB, 0x80, 0xE0, 0x38, 0x0F, 0xFF, 0xFF,
|
||||||
|
0x7F, 0x1F, 0xC0, 0x00, 0x78, 0x7F, 0x3C, 0xEE, 0x1F, 0xFF, 0xFF, 0xF8,
|
||||||
|
0x0F, 0x11, 0xFE, 0x3F, 0x00, 0x31, 0x8C, 0xC1, 0xF0, 0x00, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0x80, 0xE0, 0x3F, 0xEF, 0xFB, 0xFE, 0xE0, 0x38, 0x0E, 0x03,
|
||||||
|
0xFF, 0xFF, 0xC0, 0x63, 0x19, 0x83, 0xE0, 0x00, 0x1E, 0x1F, 0xCF, 0x3B,
|
||||||
|
0x87, 0xFF, 0xFF, 0xFE, 0x03, 0xC4, 0x7F, 0x8F, 0xC0, 0x0E, 0x03, 0x80,
|
||||||
|
0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xE0, 0x3F, 0xEF, 0xFB, 0xFE,
|
||||||
|
0xE0, 0x38, 0x0E, 0x03, 0xFF, 0xFF, 0xC0, 0x1C, 0x07, 0x01, 0xC0, 0x00,
|
||||||
|
0x1E, 0x1F, 0xCF, 0x3B, 0x87, 0xFF, 0xFF, 0xFE, 0x03, 0xC4, 0x7F, 0x8F,
|
||||||
|
0xC0, 0xFF, 0xDF, 0xFB, 0xFF, 0x70, 0x0E, 0x01, 0xFF, 0x3F, 0xE7, 0xFC,
|
||||||
|
0xE0, 0x1C, 0x03, 0x80, 0x7F, 0xEF, 0xFC, 0x03, 0x80, 0x60, 0x0C, 0x01,
|
||||||
|
0xE0, 0x1E, 0x1F, 0xCF, 0x3B, 0x87, 0xFF, 0xFF, 0xFE, 0x03, 0xC4, 0x7F,
|
||||||
|
0x8F, 0xC0, 0x60, 0x10, 0x06, 0x01, 0xE0, 0x31, 0x86, 0xC0, 0xE0, 0x00,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xE0, 0x3F, 0xEF, 0xFB, 0xFE, 0xE0, 0x38,
|
||||||
|
0x0E, 0x03, 0xFF, 0xFF, 0xC0, 0x63, 0x0D, 0x81, 0xC0, 0x00, 0x1E, 0x1F,
|
||||||
|
0xCF, 0x3B, 0x87, 0xFF, 0xFF, 0xFE, 0x03, 0xC4, 0x7F, 0x8F, 0xC0, 0x07,
|
||||||
|
0x00, 0xF8, 0x19, 0xC0, 0x00, 0x0F, 0x83, 0xFE, 0x7F, 0xF7, 0x06, 0xE0,
|
||||||
|
0x0E, 0x00, 0xE0, 0x7E, 0x07, 0xE0, 0x7F, 0x07, 0x78, 0xF3, 0xFF, 0x1F,
|
||||||
|
0xC0, 0x0E, 0x07, 0xC3, 0x38, 0x00, 0x1C, 0xDF, 0xFF, 0xFF, 0x87, 0xC1,
|
||||||
|
0xF8, 0x7E, 0x1F, 0xFF, 0x7F, 0xC2, 0x74, 0x1D, 0xFF, 0xFF, 0x87, 0x00,
|
||||||
|
0x18, 0xC1, 0x98, 0x0F, 0x80, 0x00, 0x0F, 0x83, 0xFE, 0x7F, 0xF7, 0x06,
|
||||||
|
0xE0, 0x0E, 0x00, 0xE0, 0x7E, 0x07, 0xE0, 0x7F, 0x07, 0x78, 0xF3, 0xFF,
|
||||||
|
0x1F, 0xC0, 0x31, 0x8C, 0xC1, 0xF0, 0x00, 0x1C, 0xDF, 0xFF, 0xFF, 0x87,
|
||||||
|
0xC1, 0xF8, 0x7E, 0x1F, 0xFF, 0x7F, 0xC2, 0x74, 0x1D, 0xFF, 0xFF, 0x87,
|
||||||
|
0x00, 0x07, 0x00, 0x70, 0x07, 0x00, 0x00, 0x0F, 0x83, 0xFE, 0x7F, 0xF7,
|
||||||
|
0x06, 0xE0, 0x0E, 0x00, 0xE0, 0x7E, 0x07, 0xE0, 0x7F, 0x07, 0x78, 0xF3,
|
||||||
|
0xFF, 0x1F, 0xC0, 0x0E, 0x03, 0x80, 0xE0, 0x00, 0x1C, 0xDF, 0xFF, 0xFF,
|
||||||
|
0x87, 0xC1, 0xF8, 0x7E, 0x1F, 0xFF, 0x7F, 0xC2, 0x74, 0x1D, 0xFF, 0xFF,
|
||||||
|
0x87, 0x00, 0x0F, 0x83, 0xFE, 0x7F, 0xF7, 0x06, 0xE0, 0x0E, 0x00, 0xE0,
|
||||||
|
0x7E, 0x07, 0xE0, 0x7F, 0x07, 0x78, 0xF3, 0xFF, 0x1F, 0xC0, 0x00, 0x06,
|
||||||
|
0x00, 0x70, 0x02, 0x00, 0x60, 0x06, 0x01, 0x00, 0xE0, 0x38, 0x00, 0x07,
|
||||||
|
0x37, 0xFF, 0xFF, 0xE1, 0xF0, 0x7E, 0x1F, 0x87, 0xFF, 0xDF, 0xF0, 0x9D,
|
||||||
|
0x07, 0x7F, 0xFF, 0xE1, 0xC0, 0x07, 0x00, 0xF8, 0x19, 0xC0, 0x00, 0xE0,
|
||||||
|
0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
|
||||||
|
0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x70, 0x38, 0x07, 0xC0, 0xCE, 0x00,
|
||||||
|
0x00, 0x38, 0x03, 0x80, 0x38, 0x03, 0xBC, 0x3F, 0xE3, 0xFF, 0x3C, 0x73,
|
||||||
|
0x87, 0x38, 0x73, 0x87, 0x38, 0x73, 0x87, 0x38, 0x70, 0x38, 0x38, 0x70,
|
||||||
|
0x73, 0xFF, 0xFF, 0xFF, 0xF3, 0x83, 0x87, 0x07, 0x0F, 0xFE, 0x1F, 0xFC,
|
||||||
|
0x38, 0x38, 0x70, 0x70, 0xE0, 0xE1, 0xC1, 0xC3, 0x83, 0x80, 0x30, 0x1F,
|
||||||
|
0xC0, 0xC0, 0x19, 0xC3, 0xFE, 0x7F, 0xCE, 0x39, 0x83, 0x30, 0x66, 0x0C,
|
||||||
|
0xC1, 0x98, 0x33, 0x06, 0x75, 0xB8, 0x03, 0x87, 0x0E, 0x1C, 0x38, 0x70,
|
||||||
|
0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38, 0x21, 0xDD, 0xC0, 0x38, 0xE3, 0x8E,
|
||||||
|
0x38, 0xE3, 0x8E, 0x38, 0xE0, 0xFF, 0xC1, 0xCE, 0x73, 0x9C, 0xE7, 0x39,
|
||||||
|
0xCE, 0x73, 0x9C, 0xFF, 0xC0, 0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x00,
|
||||||
|
0xC7, 0x99, 0xF0, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E,
|
||||||
|
0x1C, 0x38, 0x70, 0x8E, 0xFC, 0x07, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x38,
|
||||||
|
0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE6, 0x66, 0x70, 0xFF, 0x8F, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xF6, 0xDC, 0x77, 0x70, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
|
||||||
|
0xE0, 0xFF, 0xFF, 0xFF, 0xFC, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F,
|
||||||
|
0xC1, 0xF8, 0x38, 0x07, 0x00, 0xE0, 0x39, 0x8F, 0x7F, 0xC7, 0xF0, 0xE3,
|
||||||
|
0xF1, 0xF8, 0xE0, 0x0E, 0x77, 0x3B, 0x9D, 0xCE, 0xE7, 0x73, 0xB9, 0xDC,
|
||||||
|
0xEE, 0x77, 0x38, 0x1C, 0x3E, 0x1E, 0x0E, 0x00, 0x1C, 0x3E, 0x67, 0x00,
|
||||||
|
0x7F, 0x7F, 0x7F, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xC7, 0xFF,
|
||||||
|
0x7E, 0x1C, 0x3C, 0x36, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
|
||||||
|
0x1C, 0x1C, 0x1C, 0x1C, 0x7C, 0x78, 0x70, 0xE0, 0x77, 0x07, 0x38, 0x71,
|
||||||
|
0xC7, 0x0E, 0x70, 0x77, 0x03, 0xF8, 0x1F, 0xE0, 0xFF, 0x87, 0x9E, 0x38,
|
||||||
|
0x79, 0xC1, 0xCE, 0x07, 0x00, 0x00, 0x30, 0x01, 0xC0, 0x04, 0x00, 0x60,
|
||||||
|
0x00, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0xEE, 0x39, 0xCE, 0x3B, 0x87, 0xF0,
|
||||||
|
0xFE, 0x1E, 0xE3, 0x9E, 0x71, 0xEE, 0x1E, 0x00, 0x06, 0x00, 0xE0, 0x08,
|
||||||
|
0x03, 0x00, 0xE1, 0xDC, 0x73, 0x9C, 0x77, 0x0F, 0xE1, 0xFC, 0x3D, 0xC7,
|
||||||
|
0x3C, 0xE3, 0xDC, 0x3C, 0x1C, 0x0E, 0x07, 0x00, 0x00, 0xE0, 0x38, 0x0E,
|
||||||
|
0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0xFF,
|
||||||
|
0xFF, 0xC0, 0x3B, 0xB8, 0x0E, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9C,
|
||||||
|
0xE0, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0,
|
||||||
|
0x38, 0x0E, 0x03, 0xFF, 0xFF, 0xC0, 0x00, 0xC0, 0x38, 0x04, 0x03, 0x00,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x37, 0x58, 0xE3, 0x38, 0xCE, 0x33, 0x80,
|
||||||
|
0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0xFF, 0xFF, 0xC0,
|
||||||
|
0x0D, 0xDB, 0xB7, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x1C,
|
||||||
|
0x00, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE3, 0xB8, 0xEE, 0x3B, 0x80, 0xE0,
|
||||||
|
0x38, 0x0E, 0x03, 0xFF, 0xFF, 0xC0, 0xE1, 0xC3, 0x87, 0x0E, 0x1D, 0xBB,
|
||||||
|
0xF6, 0xE1, 0xC3, 0x87, 0x0E, 0x00, 0x70, 0x0E, 0x01, 0xC0, 0x3B, 0x87,
|
||||||
|
0xE0, 0xF8, 0x1C, 0x07, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x3F, 0xF7, 0xFE,
|
||||||
|
0x38, 0x70, 0xE1, 0xC3, 0xC7, 0xCF, 0x3C, 0xF8, 0xF0, 0xE1, 0xC3, 0x80,
|
||||||
|
0x01, 0xC0, 0x38, 0x07, 0x00, 0x00, 0xE0, 0x7F, 0x07, 0xF8, 0x7F, 0x87,
|
||||||
|
0xFC, 0x7F, 0xE7, 0xEF, 0x7E, 0x7F, 0xE3, 0xFE, 0x1F, 0xE0, 0xFE, 0x0F,
|
||||||
|
0xE0, 0x70, 0x03, 0x81, 0xC0, 0xE0, 0x00, 0xEF, 0x3F, 0xEF, 0xFF, 0xC7,
|
||||||
|
0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x70, 0xE0, 0x7F, 0x07, 0xF8,
|
||||||
|
0x7F, 0x87, 0xFC, 0x7F, 0xE7, 0xEF, 0x7E, 0x7F, 0xE3, 0xFE, 0x1F, 0xE0,
|
||||||
|
0xFE, 0x0F, 0xE0, 0x70, 0x00, 0x06, 0x00, 0x70, 0x02, 0x00, 0x60, 0xEF,
|
||||||
|
0x3F, 0xEF, 0xFF, 0xC7, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x70,
|
||||||
|
0x00, 0x30, 0x0E, 0x01, 0x00, 0xC0, 0x18, 0xC0, 0xD8, 0x07, 0x00, 0x00,
|
||||||
|
0xE0, 0x7F, 0x07, 0xF8, 0x7F, 0x87, 0xFC, 0x7F, 0xE7, 0xEF, 0x7E, 0x7F,
|
||||||
|
0xE3, 0xFE, 0x1F, 0xE0, 0xFE, 0x0F, 0xE0, 0x70, 0x31, 0x86, 0xC0, 0xE0,
|
||||||
|
0x00, 0xEF, 0x3F, 0xEF, 0xFF, 0xC7, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1,
|
||||||
|
0xF8, 0x70, 0x00, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0D, 0xDE, 0x6F, 0xFB,
|
||||||
|
0x7F, 0xE3, 0xC7, 0x1C, 0x38, 0xE1, 0xC7, 0x0E, 0x38, 0x71, 0xC3, 0x8E,
|
||||||
|
0x1C, 0xE0, 0x7F, 0x07, 0xF8, 0x7F, 0x87, 0xFC, 0x7F, 0xE7, 0xEF, 0x7E,
|
||||||
|
0x7F, 0xE3, 0xFE, 0x1F, 0xE0, 0xFE, 0x0F, 0xE0, 0x70, 0x07, 0x07, 0xF0,
|
||||||
|
0xFE, 0x03, 0x80, 0xEF, 0x3F, 0xEF, 0xFF, 0xC7, 0xE1, 0xF8, 0x7E, 0x1F,
|
||||||
|
0x87, 0xE1, 0xF8, 0x70, 0x1C, 0x1F, 0x07, 0x81, 0xC0, 0x1F, 0xC0, 0xFE,
|
||||||
|
0x00, 0x00, 0x1F, 0x03, 0xFE, 0x3F, 0xF9, 0xC1, 0xFC, 0x07, 0xE0, 0x3F,
|
||||||
|
0x00, 0xF8, 0x0F, 0xC0, 0x7F, 0x03, 0xBC, 0x78, 0xFF, 0x83, 0xF8, 0x7F,
|
||||||
|
0x1F, 0xC0, 0x00, 0x78, 0x7F, 0xBF, 0xEE, 0x1F, 0x07, 0xC1, 0xF8, 0x7F,
|
||||||
|
0x3D, 0xFE, 0x3F, 0x00, 0x18, 0xC0, 0xCC, 0x03, 0xE0, 0x00, 0x00, 0xF8,
|
||||||
|
0x1F, 0xF1, 0xFF, 0xCE, 0x0F, 0xE0, 0x3F, 0x01, 0xF8, 0x07, 0xC0, 0x7E,
|
||||||
|
0x03, 0xF8, 0x1D, 0xE3, 0xC7, 0xFC, 0x1F, 0xC0, 0x63, 0x19, 0x83, 0xE0,
|
||||||
|
0x00, 0x1E, 0x1F, 0xEF, 0xFB, 0x87, 0xC1, 0xF0, 0x7E, 0x1F, 0xCF, 0x7F,
|
||||||
|
0x8F, 0xC0, 0x06, 0xE0, 0x76, 0x03, 0x70, 0x00, 0x00, 0xF8, 0x1F, 0xF1,
|
||||||
|
0xFF, 0xCE, 0x0F, 0xE0, 0x3F, 0x01, 0xF8, 0x07, 0xC0, 0x7E, 0x03, 0xF8,
|
||||||
|
0x1D, 0xE3, 0xC7, 0xFC, 0x1F, 0xC0, 0x1B, 0x8E, 0xC3, 0x70, 0x00, 0x1E,
|
||||||
|
0x1F, 0xEF, 0xFB, 0x87, 0xC1, 0xF0, 0x7E, 0x1F, 0xCF, 0x7F, 0x8F, 0xC0,
|
||||||
|
0x07, 0xFF, 0xC7, 0xFF, 0xF9, 0xFF, 0xFF, 0x38, 0x38, 0x0E, 0x07, 0x01,
|
||||||
|
0xC0, 0xFF, 0xB8, 0x1F, 0xF7, 0x03, 0xFE, 0xE0, 0x70, 0x1E, 0x0E, 0x01,
|
||||||
|
0xF1, 0xC0, 0x1F, 0xFF, 0xF0, 0xFF, 0xFE, 0x1E, 0x1C, 0x1F, 0xDF, 0xCF,
|
||||||
|
0xFE, 0x3B, 0x87, 0x06, 0xC1, 0xFF, 0xF0, 0x7F, 0xFE, 0x1C, 0x03, 0xCF,
|
||||||
|
0x84, 0x7F, 0xFF, 0x8F, 0x8F, 0xC0, 0x03, 0x80, 0x70, 0x0E, 0x00, 0x00,
|
||||||
|
0xFE, 0x0F, 0xFC, 0xFF, 0xEE, 0x0E, 0xE0, 0xEE, 0x0E, 0xE0, 0xEF, 0xFE,
|
||||||
|
0xFF, 0xCE, 0x38, 0xE1, 0xCE, 0x1E, 0xE0, 0xE0, 0x0E, 0x38, 0xE0, 0x0E,
|
||||||
|
0xDF, 0xBF, 0x78, 0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x00, 0xFE, 0x0F, 0xFC,
|
||||||
|
0xFF, 0xEE, 0x0E, 0xE0, 0xEE, 0x0E, 0xE0, 0xEF, 0xFE, 0xFF, 0xCE, 0x38,
|
||||||
|
0xE1, 0xCE, 0x1E, 0xE0, 0xE0, 0x00, 0x0C, 0x00, 0xE0, 0x04, 0x00, 0xC0,
|
||||||
|
0xEF, 0xFF, 0xFC, 0xE3, 0x8E, 0x38, 0xE3, 0x80, 0x30, 0xE1, 0x0C, 0x00,
|
||||||
|
0x31, 0x81, 0xB0, 0x0E, 0x00, 0x00, 0xFE, 0x0F, 0xFC, 0xFF, 0xEE, 0x0E,
|
||||||
|
0xE0, 0xEE, 0x0E, 0xE0, 0xEF, 0xFE, 0xFF, 0xCE, 0x38, 0xE1, 0xCE, 0x1E,
|
||||||
|
0xE0, 0xE0, 0xC6, 0xD8, 0xE0, 0x0E, 0xDF, 0xBF, 0x78, 0xE1, 0xC3, 0x87,
|
||||||
|
0x0E, 0x1C, 0x00, 0x03, 0x80, 0xE0, 0x38, 0x00, 0x00, 0xF8, 0x7F, 0x9F,
|
||||||
|
0xF3, 0x80, 0x70, 0x0F, 0x80, 0xFE, 0x07, 0xE0, 0x1E, 0x01, 0xD8, 0x3B,
|
||||||
|
0xFE, 0x3F, 0x80, 0x07, 0x07, 0x07, 0x00, 0x01, 0xF3, 0xFD, 0xC4, 0xC0,
|
||||||
|
0x7E, 0x1F, 0xC0, 0xE8, 0x77, 0xFB, 0xF8, 0x0E, 0x03, 0xE0, 0xCE, 0x00,
|
||||||
|
0x00, 0xF8, 0x7F, 0x9F, 0xF3, 0x80, 0x70, 0x0F, 0x80, 0xFE, 0x07, 0xE0,
|
||||||
|
0x1E, 0x01, 0xD8, 0x3B, 0xFE, 0x3F, 0x80, 0x1C, 0x1F, 0x19, 0xC0, 0x01,
|
||||||
|
0xF3, 0xFD, 0xC4, 0xC0, 0x7E, 0x1F, 0xC0, 0xE8, 0x77, 0xFB, 0xF8, 0x0F,
|
||||||
|
0x87, 0xF9, 0xFF, 0x38, 0x07, 0x00, 0xF8, 0x0F, 0xE0, 0x7E, 0x01, 0xE0,
|
||||||
|
0x1D, 0x83, 0xBF, 0xE3, 0xF8, 0x18, 0x03, 0x80, 0x10, 0x1E, 0x00, 0x1F,
|
||||||
|
0x3F, 0xDC, 0x4C, 0x07, 0xE1, 0xFC, 0x0E, 0x87, 0x7F, 0xBF, 0x86, 0x03,
|
||||||
|
0x80, 0x41, 0xE0, 0x31, 0x83, 0x60, 0x38, 0x00, 0x00, 0xF8, 0x7F, 0x9F,
|
||||||
|
0xF3, 0x80, 0x70, 0x0F, 0x80, 0xFE, 0x07, 0xE0, 0x1E, 0x01, 0xD8, 0x3B,
|
||||||
|
0xFE, 0x3F, 0x80, 0x63, 0x1B, 0x07, 0x00, 0x01, 0xF3, 0xFD, 0xC4, 0xC0,
|
||||||
|
0x7E, 0x1F, 0xC0, 0xE8, 0x77, 0xFB, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x87,
|
||||||
|
0x00, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00,
|
||||||
|
0xE0, 0x18, 0x03, 0x80, 0x10, 0x1E, 0x00, 0x30, 0x30, 0xFE, 0xFE, 0x30,
|
||||||
|
0x30, 0x30, 0x30, 0x30, 0x38, 0x3E, 0x1F, 0x18, 0x1C, 0x04, 0x3C, 0x31,
|
||||||
|
0x83, 0x60, 0x38, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xF8, 0x70, 0x0E, 0x01,
|
||||||
|
0xC0, 0x38, 0x07, 0x00, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x00, 0x06,
|
||||||
|
0x06, 0x36, 0x30, 0xFE, 0xFE, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x3E,
|
||||||
|
0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0xE0, 0x1C, 0x0F, 0xE1, 0xFC,
|
||||||
|
0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xE0, 0x38, 0x38, 0x38, 0xFE, 0xFE,
|
||||||
|
0x38, 0xFC, 0xFC, 0x38, 0x38, 0x3E, 0x1F, 0x1E, 0xC1, 0xBC, 0x00, 0x0E,
|
||||||
|
0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E,
|
||||||
|
0x07, 0x70, 0xF7, 0x9E, 0x3F, 0xE1, 0xF8, 0x18, 0x0F, 0x62, 0x70, 0x00,
|
||||||
|
0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0xCF, 0x7F, 0xCF,
|
||||||
|
0xF0, 0x1F, 0xC1, 0xFC, 0x00, 0x0E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E,
|
||||||
|
0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0x70, 0xF7, 0x9E, 0x3F, 0xE1,
|
||||||
|
0xF8, 0x3F, 0x8F, 0xE0, 0x03, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1,
|
||||||
|
0xF8, 0x7F, 0x3D, 0xFF, 0x3F, 0xC0, 0x18, 0xC1, 0x98, 0x0F, 0x80, 0x00,
|
||||||
|
0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07,
|
||||||
|
0xE0, 0x77, 0x0F, 0x79, 0xE3, 0xFE, 0x1F, 0x80, 0x31, 0x8C, 0xC1, 0xF0,
|
||||||
|
0x00, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0xCF, 0x7F,
|
||||||
|
0xCF, 0xF0, 0x07, 0x00, 0xD8, 0x09, 0x80, 0x70, 0x00, 0x0E, 0x07, 0xE0,
|
||||||
|
0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0x70,
|
||||||
|
0xF7, 0x9E, 0x3F, 0xE1, 0xF8, 0x0E, 0x06, 0xC1, 0x30, 0x38, 0x00, 0x38,
|
||||||
|
0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xF3, 0xDF, 0xF3, 0xFC,
|
||||||
|
0x06, 0xE0, 0xEC, 0x0D, 0xC0, 0x00, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07,
|
||||||
|
0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x77, 0x0F, 0x79, 0xE3, 0xFE,
|
||||||
|
0x1F, 0x80, 0x0D, 0xC7, 0x61, 0xB8, 0x00, 0xE1, 0xF8, 0x7E, 0x1F, 0x87,
|
||||||
|
0xE1, 0xF8, 0x7E, 0x1F, 0xCF, 0x7F, 0xCF, 0xF0, 0xE0, 0x7E, 0x07, 0xE0,
|
||||||
|
0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x77, 0x0F, 0x79,
|
||||||
|
0xE3, 0xFC, 0x1F, 0x80, 0x60, 0x0C, 0x00, 0xC0, 0x07, 0x00, 0xE1, 0xF8,
|
||||||
|
0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0xCF, 0x7F, 0xCF, 0xF0, 0x38,
|
||||||
|
0x0C, 0x03, 0x00, 0xF0, 0x00, 0x70, 0x00, 0x07, 0xC0, 0x00, 0x67, 0x00,
|
||||||
|
0x00, 0x00, 0x0E, 0x07, 0x03, 0xB8, 0x38, 0x39, 0xC1, 0xE1, 0xCE, 0x1F,
|
||||||
|
0x0E, 0x38, 0xD8, 0xE1, 0xC6, 0xE7, 0x0E, 0x77, 0x38, 0x3B, 0x3B, 0x81,
|
||||||
|
0xD8, 0xFC, 0x0F, 0xC7, 0xE0, 0x3C, 0x3E, 0x01, 0xE0, 0xF0, 0x0F, 0x07,
|
||||||
|
0x80, 0x01, 0xC0, 0x01, 0xF0, 0x01, 0x9C, 0x00, 0x00, 0x0E, 0x1C, 0x3F,
|
||||||
|
0x0E, 0x19, 0x87, 0x0C, 0xE7, 0xCE, 0x33, 0x66, 0x1B, 0xBB, 0x0F, 0xDF,
|
||||||
|
0x83, 0xC7, 0x81, 0xE3, 0xC0, 0xE1, 0xE0, 0x07, 0x00, 0xF8, 0x19, 0xC0,
|
||||||
|
0x00, 0xE0, 0x3F, 0x07, 0x70, 0xE3, 0x8E, 0x39, 0xC1, 0xD8, 0x1F, 0x80,
|
||||||
|
0xF0, 0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00, 0x0E, 0x03, 0xE0,
|
||||||
|
0xCE, 0x00, 0x0E, 0x0F, 0xC1, 0x9C, 0x73, 0x8E, 0x33, 0x87, 0x70, 0x6C,
|
||||||
|
0x0F, 0x81, 0xE0, 0x1C, 0x03, 0x87, 0xE0, 0xF8, 0x0E, 0x00, 0x00, 0x01,
|
||||||
|
0xD8, 0x0D, 0x80, 0x00, 0xE0, 0x3F, 0x07, 0x70, 0xE3, 0x8E, 0x39, 0xC1,
|
||||||
|
0xD8, 0x1F, 0x80, 0xF0, 0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00,
|
||||||
|
0x03, 0x80, 0xE0, 0x38, 0x00, 0x0F, 0xFD, 0xFF, 0xBF, 0xF0, 0x1C, 0x07,
|
||||||
|
0x81, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x3C, 0x07, 0xFF, 0xFF, 0xE0,
|
||||||
|
0x07, 0x0E, 0x1C, 0x00, 0xFF, 0xFF, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0,
|
||||||
|
0xFF, 0xFF, 0x0E, 0x01, 0xC0, 0x38, 0x00, 0x0F, 0xFD, 0xFF, 0xBF, 0xF0,
|
||||||
|
0x1C, 0x07, 0x81, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x3C, 0x07, 0xFF,
|
||||||
|
0xFF, 0xE0, 0x1C, 0x1C, 0x1C, 0x00, 0xFF, 0xFF, 0x07, 0x0E, 0x1C, 0x38,
|
||||||
|
0x70, 0xE0, 0xFF, 0xFF, 0x31, 0x83, 0x60, 0x38, 0x00, 0x0F, 0xFD, 0xFF,
|
||||||
|
0xBF, 0xF0, 0x1C, 0x07, 0x81, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x3C,
|
||||||
|
0x07, 0xFF, 0xFF, 0xE0, 0x63, 0x36, 0x1C, 0x00, 0xFF, 0xFF, 0x07, 0x0E,
|
||||||
|
0x1C, 0x38, 0x70, 0xE0, 0xFF, 0xFF, 0x00, 0x1F, 0x3E, 0x38, 0x38, 0xF8,
|
||||||
|
0xF8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 };
|
||||||
|
|
||||||
|
const GFXglyph MontserratBold9pt8bGlyphs[] PROGMEM = {
|
||||||
|
{ 0, 1, 1, 5, 0, 0 }, // 0x20 ' '
|
||||||
|
{ 1, 3, 13, 5, 1, -12 }, // 0x21 '!'
|
||||||
|
{ 6, 6, 6, 8, 1, -12 }, // 0x22 '"'
|
||||||
|
{ 11, 13, 13, 13, 0, -12 }, // 0x23 '#'
|
||||||
|
{ 33, 11, 17, 11, 0, -14 }, // 0x24 '$'
|
||||||
|
{ 57, 15, 13, 16, 0, -12 }, // 0x25 '%'
|
||||||
|
{ 82, 12, 13, 13, 1, -12 }, // 0x26 '&'
|
||||||
|
{ 102, 2, 6, 4, 1, -12 }, // 0x27 '''
|
||||||
|
{ 104, 5, 16, 6, 1, -12 }, // 0x28 '('
|
||||||
|
{ 114, 5, 16, 6, 0, -12 }, // 0x29 ')'
|
||||||
|
{ 124, 8, 7, 8, 0, -12 }, // 0x2A '*'
|
||||||
|
{ 131, 9, 8, 11, 1, -9 }, // 0x2B '+'
|
||||||
|
{ 140, 3, 6, 5, 1, -2 }, // 0x2C ','
|
||||||
|
{ 143, 5, 2, 7, 1, -5 }, // 0x2D '-'
|
||||||
|
{ 145, 3, 3, 5, 1, -2 }, // 0x2E '.'
|
||||||
|
{ 147, 9, 17, 7, -1, -14 }, // 0x2F '/'
|
||||||
|
{ 167, 11, 13, 12, 1, -12 }, // 0x30 '0'
|
||||||
|
{ 185, 6, 13, 7, 0, -12 }, // 0x31 '1'
|
||||||
|
{ 195, 10, 13, 11, 0, -12 }, // 0x32 '2'
|
||||||
|
{ 212, 10, 13, 11, 0, -12 }, // 0x33 '3'
|
||||||
|
{ 229, 11, 13, 12, 1, -12 }, // 0x34 '4'
|
||||||
|
{ 247, 10, 13, 11, 0, -12 }, // 0x35 '5'
|
||||||
|
{ 264, 10, 13, 11, 1, -12 }, // 0x36 '6'
|
||||||
|
{ 281, 11, 13, 11, 0, -12 }, // 0x37 '7'
|
||||||
|
{ 299, 10, 13, 12, 1, -12 }, // 0x38 '8'
|
||||||
|
{ 316, 11, 13, 11, 0, -12 }, // 0x39 '9'
|
||||||
|
{ 334, 3, 9, 5, 1, -8 }, // 0x3A ':'
|
||||||
|
{ 338, 3, 12, 5, 1, -8 }, // 0x3B ';'
|
||||||
|
{ 343, 9, 9, 11, 1, -10 }, // 0x3C '<'
|
||||||
|
{ 354, 9, 7, 11, 1, -9 }, // 0x3D '='
|
||||||
|
{ 362, 9, 9, 11, 1, -10 }, // 0x3E '>'
|
||||||
|
{ 373, 10, 13, 11, 0, -12 }, // 0x3F '?'
|
||||||
|
{ 390, 17, 17, 19, 1, -12 }, // 0x40 '@'
|
||||||
|
{ 427, 14, 13, 14, 0, -12 }, // 0x41 'A'
|
||||||
|
{ 450, 12, 13, 14, 1, -12 }, // 0x42 'B'
|
||||||
|
{ 470, 12, 13, 13, 1, -12 }, // 0x43 'C'
|
||||||
|
{ 490, 13, 13, 15, 1, -12 }, // 0x44 'D'
|
||||||
|
{ 512, 10, 13, 12, 1, -12 }, // 0x45 'E'
|
||||||
|
{ 529, 10, 13, 12, 1, -12 }, // 0x46 'F'
|
||||||
|
{ 546, 12, 13, 14, 1, -12 }, // 0x47 'G'
|
||||||
|
{ 566, 12, 13, 15, 1, -12 }, // 0x48 'H'
|
||||||
|
{ 586, 3, 13, 6, 1, -12 }, // 0x49 'I'
|
||||||
|
{ 591, 8, 13, 10, 0, -12 }, // 0x4A 'J'
|
||||||
|
{ 604, 13, 13, 13, 1, -12 }, // 0x4B 'K'
|
||||||
|
{ 626, 10, 13, 11, 1, -12 }, // 0x4C 'L'
|
||||||
|
{ 643, 15, 13, 17, 1, -12 }, // 0x4D 'M'
|
||||||
|
{ 668, 12, 13, 15, 1, -12 }, // 0x4E 'N'
|
||||||
|
{ 688, 13, 13, 15, 1, -12 }, // 0x4F 'O'
|
||||||
|
{ 710, 11, 13, 13, 1, -12 }, // 0x50 'P'
|
||||||
|
{ 728, 14, 16, 15, 1, -12 }, // 0x51 'Q'
|
||||||
|
{ 756, 12, 13, 13, 1, -12 }, // 0x52 'R'
|
||||||
|
{ 776, 11, 13, 11, 0, -12 }, // 0x53 'S'
|
||||||
|
{ 794, 11, 13, 11, 0, -12 }, // 0x54 'T'
|
||||||
|
{ 812, 12, 13, 14, 1, -12 }, // 0x55 'U'
|
||||||
|
{ 832, 14, 13, 13, 0, -12 }, // 0x56 'V'
|
||||||
|
{ 855, 21, 13, 21, 0, -12 }, // 0x57 'W'
|
||||||
|
{ 890, 13, 13, 13, 0, -12 }, // 0x58 'X'
|
||||||
|
{ 912, 12, 13, 12, 0, -12 }, // 0x59 'Y'
|
||||||
|
{ 932, 11, 13, 12, 1, -12 }, // 0x5A 'Z'
|
||||||
|
{ 950, 5, 16, 7, 1, -12 }, // 0x5B '['
|
||||||
|
{ 960, 9, 17, 7, -1, -14 }, // 0x5C '\'
|
||||||
|
{ 980, 5, 16, 7, 0, -12 }, // 0x5D ']'
|
||||||
|
{ 990, 9, 7, 11, 1, -9 }, // 0x5E '^'
|
||||||
|
{ 998, 9, 2, 9, 0, 1 }, // 0x5F '_'
|
||||||
|
{ 1001, 5, 3, 11, 2, -13 }, // 0x60 '`'
|
||||||
|
{ 1003, 9, 10, 11, 1, -9 }, // 0x61 'a'
|
||||||
|
{ 1015, 11, 13, 12, 1, -12 }, // 0x62 'b'
|
||||||
|
{ 1033, 9, 10, 11, 1, -9 }, // 0x63 'c'
|
||||||
|
{ 1045, 10, 13, 12, 1, -12 }, // 0x64 'd'
|
||||||
|
{ 1062, 10, 10, 11, 1, -9 }, // 0x65 'e'
|
||||||
|
{ 1075, 8, 14, 7, 0, -13 }, // 0x66 'f'
|
||||||
|
{ 1089, 10, 14, 13, 1, -9 }, // 0x67 'g'
|
||||||
|
{ 1107, 10, 13, 12, 1, -12 }, // 0x68 'h'
|
||||||
|
{ 1124, 3, 14, 5, 1, -13 }, // 0x69 'i'
|
||||||
|
{ 1130, 6, 18, 6, -2, -13 }, // 0x6A 'j'
|
||||||
|
{ 1144, 11, 13, 12, 1, -12 }, // 0x6B 'k'
|
||||||
|
{ 1162, 3, 13, 5, 1, -12 }, // 0x6C 'l'
|
||||||
|
{ 1167, 17, 10, 19, 1, -9 }, // 0x6D 'm'
|
||||||
|
{ 1189, 10, 10, 12, 1, -9 }, // 0x6E 'n'
|
||||||
|
{ 1202, 10, 10, 12, 1, -9 }, // 0x6F 'o'
|
||||||
|
{ 1215, 11, 13, 12, 1, -9 }, // 0x70 'p'
|
||||||
|
{ 1233, 10, 13, 12, 1, -9 }, // 0x71 'q'
|
||||||
|
{ 1250, 6, 10, 8, 1, -9 }, // 0x72 'r'
|
||||||
|
{ 1258, 9, 10, 10, 0, -9 }, // 0x73 's'
|
||||||
|
{ 1270, 8, 12, 8, 0, -11 }, // 0x74 't'
|
||||||
|
{ 1282, 10, 10, 12, 1, -9 }, // 0x75 'u'
|
||||||
|
{ 1295, 11, 10, 11, 0, -9 }, // 0x76 'v'
|
||||||
|
{ 1309, 17, 10, 17, 0, -9 }, // 0x77 'w'
|
||||||
|
{ 1331, 11, 10, 11, 0, -9 }, // 0x78 'x'
|
||||||
|
{ 1345, 11, 14, 11, 0, -9 }, // 0x79 'y'
|
||||||
|
{ 1365, 8, 10, 10, 1, -9 }, // 0x7A 'z'
|
||||||
|
{ 1375, 6, 16, 7, 1, -12 }, // 0x7B '{'
|
||||||
|
{ 1387, 3, 16, 6, 1, -12 }, // 0x7C '|'
|
||||||
|
{ 1393, 6, 16, 7, 0, -12 }, // 0x7D '}'
|
||||||
|
{ 1405, 9, 3, 11, 1, -7 }, // 0x7E '~'
|
||||||
|
{ 1409, 9, 13, 11, 1, -12 }, // 0x7F
|
||||||
|
{ 1424, 9, 13, 11, 1, -12 }, // 0x80
|
||||||
|
{ 1439, 9, 13, 11, 1, -12 }, // 0x81
|
||||||
|
{ 1454, 9, 13, 11, 1, -12 }, // 0x82
|
||||||
|
{ 1469, 9, 13, 11, 1, -12 }, // 0x83
|
||||||
|
{ 1484, 9, 13, 11, 1, -12 }, // 0x84
|
||||||
|
{ 1499, 9, 13, 11, 1, -12 }, // 0x85
|
||||||
|
{ 1514, 9, 13, 11, 1, -12 }, // 0x86
|
||||||
|
{ 1529, 9, 13, 11, 1, -12 }, // 0x87
|
||||||
|
{ 1544, 9, 13, 11, 1, -12 }, // 0x88
|
||||||
|
{ 1559, 9, 13, 11, 1, -12 }, // 0x89
|
||||||
|
{ 1574, 9, 13, 11, 1, -12 }, // 0x8A
|
||||||
|
{ 1589, 9, 13, 11, 1, -12 }, // 0x8B
|
||||||
|
{ 1604, 9, 13, 11, 1, -12 }, // 0x8C
|
||||||
|
{ 1619, 9, 13, 11, 1, -12 }, // 0x8D
|
||||||
|
{ 1634, 9, 13, 11, 1, -12 }, // 0x8E
|
||||||
|
{ 1649, 9, 13, 11, 1, -12 }, // 0x8F
|
||||||
|
{ 1664, 9, 13, 11, 1, -12 }, // 0x90
|
||||||
|
{ 1679, 9, 13, 11, 1, -12 }, // 0x91
|
||||||
|
{ 1694, 9, 13, 11, 1, -12 }, // 0x92
|
||||||
|
{ 1709, 9, 13, 11, 1, -12 }, // 0x93
|
||||||
|
{ 1724, 9, 13, 11, 1, -12 }, // 0x94
|
||||||
|
{ 1739, 9, 13, 11, 1, -12 }, // 0x95
|
||||||
|
{ 1754, 9, 13, 11, 1, -12 }, // 0x96
|
||||||
|
{ 1769, 9, 13, 11, 1, -12 }, // 0x97
|
||||||
|
{ 1784, 9, 13, 11, 1, -12 }, // 0x98
|
||||||
|
{ 1799, 9, 13, 11, 1, -12 }, // 0x99
|
||||||
|
{ 1814, 9, 13, 11, 1, -12 }, // 0x9A
|
||||||
|
{ 1829, 9, 13, 11, 1, -12 }, // 0x9B
|
||||||
|
{ 1844, 9, 13, 11, 1, -12 }, // 0x9C
|
||||||
|
{ 1859, 9, 13, 11, 1, -12 }, // 0x9D
|
||||||
|
{ 1874, 9, 13, 11, 1, -12 }, // 0x9E
|
||||||
|
{ 1889, 9, 13, 11, 1, -12 }, // 0x9F
|
||||||
|
{ 1904, 1, 1, 5, 0, 0 }, // 0xA0
|
||||||
|
{ 1905, 3, 13, 5, 1, -9 }, // 0xA1
|
||||||
|
{ 1910, 9, 14, 11, 1, -11 }, // 0xA2
|
||||||
|
{ 1926, 11, 13, 12, 1, -12 }, // 0xA3
|
||||||
|
{ 1944, 12, 12, 13, 0, -11 }, // 0xA4
|
||||||
|
{ 1962, 14, 13, 13, 0, -12 }, // 0xA5
|
||||||
|
{ 1985, 3, 16, 6, 1, -12 }, // 0xA6
|
||||||
|
{ 1991, 9, 15, 9, 0, -12 }, // 0xA7
|
||||||
|
{ 2008, 6, 3, 11, 2, -13 }, // 0xA8
|
||||||
|
{ 2011, 12, 13, 14, 1, -12 }, // 0xA9
|
||||||
|
{ 2031, 7, 6, 7, 0, -13 }, // 0xAA
|
||||||
|
{ 2037, 9, 7, 10, 1, -7 }, // 0xAB
|
||||||
|
{ 2045, 9, 5, 11, 1, -6 }, // 0xAC
|
||||||
|
{ 2051, 9, 13, 11, 1, -12 }, // 0xAD
|
||||||
|
{ 2066, 12, 13, 14, 1, -12 }, // 0xAE
|
||||||
|
{ 2086, 7, 2, 11, 2, -12 }, // 0xAF
|
||||||
|
{ 2088, 6, 6, 8, 1, -12 }, // 0xB0
|
||||||
|
{ 2093, 9, 12, 11, 1, -11 }, // 0xB1
|
||||||
|
{ 2107, 7, 8, 8, 0, -13 }, // 0xB2
|
||||||
|
{ 2114, 7, 7, 8, 0, -12 }, // 0xB3
|
||||||
|
{ 2121, 5, 3, 11, 4, -13 }, // 0xB4
|
||||||
|
{ 2123, 10, 13, 12, 1, -9 }, // 0xB5
|
||||||
|
{ 2140, 11, 15, 12, 0, -12 }, // 0xB6
|
||||||
|
{ 2161, 3, 4, 5, 1, -6 }, // 0xB7
|
||||||
|
{ 2163, 4, 4, 11, 3, 1 }, // 0xB8
|
||||||
|
{ 2165, 6, 7, 8, 1, -12 }, // 0xB9
|
||||||
|
{ 2171, 7, 6, 8, 0, -13 }, // 0xBA
|
||||||
|
{ 2177, 10, 7, 10, 0, -7 }, // 0xBB
|
||||||
|
{ 2186, 17, 13, 19, 1, -12 }, // 0xBC
|
||||||
|
{ 2214, 17, 13, 19, 1, -12 }, // 0xBD
|
||||||
|
{ 2242, 18, 13, 19, 0, -12 }, // 0xBE
|
||||||
|
{ 2272, 10, 13, 11, 1, -9 }, // 0xBF
|
||||||
|
{ 2289, 14, 17, 14, 0, -16 }, // 0xC0
|
||||||
|
{ 2319, 14, 17, 14, 0, -16 }, // 0xC1
|
||||||
|
{ 2349, 14, 17, 14, 0, -16 }, // 0xC2
|
||||||
|
{ 2379, 14, 16, 14, 0, -15 }, // 0xC3
|
||||||
|
{ 2407, 14, 17, 14, 0, -16 }, // 0xC4
|
||||||
|
{ 2437, 14, 18, 14, 0, -17 }, // 0xC5
|
||||||
|
{ 2469, 19, 13, 19, 0, -12 }, // 0xC6
|
||||||
|
{ 2500, 12, 17, 13, 1, -12 }, // 0xC7
|
||||||
|
{ 2526, 10, 17, 12, 1, -16 }, // 0xC8
|
||||||
|
{ 2548, 10, 17, 12, 1, -16 }, // 0xC9
|
||||||
|
{ 2570, 10, 17, 12, 1, -16 }, // 0xCA
|
||||||
|
{ 2592, 10, 17, 12, 1, -16 }, // 0xCB
|
||||||
|
{ 2614, 5, 17, 6, 0, -16 }, // 0xCC
|
||||||
|
{ 2625, 6, 17, 6, 1, -16 }, // 0xCD
|
||||||
|
{ 2638, 7, 17, 6, 0, -16 }, // 0xCE
|
||||||
|
{ 2653, 6, 17, 6, 0, -16 }, // 0xCF
|
||||||
|
{ 2666, 13, 13, 15, 1, -12 }, // 0xD0
|
||||||
|
{ 2688, 12, 16, 15, 1, -15 }, // 0xD1
|
||||||
|
{ 2712, 13, 17, 15, 1, -16 }, // 0xD2
|
||||||
|
{ 2740, 13, 17, 15, 1, -16 }, // 0xD3
|
||||||
|
{ 2768, 13, 17, 15, 1, -16 }, // 0xD4
|
||||||
|
{ 2796, 13, 16, 15, 1, -15 }, // 0xD5
|
||||||
|
{ 2822, 13, 17, 15, 1, -16 }, // 0xD6
|
||||||
|
{ 2850, 7, 8, 11, 2, -9 }, // 0xD7
|
||||||
|
{ 2857, 13, 15, 15, 1, -13 }, // 0xD8
|
||||||
|
{ 2882, 12, 17, 14, 1, -16 }, // 0xD9
|
||||||
|
{ 2908, 12, 17, 14, 1, -16 }, // 0xDA
|
||||||
|
{ 2934, 12, 17, 14, 1, -16 }, // 0xDB
|
||||||
|
{ 2960, 12, 17, 14, 1, -16 }, // 0xDC
|
||||||
|
{ 2986, 12, 17, 12, 0, -16 }, // 0xDD
|
||||||
|
{ 3012, 11, 13, 13, 1, -12 }, // 0xDE
|
||||||
|
{ 3030, 11, 14, 12, 1, -13 }, // 0xDF
|
||||||
|
{ 3050, 9, 14, 11, 1, -13 }, // 0xE0
|
||||||
|
{ 3066, 9, 14, 11, 1, -13 }, // 0xE1
|
||||||
|
{ 3082, 9, 14, 11, 1, -13 }, // 0xE2
|
||||||
|
{ 3098, 9, 14, 11, 1, -13 }, // 0xE3
|
||||||
|
{ 3114, 9, 14, 11, 1, -13 }, // 0xE4
|
||||||
|
{ 3130, 9, 15, 11, 1, -14 }, // 0xE5
|
||||||
|
{ 3147, 16, 10, 18, 1, -9 }, // 0xE6
|
||||||
|
{ 3167, 9, 14, 11, 1, -9 }, // 0xE7
|
||||||
|
{ 3183, 10, 14, 11, 1, -13 }, // 0xE8
|
||||||
|
{ 3201, 10, 14, 11, 1, -13 }, // 0xE9
|
||||||
|
{ 3219, 10, 14, 11, 1, -13 }, // 0xEA
|
||||||
|
{ 3237, 10, 14, 11, 1, -13 }, // 0xEB
|
||||||
|
{ 3255, 5, 14, 5, -1, -13 }, // 0xEC
|
||||||
|
{ 3264, 5, 14, 5, 1, -13 }, // 0xED
|
||||||
|
{ 3273, 7, 14, 5, -1, -13 }, // 0xEE
|
||||||
|
{ 3286, 5, 13, 5, 0, -12 }, // 0xEF
|
||||||
|
{ 3295, 10, 13, 11, 0, -12 }, // 0xF0
|
||||||
|
{ 3312, 10, 14, 12, 1, -13 }, // 0xF1
|
||||||
|
{ 3330, 10, 14, 12, 1, -13 }, // 0xF2
|
||||||
|
{ 3348, 10, 14, 12, 1, -13 }, // 0xF3
|
||||||
|
{ 3366, 10, 14, 12, 1, -13 }, // 0xF4
|
||||||
|
{ 3384, 10, 14, 12, 1, -13 }, // 0xF5
|
||||||
|
{ 3402, 10, 14, 12, 1, -13 }, // 0xF6
|
||||||
|
{ 3420, 9, 11, 11, 1, -11 }, // 0xF7
|
||||||
|
{ 3433, 10, 12, 12, 1, -10 }, // 0xF8
|
||||||
|
{ 3448, 10, 14, 12, 1, -13 }, // 0xF9
|
||||||
|
{ 3466, 10, 14, 12, 1, -13 }, // 0xFA
|
||||||
|
{ 3484, 10, 14, 12, 1, -13 }, // 0xFB
|
||||||
|
{ 3502, 10, 14, 12, 1, -13 }, // 0xFC
|
||||||
|
{ 3520, 11, 18, 11, 0, -13 }, // 0xFD
|
||||||
|
{ 3545, 11, 16, 12, 1, -12 }, // 0xFE
|
||||||
|
{ 3567, 11, 18, 11, 0, -13 }, // 0xFF
|
||||||
|
{ 3592, 14, 16, 14, 0, -15 }, // 0x100
|
||||||
|
{ 3620, 9, 13, 11, 1, -12 }, // 0x101
|
||||||
|
{ 3635, 14, 17, 14, 0, -16 }, // 0x102
|
||||||
|
{ 3665, 9, 14, 11, 1, -13 }, // 0x103
|
||||||
|
{ 3681, 14, 17, 14, 0, -12 }, // 0x104
|
||||||
|
{ 3711, 9, 14, 11, 1, -9 }, // 0x105
|
||||||
|
{ 3727, 12, 17, 13, 1, -16 }, // 0x106
|
||||||
|
{ 3753, 9, 14, 11, 1, -13 }, // 0x107
|
||||||
|
{ 3769, 12, 17, 13, 1, -16 }, // 0x108
|
||||||
|
{ 3795, 9, 14, 11, 1, -13 }, // 0x109
|
||||||
|
{ 3811, 12, 17, 13, 1, -16 }, // 0x10A
|
||||||
|
{ 3837, 9, 14, 11, 1, -13 }, // 0x10B
|
||||||
|
{ 3853, 12, 17, 13, 1, -16 }, // 0x10C
|
||||||
|
{ 3879, 9, 14, 11, 1, -13 }, // 0x10D
|
||||||
|
{ 3895, 13, 17, 15, 1, -16 }, // 0x10E
|
||||||
|
{ 3923, 14, 14, 12, 1, -13 }, // 0x10F
|
||||||
|
{ 3948, 13, 13, 15, 1, -12 }, // 0x110
|
||||||
|
{ 3970, 11, 13, 12, 1, -12 }, // 0x111
|
||||||
|
{ 3988, 10, 16, 12, 1, -15 }, // 0x112
|
||||||
|
{ 4008, 10, 13, 11, 1, -12 }, // 0x113
|
||||||
|
{ 4025, 10, 17, 12, 1, -16 }, // 0x114
|
||||||
|
{ 4047, 10, 14, 11, 1, -13 }, // 0x115
|
||||||
|
{ 4065, 10, 17, 12, 1, -16 }, // 0x116
|
||||||
|
{ 4087, 10, 14, 11, 1, -13 }, // 0x117
|
||||||
|
{ 4105, 11, 17, 12, 1, -12 }, // 0x118
|
||||||
|
{ 4129, 10, 14, 11, 1, -9 }, // 0x119
|
||||||
|
{ 4147, 10, 17, 12, 1, -16 }, // 0x11A
|
||||||
|
{ 4169, 10, 14, 11, 1, -13 }, // 0x11B
|
||||||
|
{ 4187, 12, 17, 14, 1, -16 }, // 0x11C
|
||||||
|
{ 4213, 10, 18, 13, 1, -13 }, // 0x11D
|
||||||
|
{ 4236, 12, 17, 14, 1, -16 }, // 0x11E
|
||||||
|
{ 4262, 10, 18, 13, 1, -13 }, // 0x11F
|
||||||
|
{ 4285, 12, 17, 14, 1, -16 }, // 0x120
|
||||||
|
{ 4311, 10, 18, 13, 1, -13 }, // 0x121
|
||||||
|
{ 4334, 12, 18, 14, 1, -12 }, // 0x122
|
||||||
|
{ 4361, 10, 19, 13, 1, -14 }, // 0x123
|
||||||
|
{ 4385, 12, 17, 15, 1, -16 }, // 0x124
|
||||||
|
{ 4411, 12, 17, 12, -1, -16 }, // 0x125
|
||||||
|
{ 4437, 15, 13, 15, 0, -12 }, // 0x126
|
||||||
|
{ 4462, 11, 13, 13, 0, -12 }, // 0x127
|
||||||
|
{ 4480, 7, 16, 6, 0, -15 }, // 0x128
|
||||||
|
{ 4494, 6, 14, 5, -1, -13 }, // 0x129
|
||||||
|
{ 4505, 5, 16, 6, 1, -15 }, // 0x12A
|
||||||
|
{ 4515, 5, 13, 5, 0, -12 }, // 0x12B
|
||||||
|
{ 4524, 7, 17, 6, 0, -16 }, // 0x12C
|
||||||
|
{ 4539, 5, 14, 5, 0, -13 }, // 0x12D
|
||||||
|
{ 4548, 4, 17, 6, 1, -12 }, // 0x12E
|
||||||
|
{ 4557, 3, 18, 5, 1, -13 }, // 0x12F
|
||||||
|
{ 4564, 4, 17, 6, 1, -16 }, // 0x130
|
||||||
|
{ 4573, 3, 10, 5, 1, -9 }, // 0x131
|
||||||
|
{ 4577, 11, 13, 13, 1, -12 }, // 0x132
|
||||||
|
{ 4595, 9, 18, 11, 1, -13 }, // 0x133
|
||||||
|
{ 4616, 8, 17, 10, 0, -16 }, // 0x134
|
||||||
|
{ 4633, 8, 18, 6, -2, -13 }, // 0x135
|
||||||
|
{ 4651, 13, 18, 13, 1, -12 }, // 0x136
|
||||||
|
{ 4681, 11, 18, 12, 1, -12 }, // 0x137
|
||||||
|
{ 4706, 11, 10, 12, 1, -9 }, // 0x138
|
||||||
|
{ 4720, 10, 17, 11, 1, -16 }, // 0x139
|
||||||
|
{ 4742, 5, 17, 5, 1, -16 }, // 0x13A
|
||||||
|
{ 4753, 10, 18, 11, 1, -12 }, // 0x13B
|
||||||
|
{ 4776, 3, 18, 5, 1, -12 }, // 0x13C
|
||||||
|
{ 4783, 10, 13, 11, 1, -12 }, // 0x13D
|
||||||
|
{ 4800, 7, 14, 5, 1, -13 }, // 0x13E
|
||||||
|
{ 4813, 10, 13, 11, 1, -12 }, // 0x13F
|
||||||
|
{ 4830, 7, 13, 8, 1, -12 }, // 0x140
|
||||||
|
{ 4842, 11, 13, 11, 0, -12 }, // 0x141
|
||||||
|
{ 4860, 7, 13, 5, -1, -12 }, // 0x142
|
||||||
|
{ 4872, 12, 17, 15, 1, -16 }, // 0x143
|
||||||
|
{ 4898, 10, 14, 12, 1, -13 }, // 0x144
|
||||||
|
{ 4916, 12, 18, 15, 1, -12 }, // 0x145
|
||||||
|
{ 4943, 10, 15, 12, 1, -9 }, // 0x146
|
||||||
|
{ 4962, 12, 17, 15, 1, -16 }, // 0x147
|
||||||
|
{ 4988, 10, 14, 12, 1, -13 }, // 0x148
|
||||||
|
{ 5006, 13, 14, 14, 0, -13 }, // 0x149
|
||||||
|
{ 5029, 12, 17, 15, 1, -12 }, // 0x14A
|
||||||
|
{ 5055, 10, 14, 12, 1, -9 }, // 0x14B
|
||||||
|
{ 5073, 13, 16, 15, 1, -15 }, // 0x14C
|
||||||
|
{ 5099, 10, 13, 12, 1, -12 }, // 0x14D
|
||||||
|
{ 5116, 13, 17, 15, 1, -16 }, // 0x14E
|
||||||
|
{ 5144, 10, 14, 12, 1, -13 }, // 0x14F
|
||||||
|
{ 5162, 13, 17, 15, 1, -16 }, // 0x150
|
||||||
|
{ 5190, 10, 14, 12, 1, -13 }, // 0x151
|
||||||
|
{ 5208, 19, 13, 20, 1, -12 }, // 0x152
|
||||||
|
{ 5239, 18, 10, 19, 1, -9 }, // 0x153
|
||||||
|
{ 5262, 12, 17, 13, 1, -16 }, // 0x154
|
||||||
|
{ 5288, 7, 14, 8, 1, -13 }, // 0x155
|
||||||
|
{ 5301, 12, 18, 13, 1, -12 }, // 0x156
|
||||||
|
{ 5328, 6, 15, 8, 1, -9 }, // 0x157
|
||||||
|
{ 5340, 12, 17, 13, 1, -16 }, // 0x158
|
||||||
|
{ 5366, 7, 14, 8, 1, -13 }, // 0x159
|
||||||
|
{ 5379, 11, 17, 11, 0, -16 }, // 0x15A
|
||||||
|
{ 5403, 9, 14, 10, 0, -13 }, // 0x15B
|
||||||
|
{ 5419, 11, 17, 11, 0, -16 }, // 0x15C
|
||||||
|
{ 5443, 9, 14, 10, 0, -13 }, // 0x15D
|
||||||
|
{ 5459, 11, 17, 11, 0, -12 }, // 0x15E
|
||||||
|
{ 5483, 9, 14, 10, 0, -9 }, // 0x15F
|
||||||
|
{ 5499, 11, 17, 11, 0, -16 }, // 0x160
|
||||||
|
{ 5523, 9, 14, 10, 0, -13 }, // 0x161
|
||||||
|
{ 5539, 11, 17, 11, 0, -12 }, // 0x162
|
||||||
|
{ 5563, 8, 16, 8, 0, -11 }, // 0x163
|
||||||
|
{ 5579, 11, 17, 11, 0, -16 }, // 0x164
|
||||||
|
{ 5603, 8, 14, 8, 0, -13 }, // 0x165
|
||||||
|
{ 5617, 11, 13, 11, 0, -12 }, // 0x166
|
||||||
|
{ 5635, 8, 12, 8, 0, -11 }, // 0x167
|
||||||
|
{ 5647, 12, 16, 14, 1, -15 }, // 0x168
|
||||||
|
{ 5671, 10, 14, 12, 1, -13 }, // 0x169
|
||||||
|
{ 5689, 12, 16, 14, 1, -15 }, // 0x16A
|
||||||
|
{ 5713, 10, 13, 12, 1, -12 }, // 0x16B
|
||||||
|
{ 5730, 12, 17, 14, 1, -16 }, // 0x16C
|
||||||
|
{ 5756, 10, 14, 12, 1, -13 }, // 0x16D
|
||||||
|
{ 5774, 12, 18, 14, 1, -17 }, // 0x16E
|
||||||
|
{ 5801, 10, 15, 12, 1, -14 }, // 0x16F
|
||||||
|
{ 5820, 12, 17, 14, 1, -16 }, // 0x170
|
||||||
|
{ 5846, 10, 14, 12, 1, -13 }, // 0x171
|
||||||
|
{ 5864, 12, 17, 14, 1, -12 }, // 0x172
|
||||||
|
{ 5890, 10, 14, 12, 1, -9 }, // 0x173
|
||||||
|
{ 5908, 21, 17, 21, 0, -16 }, // 0x174
|
||||||
|
{ 5953, 17, 14, 17, 0, -13 }, // 0x175
|
||||||
|
{ 5983, 12, 17, 12, 0, -16 }, // 0x176
|
||||||
|
{ 6009, 11, 18, 11, 0, -13 }, // 0x177
|
||||||
|
{ 6034, 12, 17, 12, 0, -16 }, // 0x178
|
||||||
|
{ 6060, 11, 17, 12, 1, -16 }, // 0x179
|
||||||
|
{ 6084, 8, 14, 10, 1, -13 }, // 0x17A
|
||||||
|
{ 6098, 11, 17, 12, 1, -16 }, // 0x17B
|
||||||
|
{ 6122, 8, 14, 10, 1, -13 }, // 0x17C
|
||||||
|
{ 6136, 11, 17, 12, 1, -16 }, // 0x17D
|
||||||
|
{ 6160, 8, 14, 10, 1, -13 }, // 0x17E
|
||||||
|
{ 6174, 8, 14, 6, 0, -13 } }; // 0x17F
|
||||||
|
|
||||||
|
const GFXfont MontserratBold9pt8b PROGMEM = {
|
||||||
|
(uint8_t *)MontserratBold9pt8bBitmaps,
|
||||||
|
(GFXglyph *)MontserratBold9pt8bGlyphs,
|
||||||
|
0x20, 0x17F, 21 };
|
||||||
|
|
||||||
|
// Approx. 8659 bytes
|
||||||
|
|
||||||
|
#endif // MONTSERRATBOLD9PT8B_H
|
||||||
@@ -1,272 +0,0 @@
|
|||||||
#ifndef NOTOSANS12PT7B_H
|
|
||||||
#define NOTOSANS12PT7B_H
|
|
||||||
const uint8_t NotoSans_Regular12pt7bBitmaps[] PROGMEM = {
|
|
||||||
0x00, 0xDB, 0x6D, 0xB6, 0xDB, 0x60, 0x37, 0xC0, 0xCF, 0x3C, 0xF3, 0x8E,
|
|
||||||
0x30, 0x06, 0x30, 0x10, 0x80, 0xC6, 0x03, 0x18, 0x0C, 0x63, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xC6, 0x30, 0x18, 0xC0, 0x63, 0x01, 0x8C, 0x3F, 0xFE, 0x31, 0x80,
|
|
||||||
0xC6, 0x03, 0x18, 0x0C, 0x60, 0x21, 0x00, 0x04, 0x00, 0x80, 0x7E, 0x1F,
|
|
||||||
0xF6, 0x45, 0xC8, 0x39, 0x03, 0x20, 0x7C, 0x03, 0xF0, 0x1F, 0x02, 0x70,
|
|
||||||
0x46, 0x08, 0xF1, 0x3F, 0xFE, 0x3F, 0x00, 0x80, 0x10, 0x00, 0x38, 0x0C,
|
|
||||||
0x36, 0x06, 0x31, 0x86, 0x18, 0xC3, 0x0C, 0x63, 0x06, 0x31, 0x03, 0x19,
|
|
||||||
0x81, 0x8D, 0x9E, 0x66, 0xD9, 0xBE, 0xC8, 0xC4, 0x6C, 0x20, 0x66, 0x10,
|
|
||||||
0x33, 0x08, 0x30, 0x84, 0x10, 0x46, 0x18, 0x33, 0x18, 0x0F, 0x00, 0x0F,
|
|
||||||
0x00, 0x3F, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x31, 0xC0, 0x1B,
|
|
||||||
0x80, 0x0F, 0x00, 0x1E, 0x00, 0x73, 0x06, 0x61, 0x8E, 0xE0, 0xEC, 0xC0,
|
|
||||||
0x7C, 0xE0, 0x38, 0x60, 0x7C, 0x7F, 0xEE, 0x3F, 0x87, 0xFF, 0xA0, 0x19,
|
|
||||||
0x8C, 0xC6, 0x33, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x8C, 0x63, 0x0C, 0x71,
|
|
||||||
0x80, 0xC3, 0x18, 0x63, 0x18, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x66, 0x31,
|
|
||||||
0x98, 0xCC, 0x00, 0x0E, 0x01, 0x80, 0x10, 0x42, 0x1F, 0x5F, 0xFF, 0xC3,
|
|
||||||
0x80, 0xD8, 0x3B, 0x8E, 0x30, 0x44, 0x00, 0x06, 0x00, 0xC0, 0x18, 0x03,
|
|
||||||
0x00, 0x61, 0xFF, 0xFF, 0xF8, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x00, 0x76,
|
|
||||||
0x66, 0xCC, 0xFF, 0xF0, 0xDF, 0x00, 0x03, 0x81, 0x80, 0xC0, 0xC0, 0x60,
|
|
||||||
0x30, 0x30, 0x18, 0x18, 0x0C, 0x06, 0x06, 0x03, 0x01, 0x81, 0x80, 0xC0,
|
|
||||||
0xC0, 0x00, 0x1F, 0x07, 0xF1, 0xC3, 0x30, 0x76, 0x07, 0x80, 0xF0, 0x1E,
|
|
||||||
0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x06, 0xC1, 0xD8, 0x31, 0xFE,
|
|
||||||
0x1F, 0x00, 0x0C, 0x73, 0xFB, 0x4C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C,
|
|
||||||
0x30, 0xC3, 0x0C, 0x1F, 0x0F, 0xF3, 0x83, 0x00, 0x60, 0x0E, 0x01, 0x80,
|
|
||||||
0x30, 0x0E, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x07,
|
|
||||||
0xFF, 0xFF, 0xE0, 0x3F, 0x1F, 0xF9, 0x03, 0x00, 0x70, 0x0E, 0x01, 0x80,
|
|
||||||
0x70, 0xFC, 0x1F, 0x00, 0x38, 0x03, 0x80, 0x30, 0x06, 0x00, 0xE0, 0x3F,
|
|
||||||
0xFE, 0x7F, 0x80, 0x00, 0xE0, 0x0F, 0x00, 0x58, 0x06, 0xC0, 0x66, 0x03,
|
|
||||||
0x30, 0x31, 0x83, 0x0C, 0x18, 0x61, 0x83, 0x18, 0x19, 0xFF, 0xFF, 0xFF,
|
|
||||||
0x80, 0x30, 0x01, 0x80, 0x0C, 0x00, 0x60, 0x7F, 0xCF, 0xF9, 0x80, 0x30,
|
|
||||||
0x06, 0x00, 0xC0, 0x18, 0x03, 0xFC, 0x77, 0xC0, 0x1C, 0x01, 0x80, 0x30,
|
|
||||||
0x06, 0x00, 0xE0, 0x37, 0xFE, 0x7F, 0x00, 0x07, 0xC3, 0xF8, 0xE0, 0x18,
|
|
||||||
0x06, 0x00, 0xC0, 0x18, 0x86, 0xFE, 0xF0, 0xFC, 0x0F, 0x81, 0xE0, 0x36,
|
|
||||||
0x06, 0xC0, 0xDC, 0x39, 0xFE, 0x1F, 0x80, 0xFF, 0xFF, 0xFC, 0x01, 0x80,
|
|
||||||
0x70, 0x0C, 0x03, 0x80, 0x60, 0x0C, 0x03, 0x00, 0x60, 0x18, 0x03, 0x00,
|
|
||||||
0xE0, 0x18, 0x07, 0x00, 0xC0, 0x38, 0x00, 0x1F, 0x07, 0xF9, 0x83, 0x30,
|
|
||||||
0x36, 0x06, 0xC1, 0x8C, 0x70, 0xFC, 0x1F, 0x07, 0x79, 0x83, 0xE0, 0x3C,
|
|
||||||
0x07, 0x80, 0xF8, 0x1B, 0xDE, 0x3F, 0x80, 0x1F, 0x07, 0xF1, 0x83, 0x70,
|
|
||||||
0x7C, 0x07, 0x80, 0xF0, 0x1F, 0x03, 0x60, 0xE7, 0xEC, 0x79, 0x80, 0x30,
|
|
||||||
0x0C, 0x01, 0x80, 0x63, 0x7C, 0x7E, 0x00, 0xDF, 0x00, 0x00, 0x03, 0x7C,
|
|
||||||
0x67, 0x60, 0x00, 0x00, 0x00, 0x66, 0x6C, 0xCC, 0x00, 0x20, 0x1C, 0x0E,
|
|
||||||
0x07, 0x03, 0x81, 0xC0, 0x3C, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0x80,
|
|
||||||
0xFF, 0xE0, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, 0xC0, 0x1E, 0x00,
|
|
||||||
0xF0, 0x07, 0x80, 0x3C, 0x01, 0xC0, 0x78, 0x3C, 0x3E, 0x1E, 0x03, 0x00,
|
|
||||||
0x00, 0x3E, 0x3F, 0xE4, 0x18, 0x03, 0x00, 0xC0, 0x60, 0x18, 0x1C, 0x0E,
|
|
||||||
0x03, 0x01, 0x80, 0x60, 0x00, 0x00, 0x01, 0x80, 0x70, 0x1C, 0x00, 0x00,
|
|
||||||
0xF8, 0x00, 0xFF, 0xC0, 0x38, 0x0C, 0x0C, 0x00, 0xC3, 0x00, 0x0C, 0xC3,
|
|
||||||
0xF8, 0x98, 0xE3, 0x1A, 0x18, 0x63, 0xC6, 0x0C, 0x78, 0xC1, 0x0F, 0x18,
|
|
||||||
0x21, 0xE3, 0x0C, 0x24, 0x31, 0xCC, 0xC7, 0xCF, 0x18, 0x00, 0x01, 0x80,
|
|
||||||
0x00, 0x38, 0x00, 0x03, 0xF7, 0x80, 0x1F, 0xE0, 0x00, 0x03, 0x80, 0x07,
|
|
||||||
0x00, 0x0A, 0x00, 0x36, 0x00, 0x6C, 0x01, 0xCC, 0x03, 0x18, 0x06, 0x30,
|
|
||||||
0x18, 0x30, 0x30, 0x60, 0x7F, 0xC1, 0xFF, 0xC3, 0x01, 0x8E, 0x03, 0x98,
|
|
||||||
0x03, 0x30, 0x06, 0xC0, 0x06, 0xFF, 0x0F, 0xFC, 0xC0, 0xEC, 0x06, 0xC0,
|
|
||||||
0x6C, 0x06, 0xC0, 0x6F, 0xFC, 0xFF, 0x8C, 0x0E, 0xC0, 0x7C, 0x03, 0xC0,
|
|
||||||
0x3C, 0x07, 0xC0, 0x6F, 0xFE, 0xFF, 0x80, 0x07, 0xF0, 0xFF, 0xCF, 0x02,
|
|
||||||
0x60, 0x07, 0x00, 0x30, 0x01, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x18,
|
|
||||||
0x00, 0xC0, 0x06, 0x00, 0x38, 0x00, 0xE0, 0x03, 0xFE, 0x0F, 0xF0, 0xFF,
|
|
||||||
0x03, 0xFF, 0x0C, 0x0F, 0x30, 0x0C, 0xC0, 0x1B, 0x00, 0x6C, 0x01, 0xF0,
|
|
||||||
0x07, 0xC0, 0x1F, 0x00, 0x7C, 0x01, 0xF0, 0x06, 0xC0, 0x1B, 0x00, 0xCC,
|
|
||||||
0x0F, 0x3F, 0xF8, 0xFF, 0x00, 0xFF, 0xFF, 0xFC, 0x03, 0x00, 0xC0, 0x30,
|
|
||||||
0x0C, 0x03, 0xFE, 0xFF, 0xB0, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03,
|
|
||||||
0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFC, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03,
|
|
||||||
0x00, 0xFF, 0xBF, 0xEC, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0,
|
|
||||||
0x00, 0x03, 0xF8, 0x3F, 0xF1, 0xC0, 0x4C, 0x00, 0x70, 0x01, 0x80, 0x06,
|
|
||||||
0x00, 0x38, 0x00, 0xE0, 0x7F, 0x81, 0xF6, 0x00, 0xD8, 0x03, 0x60, 0x0C,
|
|
||||||
0xC0, 0x33, 0x80, 0xC7, 0xFF, 0x07, 0xFC, 0xC0, 0x1E, 0x00, 0xF0, 0x07,
|
|
||||||
0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x7F, 0xFF, 0xFF, 0xFE, 0x00, 0xF0,
|
|
||||||
0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x18, 0xFF,
|
|
||||||
0xF3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x1E, 0xFC,
|
|
||||||
0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3,
|
|
||||||
0x0C, 0x30, 0xEF, 0xF8, 0xC0, 0x36, 0x03, 0x30, 0x31, 0x83, 0x0C, 0x30,
|
|
||||||
0x63, 0x83, 0x38, 0x1B, 0x80, 0xFC, 0x07, 0xF0, 0x31, 0xC1, 0x87, 0x0C,
|
|
||||||
0x18, 0x60, 0xE3, 0x03, 0x98, 0x0C, 0xC0, 0x38, 0xC0, 0x30, 0x0C, 0x03,
|
|
||||||
0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0,
|
|
||||||
0x30, 0x0C, 0x03, 0xFF, 0xFF, 0xC0, 0xF0, 0x03, 0xF8, 0x03, 0xFC, 0x01,
|
|
||||||
0xFB, 0x00, 0xFD, 0x80, 0xDE, 0xC0, 0x6F, 0x30, 0x27, 0x98, 0x33, 0xCE,
|
|
||||||
0x19, 0xE3, 0x18, 0xF1, 0x8C, 0x78, 0x66, 0x3C, 0x36, 0x1E, 0x1B, 0x0F,
|
|
||||||
0x07, 0x07, 0x83, 0x83, 0xC1, 0xC1, 0x80, 0xE0, 0x0F, 0xC0, 0x3F, 0x00,
|
|
||||||
0xFE, 0x03, 0xD8, 0x0F, 0x30, 0x3C, 0xE0, 0xF1, 0x83, 0xC3, 0x0F, 0x0E,
|
|
||||||
0x3C, 0x18, 0xF0, 0x33, 0xC0, 0xEF, 0x01, 0xBC, 0x07, 0xF0, 0x0F, 0xC0,
|
|
||||||
0x1C, 0x07, 0xE0, 0x1F, 0xF8, 0x38, 0x1C, 0x30, 0x0E, 0x60, 0x06, 0x60,
|
|
||||||
0x07, 0x60, 0x07, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0x60, 0x03, 0x60,
|
|
||||||
0x07, 0x60, 0x06, 0x70, 0x0E, 0x38, 0x1C, 0x1F, 0xF8, 0x0F, 0xF0, 0xFE,
|
|
||||||
0x1F, 0xFB, 0x07, 0x60, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x07, 0xC7, 0xDF,
|
|
||||||
0xF3, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x00, 0x07,
|
|
||||||
0xE0, 0x1F, 0xF8, 0x38, 0x1C, 0x30, 0x0E, 0x60, 0x06, 0x60, 0x07, 0x60,
|
|
||||||
0x07, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0x60, 0x03, 0x60, 0x07, 0x60,
|
|
||||||
0x06, 0x70, 0x0E, 0x38, 0x1C, 0x1F, 0xF8, 0x0F, 0xF0, 0x00, 0x70, 0x00,
|
|
||||||
0x38, 0x00, 0x1C, 0x00, 0x0E, 0xFF, 0x0F, 0xFC, 0xC1, 0xCC, 0x0E, 0xC0,
|
|
||||||
0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8F, 0xF0, 0xC3, 0x0C, 0x18, 0xC1,
|
|
||||||
0xCC, 0x0C, 0xC0, 0xEC, 0x06, 0xC0, 0x70, 0x1F, 0x8F, 0xF9, 0x81, 0x70,
|
|
||||||
0x0E, 0x00, 0xC0, 0x1C, 0x01, 0xE0, 0x1F, 0x00, 0xF8, 0x07, 0x00, 0x70,
|
|
||||||
0x06, 0x00, 0xE0, 0x37, 0xFE, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xC1, 0xC0,
|
|
||||||
0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01,
|
|
||||||
0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0xC0,
|
|
||||||
0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03,
|
|
||||||
0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xF0, 0x1D, 0xC0, 0xC7,
|
|
||||||
0xFC, 0x1F, 0xC0, 0xC0, 0x0F, 0x80, 0x76, 0x01, 0x98, 0x06, 0x30, 0x38,
|
|
||||||
0xC0, 0xC3, 0x03, 0x06, 0x1C, 0x18, 0x60, 0x61, 0x80, 0xCC, 0x03, 0x30,
|
|
||||||
0x0C, 0xC0, 0x1E, 0x00, 0x78, 0x01, 0xE0, 0x03, 0x00, 0xE0, 0x30, 0x1D,
|
|
||||||
0x81, 0xC0, 0x66, 0x07, 0x81, 0x98, 0x1E, 0x0E, 0x70, 0xD8, 0x30, 0xC3,
|
|
||||||
0x30, 0xC3, 0x0C, 0xC3, 0x0C, 0x33, 0x1C, 0x39, 0x8C, 0x60, 0x66, 0x19,
|
|
||||||
0x81, 0x98, 0x66, 0x06, 0xC1, 0xB8, 0x0F, 0x03, 0xC0, 0x3C, 0x0F, 0x00,
|
|
||||||
0xF0, 0x3C, 0x03, 0x80, 0xE0, 0x06, 0x01, 0x80, 0xE0, 0x19, 0xC0, 0xC3,
|
|
||||||
0x03, 0x06, 0x18, 0x18, 0xE0, 0x33, 0x00, 0xF8, 0x01, 0xE0, 0x07, 0x00,
|
|
||||||
0x1E, 0x00, 0xDC, 0x03, 0x30, 0x18, 0x60, 0xE1, 0x83, 0x03, 0x18, 0x0E,
|
|
||||||
0xE0, 0x1C, 0xC0, 0x1B, 0x01, 0xDC, 0x0C, 0x60, 0xE3, 0x86, 0x0C, 0x60,
|
|
||||||
0x73, 0x01, 0xB0, 0x0F, 0x80, 0x38, 0x00, 0xC0, 0x06, 0x00, 0x30, 0x01,
|
|
||||||
0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0xFF, 0xEF, 0xFE, 0x00, 0xE0, 0x0C,
|
|
||||||
0x01, 0xC0, 0x38, 0x03, 0x00, 0x70, 0x0E, 0x00, 0xC0, 0x1C, 0x03, 0x80,
|
|
||||||
0x30, 0x07, 0x00, 0xE0, 0x0F, 0xFF, 0xFF, 0xF0, 0xFF, 0xF1, 0x8C, 0x63,
|
|
||||||
0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0xFF, 0x80, 0xC0, 0x30,
|
|
||||||
0x18, 0x0C, 0x03, 0x01, 0x80, 0x60, 0x30, 0x18, 0x06, 0x03, 0x01, 0x80,
|
|
||||||
0x60, 0x30, 0x0C, 0x06, 0x03, 0x80, 0xFF, 0xC6, 0x31, 0x8C, 0x63, 0x18,
|
|
||||||
0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC7, 0xFF, 0x80, 0x04, 0x00, 0xE0, 0x0A,
|
|
||||||
0x01, 0xB0, 0x19, 0x03, 0x18, 0x30, 0x86, 0x0C, 0x60, 0x4C, 0x06, 0xC0,
|
|
||||||
0x30, 0xFF, 0xFF, 0xF0, 0xE3, 0x0C, 0x30, 0x1F, 0x1F, 0xE2, 0x0C, 0x03,
|
|
||||||
0x00, 0xC0, 0xF3, 0xFD, 0x83, 0xC0, 0xF0, 0x3C, 0x1D, 0xDF, 0x7E, 0x40,
|
|
||||||
0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x9E, 0x37, 0xE7, 0x06, 0xE0,
|
|
||||||
0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1F, 0x06, 0xFF, 0xDB,
|
|
||||||
0xF0, 0x0F, 0x4F, 0xE7, 0x09, 0x80, 0x60, 0x38, 0x0C, 0x03, 0x00, 0xE0,
|
|
||||||
0x18, 0x07, 0x00, 0xFE, 0x1F, 0x80, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30,
|
|
||||||
0x06, 0x1C, 0xCF, 0xFB, 0x87, 0x60, 0x7C, 0x0F, 0x81, 0xE0, 0x3C, 0x07,
|
|
||||||
0xC0, 0xD8, 0x1B, 0x03, 0x3F, 0xA3, 0xE4, 0x0F, 0x07, 0xF1, 0xC3, 0x30,
|
|
||||||
0x36, 0x07, 0xFF, 0xFF, 0xFF, 0x00, 0xE0, 0x0C, 0x01, 0xC0, 0x1F, 0xE1,
|
|
||||||
0xFC, 0x0F, 0x8F, 0xC6, 0x03, 0x01, 0x81, 0xFB, 0xFC, 0x30, 0x18, 0x0C,
|
|
||||||
0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x00, 0x0E, 0x27,
|
|
||||||
0xF5, 0xC3, 0xB0, 0x36, 0x07, 0xC0, 0xF0, 0x1E, 0x03, 0xE0, 0x6C, 0x0D,
|
|
||||||
0x81, 0x9F, 0xF1, 0xF6, 0x00, 0xC0, 0x18, 0x03, 0x60, 0xEF, 0xF8, 0x38,
|
|
||||||
0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x9E, 0x37, 0xF7, 0x06,
|
|
||||||
0xE0, 0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0,
|
|
||||||
0x78, 0x0C, 0xF0, 0xFF, 0xFF, 0xFF, 0xC0, 0x18, 0xC0, 0x01, 0x8C, 0x63,
|
|
||||||
0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x33, 0xFB, 0x00, 0xC0, 0x30,
|
|
||||||
0x0C, 0x03, 0x00, 0xC0, 0x30, 0x7C, 0x1B, 0x0C, 0xC6, 0x33, 0x0D, 0x83,
|
|
||||||
0xE0, 0xEC, 0x33, 0x8C, 0x73, 0x0C, 0xC1, 0xB0, 0x70, 0xFF, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xF0, 0xCF, 0x0F, 0x37, 0xEF, 0xEE, 0x1E, 0x1F, 0x83, 0x83, 0xC0,
|
|
||||||
0xC0, 0xF0, 0x30, 0x3C, 0x0C, 0x0F, 0x03, 0x03, 0xC0, 0xC0, 0xF0, 0x30,
|
|
||||||
0x3C, 0x0C, 0x0F, 0x03, 0x03, 0xC0, 0xC0, 0xC0, 0xCF, 0x1B, 0xFB, 0x83,
|
|
||||||
0x70, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0,
|
|
||||||
0x3C, 0x06, 0x0F, 0x03, 0xFC, 0x70, 0xE6, 0x06, 0x60, 0x3E, 0x03, 0xC0,
|
|
||||||
0x3C, 0x03, 0xE0, 0x36, 0x07, 0x70, 0x63, 0xFC, 0x1F, 0x80, 0xCF, 0x1B,
|
|
||||||
0xF3, 0x83, 0x70, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F,
|
|
||||||
0x83, 0x7F, 0xED, 0xF9, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x03, 0x00,
|
|
||||||
0x00, 0x0E, 0x27, 0xF5, 0xC3, 0xB0, 0x3E, 0x07, 0xC0, 0xF0, 0x1E, 0x03,
|
|
||||||
0xE0, 0x6C, 0x0D, 0x81, 0x9F, 0xF1, 0xF6, 0x00, 0xC0, 0x18, 0x03, 0x00,
|
|
||||||
0x60, 0x0C, 0x01, 0x80, 0xCF, 0xBF, 0xC7, 0x0C, 0x18, 0x30, 0x60, 0xC1,
|
|
||||||
0x83, 0x06, 0x0C, 0x00, 0x1E, 0x3F, 0xF8, 0x38, 0x0E, 0x03, 0xC0, 0xF8,
|
|
||||||
0x0E, 0x01, 0x80, 0xC0, 0x7E, 0xFF, 0xE0, 0x10, 0x30, 0x7F, 0xFF, 0x30,
|
|
||||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1D, 0x1F, 0xC0, 0xF8,
|
|
||||||
0x1F, 0x03, 0xE0, 0x7C, 0x0F, 0x81, 0xF0, 0x3E, 0x07, 0xC0, 0xF8, 0x1F,
|
|
||||||
0x03, 0xBF, 0xB7, 0xE6, 0xC0, 0x3E, 0x07, 0x60, 0x66, 0x06, 0x30, 0xC3,
|
|
||||||
0x0C, 0x30, 0xC1, 0x98, 0x19, 0x81, 0xB0, 0x0F, 0x00, 0xF0, 0x06, 0x00,
|
|
||||||
0xC0, 0xC0, 0xD8, 0x38, 0x36, 0x1E, 0x0D, 0x87, 0x86, 0x61, 0xB1, 0x8C,
|
|
||||||
0x4C, 0x63, 0x33, 0x38, 0xCC, 0x6C, 0x33, 0x1B, 0x07, 0x86, 0xC1, 0xE0,
|
|
||||||
0xA0, 0x78, 0x38, 0x0C, 0x0E, 0x00, 0x60, 0x77, 0x06, 0x30, 0xC1, 0x9C,
|
|
||||||
0x0D, 0x80, 0xF0, 0x06, 0x00, 0xF0, 0x0D, 0x81, 0x9C, 0x30, 0xC7, 0x06,
|
|
||||||
0xE0, 0x70, 0xC0, 0x3E, 0x07, 0x60, 0x66, 0x06, 0x30, 0xC3, 0x0C, 0x38,
|
|
||||||
0xC1, 0x98, 0x19, 0x80, 0xD8, 0x0F, 0x00, 0xF0, 0x06, 0x00, 0x60, 0x06,
|
|
||||||
0x00, 0xC0, 0x1C, 0x0F, 0x80, 0xE0, 0x00, 0xFF, 0xFF, 0xC0, 0xE0, 0x60,
|
|
||||||
0x60, 0x60, 0x30, 0x30, 0x30, 0x38, 0x18, 0x1F, 0xFF, 0xF8, 0x02, 0x3C,
|
|
||||||
0x60, 0xC1, 0x83, 0x06, 0x0C, 0x31, 0xE3, 0x03, 0x83, 0x03, 0x06, 0x0C,
|
|
||||||
0x18, 0x30, 0x60, 0xF0, 0x20, 0xFF, 0xFF, 0xFF, 0x81, 0xE0, 0xC1, 0x83,
|
|
||||||
0x06, 0x0C, 0x18, 0x38, 0x3C, 0x18, 0xE3, 0x86, 0x0C, 0x18, 0x30, 0x60,
|
|
||||||
0xC7, 0x08, 0x00, 0x78, 0x3F, 0xEE, 0x1F, 0x80 };
|
|
||||||
|
|
||||||
const GFXglyph NotoSans_Regular12pt7bGlyphs[] PROGMEM = {
|
|
||||||
{ 0, 1, 1, 6, 0, 0 }, // 0x20 ' '
|
|
||||||
{ 1, 3, 17, 6, 2, -16 }, // 0x21 '!'
|
|
||||||
{ 8, 6, 6, 10, 2, -16 }, // 0x22 '"'
|
|
||||||
{ 13, 14, 17, 15, 1, -16 }, // 0x23 '#'
|
|
||||||
{ 43, 11, 19, 13, 1, -17 }, // 0x24 '$'
|
|
||||||
{ 70, 17, 17, 20, 1, -16 }, // 0x25 '%'
|
|
||||||
{ 107, 16, 17, 17, 1, -16 }, // 0x26 '&'
|
|
||||||
{ 141, 2, 6, 5, 2, -16 }, // 0x27 '''
|
|
||||||
{ 143, 5, 21, 7, 1, -16 }, // 0x28 '('
|
|
||||||
{ 157, 5, 21, 7, 1, -16 }, // 0x29 ')'
|
|
||||||
{ 171, 11, 11, 13, 1, -17 }, // 0x2A '*'
|
|
||||||
{ 187, 11, 11, 13, 1, -13 }, // 0x2B '+'
|
|
||||||
{ 203, 4, 6, 6, 1, -2 }, // 0x2C ','
|
|
||||||
{ 206, 6, 2, 8, 1, -6 }, // 0x2D '-'
|
|
||||||
{ 208, 3, 3, 6, 2, -2 }, // 0x2E '.'
|
|
||||||
{ 210, 9, 17, 9, 0, -16 }, // 0x2F '/'
|
|
||||||
{ 230, 11, 17, 13, 1, -16 }, // 0x30 '0'
|
|
||||||
{ 254, 6, 17, 13, 2, -16 }, // 0x31 '1'
|
|
||||||
{ 267, 11, 17, 13, 1, -16 }, // 0x32 '2'
|
|
||||||
{ 291, 11, 17, 13, 1, -16 }, // 0x33 '3'
|
|
||||||
{ 315, 13, 17, 13, 0, -16 }, // 0x34 '4'
|
|
||||||
{ 343, 11, 17, 13, 1, -16 }, // 0x35 '5'
|
|
||||||
{ 367, 11, 17, 13, 1, -16 }, // 0x36 '6'
|
|
||||||
{ 391, 11, 17, 13, 1, -16 }, // 0x37 '7'
|
|
||||||
{ 415, 11, 17, 13, 1, -16 }, // 0x38 '8'
|
|
||||||
{ 439, 11, 17, 13, 1, -16 }, // 0x39 '9'
|
|
||||||
{ 463, 3, 13, 6, 2, -12 }, // 0x3A ':'
|
|
||||||
{ 468, 4, 16, 6, 1, -12 }, // 0x3B ';'
|
|
||||||
{ 476, 11, 11, 13, 1, -13 }, // 0x3C '<'
|
|
||||||
{ 492, 11, 6, 13, 1, -10 }, // 0x3D '='
|
|
||||||
{ 501, 11, 11, 13, 1, -13 }, // 0x3E '>'
|
|
||||||
{ 517, 10, 17, 10, 0, -16 }, // 0x3F '?'
|
|
||||||
{ 539, 19, 19, 21, 1, -16 }, // 0x40 '@'
|
|
||||||
{ 585, 15, 17, 15, 0, -16 }, // 0x41 'A'
|
|
||||||
{ 617, 12, 17, 15, 2, -16 }, // 0x42 'B'
|
|
||||||
{ 643, 13, 17, 15, 1, -16 }, // 0x43 'C'
|
|
||||||
{ 671, 14, 17, 17, 2, -16 }, // 0x44 'D'
|
|
||||||
{ 701, 10, 17, 13, 2, -16 }, // 0x45 'E'
|
|
||||||
{ 723, 10, 17, 12, 2, -16 }, // 0x46 'F'
|
|
||||||
{ 745, 14, 17, 17, 1, -16 }, // 0x47 'G'
|
|
||||||
{ 775, 13, 17, 17, 2, -16 }, // 0x48 'H'
|
|
||||||
{ 803, 6, 17, 8, 1, -16 }, // 0x49 'I'
|
|
||||||
{ 816, 6, 21, 6, -2, -16 }, // 0x4A 'J'
|
|
||||||
{ 832, 13, 17, 15, 2, -16 }, // 0x4B 'K'
|
|
||||||
{ 860, 10, 17, 12, 2, -16 }, // 0x4C 'L'
|
|
||||||
{ 882, 17, 17, 21, 2, -16 }, // 0x4D 'M'
|
|
||||||
{ 919, 14, 17, 18, 2, -16 }, // 0x4E 'N'
|
|
||||||
{ 949, 16, 17, 18, 1, -16 }, // 0x4F 'O'
|
|
||||||
{ 983, 11, 17, 14, 2, -16 }, // 0x50 'P'
|
|
||||||
{ 1007, 16, 21, 18, 1, -16 }, // 0x51 'Q'
|
|
||||||
{ 1049, 12, 17, 15, 2, -16 }, // 0x52 'R'
|
|
||||||
{ 1075, 11, 17, 13, 1, -16 }, // 0x53 'S'
|
|
||||||
{ 1099, 13, 17, 13, 0, -16 }, // 0x54 'T'
|
|
||||||
{ 1127, 13, 17, 17, 2, -16 }, // 0x55 'U'
|
|
||||||
{ 1155, 14, 17, 14, 0, -16 }, // 0x56 'V'
|
|
||||||
{ 1185, 22, 17, 22, 0, -16 }, // 0x57 'W'
|
|
||||||
{ 1232, 14, 17, 14, 0, -16 }, // 0x58 'X'
|
|
||||||
{ 1262, 13, 17, 13, 0, -16 }, // 0x59 'Y'
|
|
||||||
{ 1290, 12, 17, 13, 1, -16 }, // 0x5A 'Z'
|
|
||||||
{ 1316, 5, 21, 8, 2, -16 }, // 0x5B '['
|
|
||||||
{ 1330, 9, 17, 9, 0, -16 }, // 0x5C '\'
|
|
||||||
{ 1350, 5, 21, 8, 1, -16 }, // 0x5D ']'
|
|
||||||
{ 1364, 12, 11, 13, 1, -16 }, // 0x5E '^'
|
|
||||||
{ 1381, 10, 2, 10, 0, 3 }, // 0x5F '_'
|
|
||||||
{ 1384, 5, 4, 7, 1, -17 }, // 0x60 '`'
|
|
||||||
{ 1387, 10, 13, 13, 1, -12 }, // 0x61 'a'
|
|
||||||
{ 1404, 11, 18, 14, 2, -17 }, // 0x62 'b'
|
|
||||||
{ 1429, 10, 13, 11, 1, -12 }, // 0x63 'c'
|
|
||||||
{ 1446, 11, 18, 14, 1, -17 }, // 0x64 'd'
|
|
||||||
{ 1471, 11, 13, 13, 1, -12 }, // 0x65 'e'
|
|
||||||
{ 1489, 9, 18, 8, 0, -17 }, // 0x66 'f'
|
|
||||||
{ 1510, 11, 19, 14, 1, -12 }, // 0x67 'g'
|
|
||||||
{ 1537, 11, 18, 15, 2, -17 }, // 0x68 'h'
|
|
||||||
{ 1562, 2, 17, 6, 2, -16 }, // 0x69 'i'
|
|
||||||
{ 1567, 5, 23, 6, -1, -16 }, // 0x6A 'j'
|
|
||||||
{ 1582, 10, 18, 13, 2, -17 }, // 0x6B 'k'
|
|
||||||
{ 1605, 2, 18, 6, 2, -17 }, // 0x6C 'l'
|
|
||||||
{ 1610, 18, 13, 22, 2, -12 }, // 0x6D 'm'
|
|
||||||
{ 1640, 11, 13, 15, 2, -12 }, // 0x6E 'n'
|
|
||||||
{ 1658, 12, 13, 14, 1, -12 }, // 0x6F 'o'
|
|
||||||
{ 1678, 11, 19, 14, 2, -12 }, // 0x70 'p'
|
|
||||||
{ 1705, 11, 19, 14, 1, -12 }, // 0x71 'q'
|
|
||||||
{ 1732, 7, 13, 10, 2, -12 }, // 0x72 'r'
|
|
||||||
{ 1744, 9, 13, 11, 1, -12 }, // 0x73 's'
|
|
||||||
{ 1759, 8, 15, 8, 0, -14 }, // 0x74 't'
|
|
||||||
{ 1774, 11, 13, 15, 2, -12 }, // 0x75 'u'
|
|
||||||
{ 1792, 12, 13, 12, 0, -12 }, // 0x76 'v'
|
|
||||||
{ 1812, 18, 13, 18, 0, -12 }, // 0x77 'w'
|
|
||||||
{ 1842, 12, 13, 12, 0, -12 }, // 0x78 'x'
|
|
||||||
{ 1862, 12, 19, 12, 0, -12 }, // 0x79 'y'
|
|
||||||
{ 1891, 9, 13, 11, 1, -12 }, // 0x7A 'z'
|
|
||||||
{ 1906, 7, 21, 9, 1, -16 }, // 0x7B '{'
|
|
||||||
{ 1925, 1, 24, 13, 6, -17 }, // 0x7C '|'
|
|
||||||
{ 1928, 7, 21, 9, 1, -16 }, // 0x7D '}'
|
|
||||||
{ 1947, 11, 3, 13, 1, -9 } }; // 0x7E '~'
|
|
||||||
|
|
||||||
const GFXfont NotoSans_Regular12pt7b PROGMEM = {
|
|
||||||
(uint8_t *)NotoSans_Regular12pt7bBitmaps,
|
|
||||||
(GFXglyph *)NotoSans_Regular12pt7bGlyphs,
|
|
||||||
0x20, 0x7E, 32 };
|
|
||||||
|
|
||||||
// Approx. 2624 bytes
|
|
||||||
|
|
||||||
#endif // NOTOSANS12PT7B_H
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,201 +0,0 @@
|
|||||||
#ifndef NOTOSANS9PT7B_H
|
|
||||||
#define NOTOSANS9PT7B_H
|
|
||||||
const uint8_t NotoSans_Regular9pt7bBitmaps[] PROGMEM = {
|
|
||||||
0x00, 0xF5, 0x55, 0x43, 0xC0, 0xDE, 0xF3, 0x9C, 0x80, 0x0C, 0x81, 0x10,
|
|
||||||
0x22, 0x04, 0x47, 0xFE, 0x32, 0x04, 0x40, 0x88, 0xFF, 0xC2, 0x60, 0xC8,
|
|
||||||
0x11, 0x02, 0x20, 0x18, 0x3E, 0x7F, 0xD8, 0xD8, 0xF8, 0x3C, 0x1F, 0x1B,
|
|
||||||
0x19, 0x9B, 0xFE, 0x18, 0x18, 0x70, 0x46, 0xC2, 0x22, 0x21, 0x13, 0x08,
|
|
||||||
0x90, 0x45, 0xB3, 0x6B, 0x4E, 0xD3, 0x04, 0x98, 0x44, 0xC2, 0x26, 0x21,
|
|
||||||
0x23, 0x07, 0x00, 0x1C, 0x07, 0x60, 0x62, 0x06, 0x20, 0x26, 0x03, 0xC0,
|
|
||||||
0x38, 0x06, 0xC6, 0xC6, 0x6C, 0x3C, 0xC1, 0x8E, 0x3C, 0x7E, 0x70, 0xFF,
|
|
||||||
0xC0, 0x32, 0x64, 0xCC, 0x88, 0x88, 0x8C, 0xC4, 0x63, 0x8C, 0x46, 0x22,
|
|
||||||
0x23, 0x33, 0x22, 0x64, 0xC8, 0x18, 0x10, 0xD3, 0xFF, 0x18, 0x2C, 0x66,
|
|
||||||
0x24, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x7E, 0xF0, 0xF0,
|
|
||||||
0x04, 0x30, 0xC2, 0x18, 0x41, 0x0C, 0x21, 0x86, 0x10, 0xC0, 0x3C, 0x7E,
|
|
||||||
0x42, 0xC3, 0xC1, 0x81, 0x81, 0x81, 0xC1, 0xC3, 0xC3, 0x66, 0x3C, 0x13,
|
|
||||||
0xD9, 0x11, 0x11, 0x11, 0x11, 0x10, 0x3C, 0xFE, 0x83, 0x03, 0x03, 0x02,
|
|
||||||
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xFF, 0x3C, 0xFE, 0x83, 0x03, 0x03,
|
|
||||||
0x06, 0x38, 0x06, 0x03, 0x03, 0x03, 0x86, 0xFC, 0x03, 0x01, 0xC0, 0x70,
|
|
||||||
0x3C, 0x1B, 0x04, 0xC2, 0x31, 0x8C, 0x43, 0x3F, 0xF0, 0x30, 0x0C, 0x03,
|
|
||||||
0x00, 0x7E, 0x7E, 0x40, 0x40, 0x40, 0xFC, 0x7E, 0x03, 0x03, 0x03, 0x03,
|
|
||||||
0x86, 0xFC, 0x0E, 0x3E, 0x60, 0x40, 0xC0, 0xDC, 0xE7, 0xC3, 0xC1, 0xC1,
|
|
||||||
0xC3, 0x63, 0x3E, 0xFF, 0xFF, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x0C, 0x18,
|
|
||||||
0x18, 0x10, 0x30, 0x60, 0x3C, 0x7E, 0xC3, 0xC3, 0x43, 0x76, 0x3C, 0x66,
|
|
||||||
0xC3, 0x81, 0x81, 0xC3, 0x7E, 0x38, 0x7E, 0xC3, 0xC3, 0x81, 0xC3, 0xC3,
|
|
||||||
0x7D, 0x03, 0x03, 0x02, 0x0E, 0x78, 0x74, 0x00, 0xF0, 0x74, 0x00, 0xFA,
|
|
||||||
0x01, 0x03, 0x0C, 0x30, 0xC0, 0xE0, 0x1C, 0x07, 0x01, 0xFF, 0xFF, 0x00,
|
|
||||||
0x00, 0xFF, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x07, 0x38, 0xE0, 0x80, 0x39,
|
|
||||||
0xFC, 0x08, 0x10, 0x60, 0x86, 0x08, 0x30, 0x00, 0x01, 0x83, 0x00, 0x03,
|
|
||||||
0x80, 0x7F, 0x83, 0x01, 0x18, 0x02, 0x47, 0xCF, 0x31, 0x38, 0x84, 0x62,
|
|
||||||
0x31, 0x88, 0xCE, 0x23, 0x2C, 0x77, 0x10, 0x00, 0x60, 0x00, 0x7F, 0x00,
|
|
||||||
0x30, 0x00, 0x04, 0x01, 0xC0, 0x28, 0x05, 0x81, 0xB0, 0x22, 0x04, 0x61,
|
|
||||||
0x84, 0x3F, 0xCC, 0x19, 0x81, 0x20, 0x3C, 0x06, 0xF8, 0x7F, 0x20, 0xD0,
|
|
||||||
0x68, 0x34, 0x33, 0xF1, 0x06, 0x81, 0x40, 0xE0, 0x50, 0xEF, 0xE0, 0x0F,
|
|
||||||
0x0F, 0xF6, 0x01, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x06,
|
|
||||||
0x00, 0xC2, 0x1F, 0x80, 0xF8, 0x3F, 0xC8, 0x3A, 0x06, 0x80, 0xE0, 0x38,
|
|
||||||
0x0E, 0x03, 0x80, 0xE0, 0x68, 0x1A, 0x1C, 0xFC, 0x00, 0xFF, 0xFE, 0x04,
|
|
||||||
0x08, 0x10, 0x3F, 0x40, 0x81, 0x02, 0x04, 0x0F, 0xE0, 0xFF, 0xFE, 0x04,
|
|
||||||
0x08, 0x10, 0x3F, 0x7E, 0x81, 0x02, 0x04, 0x08, 0x00, 0x0F, 0x87, 0xF9,
|
|
||||||
0xC0, 0x30, 0x0C, 0x01, 0x80, 0x30, 0xFE, 0x1F, 0xC0, 0x68, 0x0D, 0x81,
|
|
||||||
0x98, 0x31, 0xFE, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFF, 0x01,
|
|
||||||
0x80, 0xC0, 0x60, 0x30, 0x18, 0x08, 0xFF, 0x66, 0x66, 0x66, 0x66, 0x66,
|
|
||||||
0xF0, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x3E, 0x81, 0xC1, 0xA1,
|
|
||||||
0x91, 0x89, 0x85, 0x83, 0xC1, 0xB0, 0x8C, 0x46, 0x21, 0x90, 0x68, 0x18,
|
|
||||||
0x81, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x81, 0x02, 0x04, 0x0F, 0xE0,
|
|
||||||
0xC0, 0x3C, 0x03, 0xE0, 0x7A, 0x05, 0xB0, 0xDB, 0x09, 0x90, 0x99, 0x99,
|
|
||||||
0x89, 0x18, 0xB1, 0x8F, 0x18, 0x61, 0x86, 0x10, 0xC0, 0xF0, 0x3E, 0x0E,
|
|
||||||
0xC3, 0xB0, 0xE6, 0x38, 0x8E, 0x33, 0x86, 0xE0, 0xB8, 0x3E, 0x07, 0x80,
|
|
||||||
0xC0, 0x0F, 0x03, 0xFC, 0x60, 0x64, 0x06, 0xC0, 0x2C, 0x03, 0xC0, 0x3C,
|
|
||||||
0x03, 0xC0, 0x3C, 0x02, 0x60, 0x63, 0x0C, 0x1F, 0x80, 0xF0, 0xFE, 0x82,
|
|
||||||
0x83, 0x83, 0x83, 0x86, 0xFC, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0F, 0x03,
|
|
||||||
0xFC, 0x60, 0x64, 0x06, 0xC0, 0x2C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C,
|
|
||||||
0x02, 0x60, 0x63, 0x0C, 0x1F, 0x80, 0x18, 0x01, 0xC0, 0x0E, 0xF0, 0x7F,
|
|
||||||
0x20, 0xD0, 0x68, 0x34, 0x13, 0xF9, 0xF0, 0x8C, 0x43, 0x21, 0x90, 0x68,
|
|
||||||
0x18, 0x3D, 0x7E, 0xC0, 0xC0, 0xC0, 0x60, 0x3C, 0x0E, 0x03, 0x03, 0x03,
|
|
||||||
0x86, 0xFC, 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30,
|
|
||||||
0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x18,
|
|
||||||
0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x70, 0x7C, 0x63, 0xE0, 0xC0, 0x78,
|
|
||||||
0x09, 0x03, 0x30, 0x46, 0x18, 0x43, 0x0C, 0x40, 0x98, 0x1B, 0x03, 0x40,
|
|
||||||
0x38, 0x07, 0x00, 0xC0, 0xC1, 0x83, 0x41, 0x83, 0x41, 0xC3, 0x63, 0xC2,
|
|
||||||
0x63, 0x46, 0x22, 0x46, 0x22, 0x66, 0x36, 0x24, 0x34, 0x2C, 0x14, 0x3C,
|
|
||||||
0x14, 0x38, 0x1C, 0x18, 0x18, 0x18, 0xC0, 0xD8, 0x22, 0x18, 0xCC, 0x1A,
|
|
||||||
0x03, 0x80, 0xC0, 0x38, 0x1A, 0x0C, 0xC2, 0x19, 0x82, 0xC0, 0xC0, 0xC0,
|
|
||||||
0xD0, 0x26, 0x18, 0x84, 0x33, 0x04, 0x81, 0xE0, 0x30, 0x0C, 0x03, 0x00,
|
|
||||||
0xC0, 0x30, 0x0C, 0x00, 0xFF, 0xFF, 0x03, 0x06, 0x04, 0x0C, 0x18, 0x10,
|
|
||||||
0x30, 0x60, 0x40, 0xC0, 0xFF, 0xFF, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
|
||||||
0xCF, 0xC1, 0x04, 0x18, 0x20, 0xC3, 0x04, 0x18, 0x20, 0x83, 0x04, 0xFF,
|
|
||||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1F, 0x10, 0x18, 0x38, 0x24, 0x64,
|
|
||||||
0x42, 0x42, 0x81, 0xFF, 0xD9, 0x80, 0x18, 0xFC, 0x08, 0x11, 0xEE, 0x70,
|
|
||||||
0xC1, 0xC6, 0xF4, 0xC0, 0x60, 0x30, 0x19, 0x8F, 0xF7, 0x0B, 0x07, 0x83,
|
|
||||||
0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE0, 0x1C, 0xFD, 0x06, 0x0C, 0x18, 0x30,
|
|
||||||
0x60, 0x62, 0x7C, 0x01, 0x01, 0x01, 0x19, 0x7F, 0xC3, 0xC1, 0xC1, 0xC1,
|
|
||||||
0xC1, 0xC1, 0x63, 0x3D, 0x18, 0x7E, 0x43, 0xC3, 0xFF, 0xFF, 0xC0, 0xC0,
|
|
||||||
0x61, 0x3F, 0x1E, 0x60, 0x81, 0x0F, 0xC4, 0x08, 0x10, 0x20, 0x40, 0x81,
|
|
||||||
0x02, 0x00, 0x18, 0x7F, 0x43, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x63, 0x3D,
|
|
||||||
0x01, 0x01, 0x43, 0x7E, 0xC0, 0xC0, 0xC0, 0xCC, 0xFF, 0xE1, 0xC1, 0xC1,
|
|
||||||
0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xF0, 0xFF, 0xFF, 0xC0, 0x33, 0x00, 0x33,
|
|
||||||
0x33, 0x33, 0x33, 0x33, 0x33, 0xE0, 0xC0, 0xC0, 0xC0, 0xC1, 0xC6, 0xCC,
|
|
||||||
0xD8, 0xD0, 0xF8, 0xCC, 0xC4, 0xC6, 0xC3, 0xFF, 0xFF, 0xFF, 0xC0, 0x0C,
|
|
||||||
0x33, 0xFB, 0xFE, 0x38, 0xF0, 0xC3, 0xC1, 0x07, 0x04, 0x1C, 0x10, 0x70,
|
|
||||||
0x41, 0xC1, 0x07, 0x04, 0x10, 0x0C, 0xFF, 0xE1, 0xC1, 0xC1, 0xC1, 0xC1,
|
|
||||||
0xC1, 0xC1, 0xC1, 0x18, 0x3F, 0x10, 0xD8, 0x3C, 0x1E, 0x0F, 0x07, 0x82,
|
|
||||||
0x63, 0x1F, 0x00, 0x0C, 0x7F, 0xB8, 0x58, 0x3C, 0x1E, 0x0F, 0x07, 0x83,
|
|
||||||
0xE3, 0x6F, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x18, 0x7F, 0xC3, 0xC1, 0xC1,
|
|
||||||
0xC1, 0xC1, 0xC1, 0x63, 0x3D, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x7E, 0x30,
|
|
||||||
0xC3, 0x0C, 0x30, 0xC3, 0x00, 0x39, 0xFA, 0x06, 0x07, 0x07, 0x81, 0x83,
|
|
||||||
0x85, 0xF8, 0x20, 0x86, 0x3F, 0x20, 0x82, 0x08, 0x20, 0x83, 0x0F, 0xC1,
|
|
||||||
0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x63, 0x7D, 0xC1, 0xA0, 0x98, 0xCC,
|
|
||||||
0x42, 0x21, 0xB0, 0x50, 0x28, 0x1C, 0x00, 0xC3, 0x0D, 0x1C, 0x26, 0x79,
|
|
||||||
0x99, 0x26, 0x24, 0x90, 0xB3, 0x43, 0x8F, 0x0E, 0x18, 0x18, 0x60, 0xE3,
|
|
||||||
0x99, 0x05, 0x83, 0x80, 0xC0, 0xB0, 0xC8, 0xC6, 0xC1, 0x80, 0xC1, 0xA0,
|
|
||||||
0x98, 0xC4, 0x43, 0x21, 0xB0, 0x50, 0x38, 0x0C, 0x04, 0x06, 0x02, 0x0F,
|
|
||||||
0x00, 0xFC, 0x18, 0x20, 0xC3, 0x0C, 0x10, 0x60, 0xFE, 0x04, 0x71, 0x04,
|
|
||||||
0x10, 0x41, 0x3C, 0xE0, 0xC1, 0x04, 0x10, 0x41, 0xC3, 0xFF, 0xFF, 0xFF,
|
|
||||||
0xFF, 0xC0, 0x87, 0x18, 0x42, 0x10, 0x87, 0x39, 0x08, 0x42, 0x33, 0x90,
|
|
||||||
0xF9, 0x8F };
|
|
||||||
|
|
||||||
const GFXglyph NotoSans_Regular9pt7bGlyphs[] PROGMEM = {
|
|
||||||
{ 0, 1, 1, 5, 0, 0 }, // 0x20 ' '
|
|
||||||
{ 1, 2, 13, 5, 1, -12 }, // 0x21 '!'
|
|
||||||
{ 5, 5, 5, 7, 1, -12 }, // 0x22 '"'
|
|
||||||
{ 9, 11, 13, 11, 0, -12 }, // 0x23 '#'
|
|
||||||
{ 27, 8, 14, 10, 1, -12 }, // 0x24 '$'
|
|
||||||
{ 41, 13, 13, 15, 1, -12 }, // 0x25 '%'
|
|
||||||
{ 63, 12, 13, 13, 1, -12 }, // 0x26 '&'
|
|
||||||
{ 83, 2, 5, 4, 1, -12 }, // 0x27 '''
|
|
||||||
{ 85, 4, 16, 5, 1, -12 }, // 0x28 '('
|
|
||||||
{ 93, 4, 16, 5, 1, -12 }, // 0x29 ')'
|
|
||||||
{ 101, 8, 8, 10, 1, -12 }, // 0x2A '*'
|
|
||||||
{ 109, 8, 8, 10, 1, -9 }, // 0x2B '+'
|
|
||||||
{ 117, 2, 4, 5, 1, -1 }, // 0x2C ','
|
|
||||||
{ 118, 4, 1, 6, 1, -4 }, // 0x2D '-'
|
|
||||||
{ 119, 2, 2, 5, 1, -1 }, // 0x2E '.'
|
|
||||||
{ 120, 6, 13, 7, 0, -12 }, // 0x2F '/'
|
|
||||||
{ 130, 8, 13, 10, 1, -12 }, // 0x30 '0'
|
|
||||||
{ 143, 4, 13, 10, 2, -12 }, // 0x31 '1'
|
|
||||||
{ 150, 8, 13, 10, 1, -12 }, // 0x32 '2'
|
|
||||||
{ 163, 8, 13, 10, 1, -12 }, // 0x33 '3'
|
|
||||||
{ 176, 10, 13, 10, 0, -12 }, // 0x34 '4'
|
|
||||||
{ 193, 8, 13, 10, 1, -12 }, // 0x35 '5'
|
|
||||||
{ 206, 8, 13, 10, 1, -12 }, // 0x36 '6'
|
|
||||||
{ 219, 8, 13, 10, 1, -12 }, // 0x37 '7'
|
|
||||||
{ 232, 8, 13, 10, 1, -12 }, // 0x38 '8'
|
|
||||||
{ 245, 8, 13, 10, 1, -12 }, // 0x39 '9'
|
|
||||||
{ 258, 2, 10, 5, 1, -9 }, // 0x3A ':'
|
|
||||||
{ 261, 2, 12, 5, 1, -9 }, // 0x3B ';'
|
|
||||||
{ 264, 8, 9, 10, 1, -10 }, // 0x3C '<'
|
|
||||||
{ 273, 8, 5, 10, 1, -8 }, // 0x3D '='
|
|
||||||
{ 278, 8, 9, 10, 1, -10 }, // 0x3E '>'
|
|
||||||
{ 287, 7, 13, 8, 0, -12 }, // 0x3F '?'
|
|
||||||
{ 299, 14, 15, 16, 1, -12 }, // 0x40 '@'
|
|
||||||
{ 326, 11, 13, 11, 0, -12 }, // 0x41 'A'
|
|
||||||
{ 344, 9, 13, 11, 2, -12 }, // 0x42 'B'
|
|
||||||
{ 359, 10, 13, 11, 1, -12 }, // 0x43 'C'
|
|
||||||
{ 376, 10, 13, 13, 2, -12 }, // 0x44 'D'
|
|
||||||
{ 393, 7, 13, 10, 2, -12 }, // 0x45 'E'
|
|
||||||
{ 405, 7, 13, 9, 2, -12 }, // 0x46 'F'
|
|
||||||
{ 417, 11, 13, 13, 1, -12 }, // 0x47 'G'
|
|
||||||
{ 435, 9, 13, 13, 2, -12 }, // 0x48 'H'
|
|
||||||
{ 450, 4, 13, 6, 1, -12 }, // 0x49 'I'
|
|
||||||
{ 457, 4, 16, 5, -1, -12 }, // 0x4A 'J'
|
|
||||||
{ 465, 9, 13, 11, 2, -12 }, // 0x4B 'K'
|
|
||||||
{ 480, 7, 13, 9, 2, -12 }, // 0x4C 'L'
|
|
||||||
{ 492, 12, 13, 16, 2, -12 }, // 0x4D 'M'
|
|
||||||
{ 512, 10, 13, 13, 2, -12 }, // 0x4E 'N'
|
|
||||||
{ 529, 12, 13, 14, 1, -12 }, // 0x4F 'O'
|
|
||||||
{ 549, 8, 13, 11, 2, -12 }, // 0x50 'P'
|
|
||||||
{ 562, 12, 16, 14, 1, -12 }, // 0x51 'Q'
|
|
||||||
{ 586, 9, 13, 11, 2, -12 }, // 0x52 'R'
|
|
||||||
{ 601, 8, 13, 10, 1, -12 }, // 0x53 'S'
|
|
||||||
{ 614, 10, 13, 10, 0, -12 }, // 0x54 'T'
|
|
||||||
{ 631, 9, 13, 13, 2, -12 }, // 0x55 'U'
|
|
||||||
{ 646, 11, 13, 11, 0, -12 }, // 0x56 'V'
|
|
||||||
{ 664, 16, 13, 16, 0, -12 }, // 0x57 'W'
|
|
||||||
{ 690, 10, 13, 10, 0, -12 }, // 0x58 'X'
|
|
||||||
{ 707, 10, 13, 10, 0, -12 }, // 0x59 'Y'
|
|
||||||
{ 724, 8, 13, 10, 1, -12 }, // 0x5A 'Z'
|
|
||||||
{ 737, 4, 16, 6, 1, -12 }, // 0x5B '['
|
|
||||||
{ 745, 6, 13, 7, 0, -12 }, // 0x5C '\'
|
|
||||||
{ 755, 4, 16, 6, 0, -12 }, // 0x5D ']'
|
|
||||||
{ 763, 8, 8, 10, 1, -12 }, // 0x5E '^'
|
|
||||||
{ 771, 8, 1, 8, 0, 3 }, // 0x5F '_'
|
|
||||||
{ 772, 3, 3, 5, 1, -13 }, // 0x60 '`'
|
|
||||||
{ 774, 7, 10, 10, 1, -9 }, // 0x61 'a'
|
|
||||||
{ 783, 9, 13, 11, 1, -12 }, // 0x62 'b'
|
|
||||||
{ 798, 7, 10, 8, 1, -9 }, // 0x63 'c'
|
|
||||||
{ 807, 8, 13, 11, 1, -12 }, // 0x64 'd'
|
|
||||||
{ 820, 8, 10, 10, 1, -9 }, // 0x65 'e'
|
|
||||||
{ 830, 7, 13, 6, 0, -12 }, // 0x66 'f'
|
|
||||||
{ 842, 8, 14, 11, 1, -9 }, // 0x67 'g'
|
|
||||||
{ 856, 8, 13, 11, 1, -12 }, // 0x68 'h'
|
|
||||||
{ 869, 2, 13, 5, 1, -12 }, // 0x69 'i'
|
|
||||||
{ 873, 4, 17, 5, -1, -12 }, // 0x6A 'j'
|
|
||||||
{ 882, 8, 13, 9, 1, -12 }, // 0x6B 'k'
|
|
||||||
{ 895, 2, 13, 5, 1, -12 }, // 0x6C 'l'
|
|
||||||
{ 899, 14, 10, 16, 1, -9 }, // 0x6D 'm'
|
|
||||||
{ 917, 8, 10, 11, 1, -9 }, // 0x6E 'n'
|
|
||||||
{ 927, 9, 10, 11, 1, -9 }, // 0x6F 'o'
|
|
||||||
{ 939, 9, 14, 11, 1, -9 }, // 0x70 'p'
|
|
||||||
{ 955, 8, 14, 11, 1, -9 }, // 0x71 'q'
|
|
||||||
{ 969, 6, 10, 7, 1, -9 }, // 0x72 'r'
|
|
||||||
{ 977, 7, 10, 8, 1, -9 }, // 0x73 's'
|
|
||||||
{ 986, 6, 12, 6, 0, -11 }, // 0x74 't'
|
|
||||||
{ 995, 8, 9, 11, 1, -8 }, // 0x75 'u'
|
|
||||||
{ 1004, 9, 9, 9, 0, -8 }, // 0x76 'v'
|
|
||||||
{ 1015, 14, 9, 14, 0, -8 }, // 0x77 'w'
|
|
||||||
{ 1031, 9, 9, 9, 0, -8 }, // 0x78 'x'
|
|
||||||
{ 1042, 9, 13, 9, 0, -8 }, // 0x79 'y'
|
|
||||||
{ 1057, 7, 9, 8, 1, -8 }, // 0x7A 'z'
|
|
||||||
{ 1065, 6, 16, 7, 0, -12 }, // 0x7B '{'
|
|
||||||
{ 1077, 2, 17, 10, 4, -12 }, // 0x7C '|'
|
|
||||||
{ 1082, 5, 16, 7, 1, -12 }, // 0x7D '}'
|
|
||||||
{ 1092, 8, 2, 10, 1, -6 } }; // 0x7E '~'
|
|
||||||
|
|
||||||
const GFXfont NotoSans_Regular9pt7b PROGMEM = {
|
|
||||||
(uint8_t *)NotoSans_Regular9pt7bBitmaps,
|
|
||||||
(GFXglyph *)NotoSans_Regular9pt7bGlyphs,
|
|
||||||
0x20, 0x7E, 24 };
|
|
||||||
|
|
||||||
// Approx. 1766 bytes
|
|
||||||
|
|
||||||
#endif // NOTOSANS9PT7B_H
|
|
||||||
@@ -0,0 +1,789 @@
|
|||||||
|
// NotoSans9pt8b.h
|
||||||
|
//
|
||||||
|
// Adafruit GFX font header — Latin Extended-A coverage (U+0020 to U+017F).
|
||||||
|
// Source: Noto Sans at 9pt.
|
||||||
|
// 352 glyphs covering ASCII, Latin-1 Supplement, and Latin Extended-A.
|
||||||
|
// Supports Czech, Polish, German, French, Spanish, Italian, Croatian,
|
||||||
|
// Hungarian, Slovak, Romanian, and other European languages.
|
||||||
|
//
|
||||||
|
// Codepoints 0x7F-0x9F (C0/C1 control codes) are present as empty glyphs.
|
||||||
|
// They are never rendered in normal use because UTF-8 decoding does not
|
||||||
|
// produce them as standalone codepoints.
|
||||||
|
//
|
||||||
|
// To render glyphs above 0x7F, use a drawCodepoint(font, x, y, cp) helper
|
||||||
|
// that walks the glyph table directly. Adafruit GFX's print() / write() /
|
||||||
|
// drawChar() are byte-oriented (uint8_t) and cannot address indices > 255.
|
||||||
|
|
||||||
|
#ifndef NOTOSANS9PT8B_H
|
||||||
|
#define NOTOSANS9PT8B_H
|
||||||
|
|
||||||
|
const uint8_t NotoSans9pt8bBitmaps[] PROGMEM = {
|
||||||
|
0x00, 0xF5, 0x55, 0x43, 0xC0, 0xDE, 0xF3, 0x9C, 0x80, 0x0C, 0x81, 0x10,
|
||||||
|
0x22, 0x04, 0x47, 0xFE, 0x32, 0x04, 0x40, 0x88, 0xFF, 0xC2, 0x60, 0xC8,
|
||||||
|
0x11, 0x02, 0x20, 0x18, 0x3E, 0x7F, 0xD8, 0xD8, 0xF8, 0x3C, 0x1F, 0x1B,
|
||||||
|
0x19, 0x9B, 0xFE, 0x18, 0x18, 0x70, 0x46, 0xC2, 0x22, 0x21, 0x13, 0x08,
|
||||||
|
0x90, 0x45, 0xB3, 0x6B, 0x4E, 0xD3, 0x04, 0x98, 0x44, 0xC2, 0x26, 0x21,
|
||||||
|
0x23, 0x07, 0x00, 0x1C, 0x07, 0x60, 0x62, 0x06, 0x20, 0x26, 0x03, 0xC0,
|
||||||
|
0x38, 0x06, 0xC6, 0xC6, 0x6C, 0x3C, 0xC1, 0x8E, 0x3C, 0x7E, 0x70, 0xFF,
|
||||||
|
0xC0, 0x32, 0x64, 0xCC, 0x88, 0x88, 0x8C, 0xC4, 0x63, 0x8C, 0x46, 0x22,
|
||||||
|
0x23, 0x33, 0x22, 0x64, 0xC8, 0x18, 0x10, 0xD3, 0xFF, 0x18, 0x2C, 0x66,
|
||||||
|
0x24, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x7E, 0xF0, 0xF0,
|
||||||
|
0x04, 0x30, 0xC2, 0x18, 0x41, 0x0C, 0x21, 0x86, 0x10, 0xC0, 0x3C, 0x7E,
|
||||||
|
0x42, 0xC3, 0xC1, 0x81, 0x81, 0x81, 0xC1, 0xC3, 0xC3, 0x66, 0x3C, 0x13,
|
||||||
|
0xD9, 0x11, 0x11, 0x11, 0x11, 0x10, 0x3C, 0xFE, 0x83, 0x03, 0x03, 0x02,
|
||||||
|
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xFF, 0x3C, 0xFE, 0x83, 0x03, 0x03,
|
||||||
|
0x06, 0x38, 0x06, 0x03, 0x03, 0x03, 0x86, 0xFC, 0x03, 0x01, 0xC0, 0x70,
|
||||||
|
0x3C, 0x1B, 0x04, 0xC2, 0x31, 0x8C, 0x43, 0x3F, 0xF0, 0x30, 0x0C, 0x03,
|
||||||
|
0x00, 0x7E, 0x7E, 0x40, 0x40, 0x40, 0xFC, 0x7E, 0x03, 0x03, 0x03, 0x03,
|
||||||
|
0x86, 0xFC, 0x0E, 0x3E, 0x60, 0x40, 0xC0, 0xDC, 0xE7, 0xC3, 0xC1, 0xC1,
|
||||||
|
0xC3, 0x63, 0x3E, 0xFF, 0xFF, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x0C, 0x18,
|
||||||
|
0x18, 0x10, 0x30, 0x60, 0x3C, 0x7E, 0xC3, 0xC3, 0x43, 0x76, 0x3C, 0x66,
|
||||||
|
0xC3, 0x81, 0x81, 0xC3, 0x7E, 0x38, 0x7E, 0xC3, 0xC3, 0x81, 0xC3, 0xC3,
|
||||||
|
0x7D, 0x03, 0x03, 0x02, 0x0E, 0x78, 0x74, 0x00, 0xF0, 0x74, 0x00, 0xFA,
|
||||||
|
0x01, 0x03, 0x0C, 0x30, 0xC0, 0xE0, 0x1C, 0x07, 0x01, 0xFF, 0xFF, 0x00,
|
||||||
|
0x00, 0xFF, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x07, 0x38, 0xE0, 0x80, 0x39,
|
||||||
|
0xFC, 0x08, 0x10, 0x60, 0x86, 0x08, 0x30, 0x00, 0x01, 0x83, 0x00, 0x03,
|
||||||
|
0x80, 0x7F, 0x83, 0x01, 0x18, 0x02, 0x47, 0xCF, 0x31, 0x38, 0x84, 0x62,
|
||||||
|
0x31, 0x88, 0xCE, 0x23, 0x2C, 0x77, 0x10, 0x00, 0x60, 0x00, 0x7F, 0x00,
|
||||||
|
0x30, 0x00, 0x04, 0x01, 0xC0, 0x28, 0x05, 0x81, 0xB0, 0x22, 0x04, 0x61,
|
||||||
|
0x84, 0x3F, 0xCC, 0x19, 0x81, 0x20, 0x3C, 0x06, 0xF8, 0x7F, 0x20, 0xD0,
|
||||||
|
0x68, 0x34, 0x33, 0xF1, 0x06, 0x81, 0x40, 0xE0, 0x50, 0xEF, 0xE0, 0x0F,
|
||||||
|
0x0F, 0xF6, 0x01, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x06,
|
||||||
|
0x00, 0xC2, 0x1F, 0x80, 0xF8, 0x3F, 0xC8, 0x3A, 0x06, 0x80, 0xE0, 0x38,
|
||||||
|
0x0E, 0x03, 0x80, 0xE0, 0x68, 0x1A, 0x1C, 0xFC, 0x00, 0xFF, 0xFE, 0x04,
|
||||||
|
0x08, 0x10, 0x3F, 0x40, 0x81, 0x02, 0x04, 0x0F, 0xE0, 0xFF, 0xFE, 0x04,
|
||||||
|
0x08, 0x10, 0x3F, 0x7E, 0x81, 0x02, 0x04, 0x08, 0x00, 0x0F, 0x87, 0xF9,
|
||||||
|
0xC0, 0x30, 0x0C, 0x01, 0x80, 0x30, 0xFE, 0x1F, 0xC0, 0x68, 0x0D, 0x81,
|
||||||
|
0x98, 0x31, 0xFE, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFF, 0x01,
|
||||||
|
0x80, 0xC0, 0x60, 0x30, 0x18, 0x08, 0xFF, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||||
|
0xF0, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x3E, 0x81, 0xC1, 0xA1,
|
||||||
|
0x91, 0x89, 0x85, 0x83, 0xC1, 0xB0, 0x8C, 0x46, 0x21, 0x90, 0x68, 0x18,
|
||||||
|
0x81, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x81, 0x02, 0x04, 0x0F, 0xE0,
|
||||||
|
0xC0, 0x3C, 0x03, 0xE0, 0x7A, 0x05, 0xB0, 0xDB, 0x09, 0x90, 0x99, 0x99,
|
||||||
|
0x89, 0x18, 0xB1, 0x8F, 0x18, 0x61, 0x86, 0x10, 0xC0, 0xF0, 0x3E, 0x0E,
|
||||||
|
0xC3, 0xB0, 0xE6, 0x38, 0x8E, 0x33, 0x86, 0xE0, 0xB8, 0x3E, 0x07, 0x80,
|
||||||
|
0xC0, 0x0F, 0x03, 0xFC, 0x60, 0x64, 0x06, 0xC0, 0x2C, 0x03, 0xC0, 0x3C,
|
||||||
|
0x03, 0xC0, 0x3C, 0x02, 0x60, 0x63, 0x0C, 0x1F, 0x80, 0xF0, 0xFE, 0x82,
|
||||||
|
0x83, 0x83, 0x83, 0x86, 0xFC, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0F, 0x03,
|
||||||
|
0xFC, 0x60, 0x64, 0x06, 0xC0, 0x2C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C,
|
||||||
|
0x02, 0x60, 0x63, 0x0C, 0x1F, 0x80, 0x18, 0x01, 0xC0, 0x0E, 0xF0, 0x7F,
|
||||||
|
0x20, 0xD0, 0x68, 0x34, 0x13, 0xF9, 0xF0, 0x8C, 0x43, 0x21, 0x90, 0x68,
|
||||||
|
0x18, 0x3D, 0x7E, 0xC0, 0xC0, 0xC0, 0x60, 0x3C, 0x0E, 0x03, 0x03, 0x03,
|
||||||
|
0x86, 0xFC, 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30,
|
||||||
|
0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x18,
|
||||||
|
0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x70, 0x7C, 0x63, 0xE0, 0xC0, 0x78,
|
||||||
|
0x09, 0x03, 0x30, 0x46, 0x18, 0x43, 0x0C, 0x40, 0x98, 0x1B, 0x03, 0x40,
|
||||||
|
0x38, 0x07, 0x00, 0xC0, 0xC1, 0x83, 0x41, 0x83, 0x41, 0xC3, 0x63, 0xC2,
|
||||||
|
0x63, 0x46, 0x22, 0x46, 0x22, 0x66, 0x36, 0x24, 0x34, 0x2C, 0x14, 0x3C,
|
||||||
|
0x14, 0x38, 0x1C, 0x18, 0x18, 0x18, 0xC0, 0xD8, 0x22, 0x18, 0xCC, 0x1A,
|
||||||
|
0x03, 0x80, 0xC0, 0x38, 0x1A, 0x0C, 0xC2, 0x19, 0x82, 0xC0, 0xC0, 0xC0,
|
||||||
|
0xD0, 0x26, 0x18, 0x84, 0x33, 0x04, 0x81, 0xE0, 0x30, 0x0C, 0x03, 0x00,
|
||||||
|
0xC0, 0x30, 0x0C, 0x00, 0xFF, 0xFF, 0x03, 0x06, 0x04, 0x0C, 0x18, 0x10,
|
||||||
|
0x30, 0x60, 0x40, 0xC0, 0xFF, 0xFF, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||||
|
0xCF, 0xC1, 0x04, 0x18, 0x20, 0xC3, 0x04, 0x18, 0x20, 0x83, 0x04, 0xFF,
|
||||||
|
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1F, 0x10, 0x18, 0x38, 0x24, 0x64,
|
||||||
|
0x42, 0x42, 0x81, 0xFF, 0xD9, 0x80, 0x18, 0xFC, 0x08, 0x11, 0xEE, 0x70,
|
||||||
|
0xC1, 0xC6, 0xF4, 0xC0, 0x60, 0x30, 0x19, 0x8F, 0xF7, 0x0B, 0x07, 0x83,
|
||||||
|
0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE0, 0x1C, 0xFD, 0x06, 0x0C, 0x18, 0x30,
|
||||||
|
0x60, 0x62, 0x7C, 0x01, 0x01, 0x01, 0x19, 0x7F, 0xC3, 0xC1, 0xC1, 0xC1,
|
||||||
|
0xC1, 0xC1, 0x63, 0x3D, 0x18, 0x7E, 0x43, 0xC3, 0xFF, 0xFF, 0xC0, 0xC0,
|
||||||
|
0x61, 0x3F, 0x1E, 0x60, 0x81, 0x0F, 0xC4, 0x08, 0x10, 0x20, 0x40, 0x81,
|
||||||
|
0x02, 0x00, 0x18, 0x7F, 0x43, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x63, 0x3D,
|
||||||
|
0x01, 0x01, 0x43, 0x7E, 0xC0, 0xC0, 0xC0, 0xCC, 0xFF, 0xE1, 0xC1, 0xC1,
|
||||||
|
0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xF0, 0xFF, 0xFF, 0xC0, 0x33, 0x00, 0x33,
|
||||||
|
0x33, 0x33, 0x33, 0x33, 0x33, 0xE0, 0xC0, 0xC0, 0xC0, 0xC1, 0xC6, 0xCC,
|
||||||
|
0xD8, 0xD0, 0xF8, 0xCC, 0xC4, 0xC6, 0xC3, 0xFF, 0xFF, 0xFF, 0xC0, 0x0C,
|
||||||
|
0x33, 0xFB, 0xFE, 0x38, 0xF0, 0xC3, 0xC1, 0x07, 0x04, 0x1C, 0x10, 0x70,
|
||||||
|
0x41, 0xC1, 0x07, 0x04, 0x10, 0x0C, 0xFF, 0xE1, 0xC1, 0xC1, 0xC1, 0xC1,
|
||||||
|
0xC1, 0xC1, 0xC1, 0x18, 0x3F, 0x10, 0xD8, 0x3C, 0x1E, 0x0F, 0x07, 0x82,
|
||||||
|
0x63, 0x1F, 0x00, 0x0C, 0x7F, 0xB8, 0x58, 0x3C, 0x1E, 0x0F, 0x07, 0x83,
|
||||||
|
0xE3, 0x6F, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x18, 0x7F, 0xC3, 0xC1, 0xC1,
|
||||||
|
0xC1, 0xC1, 0xC1, 0x63, 0x3D, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x7E, 0x30,
|
||||||
|
0xC3, 0x0C, 0x30, 0xC3, 0x00, 0x39, 0xFA, 0x06, 0x07, 0x07, 0x81, 0x83,
|
||||||
|
0x85, 0xF8, 0x20, 0x86, 0x3F, 0x20, 0x82, 0x08, 0x20, 0x83, 0x0F, 0xC1,
|
||||||
|
0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x63, 0x7D, 0xC1, 0xA0, 0x98, 0xCC,
|
||||||
|
0x42, 0x21, 0xB0, 0x50, 0x28, 0x1C, 0x00, 0xC3, 0x0D, 0x1C, 0x26, 0x79,
|
||||||
|
0x99, 0x26, 0x24, 0x90, 0xB3, 0x43, 0x8F, 0x0E, 0x18, 0x18, 0x60, 0xE3,
|
||||||
|
0x99, 0x05, 0x83, 0x80, 0xC0, 0xB0, 0xC8, 0xC6, 0xC1, 0x80, 0xC1, 0xA0,
|
||||||
|
0x98, 0xC4, 0x43, 0x21, 0xB0, 0x50, 0x38, 0x0C, 0x04, 0x06, 0x02, 0x0F,
|
||||||
|
0x00, 0xFC, 0x18, 0x20, 0xC3, 0x0C, 0x10, 0x60, 0xFE, 0x04, 0x71, 0x04,
|
||||||
|
0x10, 0x41, 0x3C, 0xE0, 0xC1, 0x04, 0x10, 0x41, 0xC3, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xC0, 0x87, 0x18, 0x42, 0x10, 0x87, 0x39, 0x08, 0x42, 0x33, 0x90,
|
||||||
|
0xF9, 0x8F, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||||
|
0x1F, 0xE0, 0x00, 0x74, 0x55, 0x57, 0xC0, 0x10, 0x21, 0xFE, 0x0C, 0x10,
|
||||||
|
0x20, 0x40, 0x81, 0x81, 0xF0, 0x81, 0x00, 0x1E, 0x3F, 0x60, 0x60, 0x60,
|
||||||
|
0x60, 0xFC, 0x60, 0x60, 0x60, 0x60, 0xC0, 0xFF, 0xDB, 0x7E, 0x42, 0x43,
|
||||||
|
0x42, 0x62, 0xFF, 0x81, 0xC0, 0xD0, 0x26, 0x18, 0x84, 0x33, 0x04, 0x81,
|
||||||
|
0xE0, 0xFC, 0x0C, 0x03, 0x03, 0xF0, 0x30, 0x0C, 0x00, 0xFF, 0xF0, 0x03,
|
||||||
|
0xFF, 0xC0, 0x7F, 0x83, 0x03, 0x85, 0xD8, 0xF0, 0xB3, 0x3C, 0x1C, 0x1C,
|
||||||
|
0x3F, 0xC0, 0x9C, 0x80, 0x0F, 0x01, 0x86, 0x18, 0x08, 0x9F, 0x28, 0x81,
|
||||||
|
0x4C, 0x06, 0x60, 0x33, 0x01, 0x98, 0x0E, 0x6C, 0x91, 0xCC, 0x60, 0xC1,
|
||||||
|
0xF8, 0x00, 0x69, 0x1F, 0x9F, 0x32, 0xCB, 0x34, 0xC4, 0xCC, 0xCC, 0x80,
|
||||||
|
0xFF, 0x01, 0x01, 0x01, 0x01, 0xF0, 0x0F, 0x01, 0x86, 0x18, 0x08, 0x9E,
|
||||||
|
0x28, 0x99, 0x44, 0x46, 0x3C, 0x31, 0xE1, 0x89, 0x0E, 0x4C, 0x92, 0x3C,
|
||||||
|
0x60, 0xC1, 0xF8, 0x00, 0xFF, 0xFF, 0xC0, 0x73, 0x28, 0xE3, 0xC8, 0xC0,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x00, 0xFF, 0x7A,
|
||||||
|
0x42, 0x11, 0x11, 0x1F, 0xF9, 0x20, 0x9E, 0x08, 0x38, 0x9C, 0x6F, 0x00,
|
||||||
|
0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xE3, 0xFD, 0xC0, 0xC0, 0xC0,
|
||||||
|
0xC0, 0x7F, 0xFE, 0x7F, 0x3F, 0x9F, 0xCF, 0xE7, 0xF2, 0xF9, 0x04, 0x82,
|
||||||
|
0x41, 0x20, 0x90, 0x48, 0x24, 0x12, 0xF0, 0x66, 0x3E, 0x7E, 0x92, 0x49,
|
||||||
|
0x74, 0xE3, 0x18, 0xF8, 0x98, 0x99, 0x99, 0x96, 0x59, 0xA6, 0x00, 0x20,
|
||||||
|
0x4E, 0x0C, 0xA0, 0x82, 0x10, 0x23, 0x02, 0x22, 0x26, 0x62, 0x4A, 0x09,
|
||||||
|
0xA1, 0x92, 0x13, 0xF2, 0x02, 0x60, 0x20, 0x10, 0x63, 0x82, 0x34, 0x20,
|
||||||
|
0x23, 0x01, 0x10, 0x09, 0xB8, 0x4A, 0x62, 0x81, 0x0C, 0x18, 0x41, 0x86,
|
||||||
|
0x18, 0x21, 0x82, 0x0F, 0x80, 0x70, 0x13, 0x20, 0x80, 0x86, 0x06, 0x10,
|
||||||
|
0x78, 0xC0, 0x32, 0x68, 0xD3, 0xBE, 0xCE, 0x02, 0x58, 0x13, 0x60, 0x4F,
|
||||||
|
0xC2, 0x06, 0x18, 0x18, 0x08, 0x38, 0x20, 0x00, 0x81, 0x06, 0x18, 0x61,
|
||||||
|
0x83, 0x02, 0x17, 0xE0, 0x0C, 0x01, 0x80, 0x18, 0x00, 0x00, 0x40, 0x1C,
|
||||||
|
0x02, 0x80, 0x58, 0x1B, 0x02, 0x20, 0x46, 0x18, 0x43, 0xFC, 0xC1, 0x98,
|
||||||
|
0x12, 0x03, 0xC0, 0x60, 0x03, 0x00, 0x60, 0x18, 0x00, 0x00, 0x40, 0x1C,
|
||||||
|
0x02, 0x80, 0x58, 0x1B, 0x02, 0x20, 0x46, 0x18, 0x43, 0xFC, 0xC1, 0x98,
|
||||||
|
0x12, 0x03, 0xC0, 0x60, 0x04, 0x01, 0xC0, 0x6C, 0x00, 0x40, 0x40, 0x1C,
|
||||||
|
0x02, 0x80, 0x58, 0x1B, 0x02, 0x20, 0x46, 0x18, 0x43, 0xFC, 0xC1, 0x98,
|
||||||
|
0x12, 0x03, 0xC0, 0x60, 0x1C, 0x82, 0xF0, 0x00, 0x02, 0x00, 0xE0, 0x14,
|
||||||
|
0x02, 0xC0, 0xD8, 0x11, 0x02, 0x30, 0xC2, 0x1F, 0xE6, 0x0C, 0xC0, 0x90,
|
||||||
|
0x1E, 0x03, 0x09, 0x81, 0x20, 0x00, 0x02, 0x00, 0xE0, 0x14, 0x02, 0xC0,
|
||||||
|
0xD8, 0x11, 0x02, 0x30, 0xC2, 0x1F, 0xE6, 0x0C, 0xC0, 0x90, 0x1E, 0x03,
|
||||||
|
0x0E, 0x01, 0x20, 0x38, 0x07, 0x00, 0xA0, 0x16, 0x06, 0xC0, 0x88, 0x11,
|
||||||
|
0x86, 0x10, 0xFF, 0x30, 0x66, 0x04, 0x80, 0xF0, 0x18, 0x03, 0xFC, 0x1F,
|
||||||
|
0xF0, 0x6C, 0x03, 0x30, 0x0C, 0xC0, 0x23, 0x01, 0x8F, 0xC4, 0x30, 0x3F,
|
||||||
|
0xC0, 0x83, 0x06, 0x0C, 0x10, 0x30, 0xC0, 0xFC, 0x0F, 0x0F, 0xF6, 0x01,
|
||||||
|
0x80, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x06, 0x00, 0xC2, 0x1F,
|
||||||
|
0x81, 0x00, 0x60, 0x0C, 0x0E, 0x00, 0x60, 0xC0, 0xC0, 0x0F, 0xFF, 0xE0,
|
||||||
|
0x40, 0x81, 0x03, 0xF4, 0x08, 0x10, 0x20, 0x40, 0xFE, 0x0C, 0x18, 0x60,
|
||||||
|
0x0F, 0xFF, 0xE0, 0x40, 0x81, 0x03, 0xF4, 0x08, 0x10, 0x20, 0x40, 0xFE,
|
||||||
|
0x10, 0x71, 0xB0, 0x1F, 0xFF, 0xE0, 0x40, 0x81, 0x03, 0xF4, 0x08, 0x10,
|
||||||
|
0x20, 0x40, 0xFE, 0x4C, 0x90, 0x07, 0xFF, 0xF0, 0x20, 0x40, 0x81, 0xFA,
|
||||||
|
0x04, 0x08, 0x10, 0x20, 0x7F, 0xCC, 0x60, 0xFF, 0x66, 0x66, 0x66, 0x66,
|
||||||
|
0x66, 0xF0, 0x33, 0x60, 0xFF, 0x66, 0x66, 0x66, 0x66, 0x66, 0xF0, 0x21,
|
||||||
|
0xCD, 0x81, 0x79, 0xE3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x78,
|
||||||
|
0x9C, 0x81, 0xEF, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0x9E, 0x7C, 0x0F,
|
||||||
|
0xE1, 0x07, 0x20, 0x64, 0x06, 0x80, 0xFF, 0x1A, 0x03, 0x40, 0x68, 0x19,
|
||||||
|
0x03, 0x21, 0xC7, 0xE0, 0x39, 0x0B, 0xC0, 0x03, 0x03, 0xC0, 0xF8, 0x3B,
|
||||||
|
0x0E, 0xC3, 0x98, 0xE2, 0x38, 0xCE, 0x1B, 0x82, 0xE0, 0xF8, 0x1E, 0x03,
|
||||||
|
0x0C, 0x00, 0xC0, 0x06, 0x00, 0x00, 0x0F, 0x03, 0xFC, 0x60, 0x64, 0x06,
|
||||||
|
0xC0, 0x2C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x02, 0x60, 0x63, 0x0C,
|
||||||
|
0x1F, 0x80, 0x03, 0x00, 0x30, 0x06, 0x00, 0x00, 0x0F, 0x03, 0xFC, 0x60,
|
||||||
|
0x64, 0x06, 0xC0, 0x2C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x02, 0x60,
|
||||||
|
0x63, 0x0C, 0x1F, 0x80, 0x04, 0x00, 0xE0, 0x1B, 0x00, 0x08, 0x0F, 0x03,
|
||||||
|
0xFC, 0x60, 0x64, 0x06, 0xC0, 0x2C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C,
|
||||||
|
0x02, 0x60, 0x63, 0x0C, 0x1F, 0x80, 0x1C, 0x81, 0x78, 0x00, 0x00, 0xF0,
|
||||||
|
0x3F, 0xC6, 0x06, 0x40, 0x6C, 0x02, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03,
|
||||||
|
0xC0, 0x26, 0x06, 0x30, 0xC1, 0xF8, 0x09, 0x80, 0x90, 0x00, 0x00, 0xF0,
|
||||||
|
0x3F, 0xC6, 0x06, 0x40, 0x6C, 0x02, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03,
|
||||||
|
0xC0, 0x26, 0x06, 0x30, 0xC1, 0xF8, 0xC3, 0x66, 0x3C, 0x18, 0x3C, 0x66,
|
||||||
|
0xC3, 0x41, 0x0F, 0x63, 0xFC, 0x60, 0xE4, 0x1E, 0xC1, 0x2C, 0x23, 0xC6,
|
||||||
|
0x3C, 0xC3, 0xC8, 0x3D, 0x82, 0x70, 0x63, 0x0C, 0x7F, 0x84, 0x00, 0x30,
|
||||||
|
0x18, 0x06, 0x00, 0x08, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30,
|
||||||
|
0x18, 0x0C, 0x07, 0x07, 0xC6, 0x3E, 0x00, 0x06, 0x03, 0x03, 0x00, 0x08,
|
||||||
|
0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x07, 0x07,
|
||||||
|
0xC6, 0x3E, 0x00, 0x08, 0x0E, 0x0D, 0x80, 0x28, 0x0C, 0x06, 0x03, 0x01,
|
||||||
|
0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x07, 0x07, 0xC6, 0x3E, 0x00, 0x26,
|
||||||
|
0x12, 0x00, 0x10, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30,
|
||||||
|
0x18, 0x0E, 0x0F, 0x8C, 0x7C, 0x06, 0x01, 0x80, 0xC0, 0x00, 0xC0, 0xD0,
|
||||||
|
0x26, 0x18, 0x84, 0x33, 0x04, 0x81, 0xE0, 0x30, 0x0C, 0x03, 0x00, 0xC0,
|
||||||
|
0x30, 0x0C, 0x00, 0x80, 0x80, 0x80, 0xFE, 0x86, 0x83, 0x83, 0x83, 0x86,
|
||||||
|
0xFC, 0x80, 0x80, 0x80, 0x7F, 0x21, 0x90, 0x58, 0x6C, 0x66, 0x63, 0x31,
|
||||||
|
0x8E, 0xC3, 0xE0, 0x70, 0x3A, 0x3D, 0xF0, 0x30, 0x60, 0x60, 0x01, 0x8F,
|
||||||
|
0xC0, 0x81, 0x1E, 0xE7, 0x0C, 0x1C, 0x6F, 0x40, 0x0C, 0x18, 0x60, 0x01,
|
||||||
|
0x8F, 0xC0, 0x81, 0x1E, 0xE7, 0x0C, 0x1C, 0x6F, 0x40, 0x10, 0x71, 0xB0,
|
||||||
|
0x11, 0x8F, 0xC0, 0x81, 0x1E, 0xE7, 0x0C, 0x1C, 0x6F, 0x40, 0x72, 0xBC,
|
||||||
|
0x00, 0xC7, 0xE0, 0x40, 0x8F, 0x73, 0x86, 0x0E, 0x37, 0xA0, 0x26, 0x48,
|
||||||
|
0x00, 0xC7, 0xE0, 0x40, 0x8F, 0x73, 0x86, 0x0E, 0x37, 0xA0, 0x38, 0x48,
|
||||||
|
0xE0, 0x01, 0x8F, 0xC0, 0x81, 0x1E, 0xE7, 0x0C, 0x1C, 0x6F, 0x40, 0x18,
|
||||||
|
0x63, 0xFF, 0x81, 0xC6, 0x04, 0x11, 0xFF, 0xB9, 0xFF, 0x08, 0x10, 0xE0,
|
||||||
|
0xC5, 0x8B, 0xC7, 0xC0, 0x1C, 0xFD, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x62,
|
||||||
|
0x7C, 0x40, 0xC0, 0xC7, 0x00, 0x30, 0x30, 0x18, 0x00, 0x18, 0x7E, 0x43,
|
||||||
|
0xC3, 0xFF, 0xFF, 0xC0, 0xC0, 0x61, 0x3F, 0x0C, 0x0C, 0x18, 0x00, 0x18,
|
||||||
|
0x7E, 0x43, 0xC3, 0xFF, 0xFF, 0xC0, 0xC0, 0x61, 0x3F, 0x10, 0x38, 0x6C,
|
||||||
|
0x02, 0x18, 0x7E, 0x43, 0xC3, 0xFF, 0xFF, 0xC0, 0xC0, 0x61, 0x3F, 0x26,
|
||||||
|
0x24, 0x00, 0x18, 0x7E, 0x43, 0xC3, 0xFF, 0xFF, 0xC0, 0xC0, 0x61, 0x3F,
|
||||||
|
0xD9, 0x80, 0xDB, 0x6D, 0xB6, 0xC0, 0x33, 0x60, 0x0C, 0xCC, 0xCC, 0xCC,
|
||||||
|
0xCC, 0x21, 0xCD, 0x81, 0x01, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x80,
|
||||||
|
0x9C, 0x80, 0x06, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x00, 0x3B, 0x06, 0x0D,
|
||||||
|
0x84, 0x60, 0x33, 0xF9, 0x0F, 0x83, 0xC1, 0xE0, 0xF0, 0x4C, 0x63, 0xE0,
|
||||||
|
0x39, 0x2F, 0x00, 0x0C, 0xFF, 0xE1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
|
||||||
|
0xC1, 0x30, 0x18, 0x06, 0x00, 0x01, 0x83, 0xF1, 0x0D, 0x83, 0xC1, 0xE0,
|
||||||
|
0xF0, 0x78, 0x26, 0x31, 0xF0, 0x06, 0x03, 0x03, 0x00, 0x01, 0x83, 0xF1,
|
||||||
|
0x0D, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x26, 0x31, 0xF0, 0x08, 0x0E, 0x0D,
|
||||||
|
0x80, 0x21, 0x83, 0xF1, 0x0D, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x26, 0x31,
|
||||||
|
0xF0, 0x72, 0x2F, 0x00, 0x03, 0x07, 0xE2, 0x1B, 0x07, 0x83, 0xC1, 0xE0,
|
||||||
|
0xF0, 0x4C, 0x63, 0xE0, 0x26, 0x12, 0x00, 0x03, 0x07, 0xE2, 0x1B, 0x07,
|
||||||
|
0x83, 0xC1, 0xE0, 0xF0, 0x4C, 0x63, 0xE0, 0x18, 0x18, 0x00, 0xFF, 0x00,
|
||||||
|
0x00, 0x18, 0x18, 0x19, 0x3F, 0x90, 0xD8, 0xAC, 0xDE, 0xCF, 0x47, 0xE2,
|
||||||
|
0x63, 0x7F, 0x10, 0x00, 0x30, 0x30, 0x18, 0x00, 0x00, 0xC1, 0xC1, 0xC1,
|
||||||
|
0xC1, 0xC1, 0xC1, 0xC1, 0x63, 0x7D, 0x06, 0x06, 0x0C, 0x00, 0x00, 0xC1,
|
||||||
|
0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x63, 0x7D, 0x08, 0x1C, 0x36, 0x01,
|
||||||
|
0x00, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x63, 0x7D, 0x26, 0x24,
|
||||||
|
0x00, 0x00, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x63, 0x7D, 0x06,
|
||||||
|
0x03, 0x03, 0x00, 0x00, 0x06, 0x0D, 0x04, 0xC6, 0x22, 0x19, 0x0D, 0x82,
|
||||||
|
0x81, 0xC0, 0x60, 0x20, 0x30, 0x10, 0x78, 0x00, 0xC0, 0x60, 0x30, 0x19,
|
||||||
|
0x8F, 0xF7, 0x0B, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE6, 0x03,
|
||||||
|
0x01, 0x80, 0xC0, 0x00, 0x26, 0x12, 0x00, 0x00, 0x0C, 0x1A, 0x09, 0x8C,
|
||||||
|
0x44, 0x32, 0x1B, 0x05, 0x03, 0x80, 0xC0, 0x40, 0x60, 0x20, 0xF0, 0x00,
|
||||||
|
0x1F, 0x00, 0x00, 0x10, 0x07, 0x00, 0xA0, 0x16, 0x06, 0xC0, 0x88, 0x11,
|
||||||
|
0x86, 0x10, 0xFF, 0x30, 0x66, 0x04, 0x80, 0xF0, 0x18, 0x3E, 0x00, 0x63,
|
||||||
|
0xF0, 0x20, 0x47, 0xB9, 0xC3, 0x07, 0x1B, 0xD0, 0x11, 0x03, 0xE0, 0x00,
|
||||||
|
0x02, 0x00, 0xE0, 0x14, 0x02, 0xC0, 0xD8, 0x11, 0x02, 0x30, 0xC2, 0x1F,
|
||||||
|
0xE6, 0x0C, 0xC0, 0x90, 0x1E, 0x03, 0x22, 0x7C, 0x00, 0xC7, 0xE0, 0x40,
|
||||||
|
0x8F, 0x73, 0x86, 0x0E, 0x37, 0xA0, 0x04, 0x00, 0xE0, 0x0A, 0x00, 0xB0,
|
||||||
|
0x1B, 0x01, 0x10, 0x11, 0x83, 0x08, 0x3F, 0xC6, 0x0C, 0x60, 0x44, 0x06,
|
||||||
|
0xC0, 0x60, 0x06, 0x00, 0x40, 0x04, 0x00, 0x70, 0x18, 0x7E, 0x02, 0x02,
|
||||||
|
0x1E, 0x72, 0xC2, 0x82, 0xC6, 0x7A, 0x06, 0x04, 0x04, 0x07, 0x03, 0x00,
|
||||||
|
0xC0, 0x60, 0x00, 0x0F, 0x0F, 0xF6, 0x01, 0x80, 0xC0, 0x30, 0x0C, 0x03,
|
||||||
|
0x00, 0xC0, 0x30, 0x06, 0x00, 0xC2, 0x1F, 0x80, 0x0C, 0x18, 0x60, 0x01,
|
||||||
|
0xCF, 0xD0, 0x60, 0xC1, 0x83, 0x06, 0x06, 0x27, 0xC0, 0x04, 0x03, 0x81,
|
||||||
|
0xB0, 0x02, 0x0F, 0x0F, 0xF6, 0x01, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x00,
|
||||||
|
0xC0, 0x30, 0x06, 0x00, 0xC2, 0x1F, 0x80, 0x10, 0x71, 0xB0, 0x11, 0xCF,
|
||||||
|
0xD0, 0x60, 0xC1, 0x83, 0x06, 0x06, 0x27, 0xC0, 0x04, 0x01, 0x80, 0x00,
|
||||||
|
0x3C, 0x3F, 0xD8, 0x06, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0,
|
||||||
|
0x18, 0x03, 0x08, 0x7E, 0x10, 0x30, 0x00, 0xE7, 0xE8, 0x30, 0x60, 0xC1,
|
||||||
|
0x83, 0x03, 0x13, 0xE0, 0x10, 0x86, 0xC0, 0xE0, 0x00, 0x0F, 0x0F, 0xF6,
|
||||||
|
0x01, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x06, 0x00, 0xC2,
|
||||||
|
0x1F, 0x80, 0x42, 0xD8, 0xE0, 0x01, 0xCF, 0xD0, 0x60, 0xC1, 0x83, 0x06,
|
||||||
|
0x06, 0x27, 0xC0, 0x21, 0x0D, 0x81, 0xC0, 0x00, 0xF8, 0x3F, 0xC8, 0x3A,
|
||||||
|
0x06, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x68, 0x1A, 0x1C, 0xFC,
|
||||||
|
0x00, 0x01, 0x60, 0x28, 0x04, 0x0C, 0x87, 0xF1, 0x86, 0x30, 0x46, 0x08,
|
||||||
|
0xC1, 0x18, 0x23, 0x04, 0x31, 0x83, 0xD0, 0x7C, 0x0F, 0xE1, 0x07, 0x20,
|
||||||
|
0x64, 0x06, 0x80, 0xFF, 0x1A, 0x03, 0x40, 0x68, 0x19, 0x03, 0x21, 0xC7,
|
||||||
|
0xE0, 0x01, 0x07, 0xF0, 0x10, 0x64, 0x7F, 0x30, 0xCC, 0x13, 0x04, 0xC1,
|
||||||
|
0x30, 0x4C, 0x11, 0x8C, 0x3D, 0x00, 0x7C, 0x03, 0xFF, 0xF8, 0x10, 0x20,
|
||||||
|
0x40, 0xFD, 0x02, 0x04, 0x08, 0x10, 0x3F, 0x80, 0x3E, 0x00, 0x18, 0x7E,
|
||||||
|
0x43, 0xC3, 0xFF, 0xFF, 0xC0, 0xC0, 0x61, 0x3F, 0x44, 0xF8, 0x07, 0xFF,
|
||||||
|
0xF0, 0x20, 0x40, 0x81, 0xFA, 0x04, 0x08, 0x10, 0x20, 0x7F, 0x22, 0x3E,
|
||||||
|
0x00, 0x18, 0x7E, 0x43, 0xC3, 0xFF, 0xFF, 0xC0, 0xC0, 0x61, 0x3F, 0x10,
|
||||||
|
0x30, 0x07, 0xFF, 0xF0, 0x20, 0x40, 0x81, 0xFA, 0x04, 0x08, 0x10, 0x20,
|
||||||
|
0x7F, 0x10, 0x18, 0x00, 0x18, 0x7E, 0x43, 0xC3, 0xFF, 0xFF, 0xC0, 0xC0,
|
||||||
|
0x61, 0x3F, 0xFF, 0xFE, 0x04, 0x08, 0x10, 0x3F, 0x40, 0x81, 0x02, 0x04,
|
||||||
|
0x0F, 0xE1, 0x82, 0x04, 0x0E, 0x18, 0x7E, 0x43, 0xC3, 0xFF, 0xFF, 0xC0,
|
||||||
|
0xC0, 0x61, 0x3F, 0x06, 0x04, 0x04, 0x07, 0x42, 0xD8, 0xE0, 0x0F, 0xFF,
|
||||||
|
0xE0, 0x40, 0x81, 0x03, 0xF4, 0x08, 0x10, 0x20, 0x40, 0xFE, 0x42, 0x6C,
|
||||||
|
0x38, 0x00, 0x18, 0x7E, 0x43, 0xC3, 0xFF, 0xFF, 0xC0, 0xC0, 0x61, 0x3F,
|
||||||
|
0x04, 0x01, 0xC0, 0x6C, 0x00, 0x40, 0xF8, 0x7F, 0x9C, 0x03, 0x00, 0xC0,
|
||||||
|
0x18, 0x03, 0x0F, 0xE1, 0xFC, 0x06, 0x80, 0xD8, 0x19, 0x83, 0x1F, 0xE0,
|
||||||
|
0x08, 0x1C, 0x36, 0x01, 0x18, 0x7F, 0x43, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
|
||||||
|
0x63, 0x3D, 0x01, 0x01, 0x43, 0x7E, 0x08, 0x81, 0xF0, 0x00, 0x07, 0xC3,
|
||||||
|
0xFC, 0xE0, 0x18, 0x06, 0x00, 0xC0, 0x18, 0x7F, 0x0F, 0xE0, 0x34, 0x06,
|
||||||
|
0xC0, 0xCC, 0x18, 0xFF, 0x22, 0x3E, 0x00, 0x18, 0x7F, 0x43, 0xC1, 0xC1,
|
||||||
|
0xC1, 0xC1, 0xC1, 0x63, 0x3D, 0x01, 0x01, 0x43, 0x7E, 0x02, 0x00, 0x60,
|
||||||
|
0x00, 0x07, 0xC3, 0xFC, 0xE0, 0x18, 0x06, 0x00, 0xC0, 0x18, 0x7F, 0x0F,
|
||||||
|
0xE0, 0x34, 0x06, 0xC0, 0xCC, 0x18, 0xFF, 0x08, 0x0C, 0x00, 0x18, 0x7F,
|
||||||
|
0x43, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x63, 0x3D, 0x01, 0x01, 0x43, 0x7E,
|
||||||
|
0x0F, 0x87, 0xF9, 0xC0, 0x30, 0x0C, 0x01, 0x80, 0x30, 0xFE, 0x1F, 0xC0,
|
||||||
|
0x68, 0x0D, 0x81, 0x98, 0x31, 0xFE, 0x00, 0x00, 0x80, 0x30, 0x04, 0x00,
|
||||||
|
0x08, 0x08, 0x18, 0x00, 0x18, 0x7F, 0x43, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
|
||||||
|
0x63, 0x3D, 0x01, 0x01, 0x43, 0x7E, 0x08, 0x0E, 0x0D, 0x80, 0x28, 0x0C,
|
||||||
|
0x06, 0x03, 0x01, 0x80, 0xC0, 0x7F, 0xF0, 0x18, 0x0C, 0x06, 0x03, 0x01,
|
||||||
|
0x80, 0x80, 0x20, 0x38, 0x36, 0x00, 0x80, 0x03, 0x01, 0x80, 0xC0, 0x66,
|
||||||
|
0x3F, 0xDC, 0x2C, 0x16, 0x0B, 0x05, 0x82, 0xC1, 0x60, 0xB0, 0x40, 0x20,
|
||||||
|
0x21, 0x01, 0x08, 0x09, 0xFF, 0xF2, 0x02, 0x10, 0x10, 0xFF, 0x84, 0x04,
|
||||||
|
0x20, 0x21, 0x01, 0x08, 0x08, 0x40, 0x42, 0x02, 0x00, 0x60, 0x7F, 0x18,
|
||||||
|
0x0C, 0x06, 0xFB, 0x8D, 0x82, 0xC1, 0x60, 0xB0, 0x58, 0x2C, 0x16, 0x08,
|
||||||
|
0xE6, 0xF0, 0x1E, 0x78, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x1E,
|
||||||
|
0xE6, 0xF0, 0x00, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xF8, 0x3D,
|
||||||
|
0xE6, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x33, 0xC0, 0xF8, 0x00, 0xC6, 0x31,
|
||||||
|
0x8C, 0x63, 0x18, 0xC0, 0x8F, 0xC1, 0xEF, 0x31, 0x8C, 0x63, 0x18, 0xC6,
|
||||||
|
0x31, 0x9E, 0x8F, 0xC0, 0x06, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x00, 0xF7,
|
||||||
|
0x98, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xCF, 0x18, 0x84, 0x38, 0xD8, 0x0D,
|
||||||
|
0xB6, 0xDB, 0x6D, 0xA4, 0xE0, 0x46, 0x0F, 0xF6, 0x66, 0x66, 0x66, 0x66,
|
||||||
|
0x6F, 0xFF, 0xFF, 0xC0, 0xF1, 0xF1, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
||||||
|
0x61, 0x61, 0x61, 0x61, 0xF1, 0x01, 0x03, 0x0E, 0xC7, 0x8C, 0x00, 0x0C,
|
||||||
|
0x78, 0xF1, 0xE3, 0xC7, 0x8F, 0x1E, 0x3C, 0x60, 0xC1, 0x83, 0x1C, 0x10,
|
||||||
|
0x71, 0xB0, 0x11, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x81, 0x02, 0x04,
|
||||||
|
0x08, 0x10, 0x20, 0xC7, 0x00, 0x10, 0x71, 0xB0, 0x10, 0x06, 0x0C, 0x18,
|
||||||
|
0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x31, 0xC0, 0x81, 0xC1, 0xA1,
|
||||||
|
0x91, 0x89, 0x85, 0x83, 0xC1, 0xB0, 0x8C, 0x46, 0x21, 0x90, 0x68, 0x18,
|
||||||
|
0x00, 0x20, 0x30, 0x10, 0x00, 0xC0, 0xC0, 0xC0, 0xC1, 0xC6, 0xCC, 0xD8,
|
||||||
|
0xD0, 0xF8, 0xCC, 0xC4, 0xC6, 0xC3, 0x00, 0x08, 0x18, 0x10, 0xC7, 0xCC,
|
||||||
|
0xC8, 0xD8, 0xF8, 0xCC, 0xC4, 0xC6, 0xC3, 0x60, 0xC3, 0x00, 0x08, 0x10,
|
||||||
|
0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0xFE, 0x33, 0x60,
|
||||||
|
0x0C, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x81, 0x02, 0x04, 0x08, 0x10,
|
||||||
|
0x20, 0x40, 0x81, 0x02, 0x04, 0x0F, 0xE0, 0x04, 0x18, 0x20, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xC7, 0x80, 0x87, 0x0A, 0x14, 0x08, 0x10, 0x20, 0x40, 0x81, 0x02,
|
||||||
|
0x04, 0x0F, 0xE0, 0xDE, 0xB1, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x00,
|
||||||
|
0x81, 0x02, 0x04, 0x08, 0x10, 0x22, 0x46, 0x81, 0x02, 0x04, 0x0F, 0xE0,
|
||||||
|
0xC6, 0x31, 0x8C, 0x6B, 0x78, 0xC6, 0x31, 0x8C, 0x00, 0x20, 0x10, 0x08,
|
||||||
|
0x04, 0x02, 0x01, 0x20, 0xE0, 0xE0, 0xE0, 0x10, 0x08, 0x04, 0x03, 0xF8,
|
||||||
|
0x63, 0x18, 0xC6, 0x3D, 0xDC, 0xE3, 0x18, 0xC6, 0x00, 0x06, 0x01, 0x80,
|
||||||
|
0xC0, 0x00, 0xC0, 0xF0, 0x3E, 0x0E, 0xC3, 0xB0, 0xE6, 0x38, 0x8E, 0x33,
|
||||||
|
0x86, 0xE0, 0xB8, 0x3E, 0x07, 0x80, 0xC0, 0x06, 0x06, 0x0C, 0x00, 0x0C,
|
||||||
|
0xFF, 0xE1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC0, 0xF0, 0x3E,
|
||||||
|
0x0E, 0xC3, 0xB0, 0xE6, 0x38, 0x8E, 0x33, 0x86, 0xE0, 0xB8, 0x3E, 0x07,
|
||||||
|
0x80, 0xC0, 0x00, 0x40, 0x30, 0x08, 0x00, 0x0C, 0xFF, 0xE1, 0xC1, 0xC1,
|
||||||
|
0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x00, 0x08, 0x18, 0x10, 0x21, 0x0D, 0x81,
|
||||||
|
0xC0, 0x00, 0xC0, 0xF0, 0x3E, 0x0E, 0xC3, 0xB0, 0xE6, 0x38, 0x8E, 0x33,
|
||||||
|
0x86, 0xE0, 0xB8, 0x3E, 0x07, 0x80, 0xC0, 0x21, 0x36, 0x1C, 0x00, 0x0C,
|
||||||
|
0xFF, 0xE1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x60, 0x18, 0x04,
|
||||||
|
0x01, 0x0C, 0xBF, 0xCE, 0x13, 0x04, 0xC1, 0x30, 0x4C, 0x13, 0x04, 0xC1,
|
||||||
|
0x30, 0x40, 0xC0, 0xF0, 0x3E, 0x0E, 0xC3, 0xB0, 0xE6, 0x38, 0xCE, 0x33,
|
||||||
|
0x86, 0xE0, 0xF8, 0x1E, 0x07, 0x80, 0xC0, 0x30, 0x08, 0x1E, 0x0C, 0xFF,
|
||||||
|
0xE1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x01, 0x01, 0x01, 0x07,
|
||||||
|
0x0F, 0x80, 0x00, 0x0F, 0x03, 0xFC, 0x60, 0x64, 0x06, 0xC0, 0x2C, 0x03,
|
||||||
|
0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x02, 0x60, 0x63, 0x0C, 0x1F, 0x80, 0x3E,
|
||||||
|
0x00, 0x06, 0x0F, 0xC4, 0x36, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0x98, 0xC7,
|
||||||
|
0xC0, 0x11, 0x01, 0xF0, 0x00, 0x00, 0xF0, 0x3F, 0xC6, 0x06, 0x40, 0x6C,
|
||||||
|
0x02, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x26, 0x06, 0x30, 0xC1,
|
||||||
|
0xF8, 0x22, 0x1F, 0x00, 0x03, 0x07, 0xE2, 0x1B, 0x07, 0x83, 0xC1, 0xE0,
|
||||||
|
0xF0, 0x4C, 0x63, 0xE0, 0x0D, 0x80, 0x90, 0x13, 0x00, 0x00, 0x0F, 0x03,
|
||||||
|
0xFC, 0x60, 0x64, 0x06, 0xC0, 0x2C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C,
|
||||||
|
0x02, 0x60, 0x63, 0x0C, 0x1F, 0x80, 0x36, 0x12, 0x13, 0x00, 0x01, 0x83,
|
||||||
|
0xF1, 0x0D, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x26, 0x31, 0xF0, 0x0F, 0xFC,
|
||||||
|
0xFF, 0xF6, 0x08, 0x10, 0x20, 0xC0, 0x83, 0x02, 0x0C, 0x0F, 0xF0, 0x20,
|
||||||
|
0xC0, 0x83, 0x02, 0x06, 0x08, 0x0C, 0x20, 0x1F, 0xFC, 0x18, 0x30, 0xFD,
|
||||||
|
0xF9, 0x0E, 0x16, 0x0C, 0x3C, 0x1F, 0xF8, 0x3F, 0xF0, 0x60, 0x60, 0xC0,
|
||||||
|
0x63, 0xC4, 0x7C, 0xF8, 0x0C, 0x06, 0x06, 0x00, 0x0F, 0x07, 0xF2, 0x0D,
|
||||||
|
0x06, 0x83, 0x41, 0x3F, 0x9F, 0x08, 0xC4, 0x32, 0x19, 0x06, 0x81, 0x80,
|
||||||
|
0x0C, 0x31, 0x80, 0x0F, 0x7E, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x00, 0xF0,
|
||||||
|
0x7F, 0x20, 0xD0, 0x68, 0x34, 0x13, 0xF9, 0xF0, 0x8C, 0x43, 0x21, 0x90,
|
||||||
|
0x68, 0x18, 0x00, 0x20, 0x30, 0x10, 0x00, 0x0F, 0x7E, 0x30, 0xC3, 0x0C,
|
||||||
|
0x30, 0xC3, 0x00, 0x10, 0xC2, 0x00, 0x42, 0x36, 0x0E, 0x00, 0x0F, 0x07,
|
||||||
|
0xF2, 0x0D, 0x06, 0x83, 0x41, 0x3F, 0x9F, 0x08, 0xC4, 0x32, 0x19, 0x06,
|
||||||
|
0x81, 0x80, 0x42, 0xD8, 0xE0, 0x00, 0xDB, 0xB8, 0x60, 0xC1, 0x83, 0x06,
|
||||||
|
0x0C, 0x18, 0x00, 0x0C, 0x0C, 0x18, 0x00, 0x3D, 0x7E, 0xC0, 0xC0, 0xC0,
|
||||||
|
0x60, 0x3C, 0x0E, 0x03, 0x03, 0x03, 0x86, 0xFC, 0x0C, 0x18, 0x60, 0x03,
|
||||||
|
0x9F, 0xA0, 0x60, 0x70, 0x78, 0x18, 0x38, 0x5F, 0x80, 0x10, 0x38, 0x6C,
|
||||||
|
0x02, 0x3D, 0x7E, 0xC0, 0xC0, 0xC0, 0x60, 0x3C, 0x0E, 0x03, 0x03, 0x03,
|
||||||
|
0x86, 0xFC, 0x10, 0x71, 0xB0, 0x13, 0x9F, 0xA0, 0x60, 0x70, 0x78, 0x18,
|
||||||
|
0x38, 0x5F, 0x80, 0x3D, 0x7E, 0xC0, 0xC0, 0xC0, 0x60, 0x3C, 0x0E, 0x03,
|
||||||
|
0x03, 0x03, 0x86, 0xFC, 0x10, 0x18, 0x0C, 0x38, 0x39, 0xFA, 0x06, 0x07,
|
||||||
|
0x07, 0x81, 0x83, 0x85, 0xF8, 0x81, 0x81, 0x8E, 0x00, 0x42, 0x6C, 0x38,
|
||||||
|
0x00, 0x3D, 0x7E, 0xC0, 0xC0, 0xC0, 0x60, 0x3C, 0x0E, 0x03, 0x03, 0x03,
|
||||||
|
0x86, 0xFC, 0x42, 0xD8, 0xE0, 0x03, 0x9F, 0xA0, 0x60, 0x70, 0x78, 0x18,
|
||||||
|
0x38, 0x5F, 0x80, 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0,
|
||||||
|
0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x02, 0x00, 0xC0, 0x18, 0x1C,
|
||||||
|
0x00, 0x20, 0x86, 0x3F, 0x20, 0x82, 0x08, 0x20, 0x83, 0x0F, 0x10, 0x60,
|
||||||
|
0xCE, 0x21, 0x0D, 0x81, 0xC0, 0x00, 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C,
|
||||||
|
0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x00, 0x01,
|
||||||
|
0x23, 0x20, 0x60, 0xFC, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x3C,
|
||||||
|
0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x03, 0x07, 0xF0, 0x30, 0x0C, 0x03,
|
||||||
|
0x00, 0xC0, 0x30, 0x0C, 0x00, 0x20, 0x86, 0x3F, 0x20, 0x8F, 0xC8, 0x20,
|
||||||
|
0x83, 0x0F, 0x39, 0x17, 0x80, 0x10, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80,
|
||||||
|
0xC0, 0x60, 0x30, 0x18, 0x0E, 0x0F, 0x8C, 0x7C, 0x39, 0x2F, 0x00, 0x00,
|
||||||
|
0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x63, 0x7D, 0x3E, 0x00, 0x20,
|
||||||
|
0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x1C, 0x1F,
|
||||||
|
0x18, 0xF8, 0x3E, 0x00, 0x00, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
|
||||||
|
0x63, 0x7D, 0x22, 0x1F, 0x00, 0x10, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80,
|
||||||
|
0xC0, 0x60, 0x30, 0x18, 0x0E, 0x0F, 0x8C, 0x7C, 0x22, 0x3E, 0x00, 0x00,
|
||||||
|
0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x63, 0x7D, 0x1C, 0x09, 0x07,
|
||||||
|
0x00, 0x08, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C,
|
||||||
|
0x07, 0x07, 0xC6, 0x3E, 0x00, 0x1C, 0x12, 0x1C, 0x00, 0x00, 0xC1, 0xC1,
|
||||||
|
0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x63, 0x7D, 0x1B, 0x09, 0x09, 0x80, 0x08,
|
||||||
|
0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x07, 0x07,
|
||||||
|
0xC6, 0x3E, 0x00, 0x1B, 0x12, 0x26, 0x00, 0x00, 0xC1, 0xC1, 0xC1, 0xC1,
|
||||||
|
0xC1, 0xC1, 0xC1, 0x63, 0x7D, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06,
|
||||||
|
0x03, 0x01, 0x80, 0xC0, 0x70, 0x7C, 0x63, 0xE0, 0x10, 0x10, 0x08, 0x07,
|
||||||
|
0x00, 0xC1, 0x60, 0xB0, 0x58, 0x2C, 0x16, 0x0B, 0x04, 0xC6, 0x7D, 0x01,
|
||||||
|
0x80, 0x80, 0x40, 0x38, 0x00, 0x80, 0x01, 0xC0, 0x03, 0x60, 0x00, 0x10,
|
||||||
|
0xC1, 0x83, 0x41, 0x83, 0x41, 0xC3, 0x63, 0xC2, 0x63, 0x46, 0x22, 0x46,
|
||||||
|
0x22, 0x66, 0x36, 0x24, 0x34, 0x2C, 0x14, 0x3C, 0x14, 0x38, 0x1C, 0x18,
|
||||||
|
0x18, 0x18, 0x02, 0x00, 0x1C, 0x00, 0xD8, 0x00, 0x10, 0x00, 0x07, 0x0C,
|
||||||
|
0x24, 0x70, 0x99, 0xE6, 0x64, 0x98, 0x92, 0x42, 0xCD, 0x0E, 0x3C, 0x38,
|
||||||
|
0x60, 0x61, 0x80, 0x08, 0x07, 0x03, 0x60, 0x04, 0xC0, 0xD0, 0x26, 0x18,
|
||||||
|
0x84, 0x33, 0x04, 0x81, 0xE0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C,
|
||||||
|
0x00, 0x08, 0x0E, 0x0D, 0x80, 0x20, 0x06, 0x0D, 0x04, 0xC6, 0x22, 0x19,
|
||||||
|
0x0D, 0x82, 0x81, 0xC0, 0x60, 0x20, 0x30, 0x10, 0x78, 0x00, 0x13, 0x04,
|
||||||
|
0x80, 0x03, 0x03, 0x40, 0x98, 0x62, 0x10, 0xCC, 0x12, 0x07, 0x80, 0xC0,
|
||||||
|
0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x0C, 0x18, 0x00, 0xFF, 0xFF,
|
||||||
|
0x03, 0x06, 0x04, 0x0C, 0x18, 0x10, 0x30, 0x60, 0x40, 0xC0, 0xFF, 0x0C,
|
||||||
|
0x18, 0x60, 0x00, 0x1F, 0x83, 0x04, 0x18, 0x61, 0x82, 0x0C, 0x1F, 0xC0,
|
||||||
|
0x08, 0x0C, 0x00, 0xFF, 0xFF, 0x03, 0x06, 0x04, 0x0C, 0x18, 0x10, 0x30,
|
||||||
|
0x60, 0x40, 0xC0, 0xFF, 0x10, 0x30, 0x00, 0x0F, 0xC1, 0x82, 0x0C, 0x30,
|
||||||
|
0xC1, 0x06, 0x0F, 0xE0, 0x42, 0x6C, 0x38, 0x00, 0xFF, 0xFF, 0x03, 0x06,
|
||||||
|
0x04, 0x0C, 0x18, 0x10, 0x30, 0x60, 0x40, 0xC0, 0xFF, 0x85, 0xB1, 0xC0,
|
||||||
|
0x00, 0x1F, 0x83, 0x04, 0x18, 0x61, 0x82, 0x0C, 0x1F, 0xC0, 0x7A, 0x11,
|
||||||
|
0x8C, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x00 };
|
||||||
|
|
||||||
|
const GFXglyph NotoSans9pt8bGlyphs[] PROGMEM = {
|
||||||
|
{ 0, 1, 1, 5, 0, 0 }, // 0x20 ' '
|
||||||
|
{ 1, 2, 13, 5, 1, -12 }, // 0x21 '!'
|
||||||
|
{ 5, 5, 5, 7, 1, -12 }, // 0x22 '"'
|
||||||
|
{ 9, 11, 13, 11, 0, -12 }, // 0x23 '#'
|
||||||
|
{ 27, 8, 14, 10, 1, -12 }, // 0x24 '$'
|
||||||
|
{ 41, 13, 13, 15, 1, -12 }, // 0x25 '%'
|
||||||
|
{ 63, 12, 13, 13, 1, -12 }, // 0x26 '&'
|
||||||
|
{ 83, 2, 5, 4, 1, -12 }, // 0x27 '''
|
||||||
|
{ 85, 4, 16, 5, 1, -12 }, // 0x28 '('
|
||||||
|
{ 93, 4, 16, 5, 1, -12 }, // 0x29 ')'
|
||||||
|
{ 101, 8, 8, 10, 1, -12 }, // 0x2A '*'
|
||||||
|
{ 109, 8, 8, 10, 1, -9 }, // 0x2B '+'
|
||||||
|
{ 117, 2, 4, 5, 1, -1 }, // 0x2C ','
|
||||||
|
{ 118, 4, 1, 6, 1, -4 }, // 0x2D '-'
|
||||||
|
{ 119, 2, 2, 5, 1, -1 }, // 0x2E '.'
|
||||||
|
{ 120, 6, 13, 7, 0, -12 }, // 0x2F '/'
|
||||||
|
{ 130, 8, 13, 10, 1, -12 }, // 0x30 '0'
|
||||||
|
{ 143, 4, 13, 10, 2, -12 }, // 0x31 '1'
|
||||||
|
{ 150, 8, 13, 10, 1, -12 }, // 0x32 '2'
|
||||||
|
{ 163, 8, 13, 10, 1, -12 }, // 0x33 '3'
|
||||||
|
{ 176, 10, 13, 10, 0, -12 }, // 0x34 '4'
|
||||||
|
{ 193, 8, 13, 10, 1, -12 }, // 0x35 '5'
|
||||||
|
{ 206, 8, 13, 10, 1, -12 }, // 0x36 '6'
|
||||||
|
{ 219, 8, 13, 10, 1, -12 }, // 0x37 '7'
|
||||||
|
{ 232, 8, 13, 10, 1, -12 }, // 0x38 '8'
|
||||||
|
{ 245, 8, 13, 10, 1, -12 }, // 0x39 '9'
|
||||||
|
{ 258, 2, 10, 5, 1, -9 }, // 0x3A ':'
|
||||||
|
{ 261, 2, 12, 5, 1, -9 }, // 0x3B ';'
|
||||||
|
{ 264, 8, 9, 10, 1, -10 }, // 0x3C '<'
|
||||||
|
{ 273, 8, 5, 10, 1, -8 }, // 0x3D '='
|
||||||
|
{ 278, 8, 9, 10, 1, -10 }, // 0x3E '>'
|
||||||
|
{ 287, 7, 13, 8, 0, -12 }, // 0x3F '?'
|
||||||
|
{ 299, 14, 15, 16, 1, -12 }, // 0x40 '@'
|
||||||
|
{ 326, 11, 13, 11, 0, -12 }, // 0x41 'A'
|
||||||
|
{ 344, 9, 13, 11, 2, -12 }, // 0x42 'B'
|
||||||
|
{ 359, 10, 13, 11, 1, -12 }, // 0x43 'C'
|
||||||
|
{ 376, 10, 13, 13, 2, -12 }, // 0x44 'D'
|
||||||
|
{ 393, 7, 13, 10, 2, -12 }, // 0x45 'E'
|
||||||
|
{ 405, 7, 13, 9, 2, -12 }, // 0x46 'F'
|
||||||
|
{ 417, 11, 13, 13, 1, -12 }, // 0x47 'G'
|
||||||
|
{ 435, 9, 13, 13, 2, -12 }, // 0x48 'H'
|
||||||
|
{ 450, 4, 13, 6, 1, -12 }, // 0x49 'I'
|
||||||
|
{ 457, 4, 16, 5, -1, -12 }, // 0x4A 'J'
|
||||||
|
{ 465, 9, 13, 11, 2, -12 }, // 0x4B 'K'
|
||||||
|
{ 480, 7, 13, 9, 2, -12 }, // 0x4C 'L'
|
||||||
|
{ 492, 12, 13, 16, 2, -12 }, // 0x4D 'M'
|
||||||
|
{ 512, 10, 13, 13, 2, -12 }, // 0x4E 'N'
|
||||||
|
{ 529, 12, 13, 14, 1, -12 }, // 0x4F 'O'
|
||||||
|
{ 549, 8, 13, 11, 2, -12 }, // 0x50 'P'
|
||||||
|
{ 562, 12, 16, 14, 1, -12 }, // 0x51 'Q'
|
||||||
|
{ 586, 9, 13, 11, 2, -12 }, // 0x52 'R'
|
||||||
|
{ 601, 8, 13, 10, 1, -12 }, // 0x53 'S'
|
||||||
|
{ 614, 10, 13, 10, 0, -12 }, // 0x54 'T'
|
||||||
|
{ 631, 9, 13, 13, 2, -12 }, // 0x55 'U'
|
||||||
|
{ 646, 11, 13, 11, 0, -12 }, // 0x56 'V'
|
||||||
|
{ 664, 16, 13, 16, 0, -12 }, // 0x57 'W'
|
||||||
|
{ 690, 10, 13, 10, 0, -12 }, // 0x58 'X'
|
||||||
|
{ 707, 10, 13, 10, 0, -12 }, // 0x59 'Y'
|
||||||
|
{ 724, 8, 13, 10, 1, -12 }, // 0x5A 'Z'
|
||||||
|
{ 737, 4, 16, 6, 1, -12 }, // 0x5B '['
|
||||||
|
{ 745, 6, 13, 7, 0, -12 }, // 0x5C '\'
|
||||||
|
{ 755, 4, 16, 6, 0, -12 }, // 0x5D ']'
|
||||||
|
{ 763, 8, 8, 10, 1, -12 }, // 0x5E '^'
|
||||||
|
{ 771, 8, 1, 8, 0, 3 }, // 0x5F '_'
|
||||||
|
{ 772, 3, 3, 5, 1, -13 }, // 0x60 '`'
|
||||||
|
{ 774, 7, 10, 10, 1, -9 }, // 0x61 'a'
|
||||||
|
{ 783, 9, 13, 11, 1, -12 }, // 0x62 'b'
|
||||||
|
{ 798, 7, 10, 8, 1, -9 }, // 0x63 'c'
|
||||||
|
{ 807, 8, 13, 11, 1, -12 }, // 0x64 'd'
|
||||||
|
{ 820, 8, 10, 10, 1, -9 }, // 0x65 'e'
|
||||||
|
{ 830, 7, 13, 6, 0, -12 }, // 0x66 'f'
|
||||||
|
{ 842, 8, 14, 11, 1, -9 }, // 0x67 'g'
|
||||||
|
{ 856, 8, 13, 11, 1, -12 }, // 0x68 'h'
|
||||||
|
{ 869, 2, 13, 5, 1, -12 }, // 0x69 'i'
|
||||||
|
{ 873, 4, 17, 5, -1, -12 }, // 0x6A 'j'
|
||||||
|
{ 882, 8, 13, 9, 1, -12 }, // 0x6B 'k'
|
||||||
|
{ 895, 2, 13, 5, 1, -12 }, // 0x6C 'l'
|
||||||
|
{ 899, 14, 10, 16, 1, -9 }, // 0x6D 'm'
|
||||||
|
{ 917, 8, 10, 11, 1, -9 }, // 0x6E 'n'
|
||||||
|
{ 927, 9, 10, 11, 1, -9 }, // 0x6F 'o'
|
||||||
|
{ 939, 9, 14, 11, 1, -9 }, // 0x70 'p'
|
||||||
|
{ 955, 8, 14, 11, 1, -9 }, // 0x71 'q'
|
||||||
|
{ 969, 6, 10, 7, 1, -9 }, // 0x72 'r'
|
||||||
|
{ 977, 7, 10, 8, 1, -9 }, // 0x73 's'
|
||||||
|
{ 986, 6, 12, 6, 0, -11 }, // 0x74 't'
|
||||||
|
{ 995, 8, 9, 11, 1, -8 }, // 0x75 'u'
|
||||||
|
{ 1004, 9, 9, 9, 0, -8 }, // 0x76 'v'
|
||||||
|
{ 1015, 14, 9, 14, 0, -8 }, // 0x77 'w'
|
||||||
|
{ 1031, 9, 9, 9, 0, -8 }, // 0x78 'x'
|
||||||
|
{ 1042, 9, 13, 9, 0, -8 }, // 0x79 'y'
|
||||||
|
{ 1057, 7, 9, 8, 1, -8 }, // 0x7A 'z'
|
||||||
|
{ 1065, 6, 16, 7, 0, -12 }, // 0x7B '{'
|
||||||
|
{ 1077, 2, 17, 10, 4, -12 }, // 0x7C '|'
|
||||||
|
{ 1082, 5, 16, 7, 1, -12 }, // 0x7D '}'
|
||||||
|
{ 1092, 8, 2, 10, 1, -6 }, // 0x7E '~'
|
||||||
|
{ 1094, 7, 13, 11, 2, -12 }, // 0x7F
|
||||||
|
{ 1106, 7, 13, 11, 2, -12 }, // 0x80
|
||||||
|
{ 1118, 7, 13, 11, 2, -12 }, // 0x81
|
||||||
|
{ 1130, 7, 13, 11, 2, -12 }, // 0x82
|
||||||
|
{ 1142, 7, 13, 11, 2, -12 }, // 0x83
|
||||||
|
{ 1154, 7, 13, 11, 2, -12 }, // 0x84
|
||||||
|
{ 1166, 7, 13, 11, 2, -12 }, // 0x85
|
||||||
|
{ 1178, 7, 13, 11, 2, -12 }, // 0x86
|
||||||
|
{ 1190, 7, 13, 11, 2, -12 }, // 0x87
|
||||||
|
{ 1202, 7, 13, 11, 2, -12 }, // 0x88
|
||||||
|
{ 1214, 7, 13, 11, 2, -12 }, // 0x89
|
||||||
|
{ 1226, 7, 13, 11, 2, -12 }, // 0x8A
|
||||||
|
{ 1238, 7, 13, 11, 2, -12 }, // 0x8B
|
||||||
|
{ 1250, 7, 13, 11, 2, -12 }, // 0x8C
|
||||||
|
{ 1262, 7, 13, 11, 2, -12 }, // 0x8D
|
||||||
|
{ 1274, 7, 13, 11, 2, -12 }, // 0x8E
|
||||||
|
{ 1286, 7, 13, 11, 2, -12 }, // 0x8F
|
||||||
|
{ 1298, 7, 13, 11, 2, -12 }, // 0x90
|
||||||
|
{ 1310, 7, 13, 11, 2, -12 }, // 0x91
|
||||||
|
{ 1322, 7, 13, 11, 2, -12 }, // 0x92
|
||||||
|
{ 1334, 7, 13, 11, 2, -12 }, // 0x93
|
||||||
|
{ 1346, 7, 13, 11, 2, -12 }, // 0x94
|
||||||
|
{ 1358, 7, 13, 11, 2, -12 }, // 0x95
|
||||||
|
{ 1370, 7, 13, 11, 2, -12 }, // 0x96
|
||||||
|
{ 1382, 7, 13, 11, 2, -12 }, // 0x97
|
||||||
|
{ 1394, 7, 13, 11, 2, -12 }, // 0x98
|
||||||
|
{ 1406, 7, 13, 11, 2, -12 }, // 0x99
|
||||||
|
{ 1418, 7, 13, 11, 2, -12 }, // 0x9A
|
||||||
|
{ 1430, 7, 13, 11, 2, -12 }, // 0x9B
|
||||||
|
{ 1442, 7, 13, 11, 2, -12 }, // 0x9C
|
||||||
|
{ 1454, 7, 13, 11, 2, -12 }, // 0x9D
|
||||||
|
{ 1466, 7, 13, 11, 2, -12 }, // 0x9E
|
||||||
|
{ 1478, 7, 13, 11, 2, -12 }, // 0x9F
|
||||||
|
{ 1490, 1, 1, 5, 0, 0 }, // 0xA0
|
||||||
|
{ 1491, 2, 13, 5, 1, -9 }, // 0xA1
|
||||||
|
{ 1495, 7, 13, 10, 2, -12 }, // 0xA2
|
||||||
|
{ 1507, 8, 13, 10, 1, -12 }, // 0xA3
|
||||||
|
{ 1520, 8, 8, 10, 1, -9 }, // 0xA4
|
||||||
|
{ 1528, 10, 13, 10, 0, -12 }, // 0xA5
|
||||||
|
{ 1545, 2, 17, 10, 4, -12 }, // 0xA6
|
||||||
|
{ 1550, 7, 13, 9, 1, -12 }, // 0xA7
|
||||||
|
{ 1562, 5, 2, 10, 3, -12 }, // 0xA8
|
||||||
|
{ 1564, 13, 13, 15, 1, -12 }, // 0xA9
|
||||||
|
{ 1586, 4, 6, 6, 1, -12 }, // 0xAA
|
||||||
|
{ 1589, 7, 7, 9, 1, -7 }, // 0xAB
|
||||||
|
{ 1596, 8, 5, 10, 1, -6 }, // 0xAC
|
||||||
|
{ 1601, 4, 1, 6, 1, -4 }, // 0xAD
|
||||||
|
{ 1602, 13, 13, 15, 1, -12 }, // 0xAE
|
||||||
|
{ 1624, 9, 2, 9, 0, -14 }, // 0xAF
|
||||||
|
{ 1627, 6, 6, 8, 1, -12 }, // 0xB0
|
||||||
|
{ 1632, 8, 11, 10, 1, -10 }, // 0xB1
|
||||||
|
{ 1643, 5, 8, 6, 0, -14 }, // 0xB2
|
||||||
|
{ 1648, 6, 8, 6, 0, -14 }, // 0xB3
|
||||||
|
{ 1654, 3, 3, 5, 1, -13 }, // 0xB4
|
||||||
|
{ 1656, 8, 13, 11, 1, -8 }, // 0xB5
|
||||||
|
{ 1669, 9, 15, 12, 1, -12 }, // 0xB6
|
||||||
|
{ 1686, 2, 2, 5, 1, -6 }, // 0xB7
|
||||||
|
{ 1687, 4, 4, 4, 0, 1 }, // 0xB8
|
||||||
|
{ 1689, 3, 8, 6, 1, -14 }, // 0xB9
|
||||||
|
{ 1692, 5, 6, 7, 1, -12 }, // 0xBA
|
||||||
|
{ 1696, 7, 7, 9, 1, -7 }, // 0xBB
|
||||||
|
{ 1703, 12, 13, 13, 1, -12 }, // 0xBC
|
||||||
|
{ 1723, 13, 13, 14, 0, -12 }, // 0xBD
|
||||||
|
{ 1745, 14, 13, 14, 0, -12 }, // 0xBE
|
||||||
|
{ 1768, 7, 13, 8, 0, -9 }, // 0xBF
|
||||||
|
{ 1780, 11, 17, 11, 0, -16 }, // 0xC0
|
||||||
|
{ 1804, 11, 17, 11, 0, -16 }, // 0xC1
|
||||||
|
{ 1828, 11, 17, 11, 0, -16 }, // 0xC2
|
||||||
|
{ 1852, 11, 16, 11, 0, -15 }, // 0xC3
|
||||||
|
{ 1874, 11, 16, 11, 0, -15 }, // 0xC4
|
||||||
|
{ 1896, 11, 15, 11, 0, -14 }, // 0xC5
|
||||||
|
{ 1917, 14, 13, 16, 0, -12 }, // 0xC6
|
||||||
|
{ 1940, 10, 17, 11, 1, -12 }, // 0xC7
|
||||||
|
{ 1962, 7, 17, 10, 2, -16 }, // 0xC8
|
||||||
|
{ 1977, 7, 17, 10, 2, -16 }, // 0xC9
|
||||||
|
{ 1992, 7, 17, 10, 2, -16 }, // 0xCA
|
||||||
|
{ 2007, 7, 16, 10, 2, -15 }, // 0xCB
|
||||||
|
{ 2021, 4, 17, 6, 1, -16 }, // 0xCC
|
||||||
|
{ 2030, 4, 17, 6, 1, -16 }, // 0xCD
|
||||||
|
{ 2039, 6, 17, 6, 0, -16 }, // 0xCE
|
||||||
|
{ 2052, 5, 16, 6, 1, -15 }, // 0xCF
|
||||||
|
{ 2062, 11, 13, 13, 1, -12 }, // 0xD0
|
||||||
|
{ 2080, 10, 16, 13, 2, -15 }, // 0xD1
|
||||||
|
{ 2100, 12, 17, 14, 1, -16 }, // 0xD2
|
||||||
|
{ 2126, 12, 17, 14, 1, -16 }, // 0xD3
|
||||||
|
{ 2152, 12, 17, 14, 1, -16 }, // 0xD4
|
||||||
|
{ 2178, 12, 16, 14, 1, -15 }, // 0xD5
|
||||||
|
{ 2202, 12, 16, 14, 1, -15 }, // 0xD6
|
||||||
|
{ 2226, 8, 8, 10, 1, -9 }, // 0xD7
|
||||||
|
{ 2234, 12, 14, 14, 1, -12 }, // 0xD8
|
||||||
|
{ 2255, 9, 17, 13, 2, -16 }, // 0xD9
|
||||||
|
{ 2275, 9, 17, 13, 2, -16 }, // 0xDA
|
||||||
|
{ 2295, 9, 17, 13, 2, -16 }, // 0xDB
|
||||||
|
{ 2315, 9, 16, 13, 2, -15 }, // 0xDC
|
||||||
|
{ 2333, 10, 17, 10, 0, -16 }, // 0xDD
|
||||||
|
{ 2355, 8, 13, 11, 2, -12 }, // 0xDE
|
||||||
|
{ 2368, 9, 13, 11, 1, -12 }, // 0xDF
|
||||||
|
{ 2383, 7, 14, 10, 1, -13 }, // 0xE0
|
||||||
|
{ 2396, 7, 14, 10, 1, -13 }, // 0xE1
|
||||||
|
{ 2409, 7, 14, 10, 1, -13 }, // 0xE2
|
||||||
|
{ 2422, 7, 13, 10, 1, -12 }, // 0xE3
|
||||||
|
{ 2434, 7, 13, 10, 1, -12 }, // 0xE4
|
||||||
|
{ 2446, 7, 14, 10, 1, -13 }, // 0xE5
|
||||||
|
{ 2459, 13, 10, 15, 1, -9 }, // 0xE6
|
||||||
|
{ 2476, 7, 14, 8, 1, -9 }, // 0xE7
|
||||||
|
{ 2489, 8, 14, 10, 1, -13 }, // 0xE8
|
||||||
|
{ 2503, 8, 14, 10, 1, -13 }, // 0xE9
|
||||||
|
{ 2517, 8, 14, 10, 1, -13 }, // 0xEA
|
||||||
|
{ 2531, 8, 13, 10, 1, -12 }, // 0xEB
|
||||||
|
{ 2544, 3, 14, 5, 0, -13 }, // 0xEC
|
||||||
|
{ 2550, 4, 14, 5, 1, -13 }, // 0xED
|
||||||
|
{ 2557, 6, 14, 5, 0, -13 }, // 0xEE
|
||||||
|
{ 2568, 5, 13, 5, 0, -12 }, // 0xEF
|
||||||
|
{ 2577, 9, 13, 11, 1, -12 }, // 0xF0
|
||||||
|
{ 2592, 8, 13, 11, 1, -12 }, // 0xF1
|
||||||
|
{ 2605, 9, 14, 11, 1, -13 }, // 0xF2
|
||||||
|
{ 2621, 9, 14, 11, 1, -13 }, // 0xF3
|
||||||
|
{ 2637, 9, 14, 11, 1, -13 }, // 0xF4
|
||||||
|
{ 2653, 9, 13, 11, 1, -12 }, // 0xF5
|
||||||
|
{ 2668, 9, 13, 11, 1, -12 }, // 0xF6
|
||||||
|
{ 2683, 8, 8, 10, 1, -9 }, // 0xF7
|
||||||
|
{ 2691, 9, 11, 11, 1, -9 }, // 0xF8
|
||||||
|
{ 2704, 8, 14, 11, 1, -13 }, // 0xF9
|
||||||
|
{ 2718, 8, 14, 11, 1, -13 }, // 0xFA
|
||||||
|
{ 2732, 8, 14, 11, 1, -13 }, // 0xFB
|
||||||
|
{ 2746, 8, 13, 11, 1, -12 }, // 0xFC
|
||||||
|
{ 2759, 9, 18, 9, 0, -13 }, // 0xFD
|
||||||
|
{ 2780, 9, 17, 11, 1, -12 }, // 0xFE
|
||||||
|
{ 2800, 9, 17, 9, 0, -12 }, // 0xFF
|
||||||
|
{ 2820, 11, 15, 11, 0, -14 }, // 0x100
|
||||||
|
{ 2841, 7, 12, 10, 1, -11 }, // 0x101
|
||||||
|
{ 2852, 11, 16, 11, 0, -15 }, // 0x102
|
||||||
|
{ 2874, 7, 13, 10, 1, -12 }, // 0x103
|
||||||
|
{ 2886, 12, 17, 11, 0, -12 }, // 0x104
|
||||||
|
{ 2912, 8, 14, 10, 1, -9 }, // 0x105
|
||||||
|
{ 2926, 10, 17, 11, 1, -16 }, // 0x106
|
||||||
|
{ 2948, 7, 14, 8, 1, -13 }, // 0x107
|
||||||
|
{ 2961, 10, 17, 11, 1, -16 }, // 0x108
|
||||||
|
{ 2983, 7, 14, 8, 1, -13 }, // 0x109
|
||||||
|
{ 2996, 10, 16, 11, 1, -15 }, // 0x10A
|
||||||
|
{ 3016, 7, 13, 8, 1, -12 }, // 0x10B
|
||||||
|
{ 3028, 10, 17, 11, 1, -16 }, // 0x10C
|
||||||
|
{ 3050, 7, 14, 8, 1, -13 }, // 0x10D
|
||||||
|
{ 3063, 10, 17, 13, 2, -16 }, // 0x10E
|
||||||
|
{ 3085, 11, 13, 11, 1, -12 }, // 0x10F
|
||||||
|
{ 3103, 11, 13, 13, 1, -12 }, // 0x110
|
||||||
|
{ 3121, 10, 13, 11, 1, -12 }, // 0x111
|
||||||
|
{ 3138, 7, 15, 10, 2, -14 }, // 0x112
|
||||||
|
{ 3152, 8, 12, 10, 1, -11 }, // 0x113
|
||||||
|
{ 3164, 7, 16, 10, 2, -15 }, // 0x114
|
||||||
|
{ 3178, 8, 13, 10, 1, -12 }, // 0x115
|
||||||
|
{ 3191, 7, 16, 10, 2, -15 }, // 0x116
|
||||||
|
{ 3205, 8, 13, 10, 1, -12 }, // 0x117
|
||||||
|
{ 3218, 7, 17, 10, 2, -12 }, // 0x118
|
||||||
|
{ 3233, 8, 14, 10, 1, -9 }, // 0x119
|
||||||
|
{ 3247, 7, 17, 10, 2, -16 }, // 0x11A
|
||||||
|
{ 3262, 8, 14, 10, 1, -13 }, // 0x11B
|
||||||
|
{ 3276, 11, 17, 13, 1, -16 }, // 0x11C
|
||||||
|
{ 3300, 8, 18, 11, 1, -13 }, // 0x11D
|
||||||
|
{ 3318, 11, 16, 13, 1, -15 }, // 0x11E
|
||||||
|
{ 3340, 8, 17, 11, 1, -12 }, // 0x11F
|
||||||
|
{ 3357, 11, 16, 13, 1, -15 }, // 0x120
|
||||||
|
{ 3379, 8, 17, 11, 1, -12 }, // 0x121
|
||||||
|
{ 3396, 11, 17, 13, 1, -12 }, // 0x122
|
||||||
|
{ 3420, 8, 18, 11, 1, -13 }, // 0x123
|
||||||
|
{ 3438, 9, 17, 13, 2, -16 }, // 0x124
|
||||||
|
{ 3458, 9, 18, 11, 0, -17 }, // 0x125
|
||||||
|
{ 3479, 13, 13, 13, 0, -12 }, // 0x126
|
||||||
|
{ 3501, 9, 13, 11, 0, -12 }, // 0x127
|
||||||
|
{ 3516, 6, 16, 6, 0, -15 }, // 0x128
|
||||||
|
{ 3528, 6, 13, 5, -1, -12 }, // 0x129
|
||||||
|
{ 3538, 5, 15, 6, 1, -14 }, // 0x12A
|
||||||
|
{ 3548, 5, 12, 5, 0, -11 }, // 0x12B
|
||||||
|
{ 3556, 5, 16, 6, 1, -15 }, // 0x12C
|
||||||
|
{ 3566, 5, 13, 5, 0, -12 }, // 0x12D
|
||||||
|
{ 3575, 5, 17, 6, 1, -12 }, // 0x12E
|
||||||
|
{ 3586, 3, 17, 5, 1, -12 }, // 0x12F
|
||||||
|
{ 3593, 4, 16, 6, 1, -15 }, // 0x130
|
||||||
|
{ 3601, 2, 9, 5, 1, -8 }, // 0x131
|
||||||
|
{ 3604, 8, 16, 11, 1, -12 }, // 0x132
|
||||||
|
{ 3620, 7, 17, 9, 1, -12 }, // 0x133
|
||||||
|
{ 3635, 7, 20, 5, -1, -16 }, // 0x134
|
||||||
|
{ 3653, 7, 18, 5, -1, -13 }, // 0x135
|
||||||
|
{ 3669, 9, 17, 11, 2, -12 }, // 0x136
|
||||||
|
{ 3689, 8, 17, 9, 1, -12 }, // 0x137
|
||||||
|
{ 3706, 8, 9, 9, 1, -8 }, // 0x138
|
||||||
|
{ 3715, 7, 17, 9, 2, -16 }, // 0x139
|
||||||
|
{ 3730, 4, 18, 5, 1, -17 }, // 0x13A
|
||||||
|
{ 3739, 7, 17, 9, 2, -12 }, // 0x13B
|
||||||
|
{ 3754, 2, 17, 5, 1, -12 }, // 0x13C
|
||||||
|
{ 3759, 7, 13, 9, 2, -12 }, // 0x13D
|
||||||
|
{ 3771, 5, 13, 5, 1, -12 }, // 0x13E
|
||||||
|
{ 3780, 7, 13, 9, 2, -12 }, // 0x13F
|
||||||
|
{ 3792, 5, 13, 5, 1, -12 }, // 0x140
|
||||||
|
{ 3801, 9, 13, 9, 0, -12 }, // 0x141
|
||||||
|
{ 3816, 5, 13, 5, 0, -12 }, // 0x142
|
||||||
|
{ 3825, 10, 17, 13, 2, -16 }, // 0x143
|
||||||
|
{ 3847, 8, 14, 11, 1, -13 }, // 0x144
|
||||||
|
{ 3861, 10, 17, 13, 2, -12 }, // 0x145
|
||||||
|
{ 3883, 8, 14, 11, 1, -9 }, // 0x146
|
||||||
|
{ 3897, 10, 17, 13, 2, -16 }, // 0x147
|
||||||
|
{ 3919, 8, 14, 11, 1, -13 }, // 0x148
|
||||||
|
{ 3933, 10, 13, 12, 0, -12 }, // 0x149
|
||||||
|
{ 3950, 10, 16, 13, 2, -12 }, // 0x14A
|
||||||
|
{ 3970, 8, 14, 11, 1, -9 }, // 0x14B
|
||||||
|
{ 3984, 12, 15, 14, 1, -14 }, // 0x14C
|
||||||
|
{ 4007, 9, 12, 11, 1, -11 }, // 0x14D
|
||||||
|
{ 4021, 12, 16, 14, 1, -15 }, // 0x14E
|
||||||
|
{ 4045, 9, 13, 11, 1, -12 }, // 0x14F
|
||||||
|
{ 4060, 12, 17, 14, 1, -16 }, // 0x150
|
||||||
|
{ 4086, 9, 14, 11, 1, -13 }, // 0x151
|
||||||
|
{ 4102, 14, 13, 16, 1, -12 }, // 0x152
|
||||||
|
{ 4125, 15, 10, 17, 1, -9 }, // 0x153
|
||||||
|
{ 4144, 9, 17, 11, 2, -16 }, // 0x154
|
||||||
|
{ 4164, 6, 14, 7, 1, -13 }, // 0x155
|
||||||
|
{ 4175, 9, 17, 11, 2, -12 }, // 0x156
|
||||||
|
{ 4195, 6, 14, 7, 1, -9 }, // 0x157
|
||||||
|
{ 4206, 9, 17, 11, 2, -16 }, // 0x158
|
||||||
|
{ 4226, 7, 14, 7, 1, -13 }, // 0x159
|
||||||
|
{ 4239, 8, 17, 10, 1, -16 }, // 0x15A
|
||||||
|
{ 4256, 7, 14, 8, 1, -13 }, // 0x15B
|
||||||
|
{ 4269, 8, 17, 10, 1, -16 }, // 0x15C
|
||||||
|
{ 4286, 7, 14, 8, 1, -13 }, // 0x15D
|
||||||
|
{ 4299, 8, 17, 10, 1, -12 }, // 0x15E
|
||||||
|
{ 4316, 7, 14, 8, 1, -9 }, // 0x15F
|
||||||
|
{ 4329, 8, 17, 10, 1, -16 }, // 0x160
|
||||||
|
{ 4346, 7, 14, 8, 1, -13 }, // 0x161
|
||||||
|
{ 4359, 10, 17, 10, 0, -12 }, // 0x162
|
||||||
|
{ 4381, 6, 16, 6, 0, -11 }, // 0x163
|
||||||
|
{ 4393, 10, 17, 10, 0, -16 }, // 0x164
|
||||||
|
{ 4415, 8, 13, 6, 0, -12 }, // 0x165
|
||||||
|
{ 4428, 10, 13, 10, 0, -12 }, // 0x166
|
||||||
|
{ 4445, 6, 12, 6, 0, -11 }, // 0x167
|
||||||
|
{ 4454, 9, 16, 13, 2, -15 }, // 0x168
|
||||||
|
{ 4472, 8, 13, 11, 1, -12 }, // 0x169
|
||||||
|
{ 4485, 9, 15, 13, 2, -14 }, // 0x16A
|
||||||
|
{ 4502, 8, 12, 11, 1, -11 }, // 0x16B
|
||||||
|
{ 4514, 9, 16, 13, 2, -15 }, // 0x16C
|
||||||
|
{ 4532, 8, 13, 11, 1, -12 }, // 0x16D
|
||||||
|
{ 4545, 9, 17, 13, 2, -16 }, // 0x16E
|
||||||
|
{ 4565, 8, 14, 11, 1, -13 }, // 0x16F
|
||||||
|
{ 4579, 9, 17, 13, 2, -16 }, // 0x170
|
||||||
|
{ 4599, 8, 14, 11, 1, -13 }, // 0x171
|
||||||
|
{ 4613, 9, 17, 13, 2, -12 }, // 0x172
|
||||||
|
{ 4633, 9, 13, 11, 1, -8 }, // 0x173
|
||||||
|
{ 4648, 16, 17, 16, 0, -16 }, // 0x174
|
||||||
|
{ 4682, 14, 14, 14, 0, -13 }, // 0x175
|
||||||
|
{ 4707, 10, 17, 10, 0, -16 }, // 0x176
|
||||||
|
{ 4729, 9, 18, 9, 0, -13 }, // 0x177
|
||||||
|
{ 4750, 10, 16, 10, 0, -15 }, // 0x178
|
||||||
|
{ 4770, 8, 17, 10, 1, -16 }, // 0x179
|
||||||
|
{ 4787, 7, 14, 8, 1, -13 }, // 0x17A
|
||||||
|
{ 4800, 8, 16, 10, 1, -15 }, // 0x17B
|
||||||
|
{ 4816, 7, 13, 8, 1, -12 }, // 0x17C
|
||||||
|
{ 4828, 8, 17, 10, 1, -16 }, // 0x17D
|
||||||
|
{ 4845, 7, 14, 8, 1, -13 }, // 0x17E
|
||||||
|
{ 4858, 5, 13, 6, 1, -12 } }; // 0x17F
|
||||||
|
|
||||||
|
const GFXfont NotoSans9pt8b PROGMEM = {
|
||||||
|
(uint8_t *)NotoSans9pt8bBitmaps,
|
||||||
|
(GFXglyph *)NotoSans9pt8bGlyphs,
|
||||||
|
0x20, 0x17F, 24 };
|
||||||
|
|
||||||
|
// Approx. 7338 bytes
|
||||||
|
|
||||||
|
#endif // NOTOSANS9PT8B_H
|
||||||
@@ -54,6 +54,12 @@ static const uint8_t icon_alarm[] PROGMEM = {
|
|||||||
0x40,0x40, 0x20,0x80, 0x1F,0x00, 0x00,0x00, 0x20,0x40, 0x40,0x20,
|
0x40,0x40, 0x20,0x80, 0x1F,0x00, 0x00,0x00, 0x20,0x40, 0x40,0x20,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ➡ Right arrow (Trace Route)
|
||||||
|
static const uint8_t icon_trace[] PROGMEM = {
|
||||||
|
0x00,0x00, 0x00,0x00, 0x00,0x80, 0x00,0xC0, 0x00,0xE0, 0xFF,0xF0,
|
||||||
|
0xFF,0xF0, 0x00,0xE0, 0x00,0xC0, 0x00,0x80, 0x00,0x00, 0x00,0x00,
|
||||||
|
};
|
||||||
|
|
||||||
// 🔔 Bell — 7x8 status bar indicator (alarm enabled)
|
// 🔔 Bell — 7x8 status bar indicator (alarm enabled)
|
||||||
// MSB-first, 1 byte per row
|
// MSB-first, 1 byte per row
|
||||||
#define BELL_ICON_W 7
|
#define BELL_ICON_W 7
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ enum VKBPurpose {
|
|||||||
VKB_WEB_LINK, // Web reader link number entry
|
VKB_WEB_LINK, // Web reader link number entry
|
||||||
#endif
|
#endif
|
||||||
VKB_TEXT_PAGE, // Text reader: go to page number
|
VKB_TEXT_PAGE, // Text reader: go to page number
|
||||||
|
VKB_TRACE_PATH, // Trace screen: type comma-separated path values
|
||||||
};
|
};
|
||||||
|
|
||||||
class VirtualKeyboard {
|
class VirtualKeyboard {
|
||||||
|
|||||||
@@ -100,6 +100,10 @@ struct TelemetryData {
|
|||||||
char apn[40];
|
char apn[40];
|
||||||
char oper[24];
|
char oper[24];
|
||||||
bool mqtt_connected;
|
bool mqtt_connected;
|
||||||
|
// Routing settings (v1.8+)
|
||||||
|
uint8_t loop_detect; // 0=off, 1=minimal, 2=moderate, 3=strict
|
||||||
|
uint8_t path_hash_mode; // 0=1-byte, 1=2-byte, 2=3-byte
|
||||||
|
uint8_t flood_max; // max flood hop count (0-64)
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -501,6 +501,51 @@ bool MyMesh::filterRecvFloodPacket(mesh::Packet* pkt) {
|
|||||||
} else {
|
} else {
|
||||||
recv_pkt_region = NULL;
|
recv_pkt_region = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Loop detection (MeshCore v1.14+) ---
|
||||||
|
// Walk the packet's path and count how many times our own hash appears.
|
||||||
|
// If it exceeds the threshold for the configured detection level, drop
|
||||||
|
// the packet to break routing loops caused by misbehaving nodes.
|
||||||
|
if (_prefs.loop_detect != LOOP_DETECT_OFF) {
|
||||||
|
uint8_t hops = pkt->path_len & 0x3F;
|
||||||
|
uint8_t bph = (pkt->path_len >> 6) + 1; // bytes per hop (1, 2, or 3)
|
||||||
|
|
||||||
|
if (hops > 0 && hops * bph <= MAX_PATH_SIZE) {
|
||||||
|
// Count self-hash appearances in the path
|
||||||
|
int selfCount = 0;
|
||||||
|
for (uint8_t i = 0; i < hops; i++) {
|
||||||
|
if (self_id.isHashMatch(&pkt->path[i * bph], bph)) {
|
||||||
|
selfCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Threshold depends on detection level and path hash size
|
||||||
|
// 1-byte 2-byte 3-byte
|
||||||
|
// minimal: 4 2 1
|
||||||
|
// moderate: 2 1 1
|
||||||
|
// strict: 1 1 1
|
||||||
|
int threshold;
|
||||||
|
switch (_prefs.loop_detect) {
|
||||||
|
case LOOP_DETECT_MINIMAL:
|
||||||
|
threshold = (bph == 1) ? 4 : (bph == 2) ? 2 : 1;
|
||||||
|
break;
|
||||||
|
case LOOP_DETECT_MODERATE:
|
||||||
|
threshold = (bph == 1) ? 2 : 1;
|
||||||
|
break;
|
||||||
|
case LOOP_DETECT_STRICT:
|
||||||
|
default:
|
||||||
|
threshold = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selfCount >= threshold) {
|
||||||
|
MESH_DEBUG_PRINTLN("Loop detected: self-hash appears %d times (threshold %d, bph=%d, mode=%d) — dropping",
|
||||||
|
selfCount, threshold, (int)bph, (int)_prefs.loop_detect);
|
||||||
|
return true; // Drop the packet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// do normal processing
|
// do normal processing
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -802,6 +847,7 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
|||||||
|
|
||||||
_prefs.adc_multiplier = 0.0f; // 0.0f means use default board multiplier
|
_prefs.adc_multiplier = 0.0f; // 0.0f means use default board multiplier
|
||||||
_prefs.path_hash_mode = 0; // 1-byte path hashes (legacy default)
|
_prefs.path_hash_mode = 0; // 1-byte path hashes (legacy default)
|
||||||
|
_prefs.loop_detect = LOOP_DETECT_OFF; // no loop detection by default
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyMesh::begin(FILESYSTEM *fs) {
|
void MyMesh::begin(FILESYSTEM *fs) {
|
||||||
@@ -1120,6 +1166,26 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply
|
|||||||
} else if (n == 2 && strcmp(parts[1], "home") == 0) {
|
} else if (n == 2 && strcmp(parts[1], "home") == 0) {
|
||||||
auto home = region_map.getHomeRegion();
|
auto home = region_map.getHomeRegion();
|
||||||
sprintf(reply, " home is %s", home ? home->name : "*");
|
sprintf(reply, " home is %s", home ? home->name : "*");
|
||||||
|
} else if (n >= 3 && strcmp(parts[1], "default") == 0) {
|
||||||
|
// "region default <name>" — set default scope
|
||||||
|
auto def = region_map.findByNamePrefix(parts[2]);
|
||||||
|
if (def) {
|
||||||
|
region_map.setDefaultRegion(def);
|
||||||
|
sprintf(reply, " default is now %s", def->name);
|
||||||
|
} else {
|
||||||
|
// empty or unrecognised name → clear default scope
|
||||||
|
region_map.setDefaultRegion(NULL);
|
||||||
|
strcpy(reply, " default cleared");
|
||||||
|
}
|
||||||
|
} else if (n == 2 && strcmp(parts[1], "default") == 0) {
|
||||||
|
auto def = region_map.getDefaultRegion();
|
||||||
|
sprintf(reply, " default is %s", def ? def->name : "(none)");
|
||||||
|
} else if (n >= 3 && strcmp(parts[1], "list") == 0 && sender_timestamp == 0) {
|
||||||
|
// "region list allowed" / "region list denied" — serial only
|
||||||
|
bool denied = (strcmp(parts[2], "denied") == 0);
|
||||||
|
char buf[256];
|
||||||
|
region_map.exportNamesTo(buf, sizeof(buf), REGION_DENY_FLOOD, denied);
|
||||||
|
Serial.printf("Regions (%s): %s\n", parts[2], buf);
|
||||||
} else if (n >= 3 && strcmp(parts[1], "put") == 0) {
|
} else if (n >= 3 && strcmp(parts[1], "put") == 0) {
|
||||||
auto parent = n >= 4 ? region_map.findByNamePrefix(parts[3]) : ®ion_map.getWildcard();
|
auto parent = n >= 4 ? region_map.findByNamePrefix(parts[3]) : ®ion_map.getWildcard();
|
||||||
if (parent == NULL) {
|
if (parent == NULL) {
|
||||||
@@ -1157,6 +1223,26 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply
|
|||||||
}
|
}
|
||||||
} else if (strcmp(command, "get path.hash.mode") == 0) {
|
} else if (strcmp(command, "get path.hash.mode") == 0) {
|
||||||
sprintf(reply, "> %d (%d-byte path hashes)", _prefs.path_hash_mode, _prefs.path_hash_mode + 1);
|
sprintf(reply, "> %d (%d-byte path hashes)", _prefs.path_hash_mode, _prefs.path_hash_mode + 1);
|
||||||
|
} else if (memcmp(command, "set loop.detect ", 16) == 0) {
|
||||||
|
const char* val = &command[16];
|
||||||
|
if (strcmp(val, "off") == 0) {
|
||||||
|
_prefs.loop_detect = LOOP_DETECT_OFF;
|
||||||
|
} else if (strcmp(val, "minimal") == 0) {
|
||||||
|
_prefs.loop_detect = LOOP_DETECT_MINIMAL;
|
||||||
|
} else if (strcmp(val, "moderate") == 0) {
|
||||||
|
_prefs.loop_detect = LOOP_DETECT_MODERATE;
|
||||||
|
} else if (strcmp(val, "strict") == 0) {
|
||||||
|
_prefs.loop_detect = LOOP_DETECT_STRICT;
|
||||||
|
} else {
|
||||||
|
strcpy(reply, "ERR: use off, minimal, moderate, or strict");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
savePrefs();
|
||||||
|
sprintf(reply, "OK - loop.detect = %s", val);
|
||||||
|
} else if (strcmp(command, "get loop.detect") == 0) {
|
||||||
|
const char* labels[] = { "off", "minimal", "moderate", "strict" };
|
||||||
|
uint8_t mode = _prefs.loop_detect <= 3 ? _prefs.loop_detect : 0;
|
||||||
|
sprintf(reply, "> %s", labels[mode]);
|
||||||
} else{
|
} else{
|
||||||
_cli.handleCommand(sender_timestamp, command, reply); // common CLI commands
|
_cli.handleCommand(sender_timestamp, command, reply); // common CLI commands
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1124,19 +1124,24 @@ restart:
|
|||||||
xSemaphoreGive(_telemetryMutex);
|
xSemaphoreGive(_telemetryMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
char json[400];
|
static const char* loopLabels[] = { "off", "minimal", "moderate", "strict" };
|
||||||
|
const char* loopStr = td.loop_detect <= 3 ? loopLabels[td.loop_detect] : "off";
|
||||||
|
|
||||||
|
char json[512];
|
||||||
snprintf(json, sizeof(json),
|
snprintf(json, sizeof(json),
|
||||||
"{\"uptime\":%lu,\"batt_mv\":%d,\"batt_pct\":%d,\"temp\":%.1f,"
|
"{\"uptime\":%lu,\"batt_mv\":%d,\"batt_pct\":%d,\"temp\":%.1f,"
|
||||||
"\"csq\":%d,\"bars\":%d,\"neighbors\":%d,"
|
"\"csq\":%d,\"bars\":%d,\"neighbors\":%d,"
|
||||||
"\"freq\":%.3f,\"bw\":%.1f,\"sf\":%d,\"cr\":%d,\"tx\":%d,"
|
"\"freq\":%.3f,\"bw\":%.1f,\"sf\":%d,\"cr\":%d,\"tx\":%d,"
|
||||||
"\"name\":\"%s\",\"ip\":\"%s\",\"oper\":\"%s\",\"apn\":\"%s\","
|
"\"name\":\"%s\",\"ip\":\"%s\",\"oper\":\"%s\",\"apn\":\"%s\","
|
||||||
"\"heap\":%d}",
|
"\"heap\":%d,"
|
||||||
|
"\"loop_detect\":\"%s\",\"path_hash_mode\":%d,\"flood_max\":%d}",
|
||||||
td.uptime_secs, td.battery_mv, td.battery_pct,
|
td.uptime_secs, td.battery_mv, td.battery_pct,
|
||||||
td.temperature / 10.0f,
|
td.temperature / 10.0f,
|
||||||
_csq, getSignalBars(), td.neighbor_count,
|
_csq, getSignalBars(), td.neighbor_count,
|
||||||
td.freq, td.bw, td.sf, td.cr, td.tx_power,
|
td.freq, td.bw, td.sf, td.cr, td.tx_power,
|
||||||
td.node_name, _ipAddr, _operator, _apn,
|
td.node_name, _ipAddr, _operator, _apn,
|
||||||
ESP.getFreeHeap());
|
ESP.getFreeHeap(),
|
||||||
|
loopStr, td.path_hash_mode, td.flood_max);
|
||||||
|
|
||||||
mqttPublish(_topicTelem, json);
|
mqttPublish(_topicTelem, json);
|
||||||
lastTelem = millis();
|
lastTelem = millis();
|
||||||
|
|||||||
@@ -246,6 +246,9 @@ void loop() {
|
|||||||
strncpy(td.oper, cellularMQTT.getOperator(), sizeof(td.oper) - 1);
|
strncpy(td.oper, cellularMQTT.getOperator(), sizeof(td.oper) - 1);
|
||||||
td.mqtt_connected = cellularMQTT.isConnected();
|
td.mqtt_connected = cellularMQTT.isConnected();
|
||||||
td.neighbor_count = 0; // TODO: expose from MyMesh
|
td.neighbor_count = 0; // TODO: expose from MyMesh
|
||||||
|
td.loop_detect = p->loop_detect;
|
||||||
|
td.path_hash_mode = p->path_hash_mode;
|
||||||
|
td.flood_max = p->flood_max;
|
||||||
|
|
||||||
cellularMQTT.updateTelemetry(td);
|
cellularMQTT.updateTelemetry(td);
|
||||||
lastTelemUpdate = millis();
|
lastTelemUpdate = millis();
|
||||||
@@ -299,6 +302,9 @@ void loop() {
|
|||||||
strncpy(td.node_name, p->node_name, sizeof(td.node_name) - 1);
|
strncpy(td.node_name, p->node_name, sizeof(td.node_name) - 1);
|
||||||
td.mqtt_connected = wifiMQTT.isConnected();
|
td.mqtt_connected = wifiMQTT.isConnected();
|
||||||
td.neighbor_count = 0;
|
td.neighbor_count = 0;
|
||||||
|
td.loop_detect = p->loop_detect;
|
||||||
|
td.path_hash_mode = p->path_hash_mode;
|
||||||
|
td.flood_max = p->flood_max;
|
||||||
|
|
||||||
wifiMQTT.updateTelemetry(td);
|
wifiMQTT.updateTelemetry(td);
|
||||||
lastTelemUpdate = millis();
|
lastTelemUpdate = millis();
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#ifdef MECK_WIFI_REMOTE
|
#ifdef MECK_WIFI_REMOTE
|
||||||
|
|
||||||
|
#include "target.h"
|
||||||
#include "WiFiMQTT.h"
|
#include "WiFiMQTT.h"
|
||||||
#include <esp_mac.h>
|
#include <esp_mac.h>
|
||||||
#include <Update.h>
|
#include <Update.h>
|
||||||
#include <HTTPClient.h>
|
#include <HTTPClient.h>
|
||||||
#include "target.h"
|
|
||||||
|
|
||||||
WiFiMQTT wifiMQTT;
|
WiFiMQTT wifiMQTT;
|
||||||
|
|
||||||
@@ -373,19 +373,24 @@ void WiFiMQTT::publishQueuedResponses() {
|
|||||||
void WiFiMQTT::publishTelemetry() {
|
void WiFiMQTT::publishTelemetry() {
|
||||||
_rssi = WiFi.RSSI();
|
_rssi = WiFi.RSSI();
|
||||||
|
|
||||||
char json[400];
|
static const char* loopLabels[] = { "off", "minimal", "moderate", "strict" };
|
||||||
|
const char* loopStr = _telemetry.loop_detect <= 3 ? loopLabels[_telemetry.loop_detect] : "off";
|
||||||
|
|
||||||
|
char json[512];
|
||||||
snprintf(json, sizeof(json),
|
snprintf(json, sizeof(json),
|
||||||
"{\"uptime\":%lu,\"batt_mv\":%d,\"batt_pct\":%d,\"temp\":%.1f,"
|
"{\"uptime\":%lu,\"batt_mv\":%d,\"batt_pct\":%d,\"temp\":%.1f,"
|
||||||
"\"rssi\":%d,\"bars\":%d,\"neighbors\":%d,"
|
"\"rssi\":%d,\"bars\":%d,\"neighbors\":%d,"
|
||||||
"\"freq\":%.3f,\"bw\":%.1f,\"sf\":%d,\"cr\":%d,\"tx\":%d,"
|
"\"freq\":%.3f,\"bw\":%.1f,\"sf\":%d,\"cr\":%d,\"tx\":%d,"
|
||||||
"\"name\":\"%s\",\"ip\":\"%s\",\"ssid\":\"%s\","
|
"\"name\":\"%s\",\"ip\":\"%s\",\"ssid\":\"%s\","
|
||||||
"\"heap\":%d}",
|
"\"heap\":%d,"
|
||||||
|
"\"loop_detect\":\"%s\",\"path_hash_mode\":%d,\"flood_max\":%d}",
|
||||||
_telemetry.uptime_secs, _telemetry.battery_mv, _telemetry.battery_pct,
|
_telemetry.uptime_secs, _telemetry.battery_mv, _telemetry.battery_pct,
|
||||||
_telemetry.temperature / 10.0f,
|
_telemetry.temperature / 10.0f,
|
||||||
_rssi, getSignalBars(), _telemetry.neighbor_count,
|
_rssi, getSignalBars(), _telemetry.neighbor_count,
|
||||||
_telemetry.freq, _telemetry.bw, _telemetry.sf, _telemetry.cr, _telemetry.tx_power,
|
_telemetry.freq, _telemetry.bw, _telemetry.sf, _telemetry.cr, _telemetry.tx_power,
|
||||||
_telemetry.node_name, _ipAddr, _config.networks[_activeNetwork].ssid,
|
_telemetry.node_name, _ipAddr, _config.networks[_activeNetwork].ssid,
|
||||||
ESP.getFreeHeap());
|
ESP.getFreeHeap(),
|
||||||
|
loopStr, _telemetry.path_hash_mode, _telemetry.flood_max);
|
||||||
|
|
||||||
_mqttClient.publish(_topicTelem, json);
|
_mqttClient.publish(_topicTelem, json);
|
||||||
}
|
}
|
||||||
@@ -403,34 +408,39 @@ void WiFiMQTT::performOTA() {
|
|||||||
_mqttClient.publish(_topicRsp, "OTA: Starting download...");
|
_mqttClient.publish(_topicRsp, "OTA: Starting download...");
|
||||||
_mqttClient.loop();
|
_mqttClient.loop();
|
||||||
|
|
||||||
|
// Disconnect MQTT cleanly before starting HTTP download —
|
||||||
|
// we can't reuse _wifiClient (PubSubClient holds the socket)
|
||||||
|
_mqttClient.disconnect();
|
||||||
|
delay(100);
|
||||||
|
|
||||||
|
// Use a dedicated TLS client for the firmware download
|
||||||
|
WiFiClientSecure otaClient;
|
||||||
|
otaClient.setInsecure(); // skip cert verification (same as MQTT client)
|
||||||
|
otaClient.setTimeout(30); // 30 second socket timeout
|
||||||
|
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||||
http.setTimeout(180000);
|
http.setTimeout(180000);
|
||||||
|
|
||||||
if (!http.begin(_wifiClient, _otaUrl)) {
|
if (!http.begin(otaClient, _otaUrl)) {
|
||||||
Serial.println("[OTA] HTTP begin failed");
|
Serial.println("[OTA] HTTP begin failed");
|
||||||
_mqttClient.publish(_topicRsp, "OTA: HTTP begin failed");
|
_state = WiFiMQTTState::MQTT_CONNECTING; // trigger MQTT reconnect
|
||||||
_state = WiFiMQTTState::CONNECTED;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int httpCode = http.GET();
|
int httpCode = http.GET();
|
||||||
if (httpCode != HTTP_CODE_OK) {
|
if (httpCode != HTTP_CODE_OK) {
|
||||||
Serial.printf("[OTA] HTTP error: %d\n", httpCode);
|
Serial.printf("[OTA] HTTP error: %d\n", httpCode);
|
||||||
char msg[60];
|
|
||||||
snprintf(msg, sizeof(msg), "OTA: HTTP error %d", httpCode);
|
|
||||||
_mqttClient.publish(_topicRsp, msg);
|
|
||||||
http.end();
|
http.end();
|
||||||
_state = WiFiMQTTState::CONNECTED;
|
_state = WiFiMQTTState::MQTT_CONNECTING;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fileSize = http.getSize();
|
int fileSize = http.getSize();
|
||||||
if (fileSize <= 0) {
|
if (fileSize <= 0) {
|
||||||
Serial.println("[OTA] Unknown content length");
|
Serial.println("[OTA] Unknown content length");
|
||||||
_mqttClient.publish(_topicRsp, "OTA: Unknown file size");
|
|
||||||
http.end();
|
http.end();
|
||||||
_state = WiFiMQTTState::CONNECTED;
|
_state = WiFiMQTTState::MQTT_CONNECTING;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,9 +448,8 @@ void WiFiMQTT::performOTA() {
|
|||||||
|
|
||||||
if (!Update.begin(fileSize)) {
|
if (!Update.begin(fileSize)) {
|
||||||
Serial.printf("[OTA] Update.begin failed: %s\n", Update.errorString());
|
Serial.printf("[OTA] Update.begin failed: %s\n", Update.errorString());
|
||||||
_mqttClient.publish(_topicRsp, "OTA: Flash init failed");
|
|
||||||
http.end();
|
http.end();
|
||||||
_state = WiFiMQTTState::CONNECTED;
|
_state = WiFiMQTTState::MQTT_CONNECTING;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,10 +481,6 @@ void WiFiMQTT::performOTA() {
|
|||||||
int pct = (offset * 100) / fileSize;
|
int pct = (offset * 100) / fileSize;
|
||||||
if (pct / 10 != lastPct / 10) {
|
if (pct / 10 != lastPct / 10) {
|
||||||
Serial.printf("[OTA] Progress: %d%% (%d/%d)\n", pct, offset, fileSize);
|
Serial.printf("[OTA] Progress: %d%% (%d/%d)\n", pct, offset, fileSize);
|
||||||
char msg[60];
|
|
||||||
snprintf(msg, sizeof(msg), "OTA: Flashing %d%%", pct);
|
|
||||||
_mqttClient.publish(_topicRsp, msg);
|
|
||||||
_mqttClient.loop();
|
|
||||||
lastPct = pct;
|
lastPct = pct;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,21 +492,17 @@ void WiFiMQTT::performOTA() {
|
|||||||
if (offset < fileSize) {
|
if (offset < fileSize) {
|
||||||
Serial.printf("[OTA] Incomplete: %d of %d\n", offset, fileSize);
|
Serial.printf("[OTA] Incomplete: %d of %d\n", offset, fileSize);
|
||||||
Update.abort();
|
Update.abort();
|
||||||
_mqttClient.publish(_topicRsp, "OTA: Download incomplete");
|
_state = WiFiMQTTState::MQTT_CONNECTING;
|
||||||
_state = WiFiMQTTState::CONNECTED;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Update.end(true)) {
|
if (!Update.end(true)) {
|
||||||
Serial.printf("[OTA] Update.end failed: %s\n", Update.errorString());
|
Serial.printf("[OTA] Update.end failed: %s\n", Update.errorString());
|
||||||
_mqttClient.publish(_topicRsp, "OTA: Verification failed");
|
_state = WiFiMQTTState::MQTT_CONNECTING;
|
||||||
_state = WiFiMQTTState::CONNECTED;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println("[OTA] SUCCESS — rebooting in 3 seconds");
|
Serial.println("[OTA] SUCCESS — rebooting in 3 seconds");
|
||||||
_mqttClient.publish(_topicRsp, "OTA: Success! Rebooting...");
|
|
||||||
_mqttClient.loop();
|
|
||||||
delay(3000);
|
delay(3000);
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,6 +103,10 @@ struct TelemetryData {
|
|||||||
uint8_t tx_power;
|
uint8_t tx_power;
|
||||||
char node_name[32];
|
char node_name[32];
|
||||||
bool mqtt_connected;
|
bool mqtt_connected;
|
||||||
|
// Routing settings (v1.8+)
|
||||||
|
uint8_t loop_detect; // 0=off, 1=minimal, 2=moderate, 3=strict
|
||||||
|
uint8_t path_hash_mode; // 0=1-byte, 1=2-byte, 2=3-byte
|
||||||
|
uint8_t flood_max; // max flood hop count (0-64)
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "PDM_nrf52",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "PDM microphone library for nRF52840 (from Adafruit BSP)",
|
||||||
|
"license": "LGPL-2.1",
|
||||||
|
"frameworks": "arduino",
|
||||||
|
"platforms": "*"
|
||||||
|
}
|
||||||
@@ -0,0 +1,261 @@
|
|||||||
|
/*
|
||||||
|
PDM.cpp - library to interface with nRF52840 PDM peripheral
|
||||||
|
Part of Arduino - http://www.arduino.cc/
|
||||||
|
|
||||||
|
Copyright (c) 2019 Arduino SA
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General
|
||||||
|
Public License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PDM.h"
|
||||||
|
#include <hal/nrf_pdm.h>
|
||||||
|
|
||||||
|
#include <Adafruit_TinyUSB.h> // for Serial
|
||||||
|
|
||||||
|
#define DEFAULT_PDM_GAIN 20
|
||||||
|
#define PDM_IRQ_PRIORITY 7
|
||||||
|
|
||||||
|
#define NRF_PDM_FREQ_1280K (nrf_pdm_freq_t)(0x0A000000UL) ///< PDM_CLK= 1.280 MHz (32 MHz / 25) => Fs= 20000 Hz
|
||||||
|
#define NRF_PDM_FREQ_2000K (nrf_pdm_freq_t)(0x10000000UL) ///< PDM_CLK= 2.000 MHz (32 MHz / 16) => Fs= 31250 Hz
|
||||||
|
#define NRF_PDM_FREQ_2667K (nrf_pdm_freq_t)(0x15000000UL) ///< PDM_CLK= 2.667 MHz (32 MHz / 12) => Fs= 41667 Hz
|
||||||
|
#define NRF_PDM_FREQ_3200K (nrf_pdm_freq_t)(0x19000000UL) ///< PDM_CLK= 3.200 MHz (32 MHz / 10) => Fs= 50000 Hz
|
||||||
|
#define NRF_PDM_FREQ_4000K (nrf_pdm_freq_t)(0x20000000UL) ///< PDM_CLK= 4.000 MHz (32 MHz / 8) => Fs= 62500 Hz
|
||||||
|
|
||||||
|
PDMClass::PDMClass(int dinPin, int clkPin, int pwrPin) :
|
||||||
|
_dinPin(dinPin),
|
||||||
|
_clkPin(clkPin),
|
||||||
|
_pwrPin(pwrPin),
|
||||||
|
_onReceive(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PDMClass::~PDMClass()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDMClass::setPins(int dataPin, int clkPin, int pwrPin)
|
||||||
|
{
|
||||||
|
_dinPin = dataPin;
|
||||||
|
_clkPin = clkPin;
|
||||||
|
_pwrPin = pwrPin;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PDMClass::begin(int channels, long sampleRate)
|
||||||
|
{
|
||||||
|
_channels = channels;
|
||||||
|
|
||||||
|
// Enable high frequency oscillator if not already enabled
|
||||||
|
uint8_t sd_en = 0;
|
||||||
|
sd_softdevice_is_enabled(&sd_en);
|
||||||
|
|
||||||
|
if (sd_en)
|
||||||
|
{
|
||||||
|
uint32_t is_running;
|
||||||
|
sd_clock_hfclk_is_running(&is_running);
|
||||||
|
|
||||||
|
if (!is_running) {
|
||||||
|
sd_clock_hfclk_request();
|
||||||
|
|
||||||
|
while(!is_running) {
|
||||||
|
yield();
|
||||||
|
sd_clock_hfclk_is_running(&is_running);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) {
|
||||||
|
NRF_CLOCK->TASKS_HFCLKSTART = 1;
|
||||||
|
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure the sample rate and channels
|
||||||
|
switch (sampleRate) {
|
||||||
|
case 16000:
|
||||||
|
#ifndef NRF52832_XXAA
|
||||||
|
NRF_PDM->RATIO = ((PDM_RATIO_RATIO_Ratio80 << PDM_RATIO_RATIO_Pos) & PDM_RATIO_RATIO_Msk);
|
||||||
|
#endif
|
||||||
|
nrf_pdm_clock_set(NRF_PDM, NRF_PDM_FREQ_1280K);
|
||||||
|
break;
|
||||||
|
case 41667:
|
||||||
|
nrf_pdm_clock_set(NRF_PDM, NRF_PDM_FREQ_2667K);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0; // unsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (channels) {
|
||||||
|
case 2:
|
||||||
|
nrf_pdm_mode_set(NRF_PDM, NRF_PDM_MODE_STEREO, NRF_PDM_EDGE_LEFTFALLING);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
nrf_pdm_mode_set(NRF_PDM, NRF_PDM_MODE_MONO, NRF_PDM_EDGE_LEFTFALLING);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0; // unsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
setGain(DEFAULT_PDM_GAIN);
|
||||||
|
|
||||||
|
// configure the I/O and mux
|
||||||
|
pinMode(_clkPin, OUTPUT);
|
||||||
|
digitalWrite(_clkPin, LOW);
|
||||||
|
|
||||||
|
pinMode(_dinPin, INPUT);
|
||||||
|
|
||||||
|
nrf_pdm_psel_connect(NRF_PDM, digitalPinToPinName(_clkPin), digitalPinToPinName(_dinPin));
|
||||||
|
|
||||||
|
// clear events and enable PDM interrupts
|
||||||
|
nrf_pdm_event_clear(NRF_PDM, NRF_PDM_EVENT_STARTED);
|
||||||
|
nrf_pdm_event_clear(NRF_PDM, NRF_PDM_EVENT_END);
|
||||||
|
nrf_pdm_event_clear(NRF_PDM, NRF_PDM_EVENT_STOPPED);
|
||||||
|
nrf_pdm_int_enable(NRF_PDM, NRF_PDM_INT_STARTED | NRF_PDM_INT_STOPPED);
|
||||||
|
|
||||||
|
if (_pwrPin > -1) {
|
||||||
|
// power the mic on
|
||||||
|
pinMode(_pwrPin, OUTPUT);
|
||||||
|
digitalWrite(_pwrPin, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear the buffer
|
||||||
|
_doubleBuffer.reset();
|
||||||
|
|
||||||
|
// set the PDM IRQ priority and enable
|
||||||
|
NVIC_SetPriority(PDM_IRQn, PDM_IRQ_PRIORITY);
|
||||||
|
NVIC_ClearPendingIRQ(PDM_IRQn);
|
||||||
|
NVIC_EnableIRQ(PDM_IRQn);
|
||||||
|
|
||||||
|
// set the buffer for transfer
|
||||||
|
// nrf_pdm_buffer_set((uint32_t*)_doubleBuffer.data(), _doubleBuffer.availableForWrite() / (sizeof(int16_t) * _channels));
|
||||||
|
// _doubleBuffer.swap();
|
||||||
|
|
||||||
|
// enable and trigger start task
|
||||||
|
nrf_pdm_enable(NRF_PDM);
|
||||||
|
nrf_pdm_event_clear(NRF_PDM, NRF_PDM_EVENT_STARTED);
|
||||||
|
nrf_pdm_task_trigger(NRF_PDM, NRF_PDM_TASK_START);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDMClass::end()
|
||||||
|
{
|
||||||
|
// disable PDM and IRQ
|
||||||
|
nrf_pdm_disable(NRF_PDM);
|
||||||
|
|
||||||
|
NVIC_DisableIRQ(PDM_IRQn);
|
||||||
|
|
||||||
|
if (_pwrPin > -1) {
|
||||||
|
// power the mic off
|
||||||
|
digitalWrite(_pwrPin, LOW);
|
||||||
|
pinMode(_pwrPin, INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't disable high frequency oscillator since it could be in use by RADIO
|
||||||
|
|
||||||
|
// unconfigure the I/O and un-mux
|
||||||
|
nrf_pdm_psel_disconnect(NRF_PDM);
|
||||||
|
|
||||||
|
pinMode(_clkPin, INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PDMClass::available()
|
||||||
|
{
|
||||||
|
NVIC_DisableIRQ(PDM_IRQn);
|
||||||
|
|
||||||
|
size_t avail = _doubleBuffer.available();
|
||||||
|
|
||||||
|
NVIC_EnableIRQ(PDM_IRQn);
|
||||||
|
|
||||||
|
return avail;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PDMClass::read(void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
NVIC_DisableIRQ(PDM_IRQn);
|
||||||
|
|
||||||
|
int read = _doubleBuffer.read(buffer, size);
|
||||||
|
|
||||||
|
NVIC_EnableIRQ(PDM_IRQn);
|
||||||
|
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDMClass::onReceive(void(*function)(void))
|
||||||
|
{
|
||||||
|
_onReceive = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDMClass::setGain(int gain)
|
||||||
|
{
|
||||||
|
nrf_pdm_gain_set(NRF_PDM, gain, gain);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDMClass::setBufferSize(int bufferSize)
|
||||||
|
{
|
||||||
|
_doubleBuffer.setSize(bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDMClass::IrqHandler()
|
||||||
|
{
|
||||||
|
if (nrf_pdm_event_check(NRF_PDM, NRF_PDM_EVENT_STARTED)) {
|
||||||
|
nrf_pdm_event_clear(NRF_PDM, NRF_PDM_EVENT_STARTED);
|
||||||
|
|
||||||
|
if (_doubleBuffer.available() == 0) {
|
||||||
|
// switch to the next buffer
|
||||||
|
nrf_pdm_buffer_set(NRF_PDM, (uint32_t*)_doubleBuffer.data(), _doubleBuffer.availableForWrite() / (sizeof(int16_t) * _channels));
|
||||||
|
|
||||||
|
// make the current one available for reading
|
||||||
|
_doubleBuffer.swap(_doubleBuffer.availableForWrite());
|
||||||
|
|
||||||
|
// call receive callback if provided
|
||||||
|
if (_onReceive) {
|
||||||
|
_onReceive();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// buffer overflow, stop
|
||||||
|
nrf_pdm_disable(NRF_PDM);
|
||||||
|
}
|
||||||
|
} else if (nrf_pdm_event_check(NRF_PDM, NRF_PDM_EVENT_STOPPED)) {
|
||||||
|
nrf_pdm_event_clear(NRF_PDM, NRF_PDM_EVENT_STOPPED);
|
||||||
|
} else if (nrf_pdm_event_check(NRF_PDM, NRF_PDM_EVENT_END)) {
|
||||||
|
nrf_pdm_event_clear(NRF_PDM, NRF_PDM_EVENT_END);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
void PDM_IRQHandler(void)
|
||||||
|
{
|
||||||
|
PDM.IrqHandler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef PIN_PDM_DIN
|
||||||
|
#define PIN_PDM_DIN -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PIN_PDM_CLK
|
||||||
|
#define PIN_PDM_CLK -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PIN_PDM_PWR
|
||||||
|
#define PIN_PDM_PWR -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PDMClass PDM(PIN_PDM_DIN, PIN_PDM_CLK, PIN_PDM_PWR);
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2019 Arduino LLC. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
See the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PDM_H_INCLUDED
|
||||||
|
#define _PDM_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(ARDUINO_NRF52_ADAFRUIT)
|
||||||
|
#error "This library targets only Adafruit NRF52840 boards"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Adafruit_TinyUSB.h> // for Serial
|
||||||
|
#include "utility/PDMDoubleBuffer.h"
|
||||||
|
|
||||||
|
class PDMClass
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PDMClass(int dataPin, int clkPin, int pwrPin);
|
||||||
|
virtual ~PDMClass();
|
||||||
|
|
||||||
|
void setPins(int dataPin, int clkPin, int pwrPin);
|
||||||
|
int begin(int channels, long sampleRate);
|
||||||
|
void end();
|
||||||
|
|
||||||
|
virtual int available();
|
||||||
|
virtual int read(void* buffer, size_t size);
|
||||||
|
|
||||||
|
void onReceive(void(*)(void));
|
||||||
|
|
||||||
|
void setGain(int gain);
|
||||||
|
void setBufferSize(int bufferSize);
|
||||||
|
|
||||||
|
// private:
|
||||||
|
void IrqHandler();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _dinPin;
|
||||||
|
int _clkPin;
|
||||||
|
int _pwrPin;
|
||||||
|
|
||||||
|
int _channels;
|
||||||
|
|
||||||
|
PDMDoubleBuffer _doubleBuffer;
|
||||||
|
|
||||||
|
void (*_onReceive)(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern PDMClass PDM;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016 Arduino LLC. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
See the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "PDMDoubleBuffer.h"
|
||||||
|
|
||||||
|
PDMDoubleBuffer::PDMDoubleBuffer() :
|
||||||
|
_size(DEFAULT_PDM_BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
PDMDoubleBuffer::~PDMDoubleBuffer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDMDoubleBuffer::setSize(int size)
|
||||||
|
{
|
||||||
|
_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDMDoubleBuffer::reset()
|
||||||
|
{
|
||||||
|
_buffer[0] = (uint8_t*)realloc(_buffer[0], _size);
|
||||||
|
_buffer[1] = (uint8_t*)realloc(_buffer[1], _size);
|
||||||
|
|
||||||
|
memset(_buffer[0], 0x00, _size);
|
||||||
|
memset(_buffer[1], 0x00, _size);
|
||||||
|
|
||||||
|
_index = 0;
|
||||||
|
_length[0] = 0;
|
||||||
|
_length[1] = 0;
|
||||||
|
_readOffset[0] = 0;
|
||||||
|
_readOffset[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t PDMDoubleBuffer::availableForWrite()
|
||||||
|
{
|
||||||
|
return (_size - (_length[_index] - _readOffset[_index]));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t PDMDoubleBuffer::write(const void *buffer, size_t size)
|
||||||
|
{
|
||||||
|
size_t space = availableForWrite();
|
||||||
|
|
||||||
|
if (size > space) {
|
||||||
|
size = space;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&_buffer[_index][_length[_index]], buffer, size);
|
||||||
|
|
||||||
|
_length[_index] += size;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t PDMDoubleBuffer::read(void *buffer, size_t size)
|
||||||
|
{
|
||||||
|
size_t avail = available();
|
||||||
|
|
||||||
|
if (size > avail) {
|
||||||
|
size = avail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, &_buffer[_index][_readOffset[_index]], size);
|
||||||
|
_readOffset[_index] += size;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t PDMDoubleBuffer::peek(void *buffer, size_t size)
|
||||||
|
{
|
||||||
|
size_t avail = available();
|
||||||
|
|
||||||
|
if (size > avail) {
|
||||||
|
size = avail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, &_buffer[_index][_readOffset[_index]], size);
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* PDMDoubleBuffer::data()
|
||||||
|
{
|
||||||
|
return (void*)_buffer[_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t PDMDoubleBuffer::available()
|
||||||
|
{
|
||||||
|
return _length[_index] - _readOffset[_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDMDoubleBuffer::swap(int length)
|
||||||
|
{
|
||||||
|
if (_index == 0) {
|
||||||
|
_index = 1;
|
||||||
|
} else {
|
||||||
|
_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_length[_index] = length;
|
||||||
|
_readOffset[_index] = 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016 Arduino LLC. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
See the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PDM_DOUBLE_BUFFER_H_INCLUDED
|
||||||
|
#define _PDM_DOUBLE_BUFFER_H_INCLUDED
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define DEFAULT_PDM_BUFFER_SIZE 512
|
||||||
|
|
||||||
|
class PDMDoubleBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PDMDoubleBuffer();
|
||||||
|
virtual ~PDMDoubleBuffer();
|
||||||
|
|
||||||
|
void setSize(int size);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
size_t availableForWrite();
|
||||||
|
size_t write(const void *buffer, size_t size);
|
||||||
|
size_t read(void *buffer, size_t size);
|
||||||
|
size_t peek(void *buffer, size_t size);
|
||||||
|
void* data();
|
||||||
|
size_t available();
|
||||||
|
void swap(int length = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t* _buffer[2];
|
||||||
|
int _size;
|
||||||
|
volatile int _length[2];
|
||||||
|
volatile int _readOffset[2];
|
||||||
|
volatile int _index;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "codec2_nrf52",
|
||||||
|
"version": "0.7.0",
|
||||||
|
"description": "Codec2 low-bitrate speech codec - stripped for nRF52840 (1200bps mode)",
|
||||||
|
"license": "LGPL-2.1",
|
||||||
|
"frameworks": "arduino",
|
||||||
|
"platforms": "*",
|
||||||
|
"build": {
|
||||||
|
"flags": "-DCODEC2_MODE_EN_DEFAULT"
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
FILE....: ../src/HRA_112_112.h
|
||||||
|
|
||||||
|
Static arrays for CML LDPC, generated by ldpc_gen_h_file.m.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HRA_112_112_NUMBERPARITYBITS 112
|
||||||
|
#define HRA_112_112_MAX_ROW_WEIGHT 3
|
||||||
|
#define HRA_112_112_CODELENGTH 224
|
||||||
|
#define HRA_112_112_NUMBERROWSHCOLS 112
|
||||||
|
#define HRA_112_112_MAX_COL_WEIGHT 3
|
||||||
|
#define HRA_112_112_DEC_TYPE 0
|
||||||
|
#define HRA_112_112_MAX_ITER 100
|
||||||
|
|
||||||
|
double HRA_112_112_H_rows[] = {
|
||||||
|
22, 18, 15, 63, 16, 13, 1, 2, 29, 25, 28, 4, 36, 10, 38, 7, 60, 23, 11, 38, 28, 1, 12, 31, 57, 45, 57, 30, 23, 59, 67, 14, 16, 4, 14, 62, 15, 50, 7, 70, 64, 6, 42, 48, 9, 31, 19, 40, 49, 2, 25, 3, 41, 49, 36, 9, 29, 39, 31, 5, 17, 1, 29, 25, 11, 21, 18, 2, 8, 22, 39, 15, 8, 22, 13, 3, 19, 4, 21, 62, 34, 43, 6, 24, 17, 60, 8, 74, 6, 44, 60, 10, 33, 12, 26, 24, 45, 81, 69, 80, 41, 28, 23, 5, 10, 20, 52, 18, 13, 86, 3, 7, 59, 21, 65, 72, 34, 37, 26, 55, 47, 48, 34, 5, 44, 47, 68, 96, 82, 111, 61, 74, 30, 17, 55, 98, 81, 66, 89, 35, 74, 82, 91, 51, 55, 51, 30, 89, 61, 75, 40, 71, 73, 11, 56, 54, 19, 47, 94, 69, 64, 20, 64, 12, 54, 77, 42, 88, 36, 52, 90, 63, 70, 27, 32, 73, 91, 32, 56, 46, 9, 78, 51, 68, 88, 67, 20, 43, 40, 14, 66, 86, 39, 97, 38, 27, 50, 84, 54, 92, 61, 46, 67, 24, 58, 35, 58, 37, 98, 85, 73, 84, 48, 35, 57, 16, 26, 37, 65, 32, 72, 95, 107, 33, 77, 33, 85, 105, 106, 75, 56, 71, 79, 59, 52, 105, 79, 90, 93, 100, 88, 112, 86, 80, 65, 42, 106, 100, 93, 94, 99, 97, 93, 101, 111, 99, 83, 53, 85, 95, 108, 107, 41, 109, 84, 78, 104, 101, 69, 110, 98, 103, 80, 83, 77, 71, 76, 78, 87, 102, 104, 95, 96, 83, 87, 50, 110, 103, 112, 45, 58, 70, 94, 91, 89, 81, 101, 82, 63, 72, 100, 97, 76, 112, 53, 105, 49, 75, 109, 102, 66, 111, 68, 87, 92, 79, 96, 43, 90, 44, 110, 99, 102, 92, 103, 106, 62, 53, 27, 46, 108, 104, 107, 108, 109, 76
|
||||||
|
};
|
||||||
|
|
||||||
|
double HRA_112_112_H_cols[] = {
|
||||||
|
7, 8, 52, 12, 12, 42, 16, 69, 45, 14, 19, 23, 6, 32, 3, 5, 22, 2, 45, 50, 2, 1, 18, 84, 10, 7, 62, 11, 9, 21, 24, 63, 2, 5, 28, 13, 6, 15, 58, 39, 39, 22, 76, 13, 26, 68, 9, 10, 49, 38, 32, 11, 34, 44, 8, 7, 25, 67, 1, 17, 19, 36, 4, 41, 3, 26, 31, 15, 45, 40, 8, 4, 41, 20, 6, 53, 1, 42, 9, 20, 25, 17, 33, 41, 3, 19, 55, 17, 27, 14, 31, 88, 15, 26, 36, 16, 28, 24, 27, 16, 30, 56, 48, 43, 4, 5, 38, 37, 40, 46, 18, 18, 22, 50, 76, 34, 60, 83, 39, 73, 56, 92, 42, 52, 75, 35, 37, 33, 61, 67, 47, 75, 66, 70, 29, 92, 51, 95, 84, 21, 57, 28, 46, 66, 93, 11, 94, 55, 96, 20, 71, 48, 53, 43, 82, 90, 66, 90, 14, 44, 54, 62, 34, 58, 81, 53, 23, 43, 27, 93, 10, 86, 37, 80, 60, 49, 21, 79, 74, 72, 48, 61, 40, 76, 64, 29, 38, 79, 51, 54, 13, 49, 72, 30, 50, 86, 35, 80, 61, 56, 36, 59, 65, 91, 25, 47, 58, 59, 78, 47, 32, 24, 44, 86, 64, 57, 12, 23, 109, 107, 85, 63, 31, 65, 62, 68, 111, 78, 104, 89, 112, 87, 69, 105, 65, 94, 109, 78, 72, 104, 85, 108, 77, 106, 79, 74, 103, 96, 64, 105, 105, 102, 63, 35, 59, 108, 112, 81, 102, 57, 106, 83, 81, 77, 101, 55, 94, 96, 97, 106, 46, 101, 83, 85, 71, 107, 104, 87, 33, 67, 103, 95, 30, 91, 89, 103, 75, 51, 107, 87, 91, 89, 99, 68, 52, 109, 99, 88, 84, 112, 54, 70, 92, 100, 98, 74, 60, 100, 98, 110, 90, 73, 71, 95, 70, 100, 29, 69, 110, 93, 82, 97, 98, 77, 73, 99, 101, 108, 82, 102, 111, 110, 111, 97, 88, 80
|
||||||
|
};
|
||||||
|
|
||||||
|
double HRA_112_112_input[] = {
|
||||||
|
-5.7868467875518395, -6.340739523388657, 3.6654768375589399, 4.1452438183910827, -4.6746135252043111, -4.8353634065473701, -6.0729133999971285, 4.0335561282226271, -6.1114855315699135, 4.1029513876344916, -4.6481634503883624, 5.7650915278538646, 6.5567610490570312, 5.1810523550761207, 3.4789051916752669, 4.2678848515507122, 4.0314705275547089, 6.0297078342283799, 4.9101169653222163, -6.4577297598332324, -7.4273487270443095, 3.472130985267488, -6.5346233967202254, 7.5312028458762414, -5.2618748211985915, 6.4198074556254969, 3.7500207659511484, 5.4040878141701141, 5.7554260586578803, 3.3973620625026886, 7.1815269888532907, 5.0031747952824963, 5.1377243276145599, 5.385229914081755, -0.61384230253605643, 0.46954911161835722, 3.5182611493679663, 3.393698829567279, 6.147483866535171, 3.8374563885989228, 1.3663773773557015, -4.0917661778352352, -3.2968298202652835, -6.0371912041431148, -8.4279246895331781, -0.98556788606912304, -3.515442879601625, 4.2642476942514875, -5.5905016743156972, 3.6920101668161727, -4.035860013856472, 5.3290190966269995, -2.9729656070594057, -2.5054371041338537, 6.8683150013190115, -7.1109038108500098, 6.7301890172695158, 2.5782062882356374, 4.4161464916633282, 2.2692851122935322, -1.3682527221025034, 3.0794629981237631, -7.8655412763279973, 1.1479897597156494, 0.22370696314520414, 1.1222453403894148, -3.1335220808128219, -3.8352985265277089, -1.2463521619727009, 2.9511814015293218, -8.668811041413111, 3.0185610517830548, -6.9592962351476091, 3.9653416636625414, -3.9384322074229408, 1.6789027505247516, 2.9579632055145502, -2.1212672699995125, -3.8892168640945193, 7.516114544807583, -0.84285604179011253, 4.1295390817792512, 0.26093278495228162, -3.6071666499996047, -0.065323173773821908, -1.9146584862100915, 4.7951161310834367, 5.5440002982088803, 3.5917539980319364, -0.81416023563684481, -2.6588977758747721, -3.0404494660606227, 4.5389936536649662, 2.7870543501114082, 3.5622966707453889, 5.1982116994791161, 2.4775319712999302, 0.70541080068007755, 0.89622787904518464, 4.3789020039207758, -2.4976040580619445, -0.7201255450933205, 4.2071986295109394, -5.2418379271657001, -4.092365654835163, -4.3510198326542557, 3.7404138637596001, 1.2496890930262492, -7.1053909336149728, -4.8888279905256748, -6.3523901926735249, -1.8757980409249277, 3.6256343910366273, -3.6165398844758228, -0.38322352317510561, -0.84747550047769449, -1.2717892264620718, -2.3899810721111154, 4.1368500898628637, 3.0440159002314924, 3.4235543074310728, -2.146097053557551, -1.7537615307751735, -1.0280987119225686, 4.9009275359419204, 5.0046047156368116, -0.47700833783807428, -4.5989492891875567, 1.4154839158712684, 0.33410724822249849, -4.771937854508927, -1.1817007924012972, -2.5960865023249302, 0.30422629502493687, -2.2097849377516763, -4.343244940878872, 1.9464288912612249, -9.0976989032526809, -8.6454142547592685, -1.8164317522989997, 2.2780845702169961, -4.8775405042023356, -0.61834757216625769, -1.985554501661331, -0.87599558657596699, -8.0610201531782124, -5.9847574894882554, -10.365536404711067, 2.9782191161319376, -6.9443820217795169, 0.72935566343949876, -4.5326632961380664, 1.1307250622386897, -4.0853969692041314, 5.4926924507347596, 5.6722555096362042, -2.5069992226180222, 2.0460084066662092, 2.5375899018238197, -3.5264293517823679, 3.2103083878487557, 5.793713046583183, -2.7633653287377995, 6.482851815629938, -1.2471646528152021, 3.0010491047486085, 0.29072399293868856, -4.0686659405747738, -2.6253508133431289, -6.3896590677017171, 5.7054076607727886, 4.3053292399977092, 2.2372599539047151, -4.8975607398431897, 5.8124794005531406, -0.69648233429781359, 5.5509723605410004, 2.0900652762982923, -4.7944253330785118, -2.9224693872108287, 6.0218579796888303, 4.7027436964063387, -4.1564871824868659, -1.324779121305123, 0.38031612697724176, -0.69335927945709175, -0.4028295686263082, 2.0967669774299189, 2.7947186736855909, 2.1473880039026203, 6.368702510367898, -3.0691782325684049, 1.6125827087903837, 3.5925359669662518, 5.178224480471127, -2.5070763799556617, 4.4280512389456632, -6.5385259627250134, 2.8047951999607603, -3.0185715385981151, -0.33348983718789993, -4.3285127692183556, -7.9609407359365134, 7.064973172264966, 0.95714371675898213, -5.5481272272415545, -1.6024149180708045, -4.5740915350065992, -1.5117120929647263, 1.9996824689403947, 5.9527526663437724, 5.0239857792804967, 6.2677418491798784, -1.9758548902654505, 2.1709284879472324, 2.5054563138111572, 4.4483685492445115, 3.2098357106645676, -4.5306213859481099, 1.1291114493451548, 1.5827945023160555, -5.2733490015732292, 5.0664709821503457, 1.9652801880230106
|
||||||
|
};
|
||||||
|
|
||||||
|
char HRA_112_112_detected_data[] = {
|
||||||
|
1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0
|
||||||
|
};
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2003-2010, Mark Borgerding
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* kiss_fft.h
|
||||||
|
defines kiss_fft_scalar as either short or a float type
|
||||||
|
and defines
|
||||||
|
typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
|
||||||
|
#include "kiss_fft.h"
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#define MAXFACTORS 32
|
||||||
|
/* e.g. an fft of length 128 has 4 factors
|
||||||
|
as far as kissfft is concerned
|
||||||
|
4*4*4*2
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct kiss_fft_state{
|
||||||
|
int nfft;
|
||||||
|
int inverse;
|
||||||
|
int factors[2*MAXFACTORS];
|
||||||
|
kiss_fft_cpx twiddles[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Explanation of macros dealing with complex math:
|
||||||
|
|
||||||
|
C_MUL(m,a,b) : m = a*b
|
||||||
|
C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise
|
||||||
|
C_SUB( res, a,b) : res = a - b
|
||||||
|
C_SUBFROM( res , a) : res -= a
|
||||||
|
C_ADDTO( res , a) : res += a
|
||||||
|
* */
|
||||||
|
#ifdef FIXED_POINT
|
||||||
|
#if (FIXED_POINT==32)
|
||||||
|
# define FRACBITS 31
|
||||||
|
# define SAMPPROD int64_t
|
||||||
|
#define SAMP_MAX 2147483647
|
||||||
|
#else
|
||||||
|
# define FRACBITS 15
|
||||||
|
# define SAMPPROD int32_t
|
||||||
|
#define SAMP_MAX 32767
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SAMP_MIN -SAMP_MAX
|
||||||
|
|
||||||
|
#if defined(CHECK_OVERFLOW)
|
||||||
|
# define CHECK_OVERFLOW_OP(a,op,b) \
|
||||||
|
if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
|
||||||
|
fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
# define smul(a,b) ( (SAMPPROD)(a)*(b) )
|
||||||
|
# define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS )
|
||||||
|
|
||||||
|
# define S_MUL(a,b) sround( smul(a,b) )
|
||||||
|
|
||||||
|
# define C_MUL(m,a,b) \
|
||||||
|
do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
|
||||||
|
(m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
|
||||||
|
|
||||||
|
# define DIVSCALAR(x,k) \
|
||||||
|
(x) = sround( smul( x, SAMP_MAX/k ) )
|
||||||
|
|
||||||
|
# define C_FIXDIV(c,div) \
|
||||||
|
do { DIVSCALAR( (c).r , div); \
|
||||||
|
DIVSCALAR( (c).i , div); }while (0)
|
||||||
|
|
||||||
|
# define C_MULBYSCALAR( c, s ) \
|
||||||
|
do{ (c).r = sround( smul( (c).r , s ) ) ;\
|
||||||
|
(c).i = sround( smul( (c).i , s ) ) ; }while(0)
|
||||||
|
|
||||||
|
#else /* not FIXED_POINT*/
|
||||||
|
|
||||||
|
# define S_MUL(a,b) ( (a)*(b) )
|
||||||
|
#define C_MUL(m,a,b) \
|
||||||
|
do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
|
||||||
|
(m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
|
||||||
|
# define C_FIXDIV(c,div) /* NOOP */
|
||||||
|
# define C_MULBYSCALAR( c, s ) \
|
||||||
|
do{ (c).r *= (s);\
|
||||||
|
(c).i *= (s); }while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CHECK_OVERFLOW_OP
|
||||||
|
# define CHECK_OVERFLOW_OP(a,op,b) /* noop */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define C_ADD( res, a,b)\
|
||||||
|
do { \
|
||||||
|
CHECK_OVERFLOW_OP((a).r,+,(b).r)\
|
||||||
|
CHECK_OVERFLOW_OP((a).i,+,(b).i)\
|
||||||
|
(res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \
|
||||||
|
}while(0)
|
||||||
|
#define C_SUB( res, a,b)\
|
||||||
|
do { \
|
||||||
|
CHECK_OVERFLOW_OP((a).r,-,(b).r)\
|
||||||
|
CHECK_OVERFLOW_OP((a).i,-,(b).i)\
|
||||||
|
(res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \
|
||||||
|
}while(0)
|
||||||
|
#define C_ADDTO( res , a)\
|
||||||
|
do { \
|
||||||
|
CHECK_OVERFLOW_OP((res).r,+,(a).r)\
|
||||||
|
CHECK_OVERFLOW_OP((res).i,+,(a).i)\
|
||||||
|
(res).r += (a).r; (res).i += (a).i;\
|
||||||
|
}while(0)
|
||||||
|
|
||||||
|
#define C_SUBFROM( res , a)\
|
||||||
|
do {\
|
||||||
|
CHECK_OVERFLOW_OP((res).r,-,(a).r)\
|
||||||
|
CHECK_OVERFLOW_OP((res).i,-,(a).i)\
|
||||||
|
(res).r -= (a).r; (res).i -= (a).i; \
|
||||||
|
}while(0)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef FIXED_POINT
|
||||||
|
# define KISS_FFT_COS(phase) floorf(.5+SAMP_MAX * cosf (phase))
|
||||||
|
# define KISS_FFT_SIN(phase) floorf(.5+SAMP_MAX * sinf (phase))
|
||||||
|
# define HALF_OF(x) ((x)>>1)
|
||||||
|
#elif defined(USE_SIMD)
|
||||||
|
# define KISS_FFT_COS(phase) _mm_set1_ps( cosf(phase) )
|
||||||
|
# define KISS_FFT_SIN(phase) _mm_set1_ps( sinf(phase) )
|
||||||
|
# define HALF_OF(x) ((x)*_mm_set1_ps(.5))
|
||||||
|
#else
|
||||||
|
# define KISS_FFT_COS(phase) (kiss_fft_scalar) cosf(phase)
|
||||||
|
# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sinf(phase)
|
||||||
|
# define HALF_OF(x) ((x)*.5)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define kf_cexp(x,phase) \
|
||||||
|
do{ \
|
||||||
|
(x)->r = KISS_FFT_COS(phase);\
|
||||||
|
(x)->i = KISS_FFT_SIN(phase);\
|
||||||
|
}while(0)
|
||||||
|
|
||||||
|
|
||||||
|
/* a debugging function */
|
||||||
|
#define pcpx(c)\
|
||||||
|
fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) )
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef KISS_FFT_USE_ALLOCA
|
||||||
|
// define this to allow use of alloca instead of malloc for temporary buffers
|
||||||
|
// Temporary buffers are used in two case:
|
||||||
|
// 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5
|
||||||
|
// 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an in-place transform.
|
||||||
|
#include <alloca.h>
|
||||||
|
#define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes)
|
||||||
|
#define KISS_FFT_TMP_FREE(ptr)
|
||||||
|
#else
|
||||||
|
#define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes)
|
||||||
|
#define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr)
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: ampexp.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: & August 2012
|
||||||
|
|
||||||
|
Functions for experimenting with amplitude quantisation.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2012 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not,see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AMPEX__
|
||||||
|
#define __AMPEXP__
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
struct AEXP;
|
||||||
|
|
||||||
|
struct AEXP *amp_experiment_create();
|
||||||
|
void amp_experiment_destroy(struct AEXP *aexp);
|
||||||
|
void amp_experiment(struct AEXP *aexp, MODEL *model, char *arg);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
#define BPF_N 101
|
||||||
|
|
||||||
|
float bpf[]={
|
||||||
|
0.002174,
|
||||||
|
0.003245,
|
||||||
|
0.002147,
|
||||||
|
0.001866,
|
||||||
|
0.002764,
|
||||||
|
0.000567,
|
||||||
|
-0.001641,
|
||||||
|
-0.000565,
|
||||||
|
-0.002415,
|
||||||
|
-0.005837,
|
||||||
|
-0.003620,
|
||||||
|
-0.002828,
|
||||||
|
-0.006268,
|
||||||
|
-0.002787,
|
||||||
|
0.001963,
|
||||||
|
-0.001234,
|
||||||
|
0.001446,
|
||||||
|
0.009200,
|
||||||
|
0.005331,
|
||||||
|
0.003521,
|
||||||
|
0.011821,
|
||||||
|
0.006951,
|
||||||
|
-0.002015,
|
||||||
|
0.005137,
|
||||||
|
0.001828,
|
||||||
|
-0.013390,
|
||||||
|
-0.007058,
|
||||||
|
-0.003273,
|
||||||
|
-0.020458,
|
||||||
|
-0.014321,
|
||||||
|
0.001751,
|
||||||
|
-0.012891,
|
||||||
|
-0.009730,
|
||||||
|
0.018993,
|
||||||
|
0.008544,
|
||||||
|
0.000534,
|
||||||
|
0.035755,
|
||||||
|
0.029074,
|
||||||
|
-0.001192,
|
||||||
|
0.030852,
|
||||||
|
0.030983,
|
||||||
|
-0.029834,
|
||||||
|
-0.009550,
|
||||||
|
0.011945,
|
||||||
|
-0.081971,
|
||||||
|
-0.082875,
|
||||||
|
0.000423,
|
||||||
|
-0.133526,
|
||||||
|
-0.211778,
|
||||||
|
0.182628,
|
||||||
|
0.514906,
|
||||||
|
0.182628,
|
||||||
|
-0.211778,
|
||||||
|
-0.133526,
|
||||||
|
0.000423,
|
||||||
|
-0.082875,
|
||||||
|
-0.081971,
|
||||||
|
0.011945,
|
||||||
|
-0.009550,
|
||||||
|
-0.029834,
|
||||||
|
0.030983,
|
||||||
|
0.030852,
|
||||||
|
-0.001192,
|
||||||
|
0.029074,
|
||||||
|
0.035755,
|
||||||
|
0.000534,
|
||||||
|
0.008544,
|
||||||
|
0.018993,
|
||||||
|
-0.009730,
|
||||||
|
-0.012891,
|
||||||
|
0.001751,
|
||||||
|
-0.014321,
|
||||||
|
-0.020458,
|
||||||
|
-0.003273,
|
||||||
|
-0.007058,
|
||||||
|
-0.013390,
|
||||||
|
0.001828,
|
||||||
|
0.005137,
|
||||||
|
-0.002015,
|
||||||
|
0.006951,
|
||||||
|
0.011821,
|
||||||
|
0.003521,
|
||||||
|
0.005331,
|
||||||
|
0.009200,
|
||||||
|
0.001446,
|
||||||
|
-0.001234,
|
||||||
|
0.001963,
|
||||||
|
-0.002787,
|
||||||
|
-0.006268,
|
||||||
|
-0.002828,
|
||||||
|
-0.003620,
|
||||||
|
-0.005837,
|
||||||
|
-0.002415,
|
||||||
|
-0.000565,
|
||||||
|
-0.001641,
|
||||||
|
0.000567,
|
||||||
|
0.002764,
|
||||||
|
0.001866,
|
||||||
|
0.002147,
|
||||||
|
0.003245,
|
||||||
|
0.002174
|
||||||
|
};
|
||||||
|
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
#define BPFB_N 101
|
||||||
|
|
||||||
|
float bpfb[]={
|
||||||
|
0.003795,
|
||||||
|
0.006827,
|
||||||
|
0.002261,
|
||||||
|
0.002523,
|
||||||
|
0.005758,
|
||||||
|
-0.000264,
|
||||||
|
-0.000674,
|
||||||
|
0.003113,
|
||||||
|
-0.004144,
|
||||||
|
-0.004923,
|
||||||
|
0.000043,
|
||||||
|
-0.008017,
|
||||||
|
-0.008711,
|
||||||
|
-0.001802,
|
||||||
|
-0.010210,
|
||||||
|
-0.010428,
|
||||||
|
-0.000899,
|
||||||
|
-0.009413,
|
||||||
|
-0.009072,
|
||||||
|
0.003469,
|
||||||
|
-0.005335,
|
||||||
|
-0.004828,
|
||||||
|
0.010724,
|
||||||
|
0.000941,
|
||||||
|
0.000708,
|
||||||
|
0.018957,
|
||||||
|
0.007084,
|
||||||
|
0.004825,
|
||||||
|
0.025418,
|
||||||
|
0.010147,
|
||||||
|
0.004452,
|
||||||
|
0.027434,
|
||||||
|
0.007550,
|
||||||
|
-0.002861,
|
||||||
|
0.023483,
|
||||||
|
-0.001944,
|
||||||
|
-0.018138,
|
||||||
|
0.014122,
|
||||||
|
-0.017583,
|
||||||
|
-0.040768,
|
||||||
|
0.002598,
|
||||||
|
-0.036604,
|
||||||
|
-0.069541,
|
||||||
|
-0.004273,
|
||||||
|
-0.054876,
|
||||||
|
-0.107289,
|
||||||
|
0.010068,
|
||||||
|
-0.068052,
|
||||||
|
-0.200119,
|
||||||
|
0.207287,
|
||||||
|
0.597150,
|
||||||
|
0.207287,
|
||||||
|
-0.200119,
|
||||||
|
-0.068052,
|
||||||
|
0.010068,
|
||||||
|
-0.107289,
|
||||||
|
-0.054876,
|
||||||
|
-0.004273,
|
||||||
|
-0.069541,
|
||||||
|
-0.036604,
|
||||||
|
0.002598,
|
||||||
|
-0.040768,
|
||||||
|
-0.017583,
|
||||||
|
0.014122,
|
||||||
|
-0.018138,
|
||||||
|
-0.001944,
|
||||||
|
0.023483,
|
||||||
|
-0.002861,
|
||||||
|
0.007550,
|
||||||
|
0.027434,
|
||||||
|
0.004452,
|
||||||
|
0.010147,
|
||||||
|
0.025418,
|
||||||
|
0.004825,
|
||||||
|
0.007084,
|
||||||
|
0.018957,
|
||||||
|
0.000708,
|
||||||
|
0.000941,
|
||||||
|
0.010724,
|
||||||
|
-0.004828,
|
||||||
|
-0.005335,
|
||||||
|
0.003469,
|
||||||
|
-0.009072,
|
||||||
|
-0.009413,
|
||||||
|
-0.000899,
|
||||||
|
-0.010428,
|
||||||
|
-0.010210,
|
||||||
|
-0.001802,
|
||||||
|
-0.008711,
|
||||||
|
-0.008017,
|
||||||
|
0.000043,
|
||||||
|
-0.004923,
|
||||||
|
-0.004144,
|
||||||
|
0.003113,
|
||||||
|
-0.000674,
|
||||||
|
-0.000264,
|
||||||
|
0.005758,
|
||||||
|
0.002523,
|
||||||
|
0.002261,
|
||||||
|
0.006827,
|
||||||
|
0.003795
|
||||||
|
};
|
||||||
@@ -0,0 +1,245 @@
|
|||||||
|
/* THIS IS A GENERATED FILE. Edit generate_codebook.c and its input */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This intermediary file and the files that used to create it are under
|
||||||
|
* The LGPL. See the file COPYING.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp1.txt */
|
||||||
|
static const float codes0[] = {
|
||||||
|
225,
|
||||||
|
250,
|
||||||
|
275,
|
||||||
|
300,
|
||||||
|
325,
|
||||||
|
350,
|
||||||
|
375,
|
||||||
|
400,
|
||||||
|
425,
|
||||||
|
450,
|
||||||
|
475,
|
||||||
|
500,
|
||||||
|
525,
|
||||||
|
550,
|
||||||
|
575,
|
||||||
|
600
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp2.txt */
|
||||||
|
static const float codes1[] = {
|
||||||
|
325,
|
||||||
|
350,
|
||||||
|
375,
|
||||||
|
400,
|
||||||
|
425,
|
||||||
|
450,
|
||||||
|
475,
|
||||||
|
500,
|
||||||
|
525,
|
||||||
|
550,
|
||||||
|
575,
|
||||||
|
600,
|
||||||
|
625,
|
||||||
|
650,
|
||||||
|
675,
|
||||||
|
700
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp3.txt */
|
||||||
|
static const float codes2[] = {
|
||||||
|
500,
|
||||||
|
550,
|
||||||
|
600,
|
||||||
|
650,
|
||||||
|
700,
|
||||||
|
750,
|
||||||
|
800,
|
||||||
|
850,
|
||||||
|
900,
|
||||||
|
950,
|
||||||
|
1000,
|
||||||
|
1050,
|
||||||
|
1100,
|
||||||
|
1150,
|
||||||
|
1200,
|
||||||
|
1250
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp4.txt */
|
||||||
|
static const float codes3[] = {
|
||||||
|
700,
|
||||||
|
800,
|
||||||
|
900,
|
||||||
|
1000,
|
||||||
|
1100,
|
||||||
|
1200,
|
||||||
|
1300,
|
||||||
|
1400,
|
||||||
|
1500,
|
||||||
|
1600,
|
||||||
|
1700,
|
||||||
|
1800,
|
||||||
|
1900,
|
||||||
|
2000,
|
||||||
|
2100,
|
||||||
|
2200
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp5.txt */
|
||||||
|
static const float codes4[] = {
|
||||||
|
950,
|
||||||
|
1050,
|
||||||
|
1150,
|
||||||
|
1250,
|
||||||
|
1350,
|
||||||
|
1450,
|
||||||
|
1550,
|
||||||
|
1650,
|
||||||
|
1750,
|
||||||
|
1850,
|
||||||
|
1950,
|
||||||
|
2050,
|
||||||
|
2150,
|
||||||
|
2250,
|
||||||
|
2350,
|
||||||
|
2450
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp6.txt */
|
||||||
|
static const float codes5[] = {
|
||||||
|
1100,
|
||||||
|
1200,
|
||||||
|
1300,
|
||||||
|
1400,
|
||||||
|
1500,
|
||||||
|
1600,
|
||||||
|
1700,
|
||||||
|
1800,
|
||||||
|
1900,
|
||||||
|
2000,
|
||||||
|
2100,
|
||||||
|
2200,
|
||||||
|
2300,
|
||||||
|
2400,
|
||||||
|
2500,
|
||||||
|
2600
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp7.txt */
|
||||||
|
static const float codes6[] = {
|
||||||
|
1500,
|
||||||
|
1600,
|
||||||
|
1700,
|
||||||
|
1800,
|
||||||
|
1900,
|
||||||
|
2000,
|
||||||
|
2100,
|
||||||
|
2200,
|
||||||
|
2300,
|
||||||
|
2400,
|
||||||
|
2500,
|
||||||
|
2600,
|
||||||
|
2700,
|
||||||
|
2800,
|
||||||
|
2900,
|
||||||
|
3000
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp8.txt */
|
||||||
|
static const float codes7[] = {
|
||||||
|
2300,
|
||||||
|
2400,
|
||||||
|
2500,
|
||||||
|
2600,
|
||||||
|
2700,
|
||||||
|
2800,
|
||||||
|
2900,
|
||||||
|
3000
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp9.txt */
|
||||||
|
static const float codes8[] = {
|
||||||
|
2500,
|
||||||
|
2600,
|
||||||
|
2700,
|
||||||
|
2800,
|
||||||
|
2900,
|
||||||
|
3000,
|
||||||
|
3100,
|
||||||
|
3200
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp10.txt */
|
||||||
|
static const float codes9[] = {
|
||||||
|
2900,
|
||||||
|
3100,
|
||||||
|
3300,
|
||||||
|
3500
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct lsp_codebook lsp_cb[] = {
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp1.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
4,
|
||||||
|
16,
|
||||||
|
codes0
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp2.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
4,
|
||||||
|
16,
|
||||||
|
codes1
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp3.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
4,
|
||||||
|
16,
|
||||||
|
codes2
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp4.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
4,
|
||||||
|
16,
|
||||||
|
codes3
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp5.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
4,
|
||||||
|
16,
|
||||||
|
codes4
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp6.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
4,
|
||||||
|
16,
|
||||||
|
codes5
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp7.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
4,
|
||||||
|
16,
|
||||||
|
codes6
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp8.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
8,
|
||||||
|
codes7
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp9.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
8,
|
||||||
|
codes8
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lsp10.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
4,
|
||||||
|
codes9
|
||||||
|
},
|
||||||
|
{ 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
@@ -0,0 +1,433 @@
|
|||||||
|
/* THIS IS A GENERATED FILE. Edit generate_codebook.c and its input */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This intermediary file and the files that used to create it are under
|
||||||
|
* The LGPL. See the file COPYING.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp1.txt */
|
||||||
|
static const float codes0[] = {
|
||||||
|
25,
|
||||||
|
50,
|
||||||
|
75,
|
||||||
|
100,
|
||||||
|
125,
|
||||||
|
150,
|
||||||
|
175,
|
||||||
|
200,
|
||||||
|
225,
|
||||||
|
250,
|
||||||
|
275,
|
||||||
|
300,
|
||||||
|
325,
|
||||||
|
350,
|
||||||
|
375,
|
||||||
|
400,
|
||||||
|
425,
|
||||||
|
450,
|
||||||
|
475,
|
||||||
|
500,
|
||||||
|
525,
|
||||||
|
550,
|
||||||
|
575,
|
||||||
|
600,
|
||||||
|
625,
|
||||||
|
650,
|
||||||
|
675,
|
||||||
|
700,
|
||||||
|
725,
|
||||||
|
750,
|
||||||
|
775,
|
||||||
|
800
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp2.txt */
|
||||||
|
static const float codes1[] = {
|
||||||
|
25,
|
||||||
|
50,
|
||||||
|
75,
|
||||||
|
100,
|
||||||
|
125,
|
||||||
|
150,
|
||||||
|
175,
|
||||||
|
200,
|
||||||
|
225,
|
||||||
|
250,
|
||||||
|
275,
|
||||||
|
300,
|
||||||
|
325,
|
||||||
|
350,
|
||||||
|
375,
|
||||||
|
400,
|
||||||
|
425,
|
||||||
|
450,
|
||||||
|
475,
|
||||||
|
500,
|
||||||
|
525,
|
||||||
|
550,
|
||||||
|
575,
|
||||||
|
600,
|
||||||
|
625,
|
||||||
|
650,
|
||||||
|
675,
|
||||||
|
700,
|
||||||
|
725,
|
||||||
|
750,
|
||||||
|
775,
|
||||||
|
800
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp3.txt */
|
||||||
|
static const float codes2[] = {
|
||||||
|
25,
|
||||||
|
50,
|
||||||
|
75,
|
||||||
|
100,
|
||||||
|
125,
|
||||||
|
150,
|
||||||
|
175,
|
||||||
|
200,
|
||||||
|
225,
|
||||||
|
250,
|
||||||
|
275,
|
||||||
|
300,
|
||||||
|
325,
|
||||||
|
350,
|
||||||
|
375,
|
||||||
|
400,
|
||||||
|
425,
|
||||||
|
450,
|
||||||
|
475,
|
||||||
|
500,
|
||||||
|
525,
|
||||||
|
550,
|
||||||
|
575,
|
||||||
|
600,
|
||||||
|
625,
|
||||||
|
650,
|
||||||
|
675,
|
||||||
|
700,
|
||||||
|
725,
|
||||||
|
750,
|
||||||
|
775,
|
||||||
|
800
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp4.txt */
|
||||||
|
static const float codes3[] = {
|
||||||
|
25,
|
||||||
|
50,
|
||||||
|
75,
|
||||||
|
100,
|
||||||
|
125,
|
||||||
|
150,
|
||||||
|
175,
|
||||||
|
200,
|
||||||
|
250,
|
||||||
|
300,
|
||||||
|
350,
|
||||||
|
400,
|
||||||
|
450,
|
||||||
|
500,
|
||||||
|
550,
|
||||||
|
600,
|
||||||
|
650,
|
||||||
|
700,
|
||||||
|
750,
|
||||||
|
800,
|
||||||
|
850,
|
||||||
|
900,
|
||||||
|
950,
|
||||||
|
1000,
|
||||||
|
1050,
|
||||||
|
1100,
|
||||||
|
1150,
|
||||||
|
1200,
|
||||||
|
1250,
|
||||||
|
1300,
|
||||||
|
1350,
|
||||||
|
1400
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp5.txt */
|
||||||
|
static const float codes4[] = {
|
||||||
|
25,
|
||||||
|
50,
|
||||||
|
75,
|
||||||
|
100,
|
||||||
|
125,
|
||||||
|
150,
|
||||||
|
175,
|
||||||
|
200,
|
||||||
|
250,
|
||||||
|
300,
|
||||||
|
350,
|
||||||
|
400,
|
||||||
|
450,
|
||||||
|
500,
|
||||||
|
550,
|
||||||
|
600,
|
||||||
|
650,
|
||||||
|
700,
|
||||||
|
750,
|
||||||
|
800,
|
||||||
|
850,
|
||||||
|
900,
|
||||||
|
950,
|
||||||
|
1000,
|
||||||
|
1050,
|
||||||
|
1100,
|
||||||
|
1150,
|
||||||
|
1200,
|
||||||
|
1250,
|
||||||
|
1300,
|
||||||
|
1350,
|
||||||
|
1400
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp6.txt */
|
||||||
|
static const float codes5[] = {
|
||||||
|
25,
|
||||||
|
50,
|
||||||
|
75,
|
||||||
|
100,
|
||||||
|
125,
|
||||||
|
150,
|
||||||
|
175,
|
||||||
|
200,
|
||||||
|
250,
|
||||||
|
300,
|
||||||
|
350,
|
||||||
|
400,
|
||||||
|
450,
|
||||||
|
500,
|
||||||
|
550,
|
||||||
|
600,
|
||||||
|
650,
|
||||||
|
700,
|
||||||
|
750,
|
||||||
|
800,
|
||||||
|
850,
|
||||||
|
900,
|
||||||
|
950,
|
||||||
|
1000,
|
||||||
|
1050,
|
||||||
|
1100,
|
||||||
|
1150,
|
||||||
|
1200,
|
||||||
|
1250,
|
||||||
|
1300,
|
||||||
|
1350,
|
||||||
|
1400
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp7.txt */
|
||||||
|
static const float codes6[] = {
|
||||||
|
25,
|
||||||
|
50,
|
||||||
|
75,
|
||||||
|
100,
|
||||||
|
125,
|
||||||
|
150,
|
||||||
|
175,
|
||||||
|
200,
|
||||||
|
225,
|
||||||
|
250,
|
||||||
|
275,
|
||||||
|
300,
|
||||||
|
325,
|
||||||
|
350,
|
||||||
|
375,
|
||||||
|
400,
|
||||||
|
425,
|
||||||
|
450,
|
||||||
|
475,
|
||||||
|
500,
|
||||||
|
525,
|
||||||
|
550,
|
||||||
|
575,
|
||||||
|
600,
|
||||||
|
625,
|
||||||
|
650,
|
||||||
|
675,
|
||||||
|
700,
|
||||||
|
725,
|
||||||
|
750,
|
||||||
|
775,
|
||||||
|
800
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp8.txt */
|
||||||
|
static const float codes7[] = {
|
||||||
|
25,
|
||||||
|
50,
|
||||||
|
75,
|
||||||
|
100,
|
||||||
|
125,
|
||||||
|
150,
|
||||||
|
175,
|
||||||
|
200,
|
||||||
|
225,
|
||||||
|
250,
|
||||||
|
275,
|
||||||
|
300,
|
||||||
|
325,
|
||||||
|
350,
|
||||||
|
375,
|
||||||
|
400,
|
||||||
|
425,
|
||||||
|
450,
|
||||||
|
475,
|
||||||
|
500,
|
||||||
|
525,
|
||||||
|
550,
|
||||||
|
575,
|
||||||
|
600,
|
||||||
|
625,
|
||||||
|
650,
|
||||||
|
675,
|
||||||
|
700,
|
||||||
|
725,
|
||||||
|
750,
|
||||||
|
775,
|
||||||
|
800
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp9.txt */
|
||||||
|
static const float codes8[] = {
|
||||||
|
25,
|
||||||
|
50,
|
||||||
|
75,
|
||||||
|
100,
|
||||||
|
125,
|
||||||
|
150,
|
||||||
|
175,
|
||||||
|
200,
|
||||||
|
225,
|
||||||
|
250,
|
||||||
|
275,
|
||||||
|
300,
|
||||||
|
325,
|
||||||
|
350,
|
||||||
|
375,
|
||||||
|
400,
|
||||||
|
425,
|
||||||
|
450,
|
||||||
|
475,
|
||||||
|
500,
|
||||||
|
525,
|
||||||
|
550,
|
||||||
|
575,
|
||||||
|
600,
|
||||||
|
625,
|
||||||
|
650,
|
||||||
|
675,
|
||||||
|
700,
|
||||||
|
725,
|
||||||
|
750,
|
||||||
|
775,
|
||||||
|
800
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp10.txt */
|
||||||
|
static const float codes9[] = {
|
||||||
|
25,
|
||||||
|
50,
|
||||||
|
75,
|
||||||
|
100,
|
||||||
|
125,
|
||||||
|
150,
|
||||||
|
175,
|
||||||
|
200,
|
||||||
|
225,
|
||||||
|
250,
|
||||||
|
275,
|
||||||
|
300,
|
||||||
|
325,
|
||||||
|
350,
|
||||||
|
375,
|
||||||
|
400,
|
||||||
|
425,
|
||||||
|
450,
|
||||||
|
475,
|
||||||
|
500,
|
||||||
|
525,
|
||||||
|
550,
|
||||||
|
575,
|
||||||
|
600,
|
||||||
|
625,
|
||||||
|
650,
|
||||||
|
675,
|
||||||
|
700,
|
||||||
|
725,
|
||||||
|
750,
|
||||||
|
775,
|
||||||
|
800
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct lsp_codebook lsp_cbd[] = {
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp1.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
32,
|
||||||
|
codes0
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp2.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
32,
|
||||||
|
codes1
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp3.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
32,
|
||||||
|
codes2
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp4.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
32,
|
||||||
|
codes3
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp5.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
32,
|
||||||
|
codes4
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp6.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
32,
|
||||||
|
codes5
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp7.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
32,
|
||||||
|
codes6
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp8.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
32,
|
||||||
|
codes7
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp9.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
32,
|
||||||
|
codes8
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/dlsp10.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
32,
|
||||||
|
codes9
|
||||||
|
},
|
||||||
|
{ 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
@@ -0,0 +1,279 @@
|
|||||||
|
/* THIS IS A GENERATED FILE. Edit generate_codebook.c and its input */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This intermediary file and the files that used to create it are under
|
||||||
|
* The LGPL. See the file COPYING.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/gecb.txt */
|
||||||
|
static const float codes0[] = {
|
||||||
|
2.71, 12.0184,
|
||||||
|
0.04675, -2.73881,
|
||||||
|
0.120993, 8.38895,
|
||||||
|
-1.58028, -0.892307,
|
||||||
|
1.19307, -1.91561,
|
||||||
|
0.187101, -3.27679,
|
||||||
|
0.332251, -7.66455,
|
||||||
|
-1.47944, 31.2461,
|
||||||
|
1.52761, 27.7095,
|
||||||
|
-0.524379, 5.25012,
|
||||||
|
0.55333, 7.4388,
|
||||||
|
-0.843451, -1.95299,
|
||||||
|
2.26389, 8.61029,
|
||||||
|
0.143143, 2.36549,
|
||||||
|
0.616506, 1.28427,
|
||||||
|
-1.71133, 22.0967,
|
||||||
|
1.00813, 17.3965,
|
||||||
|
-0.106718, 1.41891,
|
||||||
|
-0.136246, 14.2736,
|
||||||
|
-1.70909, -20.5319,
|
||||||
|
1.65787, -3.39107,
|
||||||
|
0.138049, -4.95785,
|
||||||
|
0.536729, -1.94375,
|
||||||
|
0.196307, 36.8519,
|
||||||
|
1.27248, 22.5565,
|
||||||
|
-0.670219, -1.90604,
|
||||||
|
0.382092, 6.40113,
|
||||||
|
-0.756911, -4.90102,
|
||||||
|
1.82931, 4.6138,
|
||||||
|
0.318794, 0.73683,
|
||||||
|
0.612815, -2.07505,
|
||||||
|
-0.410151, 24.7871,
|
||||||
|
1.77602, 13.1909,
|
||||||
|
0.106457, -0.104492,
|
||||||
|
0.192206, 10.1838,
|
||||||
|
-1.82442, -7.71565,
|
||||||
|
0.931346, 4.34835,
|
||||||
|
0.308813, -4.086,
|
||||||
|
0.397143, -11.8089,
|
||||||
|
-0.048715, 41.2273,
|
||||||
|
0.877342, 35.8503,
|
||||||
|
-0.759794, 0.476634,
|
||||||
|
0.978593, 7.67467,
|
||||||
|
-1.19506, 3.03883,
|
||||||
|
2.63989, -3.41106,
|
||||||
|
0.191127, 3.60351,
|
||||||
|
0.402932, 1.0843,
|
||||||
|
-2.15202, 18.1076,
|
||||||
|
1.5468, 8.32271,
|
||||||
|
-0.143089, -4.07592,
|
||||||
|
-0.150142, 5.86674,
|
||||||
|
-1.40844, -3.2507,
|
||||||
|
1.56615, -10.4132,
|
||||||
|
0.178171, -10.2267,
|
||||||
|
0.362164, -0.028556,
|
||||||
|
-0.070125, 24.3907,
|
||||||
|
0.594752, 17.4828,
|
||||||
|
-0.28698, -6.90407,
|
||||||
|
0.464818, 10.2055,
|
||||||
|
-1.00684, -14.3572,
|
||||||
|
2.32957, -3.69161,
|
||||||
|
0.335745, 2.40714,
|
||||||
|
1.01966, -3.15565,
|
||||||
|
-1.25945, 7.9919,
|
||||||
|
2.38369, 19.6806,
|
||||||
|
-0.094947, -2.41374,
|
||||||
|
0.20933, 6.66477,
|
||||||
|
-2.22103, 1.37986,
|
||||||
|
1.29239, 2.04633,
|
||||||
|
0.243626, -0.890741,
|
||||||
|
0.428773, -7.19366,
|
||||||
|
-1.11374, 41.3414,
|
||||||
|
2.6098, 31.1405,
|
||||||
|
-0.446468, 2.53419,
|
||||||
|
0.490104, 4.62757,
|
||||||
|
-1.11723, -3.24174,
|
||||||
|
1.79156, 8.41493,
|
||||||
|
0.156012, 0.183336,
|
||||||
|
0.532447, 3.15455,
|
||||||
|
-0.764484, 18.514,
|
||||||
|
0.952395, 11.7713,
|
||||||
|
-0.332567, 0.346987,
|
||||||
|
0.202165, 14.7168,
|
||||||
|
-2.12924, -15.559,
|
||||||
|
1.35358, -1.92679,
|
||||||
|
-0.010963, -16.3364,
|
||||||
|
0.399053, -2.79057,
|
||||||
|
0.750657, 31.1483,
|
||||||
|
0.655743, 24.4819,
|
||||||
|
-0.45321, -0.735879,
|
||||||
|
0.2869, 6.5467,
|
||||||
|
-0.715673, -12.3578,
|
||||||
|
1.54849, 3.87217,
|
||||||
|
0.271874, 0.802339,
|
||||||
|
0.502073, -4.85485,
|
||||||
|
-0.497037, 17.7619,
|
||||||
|
1.19116, 13.9544,
|
||||||
|
0.01563, 1.33157,
|
||||||
|
0.341867, 8.93537,
|
||||||
|
-2.31601, -5.39506,
|
||||||
|
0.75861, 1.9645,
|
||||||
|
0.24132, -3.23769,
|
||||||
|
0.267151, -11.2344,
|
||||||
|
-0.273126, 32.6248,
|
||||||
|
1.75352, 40.432,
|
||||||
|
-0.784011, 3.04576,
|
||||||
|
0.705987, 5.66118,
|
||||||
|
-1.3864, 1.35356,
|
||||||
|
2.37646, 1.67485,
|
||||||
|
0.242973, 4.73218,
|
||||||
|
0.491227, 0.354061,
|
||||||
|
-1.60676, 8.65895,
|
||||||
|
1.16711, 5.9871,
|
||||||
|
-0.137601, -12.0417,
|
||||||
|
-0.251375, 10.3972,
|
||||||
|
-1.43151, -8.90411,
|
||||||
|
0.98828, -13.209,
|
||||||
|
0.261484, -6.35497,
|
||||||
|
0.395932, -0.702529,
|
||||||
|
0.283704, 26.8996,
|
||||||
|
0.420959, 15.4418,
|
||||||
|
-0.355804, -13.7278,
|
||||||
|
0.527372, 12.3985,
|
||||||
|
-1.16956, -15.9985,
|
||||||
|
1.90669, -5.81605,
|
||||||
|
0.354492, 3.85157,
|
||||||
|
0.82576, -4.16264,
|
||||||
|
-0.49019, 13.0572,
|
||||||
|
2.25577, 13.5264,
|
||||||
|
-0.004956, -3.23713,
|
||||||
|
0.026709, 7.86645,
|
||||||
|
-1.81037, -0.451183,
|
||||||
|
1.08383, -0.18362,
|
||||||
|
0.135836, -2.26658,
|
||||||
|
0.375812, -5.51225,
|
||||||
|
-1.96644, 38.6829,
|
||||||
|
1.97799, 24.5655,
|
||||||
|
-0.704656, 6.35881,
|
||||||
|
0.480786, 7.05175,
|
||||||
|
-0.976417, -2.42273,
|
||||||
|
2.50215, 6.75935,
|
||||||
|
0.083588, 3.2588,
|
||||||
|
0.543629, 0.910013,
|
||||||
|
-1.23196, 23.0915,
|
||||||
|
0.785492, 14.807,
|
||||||
|
-0.213554, 1.688,
|
||||||
|
0.004748, 18.1718,
|
||||||
|
-1.54719, -16.1168,
|
||||||
|
1.50104, -3.28114,
|
||||||
|
0.080133, -4.63472,
|
||||||
|
0.476592, -2.18093,
|
||||||
|
0.44247, 40.304,
|
||||||
|
1.07277, 27.592,
|
||||||
|
-0.594738, -4.16681,
|
||||||
|
0.42248, 7.61609,
|
||||||
|
-0.927521, -7.27441,
|
||||||
|
1.99162, 1.29636,
|
||||||
|
0.291307, 2.39878,
|
||||||
|
0.721081, -1.95062,
|
||||||
|
-0.804256, 24.9295,
|
||||||
|
1.64839, 19.1197,
|
||||||
|
0.060852, -0.590639,
|
||||||
|
0.266085, 9.10325,
|
||||||
|
-1.9574, -2.88461,
|
||||||
|
1.11693, 2.6724,
|
||||||
|
0.35458, -2.74854,
|
||||||
|
0.330733, -14.1561,
|
||||||
|
-0.527851, 39.5756,
|
||||||
|
0.991152, 43.195,
|
||||||
|
-0.589619, 1.26919,
|
||||||
|
0.787401, 8.73071,
|
||||||
|
-1.0138, 1.02507,
|
||||||
|
2.8254, 1.89538,
|
||||||
|
0.24089, 2.74557,
|
||||||
|
0.427195, 2.54446,
|
||||||
|
-1.95311, 12.244,
|
||||||
|
1.44862, 12.0607,
|
||||||
|
-0.210492, -3.37906,
|
||||||
|
-0.056713, 10.204,
|
||||||
|
-1.65237, -5.10274,
|
||||||
|
1.29475, -12.2708,
|
||||||
|
0.111608, -8.67592,
|
||||||
|
0.326634, -1.16763,
|
||||||
|
0.021781, 31.1258,
|
||||||
|
0.455335, 21.4684,
|
||||||
|
-0.37544, -3.37121,
|
||||||
|
0.39362, 11.302,
|
||||||
|
-0.851456, -19.4149,
|
||||||
|
2.10703, -2.22886,
|
||||||
|
0.373233, 1.92406,
|
||||||
|
0.884438, -1.72058,
|
||||||
|
-0.975127, 9.84013,
|
||||||
|
2.0033, 17.3954,
|
||||||
|
-0.036915, -1.11137,
|
||||||
|
0.148456, 5.39997,
|
||||||
|
-1.91441, 4.77382,
|
||||||
|
1.44791, 0.537122,
|
||||||
|
0.194979, -1.03818,
|
||||||
|
0.495771, -9.95502,
|
||||||
|
-1.05899, 32.9471,
|
||||||
|
2.01122, 32.4544,
|
||||||
|
-0.30965, 4.71911,
|
||||||
|
0.436082, 4.63552,
|
||||||
|
-1.23711, -1.25428,
|
||||||
|
2.02274, 9.42834,
|
||||||
|
0.190342, 1.46077,
|
||||||
|
0.479017, 2.48479,
|
||||||
|
-1.07848, 16.2217,
|
||||||
|
1.20764, 9.65421,
|
||||||
|
-0.258087, -1.67236,
|
||||||
|
0.071852, 13.416,
|
||||||
|
-1.87723, -16.072,
|
||||||
|
1.28957, -4.87118,
|
||||||
|
0.067713, -13.4427,
|
||||||
|
0.435551, -4.1655,
|
||||||
|
0.46614, 30.5895,
|
||||||
|
0.904895, 21.598,
|
||||||
|
-0.518369, -2.53205,
|
||||||
|
0.337363, 5.63726,
|
||||||
|
-0.554975, -17.4005,
|
||||||
|
1.69188, 1.14574,
|
||||||
|
0.227934, 0.889297,
|
||||||
|
0.587303, -5.72973,
|
||||||
|
-0.262133, 18.6666,
|
||||||
|
1.39505, 17.0029,
|
||||||
|
-0.01909, 4.30838,
|
||||||
|
0.304235, 12.6699,
|
||||||
|
-2.07406, -6.46084,
|
||||||
|
0.920546, 1.21296,
|
||||||
|
0.284927, -1.78547,
|
||||||
|
0.209724, -16.024,
|
||||||
|
-0.636067, 31.5768,
|
||||||
|
1.34989, 34.6775,
|
||||||
|
-0.971625, 5.30086,
|
||||||
|
0.590249, 4.44971,
|
||||||
|
-1.56787, 3.60239,
|
||||||
|
2.1455, 4.51666,
|
||||||
|
0.296022, 4.12017,
|
||||||
|
0.445299, 0.868772,
|
||||||
|
-1.44193, 14.1284,
|
||||||
|
1.35575, 6.0074,
|
||||||
|
-0.012814, -7.49657,
|
||||||
|
-0.43, 8.50012,
|
||||||
|
-1.20469, -7.11326,
|
||||||
|
1.10102, -6.83682,
|
||||||
|
0.196463, -6.234,
|
||||||
|
0.436747, -1.12979,
|
||||||
|
0.141052, 22.8549,
|
||||||
|
0.290821, 18.8114,
|
||||||
|
-0.529536, -7.73251,
|
||||||
|
0.63428, 10.7898,
|
||||||
|
-1.33472, -20.3258,
|
||||||
|
1.81564, -1.90332,
|
||||||
|
0.394778, 3.79758,
|
||||||
|
0.732682, -8.18382,
|
||||||
|
-0.741244, 11.7683
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct lsp_codebook ge_cb[] = {
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/gecb.txt */
|
||||||
|
{
|
||||||
|
2,
|
||||||
|
8,
|
||||||
|
256,
|
||||||
|
codes0
|
||||||
|
},
|
||||||
|
{ 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,235 @@
|
|||||||
|
/* THIS IS A GENERATED FILE. Edit generate_codebook.c and its input */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This intermediary file and the files that used to create it are under
|
||||||
|
* The LGPL. See the file COPYING.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lspmelvq1.txt */
|
||||||
|
static const float codes0[] = {
|
||||||
|
640.185, 893.139, 1393.85, 1494.06, 1656.26, 1700.82,
|
||||||
|
558.516, 716.906, 1057.36, 1182.62, 1503.8, 1610.03,
|
||||||
|
615.108, 769.622, 1120.16, 1222.84, 1366.46, 1465.05,
|
||||||
|
663.458, 736.833, 964.764, 1043.54, 1623.17, 1681.29,
|
||||||
|
487.957, 577.723, 1017.43, 1177.04, 1552.1, 1615.69,
|
||||||
|
536.099, 733.407, 1292.28, 1406.09, 1577.7, 1637.49,
|
||||||
|
473.015, 542.559, 877.397, 1285.82, 1591.04, 1647.44,
|
||||||
|
525.343, 652.014, 1206.83, 1493.96, 1647.97, 1698.3,
|
||||||
|
510.887, 572.868, 945.226, 1445.68, 1678.17, 1705.53,
|
||||||
|
534.915, 721.265, 1275.92, 1415.76, 1648.5, 1695.73,
|
||||||
|
865.189, 1047, 1267.14, 1389.32, 1646.57, 1696.97,
|
||||||
|
608.033, 869.887, 1300.95, 1432.87, 1639.74, 1689.41,
|
||||||
|
554.972, 649.352, 866.845, 979.873, 1645.31, 1695.39,
|
||||||
|
696.079, 813.97, 1102.49, 1219.79, 1536.49, 1621.94,
|
||||||
|
553.879, 691.097, 1200.84, 1339.34, 1629.08, 1683.5,
|
||||||
|
778.561, 997.776, 1258.63, 1390.34, 1601.99, 1657.86,
|
||||||
|
713.107, 778.893, 992.875, 1051.95, 1497.45, 1650.66,
|
||||||
|
490.27, 598.18, 1116.02, 1244.13, 1622.26, 1672.21,
|
||||||
|
448.556, 512.085, 1271.7, 1448.18, 1579.37, 1642.48,
|
||||||
|
465.688, 535.312, 1099.19, 1535.79, 1684.29, 1710.9,
|
||||||
|
812.222, 1087.53, 1470.44, 1559.73, 1692.18, 1726.38,
|
||||||
|
428.174, 489.426, 1160.33, 1409.3, 1597.5, 1651.3,
|
||||||
|
712.81, 957.56, 1433.02, 1516.37, 1675.39, 1710.06,
|
||||||
|
717.255, 934.073, 1305.2, 1436.72, 1647.2, 1693.09,
|
||||||
|
492.888, 580.393, 1339.52, 1461.07, 1592, 1653.42,
|
||||||
|
550.467, 675.888, 990.888, 1177.44, 1615.64, 1658,
|
||||||
|
714.528, 801.792, 1072.94, 1146.08, 1637.06, 1706.58,
|
||||||
|
513.819, 590.989, 798.691, 895.755, 1557.76, 1624.56,
|
||||||
|
436.653, 518.413, 1281.99, 1547.08, 1685.12, 1717.76,
|
||||||
|
681.854, 758.354, 1046.65, 1120.92, 1412.25, 1603.42,
|
||||||
|
873.962, 1118.49, 1376.61, 1465.07, 1665.38, 1707.18,
|
||||||
|
553.529, 634.092, 1144.77, 1284.8, 1542.87, 1620.63,
|
||||||
|
448.532, 519.097, 1054.57, 1319.66, 1591.26, 1649.85,
|
||||||
|
742.267, 885.293, 1152.83, 1318.51, 1569.36, 1631.45,
|
||||||
|
529.03, 654.522, 1355.76, 1511.75, 1662.39, 1706.4,
|
||||||
|
463.794, 597.77, 1176.05, 1366.13, 1629.37, 1678.01,
|
||||||
|
626.936, 706.66, 1058.04, 1323.62, 1473.28, 1599.68,
|
||||||
|
477.322, 615.5, 1488.89, 1550.5, 1683.1, 1712.34,
|
||||||
|
547.442, 815.442, 1313.38, 1486.96, 1671.97, 1717.4,
|
||||||
|
610.671, 819.955, 1219.11, 1363.66, 1592.05, 1654.31,
|
||||||
|
547.414, 746.54, 1438.43, 1517.72, 1659.64, 1695.57,
|
||||||
|
604.823, 821.146, 1137.94, 1358.29, 1598.94, 1655.64,
|
||||||
|
525.935, 616.739, 1060.13, 1427.33, 1593.35, 1657.48,
|
||||||
|
622.5, 762.143, 1318.65, 1410.96, 1618.12, 1680.06,
|
||||||
|
436.917, 516.583, 1390.29, 1475.86, 1594.71, 1633.74,
|
||||||
|
792.487, 1031.24, 1362.62, 1472.68, 1649.26, 1697.35,
|
||||||
|
457.707, 526.207, 865.966, 1120.47, 1564.83, 1625.28,
|
||||||
|
526.39, 624.21, 1269.65, 1374.23, 1558.07, 1620.96,
|
||||||
|
483.768, 573.505, 1440.66, 1512.43, 1622.37, 1671.31,
|
||||||
|
953.061, 1194.03, 1416.67, 1515.82, 1678.82, 1718.21,
|
||||||
|
499.947, 627.358, 1299.94, 1394.23, 1643.17, 1685.33,
|
||||||
|
648.723, 838.181, 1225.5, 1383.45, 1637.46, 1691.67,
|
||||||
|
672.588, 1022.6, 1346.21, 1443.75, 1651.15, 1695.43,
|
||||||
|
581.833, 674.944, 955.167, 1020.5, 1370.5, 1503.11,
|
||||||
|
536.143, 652.531, 1243.84, 1315.27, 1425.1, 1505.73,
|
||||||
|
560.558, 786.65, 1224.66, 1373.98, 1630.06, 1682.68,
|
||||||
|
591.926, 783.722, 982, 1140.81, 1581.61, 1625.28,
|
||||||
|
548.537, 644.524, 940.451, 1048.74, 1557.89, 1609.48,
|
||||||
|
516.916, 723.253, 1135.95, 1309.19, 1600.08, 1669.48,
|
||||||
|
426.521, 506.077, 1457.73, 1535.02, 1641.35, 1678.45,
|
||||||
|
645.189, 776.595, 1020.78, 1240.07, 1597, 1648.7,
|
||||||
|
637.105, 941.474, 1242.21, 1372.49, 1646.7, 1694.8,
|
||||||
|
691.228, 788.141, 1202.12, 1294.89, 1626.97, 1681.77,
|
||||||
|
699.08, 886.655, 1300.9, 1399.28, 1579.94, 1646.79
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lspmelvq2.txt */
|
||||||
|
static const float codes1[] = {
|
||||||
|
4.44342, 51.1708, 7.45726, -27.4373, -18.5056, -18.1989,
|
||||||
|
51.58, 63.3166, 57.7796, -44.1591, -18.4834, -6.93392,
|
||||||
|
-20.2795, -21.7454, 4.66947, 52.1569, 30.4367, 36.8582,
|
||||||
|
-29.1104, -5.63933, -3.45383, -63.0261, -20.4423, -19.0485,
|
||||||
|
2.91622, 40.8374, 16.579, -51.8461, 38.5045, 18.1728,
|
||||||
|
-20.6977, -11.4022, -36.6173, -16.6116, -56.8965, -24.301,
|
||||||
|
-20.2385, 26.6332, 33.1191, 27.6284, -36.7493, -25.6041,
|
||||||
|
54.9871, 0.71748, 23.0674, -22.1031, 11.6643, 10.9938,
|
||||||
|
-62.7215, 21.7547, 21.2907, -7.64891, -4.5533, -9.71777,
|
||||||
|
-9.56338, -3.85841, 25.0454, -9.45216, 6.05017, 5.35043,
|
||||||
|
47.3823, 56.6122, -27.0315, -24.67, 4.86343, -0.225495,
|
||||||
|
26.3997, 26.7857, -1.66167, 62.8366, -19.7653, -8.55169,
|
||||||
|
-8.77648, -9.04545, -7.88996, 28.2433, -35.0963, -21.9709,
|
||||||
|
14.8423, 25.4563, -56.1262, -50.2934, -22.9393, -15.8113,
|
||||||
|
4.94186, 27.7798, 8.34579, 10.8553, -3.12587, -3.97807,
|
||||||
|
12.6426, -52.2317, 37.2487, -57.2067, -14.5125, -5.54035,
|
||||||
|
13.485, 15.3246, -23.9644, -21.3135, 19.5779, 14.1597,
|
||||||
|
-55.3543, -45.2077, 10.5185, 43.0461, -24.9859, -19.3484,
|
||||||
|
27.7226, 32.1882, 20.0321, 24.3328, -72.8194, -51.1823,
|
||||||
|
-31.3818, -5.25745, -43.7806, 14.1312, 17.6392, 9.81024,
|
||||||
|
-48.26, -26.2973, -44.1428, -31.9001, 22.5085, -0.467938,
|
||||||
|
7.37202, -7.79071, -12.5732, 27.1074, 9.34052, 14.4477,
|
||||||
|
14.5295, 8.82597, 57.0009, -16.3234, -32.4142, -21.0224,
|
||||||
|
32.4616, 48.6062, 38.5452, 9.77182, 1.82856, 11.5063,
|
||||||
|
-43.8275, -22.6263, -29.8278, 13.6115, 9.66849, -63.5218,
|
||||||
|
-11.9967, 2.74308, -73.6375, -20.9809, -4.11839, 7.71405,
|
||||||
|
24.0162, -2.29513, -6.80983, -26.4043, -21.8529, -16.3381,
|
||||||
|
-16.1484, 35.9086, -3.0837, 3.83958, 42.3003, 17.5003,
|
||||||
|
54.1225, -48.7513, -14.8712, -38.1256, 15.2903, 7.33079,
|
||||||
|
53.0929, 13.9221, 10.6536, 24.345, -16.5952, -16.0365,
|
||||||
|
33.1415, 38.5714, -26.0251, 22.021, 15.6866, 13.2593,
|
||||||
|
15.7194, -49.4061, 31.4552, 10.1896, 0.219911, 1.62902,
|
||||||
|
4.10868, 14.2755, 58.475, -1.16668, 52.6265, 43.4938,
|
||||||
|
358.653, -112.587, 85.9867, 52.08, -52.88, -249.24,
|
||||||
|
-12.5792, -6.64039, -33.0106, 1.51449, 50.3259, 61.6091,
|
||||||
|
-6.81685, 14.3146, 14.1563, 53.6363, 83.6051, 38.174,
|
||||||
|
-18.0006, 41.3575, -46.3736, 8.47794, -10.4611, -11.3847,
|
||||||
|
28.7711, 31.4689, -39.5744, 1.43977, -37.7309, -30.5309,
|
||||||
|
-34.4692, -11.0778, 44.4681, -60.0045, -44.9729, -34.8364,
|
||||||
|
38.7401, 41.0529, -7.92946, 20.0279, 74.4246, 54.6498,
|
||||||
|
81.8008, 133.531, -5.47375, 34.4759, 75.7417, 52.6112,
|
||||||
|
-61.5067, -76.6328, -47.2471, -43.5928, -9.46878, 0.832598,
|
||||||
|
-11.544, -44.7728, -13.9257, -3.32122, 24.816, 21.9064,
|
||||||
|
2.83945, -45.0522, -36.8776, -14.7577, -11.9912, -8.75366,
|
||||||
|
-8.97657, -14.0499, 39.2628, 48.8038, -14.3789, -4.79625,
|
||||||
|
31.6292, 32.0168, 5.52278, -79.8411, -24.1789, -15.7597,
|
||||||
|
15.893, 10.4667, -43.9057, -20.4885, 80.7594, 6.8023,
|
||||||
|
22.3285, -69.4942, -5.16156, 48.8868, 4.01995, -3.04376,
|
||||||
|
31.4062, -20.0952, -55.1259, 0.505988, 20.86, 15.0816,
|
||||||
|
-12.9696, 37.2548, 18.1009, 51.0767, 18.2053, 19.8474,
|
||||||
|
-45.4855, -45.3454, -4.22795, -15.8693, -6.07272, -1.99631,
|
||||||
|
-9.25462, 45.0241, 70.2879, -44.4484, 2.63165, 4.15336,
|
||||||
|
-51.1589, -27.7586, 19.7999, -9.87882, 63.4125, 48.3124,
|
||||||
|
-8.94084, -13.4815, -44.9602, 52.839, -17.2582, -1.59439,
|
||||||
|
23.18, -3.00374, 33.162, 31.5424, 29.111, 25.9327,
|
||||||
|
-28.4665, -10.6868, 88.7543, -3.88024, 17.5881, 13.7336,
|
||||||
|
-10.6578, 7.43021, -20.945, -17.6491, -11.2815, -10.8001,
|
||||||
|
-35.6182, -6.90301, 3.92829, 26.9695, 2.8894, 5.01685,
|
||||||
|
-3.78263, -19.2095, -10.5568, -67.7468, 20.3733, 29.552,
|
||||||
|
53.8109, -33.8374, -27.8223, -7.73289, -31.3462, -23.5678,
|
||||||
|
-38.8762, -17.7679, 11.457, 28.4607, 50.7006, -19.2488,
|
||||||
|
-44.6024, -60.2806, 56.35, 21.7545, 5.23677, 7.66608,
|
||||||
|
-3.80758, -39.1425, 28.8305, -3.09285, -42.7534, -25.1803,
|
||||||
|
45.2559, 28.8742, 60.0723, 64.461, 3.51203, -27.883
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lspmelvq3.txt */
|
||||||
|
static const float codes2[] = {
|
||||||
|
-9.63558, 27.5501, 15.4445, -4.34872, -1.8587, 1.27054,
|
||||||
|
-15.5343, 23.0515, -15.4436, -2.01887, -6.19433, -13.5085,
|
||||||
|
8.38867, -1.60998, -32.3903, 10.1765, 1.9467, 12.2454,
|
||||||
|
-3.06306, -9.55983, 14.367, -1.87159, 19.6192, -3.78366,
|
||||||
|
-18.495, -13.3811, -23.8928, -20.3745, -6.87856, -17.4887,
|
||||||
|
15.4925, 14.707, -0.0697855, 15.7541, 12.6051, -3.19768,
|
||||||
|
9.60466, -4.56494, 10.1616, 15.5594, 6.89224, -31.5602,
|
||||||
|
-11.5625, -23.0872, 34.9163, 12.3052, 7.67426, -1.26298,
|
||||||
|
2.5486, -3.90251, -19.1132, 7.6131, -31.0016, 12.4759,
|
||||||
|
2.74156, 12.4124, -39.5057, -0.325024, -22.9186, -28.5606,
|
||||||
|
6.30148, 15.4402, -2.6284, -20.1603, 5.22906, -12.3451,
|
||||||
|
-6.91862, 16.6335, -1.65064, 2.99602, -23.9479, -1.43947,
|
||||||
|
-14.3907, -31.417, 10.1113, 1.70013, -21.5733, 4.736,
|
||||||
|
-1.67171, 6.22751, -13.7187, 21.0936, -9.69243, -10.5756,
|
||||||
|
2.15266, 21.2198, -13.0171, -1.43135, 18.8831, 10.6664,
|
||||||
|
13.8913, 27.3565, 0.472838, -7.40477, -14.8705, 25.7448,
|
||||||
|
28.402, -2.05484, -9.32712, -17.3169, 15.643, 6.96908,
|
||||||
|
-15.863, -17.8482, -24.9238, 12.5574, 7.17566, 0.0161972,
|
||||||
|
5.99291, -41.0228, 1.95791, -6.78012, 9.20162, 4.6234,
|
||||||
|
-6.33629, -7.61679, 27.7318, -8.9214, -14.1931, 7.88247,
|
||||||
|
-12.2367, -21.245, -2.5927, 13.7776, -2.7864, -24.5072,
|
||||||
|
23.15, -9.93687, -2.92559, 3.88086, 11.2667, 11.1998,
|
||||||
|
9.67437, -9.4269, 6.2582, 36.5694, 2.88654, 1.82052,
|
||||||
|
15.385, -2.88243, 19.8377, -14.5111, 5.92264, -2.55757,
|
||||||
|
-20.9648, 3.76147, 18.5074, -13.5547, -7.84261, -19.98,
|
||||||
|
24.6032, 16.989, -19.1622, 1.35535, -0.0122027, 0.166227,
|
||||||
|
9.98886, -6.89666, -20.5111, -2.89196, 2.58467, -17.049,
|
||||||
|
-9.17761, -23.7209, 12.6088, -18.2654, 2.17718, -13.0865,
|
||||||
|
-9.73326, -12.2682, 6.80914, 20.3469, -10.2912, 4.85191,
|
||||||
|
-5.19406, 6.78014, 18.0099, 14.3782, -0.124328, -10.0141,
|
||||||
|
-4.69806, 6.71393, -19.1371, 8.19814, 23.3987, -10.3316,
|
||||||
|
1.02965, -4.63654, 21.9822, 11.5088, -30.9617, -20.6354,
|
||||||
|
-33.2824, 31.4666, -11.4837, 11.5144, -1.36834, 9.44599,
|
||||||
|
-37.5431, -3.16317, -2.09497, -2.62712, 40.4714, -33.0527,
|
||||||
|
-8.79595, -15.5174, -15.7916, 7.97003, 37.2542, 40.7063,
|
||||||
|
-14.7261, -12.6884, 2.42105, -10.2686, 25.9033, 14.8525,
|
||||||
|
22.9598, -16.6224, -3.64949, 4.44269, -22.3897, 13.6968,
|
||||||
|
-10.874, 4.18931, -24.2284, -3.63764, -15.1379, 40.9515,
|
||||||
|
28.2393, -8.63225, -12.544, 28.8282, -0.987894, -4.9824,
|
||||||
|
-25.0777, -0.481678, -3.37082, 5.55114, -9.89898, -8.07628,
|
||||||
|
23.3581, 3.12034, -8.63348, 0.63042, -18.2216, -22.1886,
|
||||||
|
44.9505, 19.8267, 23.7129, 8.58075, 7.80458, 1.78796,
|
||||||
|
-8.13112, -2.1262, -7.12776, -25.0529, -16.7287, 8.41402,
|
||||||
|
2.01965, 19.2579, 20.0963, 5.99199, 28.1098, 5.96128,
|
||||||
|
2.42493, -6.33216, -26.5858, -23.8607, 8.27049, 3.05805,
|
||||||
|
0.0153248, 0.446112, -4.92759, 19.0023, 22.7346, 15.5451,
|
||||||
|
-7.39591, 40.285, 10.8414, 25.7961, -8.81069, -13.5,
|
||||||
|
5.81306, 11.2384, 6.93765, -9.43067, 9.51418, 22.9709,
|
||||||
|
-9.17611, -16.4993, -1.56929, -2.9111, 4.17113, 10.9228,
|
||||||
|
10.0376, -27.4993, -8.25332, -1.715, -11.5063, -10.467,
|
||||||
|
23.6637, -13.8338, 14.7284, 8.00341, -2.71881, -8.80708,
|
||||||
|
27.101, 2.42801, 11.4599, -24.1577, -20.9901, 4.52358,
|
||||||
|
16.8065, 19.3315, 11.1219, 13.3391, -13.1522, 0.91428,
|
||||||
|
-25.2603, 6.04837, 12.1994, 21.9372, 14.8795, 6.93368,
|
||||||
|
-1.24639, -7.96856, 16.4064, -2.36409, -25.9093, 46.0938,
|
||||||
|
8.81687, 24.8004, 11.4475, -13.261, -19.8693, -28.4793,
|
||||||
|
15.3175, -12.5335, 24.1778, 10.5133, 22.2244, 9.93191,
|
||||||
|
-18.7982, 38.939, -20.0631, -35.4052, 7.5879, -0.599373,
|
||||||
|
-18.1388, 9.5843, 17.4375, -21.057, 8.1634, 6.31216,
|
||||||
|
-61.5486, -8.71159, 19.7502, -25.2365, 3.56558, -1.64973,
|
||||||
|
-26.9863, 0.291017, -12.5337, -10.505, 11.0614, 4.84072,
|
||||||
|
-0.630579, -3.87056, -0.707795, -13.1306, -19.6548, -16.2436,
|
||||||
|
4.87022, -5.90744, 3.46971, -40.0866, 16.8741, 10.3333,
|
||||||
|
-1.00985, 16.234, -0.475836, 28.3848, 1.75473, 28.2608
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct lsp_codebook lspmelvq_cb[] = {
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lspmelvq1.txt */
|
||||||
|
{
|
||||||
|
6,
|
||||||
|
6,
|
||||||
|
64,
|
||||||
|
codes0
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lspmelvq2.txt */
|
||||||
|
{
|
||||||
|
6,
|
||||||
|
6,
|
||||||
|
64,
|
||||||
|
codes1
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/lspmelvq3.txt */
|
||||||
|
{
|
||||||
|
6,
|
||||||
|
6,
|
||||||
|
64,
|
||||||
|
codes2
|
||||||
|
},
|
||||||
|
{ 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/* THIS IS A GENERATED FILE. Edit generate_codebook.c and its input */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This intermediary file and the files that used to create it are under
|
||||||
|
* The LGPL. See the file COPYING.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/mel1.txt */
|
||||||
|
static const float codes0[] = {
|
||||||
|
550,
|
||||||
|
600,
|
||||||
|
650,
|
||||||
|
700,
|
||||||
|
750,
|
||||||
|
800,
|
||||||
|
850,
|
||||||
|
900
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/mel2.txt */
|
||||||
|
static const float codes1[] = {
|
||||||
|
50,
|
||||||
|
100,
|
||||||
|
200,
|
||||||
|
300
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/mel3.txt */
|
||||||
|
static const float codes2[] = {
|
||||||
|
800,
|
||||||
|
850,
|
||||||
|
900,
|
||||||
|
950,
|
||||||
|
1000,
|
||||||
|
1050,
|
||||||
|
1100,
|
||||||
|
1150,
|
||||||
|
1200,
|
||||||
|
1250,
|
||||||
|
1300,
|
||||||
|
1350,
|
||||||
|
1400,
|
||||||
|
1450,
|
||||||
|
1500,
|
||||||
|
1650
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/mel4.txt */
|
||||||
|
static const float codes3[] = {
|
||||||
|
25,
|
||||||
|
50,
|
||||||
|
75,
|
||||||
|
100,
|
||||||
|
125,
|
||||||
|
150,
|
||||||
|
175,
|
||||||
|
250
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/mel5.txt */
|
||||||
|
static const float codes4[] = {
|
||||||
|
1350,
|
||||||
|
1400,
|
||||||
|
1450,
|
||||||
|
1500,
|
||||||
|
1550,
|
||||||
|
1600,
|
||||||
|
1650,
|
||||||
|
1700
|
||||||
|
};
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/mel6.txt */
|
||||||
|
static const float codes5[] = {
|
||||||
|
25,
|
||||||
|
50,
|
||||||
|
100,
|
||||||
|
150
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct lsp_codebook mel_cb[] = {
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/mel1.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
8,
|
||||||
|
codes0
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/mel2.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
4,
|
||||||
|
codes1
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/mel3.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
4,
|
||||||
|
16,
|
||||||
|
codes2
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/mel4.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
8,
|
||||||
|
codes3
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/mel5.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
8,
|
||||||
|
codes4
|
||||||
|
},
|
||||||
|
/* /Users/brandon/freetel-code/codec2/branches/0.6/src/codebook/mel6.txt */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
4,
|
||||||
|
codes5
|
||||||
|
},
|
||||||
|
{ 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,69 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: codec2.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 21 August 2010
|
||||||
|
|
||||||
|
Codec 2 fully quantised encoder and decoder functions. If you want use
|
||||||
|
Codec 2, these are the functions you need to call.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2010 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __CODEC2__
|
||||||
|
#define __CODEC2__
|
||||||
|
|
||||||
|
#define CODEC2_MODE_3200 0
|
||||||
|
#define CODEC2_MODE_2400 1
|
||||||
|
#define CODEC2_MODE_1600 2
|
||||||
|
#define CODEC2_MODE_1400 3
|
||||||
|
#define CODEC2_MODE_1300 4
|
||||||
|
#define CODEC2_MODE_1200 5
|
||||||
|
#define CODEC2_MODE_700 6
|
||||||
|
#define CODEC2_MODE_700B 7
|
||||||
|
#define CODEC2_MODE_700C 8
|
||||||
|
|
||||||
|
struct CODEC2;
|
||||||
|
|
||||||
|
struct CODEC2 * codec2_create(int mode);
|
||||||
|
void codec2_destroy(struct CODEC2 *codec2_state);
|
||||||
|
void codec2_encode(struct CODEC2 *codec2_state, unsigned char * bits, short speech_in[]);
|
||||||
|
void codec2_decode(struct CODEC2 *codec2_state, short speech_out[], const unsigned char *bits);
|
||||||
|
void codec2_decode_ber(struct CODEC2 *codec2_state, short speech_out[], const unsigned char *bits, float ber_est);
|
||||||
|
int codec2_samples_per_frame(struct CODEC2 *codec2_state);
|
||||||
|
int codec2_bits_per_frame(struct CODEC2 *codec2_state);
|
||||||
|
|
||||||
|
void codec2_set_lpc_post_filter(struct CODEC2 *codec2_state, int enable, int bass_boost, float beta, float gamma);
|
||||||
|
int codec2_get_spare_bit_index(struct CODEC2 *codec2_state);
|
||||||
|
int codec2_rebuild_spare_bit(struct CODEC2 *codec2_state, int unpacked_bits[]);
|
||||||
|
void codec2_set_natural_or_gray(struct CODEC2 *codec2_state, int gray);
|
||||||
|
void codec2_set_softdec(struct CODEC2 *c2, float *softdec);
|
||||||
|
float codec2_get_energy(struct CODEC2 *codec2_state, const unsigned char *bits);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: codec2_cohpsk.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: March 2015
|
||||||
|
|
||||||
|
Functions that implement a coherent PSK FDM modem.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2015 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CODEC2_COHPSK__
|
||||||
|
#define __CODEC2_COHPSK__
|
||||||
|
|
||||||
|
#define COHPSK_BITS_PER_FRAME 56 /* hard coded for now */
|
||||||
|
#define COHPSK_NC 7 /* hard coded for now */
|
||||||
|
#define COHPSK_NOM_SAMPLES_PER_FRAME 600
|
||||||
|
#define COHPSK_MAX_SAMPLES_PER_FRAME 625
|
||||||
|
#define COHPSK_RS 75
|
||||||
|
#define COHPSK_FS 7500 /* note this is a wierd
|
||||||
|
value to get an integer
|
||||||
|
oversampling rate */
|
||||||
|
|
||||||
|
#include "comp.h"
|
||||||
|
#include "modem_stats.h"
|
||||||
|
|
||||||
|
struct COHPSK;
|
||||||
|
|
||||||
|
extern const int test_bits_coh[];
|
||||||
|
|
||||||
|
struct COHPSK *cohpsk_create(void);
|
||||||
|
void cohpsk_destroy(struct COHPSK *coh);
|
||||||
|
void cohpsk_mod(struct COHPSK *cohpsk, COMP tx_fdm[], int tx_bits[], int nbits);
|
||||||
|
void cohpsk_clip(COMP tx_fdm[]);
|
||||||
|
void cohpsk_demod(struct COHPSK *cohpsk, float rx_bits[], int *sync, COMP rx_fdm[], int *nin_frame);
|
||||||
|
void cohpsk_get_demod_stats(struct COHPSK *cohpsk, struct MODEM_STATS *stats);
|
||||||
|
void cohpsk_set_verbose(struct COHPSK *coh, int verbose);
|
||||||
|
void cohpsk_get_test_bits(struct COHPSK *coh, int rx_bits[]);
|
||||||
|
void cohpsk_put_test_bits(struct COHPSK *coh, int *state, short error_pattern[],
|
||||||
|
int *bit_errors, char rx_bits[], int channel);
|
||||||
|
int cohpsk_error_pattern_size(void);
|
||||||
|
void cohpsk_set_frame(struct COHPSK *coh, int frame);
|
||||||
|
void fdmdv_freq_shift_coh(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff, float Fs,
|
||||||
|
COMP *foff_phase_rect, int nin);
|
||||||
|
|
||||||
|
/* used for accessing upper and lower bits before diversity combination */
|
||||||
|
|
||||||
|
float *cohpsk_get_rx_bits_lower(struct COHPSK *coh);
|
||||||
|
float *cohpsk_get_rx_bits_upper(struct COHPSK *coh);
|
||||||
|
void cohpsk_set_carrier_ampl(struct COHPSK *coh, int c, float ampl);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: codec2_fdmdv.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: April 14 2012
|
||||||
|
|
||||||
|
A 1400 bit/s (nominal) Frequency Division Multiplexed Digital Voice
|
||||||
|
(FDMDV) modem. Used for digital audio over HF SSB. See
|
||||||
|
README_fdmdv.txt for more information, and fdmdv_mod.c and
|
||||||
|
fdmdv_demod.c for example usage.
|
||||||
|
|
||||||
|
The name codec2_fdmdv.h is used to make it unique when "make
|
||||||
|
installed".
|
||||||
|
|
||||||
|
References:
|
||||||
|
|
||||||
|
[1] http://n1su.com/fdmdv/FDMDV_Docs_Rel_1_4b.pdf
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2012 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FDMDV__
|
||||||
|
#define __FDMDV__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* set up the calling convention for DLL function import/export for
|
||||||
|
WIN32 cross compiling */
|
||||||
|
|
||||||
|
#ifdef __CODEC2_WIN32__
|
||||||
|
#ifdef __CODEC2_BUILDING_DLL__
|
||||||
|
#define CODEC2_WIN32SUPPORT __declspec(dllexport) __stdcall
|
||||||
|
#else
|
||||||
|
#define CODEC2_WIN32SUPPORT __declspec(dllimport) __stdcall
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define CODEC2_WIN32SUPPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "comp.h"
|
||||||
|
#include "modem_stats.h"
|
||||||
|
|
||||||
|
#define FDMDV_NC 14 /* default number of data carriers */
|
||||||
|
#define FDMDV_NC_MAX 20 /* maximum number of data carriers */
|
||||||
|
#define FDMDV_BITS_PER_FRAME 28 /* 20ms frames, for nominal 1400 bit/s */
|
||||||
|
#define FDMDV_NOM_SAMPLES_PER_FRAME 160 /* modulator output samples/frame and nominal demod samples/frame */
|
||||||
|
/* at 8000 Hz sample rate */
|
||||||
|
#define FDMDV_MAX_SAMPLES_PER_FRAME 200 /* max demod samples/frame, use this to allocate storage */
|
||||||
|
#define FDMDV_SCALE 1000 /* suggested scaling for 16 bit shorts */
|
||||||
|
#define FDMDV_FCENTRE 1500 /* Centre frequency, Nc/2 carriers below this, Nc/2 carriers above (Hz) */
|
||||||
|
|
||||||
|
/* 8 to 48 kHz sample rate conversion */
|
||||||
|
|
||||||
|
#define FDMDV_OS 2 /* oversampling rate */
|
||||||
|
#define FDMDV_OS_TAPS_16K 48 /* number of OS filter taps at 16kHz */
|
||||||
|
#define FDMDV_OS_TAPS_8K (FDMDV_OS_TAPS_16K/FDMDV_OS) /* number of OS filter taps at 8kHz */
|
||||||
|
|
||||||
|
/* FDMDV states and stats structures */
|
||||||
|
|
||||||
|
struct FDMDV;
|
||||||
|
|
||||||
|
struct FDMDV * fdmdv_create(int Nc);
|
||||||
|
void fdmdv_destroy(struct FDMDV *fdmdv_state);
|
||||||
|
void fdmdv_use_old_qpsk_mapping(struct FDMDV *fdmdv_state);
|
||||||
|
int fdmdv_bits_per_frame(struct FDMDV *fdmdv_state);
|
||||||
|
float fdmdv_get_fsep(struct FDMDV *fdmdv_state);
|
||||||
|
void fdmdv_set_fsep(struct FDMDV *fdmdv_state, float fsep);
|
||||||
|
|
||||||
|
void fdmdv_mod(struct FDMDV *fdmdv_state, COMP tx_fdm[], int tx_bits[], int *sync_bit);
|
||||||
|
void fdmdv_demod(struct FDMDV *fdmdv_state, int rx_bits[], int *reliable_sync_bit, COMP rx_fdm[], int *nin);
|
||||||
|
|
||||||
|
void fdmdv_get_test_bits(struct FDMDV *fdmdv_state, int tx_bits[]);
|
||||||
|
int fdmdv_error_pattern_size(struct FDMDV *fdmdv_state);
|
||||||
|
void fdmdv_put_test_bits(struct FDMDV *f, int *sync, short error_pattern[], int *bit_errors, int *ntest_bits, int rx_bits[]);
|
||||||
|
|
||||||
|
void fdmdv_get_demod_stats(struct FDMDV *fdmdv_state, struct MODEM_STATS *stats);
|
||||||
|
|
||||||
|
void fdmdv_8_to_16(float out16k[], float in8k[], int n);
|
||||||
|
void fdmdv_8_to_16_short(short out16k[], short in8k[], int n);
|
||||||
|
void fdmdv_16_to_8(float out8k[], float in16k[], int n);
|
||||||
|
void fdmdv_16_to_8_short(short out8k[], short in16k[], int n);
|
||||||
|
|
||||||
|
void fdmdv_freq_shift(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff, COMP *foff_phase_rect, int nin);
|
||||||
|
|
||||||
|
/* debug/development function(s) */
|
||||||
|
|
||||||
|
void fdmdv_dump_osc_mags(struct FDMDV *f);
|
||||||
|
void fdmdv_simulate_channel(float *sig_pwr_av, COMP samples[], int nin, float target_snr);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* codec2_fft.c
|
||||||
|
*
|
||||||
|
* Created on: 24.09.2016
|
||||||
|
* Author: danilo
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "codec2_fft.h"
|
||||||
|
#ifdef USE_KISS_FFT
|
||||||
|
#include "_kiss_fft_guts.h"
|
||||||
|
|
||||||
|
#else
|
||||||
|
#if 0
|
||||||
|
// caching constants in RAM did not seem to have an effect on performance
|
||||||
|
// TODO: Decide what to with this code
|
||||||
|
#define FFT_INIT_CACHE_SIZE 4
|
||||||
|
const arm_cfft_instance_f32* fft_init_cache[FFT_INIT_CACHE_SIZE];
|
||||||
|
|
||||||
|
static const arm_cfft_instance_f32* arm_fft_instance2ram(const arm_cfft_instance_f32* in)
|
||||||
|
{
|
||||||
|
|
||||||
|
arm_cfft_instance_f32* out = malloc(sizeof(arm_cfft_instance_f32));
|
||||||
|
|
||||||
|
if (out) {
|
||||||
|
memcpy(out,in,sizeof(arm_cfft_instance_f32));
|
||||||
|
out->pBitRevTable = malloc(out->bitRevLength * sizeof(uint16_t));
|
||||||
|
out->pTwiddle = malloc(out->fftLen * sizeof(float32_t));
|
||||||
|
memcpy((void*)out->pBitRevTable,in->pBitRevTable,out->bitRevLength * sizeof(uint16_t));
|
||||||
|
memcpy((void*)out->pTwiddle,in->pTwiddle,out->fftLen * sizeof(float32_t));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const arm_cfft_instance_f32* arm_fft_cache_get(const arm_cfft_instance_f32* romfft)
|
||||||
|
{
|
||||||
|
const arm_cfft_instance_f32* retval = NULL;
|
||||||
|
static int used = 0;
|
||||||
|
for (int i = 0; fft_init_cache[i] != NULL && i < used; i++)
|
||||||
|
{
|
||||||
|
if (romfft->fftLen == fft_init_cache[i]->fftLen)
|
||||||
|
{
|
||||||
|
retval = fft_init_cache[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (retval == NULL && used < FFT_INIT_CACHE_SIZE)
|
||||||
|
{
|
||||||
|
retval = arm_fft_instance2ram(romfft);
|
||||||
|
fft_init_cache[used++] = retval;
|
||||||
|
}
|
||||||
|
if (retval == NULL)
|
||||||
|
{
|
||||||
|
retval = romfft;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void codec2_fft_free(codec2_fft_cfg cfg)
|
||||||
|
{
|
||||||
|
#ifdef USE_KISS_FFT
|
||||||
|
KISS_FFT_FREE(cfg);
|
||||||
|
#else
|
||||||
|
free(cfg);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
codec2_fft_cfg codec2_fft_alloc(int nfft, int inverse_fft, void* mem, size_t* lenmem)
|
||||||
|
{
|
||||||
|
codec2_fft_cfg retval;
|
||||||
|
#ifdef USE_KISS_FFT
|
||||||
|
retval = kiss_fft_alloc(nfft, inverse_fft, mem, lenmem);
|
||||||
|
#else
|
||||||
|
retval = malloc(sizeof(codec2_fft_struct));
|
||||||
|
retval->inverse = inverse_fft;
|
||||||
|
switch(nfft)
|
||||||
|
{
|
||||||
|
case 128:
|
||||||
|
retval->instance = &arm_cfft_sR_f32_len128;
|
||||||
|
break;
|
||||||
|
case 256:
|
||||||
|
retval->instance = &arm_cfft_sR_f32_len256;
|
||||||
|
break;
|
||||||
|
case 512:
|
||||||
|
retval->instance = &arm_cfft_sR_f32_len512;
|
||||||
|
break;
|
||||||
|
// case 1024:
|
||||||
|
// retval->instance = &arm_cfft_sR_f32_len1024;
|
||||||
|
// break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
// retval->instance = arm_fft_cache_get(retval->instance);
|
||||||
|
#endif
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
codec2_fftr_cfg codec2_fftr_alloc(int nfft, int inverse_fft, void* mem, size_t* lenmem)
|
||||||
|
{
|
||||||
|
codec2_fftr_cfg retval;
|
||||||
|
#ifdef USE_KISS_FFT
|
||||||
|
retval = kiss_fftr_alloc(nfft, inverse_fft, mem, lenmem);
|
||||||
|
#else
|
||||||
|
retval = malloc(sizeof(codec2_fftr_struct));
|
||||||
|
retval->inverse = inverse_fft;
|
||||||
|
retval->instance = malloc(sizeof(arm_rfft_fast_instance_f32));
|
||||||
|
arm_rfft_fast_init_f32(retval->instance,nfft);
|
||||||
|
// memcpy(&retval->instance->Sint,arm_fft_cache_get(&retval->instance->Sint),sizeof(arm_cfft_instance_f32));
|
||||||
|
#endif
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
void codec2_fftr_free(codec2_fftr_cfg cfg)
|
||||||
|
{
|
||||||
|
#ifdef USE_KISS_FFT
|
||||||
|
KISS_FFT_FREE(cfg);
|
||||||
|
#else
|
||||||
|
free(cfg->instance);
|
||||||
|
free(cfg);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// there is a little overhead for inplace kiss_fft but this is
|
||||||
|
// on the powerful platforms like the Raspberry or even x86 PC based ones
|
||||||
|
// not noticeable
|
||||||
|
// the reduced usage of RAM and increased performance on STM32 platforms
|
||||||
|
// should be worth it.
|
||||||
|
void codec2_fft_inplace(codec2_fft_cfg cfg, codec2_fft_cpx* inout)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef USE_KISS_FFT
|
||||||
|
kiss_fft_cpx in[512];
|
||||||
|
// decide whether to use the local stack based buffer for in
|
||||||
|
// or to allow kiss_fft to allocate RAM
|
||||||
|
// second part is just to play safe since first method
|
||||||
|
// is much faster and uses less RAM
|
||||||
|
if (cfg->nfft <= 512)
|
||||||
|
{
|
||||||
|
memcpy(in,inout,cfg->nfft*sizeof(kiss_fft_cpx));
|
||||||
|
kiss_fft(cfg, in, (kiss_fft_cpx*)inout);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kiss_fft(cfg, (kiss_fft_cpx*)inout, (kiss_fft_cpx*)inout);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
arm_cfft_f32(cfg->instance,(float*)inout,cfg->inverse,1);
|
||||||
|
if (cfg->inverse)
|
||||||
|
{
|
||||||
|
arm_scale_f32(inout,cfg->instance->fftLen,inout,cfg->instance->fftLen*2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* codec2_fft.h
|
||||||
|
*
|
||||||
|
* Created on: 17.09.2016
|
||||||
|
* Author: danilo
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DRIVERS_FREEDV_CODEC2_FFT_H_
|
||||||
|
#define DRIVERS_FREEDV_CODEC2_FFT_H_
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifdef ARM_MATH_CM4
|
||||||
|
#include "stm32f4xx.h"
|
||||||
|
#include "core_cm4.h"
|
||||||
|
#include "arm_math.h"
|
||||||
|
#include "arm_const_structs.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
#include "comp.h"
|
||||||
|
|
||||||
|
#ifndef ARM_MATH_CM4
|
||||||
|
#define USE_KISS_FFT
|
||||||
|
#endif
|
||||||
|
// #define USE_KISS_FFT
|
||||||
|
|
||||||
|
|
||||||
|
typedef COMP codec2_fft_cpx;
|
||||||
|
#include "kiss_fftr.h"
|
||||||
|
|
||||||
|
#ifdef USE_KISS_FFT
|
||||||
|
#include "kiss_fft.h"
|
||||||
|
typedef kiss_fftr_cfg codec2_fftr_cfg;
|
||||||
|
typedef kiss_fft_cfg codec2_fft_cfg;
|
||||||
|
typedef kiss_fft_scalar codec2_fft_scalar;
|
||||||
|
#else
|
||||||
|
typedef float32_t codec2_fft_scalar;
|
||||||
|
typedef struct {
|
||||||
|
arm_rfft_fast_instance_f32* instance;
|
||||||
|
int inverse;
|
||||||
|
} codec2_fftr_struct;
|
||||||
|
|
||||||
|
typedef codec2_fftr_struct* codec2_fftr_cfg;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const arm_cfft_instance_f32* instance;
|
||||||
|
int inverse;
|
||||||
|
} codec2_fft_struct;
|
||||||
|
typedef codec2_fft_struct* codec2_fft_cfg;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static inline void codec2_fftr(codec2_fftr_cfg cfg, codec2_fft_scalar* in, codec2_fft_cpx* out)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef USE_KISS_FFT
|
||||||
|
kiss_fftr(cfg, in, (kiss_fft_cpx*)out);
|
||||||
|
#else
|
||||||
|
arm_rfft_fast_f32(cfg->instance,in,(float*)out,cfg->inverse);
|
||||||
|
out->imag = 0; // remove out[FFT_ENC/2]->real stored in out[0].imag
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void codec2_fftri(codec2_fftr_cfg cfg, codec2_fft_cpx* in, codec2_fft_scalar* out)
|
||||||
|
{
|
||||||
|
#ifdef USE_KISS_FFT
|
||||||
|
kiss_fftri(cfg, (kiss_fft_cpx*)in, out);
|
||||||
|
#else
|
||||||
|
arm_rfft_fast_f32(cfg->instance,(float*)in,out,cfg->inverse);
|
||||||
|
// arm_scale_f32(out,cfg->instance->fftLenRFFT,out,cfg->instance->fftLenRFFT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
codec2_fft_cfg codec2_fft_alloc(int nfft, int inverse_fft, void* mem, size_t* lenmem);
|
||||||
|
codec2_fftr_cfg codec2_fftr_alloc(int nfft, int inverse_fft, void* mem, size_t* lenmem);
|
||||||
|
void codec2_fft_free(codec2_fft_cfg cfg);
|
||||||
|
void codec2_fftr_free(codec2_fftr_cfg cfg);
|
||||||
|
|
||||||
|
|
||||||
|
static inline void codec2_fft(codec2_fft_cfg cfg, codec2_fft_cpx* in, codec2_fft_cpx* out)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef USE_KISS_FFT
|
||||||
|
kiss_fft(cfg, (kiss_fft_cpx*)in, (kiss_fft_cpx*)out);
|
||||||
|
#else
|
||||||
|
memcpy(out,in,cfg->instance->fftLen*2*sizeof(float));
|
||||||
|
arm_cfft_f32(cfg->instance,(float*)out,cfg->inverse,0);
|
||||||
|
// TODO: this is not nice, but for now required to keep changes minimal
|
||||||
|
// however, since main goal is to reduce the memory usage
|
||||||
|
// we should convert to an in place interface
|
||||||
|
// on PC like platforms the overhead of using the "inplace" kiss_fft calls
|
||||||
|
// is neglectable compared to the gain in memory usage on STM32 platforms
|
||||||
|
if (cfg->inverse)
|
||||||
|
{
|
||||||
|
arm_scale_f32((float*)out,cfg->instance->fftLen,(float*)out,cfg->instance->fftLen*2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void codec2_fft_inplace(codec2_fft_cfg cfg, codec2_fft_cpx* inout);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: codec2_fifo.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: Oct 15 2012
|
||||||
|
|
||||||
|
A FIFO design useful in gluing the FDMDV modem and codec together in
|
||||||
|
integrated applications.
|
||||||
|
|
||||||
|
The name codec2_fifo.h is used to make it unique when "make
|
||||||
|
installed".
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2012 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FIFO__
|
||||||
|
#define __FIFO__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct FIFO;
|
||||||
|
|
||||||
|
struct FIFO *fifo_create(int nshort);
|
||||||
|
void fifo_destroy(struct FIFO *fifo);
|
||||||
|
int fifo_write(struct FIFO *fifo, short data[], int n);
|
||||||
|
int fifo_read(struct FIFO *fifo, short data[], int n);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Return the number of bytes stored in the FIFO.
|
||||||
|
*/
|
||||||
|
int fifo_used(const struct FIFO * const fifo);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Return the space available in the FIFO.
|
||||||
|
*/
|
||||||
|
int fifo_free(const struct FIFO * const fifo);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: codec2_fm.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: February 2015
|
||||||
|
|
||||||
|
Functions that implement analog FM, see also octave/fm.m.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2015 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CODEC2_FM__
|
||||||
|
#define __CODEC2_FM__
|
||||||
|
|
||||||
|
#include "comp.h"
|
||||||
|
|
||||||
|
struct FM {
|
||||||
|
float Fs; /* setme: sample rate */
|
||||||
|
float fm_max; /* setme: maximum modulation frequency */
|
||||||
|
float fd; /* setme: maximum deviation */
|
||||||
|
float fc; /* setme: carrier frequency */
|
||||||
|
COMP *rx_bb;
|
||||||
|
COMP rx_bb_filt_prev;
|
||||||
|
float *rx_dem_mem;
|
||||||
|
float tx_phase;
|
||||||
|
int nsam;
|
||||||
|
COMP lo_phase;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FM *fm_create(int nsam);
|
||||||
|
void fm_destroy(struct FM *fm_states);
|
||||||
|
void fm_demod(struct FM *fm, float rx_out[], float rx[]);
|
||||||
|
void fm_mod(struct FM *fm, float tx_in[], float tx_out[]);
|
||||||
|
void fm_mod_comp(struct FM *fm_states, float tx_in[], COMP tx_out[]);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: codec2_internal.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: April 16 2012
|
||||||
|
|
||||||
|
Header file for Codec2 internal states, exposed via this header
|
||||||
|
file to assist in testing.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2012 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CODEC2_INTERNAL__
|
||||||
|
#define __CODEC2_INTERNAL__
|
||||||
|
|
||||||
|
#include "codec2_fft.h"
|
||||||
|
|
||||||
|
struct CODEC2 {
|
||||||
|
int mode;
|
||||||
|
C2CONST c2const;
|
||||||
|
int Fs;
|
||||||
|
int n_samp;
|
||||||
|
int m_pitch;
|
||||||
|
codec2_fft_cfg fft_fwd_cfg; /* forward FFT config */
|
||||||
|
codec2_fftr_cfg fftr_fwd_cfg; /* forward real FFT config */
|
||||||
|
float *w; /* [m_pitch] time domain hamming window */
|
||||||
|
COMP W[FFT_ENC]; /* DFT of w[] */
|
||||||
|
float *Pn; /* [2*n_samp] trapezoidal synthesis window */
|
||||||
|
float *bpf_buf; /* buffer for band pass filter */
|
||||||
|
float *Sn; /* [m_pitch] input speech */
|
||||||
|
float hpf_states[2]; /* high pass filter states */
|
||||||
|
void *nlp; /* pitch predictor states */
|
||||||
|
int gray; /* non-zero for gray encoding */
|
||||||
|
|
||||||
|
codec2_fftr_cfg fftr_inv_cfg; /* inverse FFT config */
|
||||||
|
float *Sn_; /* [2*n_samp] synthesised output speech */
|
||||||
|
float ex_phase; /* excitation model phase track */
|
||||||
|
float bg_est; /* background noise estimate for post filter */
|
||||||
|
float prev_f0_enc; /* previous frame's f0 estimate */
|
||||||
|
MODEL prev_model_dec; /* previous frame's model parameters */
|
||||||
|
float prev_lsps_dec[LPC_ORD]; /* previous frame's LSPs */
|
||||||
|
float prev_e_dec; /* previous frame's LPC energy */
|
||||||
|
|
||||||
|
int lpc_pf; /* LPC post filter on */
|
||||||
|
int bass_boost; /* LPC post filter bass boost */
|
||||||
|
float beta; /* LPC post filter parameters */
|
||||||
|
float gamma;
|
||||||
|
|
||||||
|
float xq_enc[2]; /* joint pitch and energy VQ states */
|
||||||
|
float xq_dec[2];
|
||||||
|
|
||||||
|
int smoothing; /* enable smoothing for channels with errors */
|
||||||
|
float *softdec; /* optional soft decn bits from demod */
|
||||||
|
|
||||||
|
/* newamp1 states */
|
||||||
|
|
||||||
|
float Wo_left;
|
||||||
|
int voicing_left;
|
||||||
|
codec2_fft_cfg phase_fft_fwd_cfg;
|
||||||
|
codec2_fft_cfg phase_fft_inv_cfg;
|
||||||
|
};
|
||||||
|
|
||||||
|
// test and debug
|
||||||
|
void analyse_one_frame(struct CODEC2 *c2, MODEL *model, short speech[]);
|
||||||
|
void synthesise_one_frame(struct CODEC2 *c2, short speech[], MODEL *model,
|
||||||
|
COMP Aw[]);
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: codec2_ofdm.h
|
||||||
|
AUTHORS.....: David Rowe & Steve Sampson
|
||||||
|
DATE CREATED: June 2017
|
||||||
|
|
||||||
|
External user references to the modem library.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2017 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CODEC2_OFDM_H
|
||||||
|
#define CODEC2_OFDM_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Includes */
|
||||||
|
|
||||||
|
#include <complex.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "comp.h"
|
||||||
|
|
||||||
|
/* Defines */
|
||||||
|
|
||||||
|
struct OFDM;
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
|
||||||
|
struct OFDM *ofdm_create(void);
|
||||||
|
void ofdm_destroy(struct OFDM *);
|
||||||
|
void ofdm_mod(struct OFDM *, COMP *, const int *);
|
||||||
|
void ofdm_demod(struct OFDM *, int *, COMP *);
|
||||||
|
int ofdm_get_nin(struct OFDM *);
|
||||||
|
int ofdm_get_samples_per_frame(void);
|
||||||
|
int ofdm_get_max_samples_per_frame(void);
|
||||||
|
|
||||||
|
/* option setters */
|
||||||
|
|
||||||
|
void ofdm_set_verbose(struct OFDM *, int);
|
||||||
|
void ofdm_set_timing_enable(struct OFDM *, bool);
|
||||||
|
void ofdm_set_foff_est_enable(struct OFDM *, bool);
|
||||||
|
void ofdm_set_phase_est_enable(struct OFDM *, bool);
|
||||||
|
void ofdm_set_off_est_hz(struct OFDM *, float);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
/* Generated by write_pilot_file() Octave function */
|
||||||
|
|
||||||
|
#define NSYMROW 4 /* number of data symbols per carrier (number of rows) */
|
||||||
|
#define NS 4 /* number of data symbols between pilots */
|
||||||
|
#define NPILOTSFRAME 2 /* number of pilot symbols per carrier */
|
||||||
|
#define PILOTS_NC 7 /* number of carriers */
|
||||||
|
|
||||||
|
#define NSYMROWPILOT 6 /* number of rows after pilots inserted */
|
||||||
|
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: cohpsk_internal.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: March 2015
|
||||||
|
|
||||||
|
Functions that implement a coherent PSK FDM modem.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2015 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __COHPSK_INTERNAL__
|
||||||
|
#define __COHPSK_INTERNAL__
|
||||||
|
|
||||||
|
#define NCT_SYMB_BUF (2*NSYMROWPILOT+2)
|
||||||
|
#define ND 2 /* diversity factor ND 1 is no diveristy, ND we have orginal plus
|
||||||
|
one copy */
|
||||||
|
#define NSW 4 /* number of sync window frames */
|
||||||
|
#define COHPSK_ND 2 /* diversity factor */
|
||||||
|
#define COHPSK_M 100 /* oversampling rate */
|
||||||
|
#define COHPSK_NSYM 6
|
||||||
|
#define COHPSK_NFILTER (COHPSK_NSYM*COHPSK_M)
|
||||||
|
#define COHPSK_EXCESS_BW 0.5 /* excess BW factor of root nyq filter */
|
||||||
|
#define COHPSK_NT 5 /* number of symbols we estimate timing over */
|
||||||
|
#define COHPSK_CLIP 6.5 /* hard clipping for Nc*Nc=14 to reduce PAPR */
|
||||||
|
|
||||||
|
#include "fdmdv_internal.h"
|
||||||
|
#include "kiss_fft.h"
|
||||||
|
|
||||||
|
struct COHPSK {
|
||||||
|
COMP ch_fdm_frame_buf[NSW*NSYMROWPILOT*COHPSK_M]; /* buffer of several frames of symbols from channel */
|
||||||
|
float pilot2[2*NPILOTSFRAME][COHPSK_NC];
|
||||||
|
float phi_[NSYMROWPILOT][COHPSK_NC*ND]; /* phase estimates for this frame of rx data symbols */
|
||||||
|
float amp_[NSYMROW][COHPSK_NC*ND]; /* amplitude estimates for this frame of rx data symbols */
|
||||||
|
COMP rx_symb[NSYMROWPILOT][COHPSK_NC*ND]; /* demodulated symbols */
|
||||||
|
float f_est;
|
||||||
|
COMP rx_filter_memory[COHPSK_NC*ND][COHPSK_NFILTER];
|
||||||
|
COMP ct_symb_buf[NCT_SYMB_BUF][COHPSK_NC*ND];
|
||||||
|
int ct; /* coarse timing offset in symbols */
|
||||||
|
float rx_timing; /* fine timing for last symbol in frame */
|
||||||
|
int nin; /* number of samples to input for next symbol */
|
||||||
|
float f_fine_est;
|
||||||
|
COMP ff_rect;
|
||||||
|
COMP ff_phase;
|
||||||
|
COMP ct_symb_ff_buf[NSYMROWPILOT+2][COHPSK_NC*ND];
|
||||||
|
int sync;
|
||||||
|
int sync_timer;
|
||||||
|
|
||||||
|
int frame;
|
||||||
|
float ratio;
|
||||||
|
|
||||||
|
float sig_rms;
|
||||||
|
float noise_rms;
|
||||||
|
|
||||||
|
struct FDMDV *fdmdv;
|
||||||
|
|
||||||
|
int verbose;
|
||||||
|
|
||||||
|
int *ptest_bits_coh_tx;
|
||||||
|
int *ptest_bits_coh_rx[2];
|
||||||
|
int *ptest_bits_coh_end;
|
||||||
|
|
||||||
|
/* counting bit errors using pilots */
|
||||||
|
|
||||||
|
int npilotbits;
|
||||||
|
int npilotbiterrors;
|
||||||
|
|
||||||
|
/* optional log variables used for testing Octave to C port */
|
||||||
|
|
||||||
|
COMP *rx_baseband_log;
|
||||||
|
int rx_baseband_log_col_index;
|
||||||
|
int rx_baseband_log_col_sz;
|
||||||
|
|
||||||
|
COMP *rx_filt_log;
|
||||||
|
int rx_filt_log_col_index;
|
||||||
|
int rx_filt_log_col_sz;
|
||||||
|
|
||||||
|
COMP *ch_symb_log;
|
||||||
|
int ch_symb_log_r;
|
||||||
|
int ch_symb_log_col_sz;
|
||||||
|
|
||||||
|
float *rx_timing_log;
|
||||||
|
int rx_timing_log_index;
|
||||||
|
|
||||||
|
/* demodulated bits before diversity combination for test/instrumentation purposes */
|
||||||
|
|
||||||
|
float rx_bits_lower[COHPSK_BITS_PER_FRAME];
|
||||||
|
float rx_bits_upper[COHPSK_BITS_PER_FRAME];
|
||||||
|
|
||||||
|
/* tx amplitude weights for each carrier for test/instrumentation */
|
||||||
|
|
||||||
|
float carrier_ampl[COHPSK_NC*ND];
|
||||||
|
};
|
||||||
|
|
||||||
|
void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC*COHPSK_ND], int tx_bits[], int nbits);
|
||||||
|
void qpsk_symbols_to_bits(struct COHPSK *coh, float rx_bits[], COMP ct_symb_buf[][COHPSK_NC*COHPSK_ND]);
|
||||||
|
void tx_filter_and_upconvert_coh(COMP tx_fdm[], int Nc, COMP tx_symbols[],
|
||||||
|
COMP tx_filter_memory[COHPSK_NC][COHPSK_NSYM],
|
||||||
|
COMP phase_tx[], COMP freq[],
|
||||||
|
COMP *fbb_phase, COMP fbb_rect);
|
||||||
|
void fdm_downconvert_coh(COMP rx_baseband[COHPSK_NC][COHPSK_M+COHPSK_M/P], int Nc, COMP rx_fdm[], COMP phase_rx[], COMP freq[], int nin);
|
||||||
|
void rx_filter_coh(COMP rx_filt[COHPSK_NC+1][P+1], int Nc, COMP rx_baseband[COHPSK_NC+1][COHPSK_M+COHPSK_M/P], COMP rx_filter_memory[COHPSK_NC+1][COHPSK_NFILTER], int nin);
|
||||||
|
void frame_sync_fine_freq_est(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*COHPSK_ND], int sync, int *next_sync);
|
||||||
|
void fine_freq_correct(struct COHPSK *coh, int sync, int next_sync);
|
||||||
|
int sync_state_machine(struct COHPSK *coh, int sync, int next_sync);
|
||||||
|
int cohpsk_fs_offset(COMP out[], COMP in[], int n, float sample_rate_ppm);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: comp.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 24/08/09
|
||||||
|
|
||||||
|
Complex number definition.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2009 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __COMP__
|
||||||
|
#define __COMP__
|
||||||
|
|
||||||
|
/* Complex number */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float real;
|
||||||
|
float imag;
|
||||||
|
} COMP;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: comp_prim.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: Marh 2015
|
||||||
|
|
||||||
|
Complex number maths primitives.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2015 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __COMP_PRIM__
|
||||||
|
#define __COMP_PRIM__
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FUNCTIONS
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
inline static COMP cneg(COMP a)
|
||||||
|
{
|
||||||
|
COMP res;
|
||||||
|
|
||||||
|
res.real = -a.real;
|
||||||
|
res.imag = -a.imag;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static COMP cconj(COMP a)
|
||||||
|
{
|
||||||
|
COMP res;
|
||||||
|
|
||||||
|
res.real = a.real;
|
||||||
|
res.imag = -a.imag;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static COMP cmult(COMP a, COMP b)
|
||||||
|
{
|
||||||
|
COMP res;
|
||||||
|
|
||||||
|
res.real = a.real*b.real - a.imag*b.imag;
|
||||||
|
res.imag = a.real*b.imag + a.imag*b.real;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static COMP fcmult(float a, COMP b)
|
||||||
|
{
|
||||||
|
COMP res;
|
||||||
|
|
||||||
|
res.real = a*b.real;
|
||||||
|
res.imag = a*b.imag;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static COMP cadd(COMP a, COMP b)
|
||||||
|
{
|
||||||
|
COMP res;
|
||||||
|
|
||||||
|
res.real = a.real + b.real;
|
||||||
|
res.imag = a.imag + b.imag;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static float cabsolute(COMP a)
|
||||||
|
{
|
||||||
|
return sqrtf(powf(a.real, 2.0) + powf(a.imag, 2.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Euler's formula in a new convenient function
|
||||||
|
*/
|
||||||
|
inline static COMP comp_exp_j(float phi){
|
||||||
|
COMP res;
|
||||||
|
res.real = cosf(phi);
|
||||||
|
res.imag = sinf(phi);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quick and easy complex 0
|
||||||
|
*/
|
||||||
|
inline static COMP comp0(){
|
||||||
|
COMP res;
|
||||||
|
res.real = 0;
|
||||||
|
res.imag = 0;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quick and easy complex subtract
|
||||||
|
*/
|
||||||
|
inline static COMP csub(COMP a, COMP b){
|
||||||
|
COMP res;
|
||||||
|
res.real = a.real-b.real;
|
||||||
|
res.imag = a.imag-b.imag;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compare the magnitude of a and b. if |a|>|b|, return true, otw false.
|
||||||
|
* This needs no square roots
|
||||||
|
*/
|
||||||
|
inline static int comp_mag_gt(COMP a,COMP b){
|
||||||
|
return ((a.real*a.real)+(a.imag*a.imag)) > ((b.real*b.real)+(b.imag*b.imag));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Normalize a complex number's magnitude to 1
|
||||||
|
*/
|
||||||
|
inline static COMP comp_normalize(COMP a){
|
||||||
|
COMP b;
|
||||||
|
float av = cabsolute(a);
|
||||||
|
b.real = a.real/av;
|
||||||
|
b.imag = a.imag/av;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: defines.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 23/4/93
|
||||||
|
|
||||||
|
Defines and structures used throughout the codec.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2009 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DEFINES__
|
||||||
|
#define __DEFINES__
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
DEFINES
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* General defines */
|
||||||
|
|
||||||
|
#define N_S 0.010 /* buffer size in s */
|
||||||
|
#define TW_S 0.005 /* trapezoidal synth window overlap */
|
||||||
|
#define MAX_AMP 160 /* maximum number of harmonics */
|
||||||
|
#ifndef PI
|
||||||
|
#define PI 3.141592654 /* mathematical constant */
|
||||||
|
#endif
|
||||||
|
#define TWO_PI 6.283185307 /* mathematical constant */
|
||||||
|
#define MAX_STR 2048 /* maximum string size */
|
||||||
|
|
||||||
|
#define FFT_ENC 512 /* size of FFT used for encoder */
|
||||||
|
#define FFT_DEC 512 /* size of FFT used in decoder */
|
||||||
|
#define V_THRESH 6.0 /* voicing threshold in dB */
|
||||||
|
#define LPC_ORD 10 /* LPC order */
|
||||||
|
#define LPC_ORD_LOW 6 /* LPC order for lower rates */
|
||||||
|
|
||||||
|
/* Pitch estimation defines */
|
||||||
|
|
||||||
|
#define M_PITCH_S 0.0400 /* pitch analysis window in s */
|
||||||
|
#define P_MIN_S 0.0025 /* minimum pitch period in s */
|
||||||
|
#define P_MAX_S 0.0200 /* maximum pitch period in s */
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
TYPEDEFS
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Structure to hold constants calculated at run time based on sample rate */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int Fs; /* sample rate of this instance */
|
||||||
|
int n_samp; /* number of samples per 10ms frame at Fs */
|
||||||
|
int max_amp; /* maximum number of harmonics */
|
||||||
|
int m_pitch; /* pitch estimation window size in samples */
|
||||||
|
int p_min; /* minimum pitch period in samples */
|
||||||
|
int p_max; /* maximum pitch period in samples */
|
||||||
|
float Wo_min;
|
||||||
|
float Wo_max;
|
||||||
|
int nw; /* analysis window size in samples */
|
||||||
|
int tw; /* trapezoidal synthesis window overlap */
|
||||||
|
} C2CONST;
|
||||||
|
|
||||||
|
/* Structure to hold model parameters for one frame */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float Wo; /* fundamental frequency estimate in radians */
|
||||||
|
int L; /* number of harmonics */
|
||||||
|
float A[MAX_AMP+1]; /* amplitiude of each harmonic */
|
||||||
|
float phi[MAX_AMP+1]; /* phase of each harmonic */
|
||||||
|
int voiced; /* non-zero if this frame is voiced */
|
||||||
|
} MODEL;
|
||||||
|
|
||||||
|
/* describes each codebook */
|
||||||
|
|
||||||
|
struct lsp_codebook {
|
||||||
|
int k; /* dimension of vector */
|
||||||
|
int log2m; /* number of bits in m */
|
||||||
|
int m; /* elements in codebook */
|
||||||
|
const float * cb; /* The elements */
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct lsp_codebook lsp_cb[];
|
||||||
|
extern const struct lsp_codebook lsp_cbd[];
|
||||||
|
extern const struct lsp_codebook lsp_cbvq[];
|
||||||
|
extern const struct lsp_codebook lsp_cbjnd[];
|
||||||
|
extern const struct lsp_codebook lsp_cbdt[];
|
||||||
|
extern const struct lsp_codebook lsp_cbjvm[];
|
||||||
|
extern const struct lsp_codebook lsp_cbvqanssi[];
|
||||||
|
extern const struct lsp_codebook mel_cb[];
|
||||||
|
extern const struct lsp_codebook ge_cb[];
|
||||||
|
extern const struct lsp_codebook lspmelvq_cb[];
|
||||||
|
extern const struct lsp_codebook newamp1vq_cb[];
|
||||||
|
extern const struct lsp_codebook newamp1_energy_cb[];
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,674 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: dump.c
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 25/8/09
|
||||||
|
|
||||||
|
Routines to dump data to text files for Octave analysis.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
#include "comp.h"
|
||||||
|
#include "dump.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifdef __EMBEDDED__
|
||||||
|
#include "gdb_stdio.h"
|
||||||
|
#define fprintf gdb_stdio_fprintf
|
||||||
|
#define fopen gdb_stdio_fopen
|
||||||
|
#define fclose gdb_stdio_fclose
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DUMP
|
||||||
|
static int dumpon = 0;
|
||||||
|
|
||||||
|
static FILE *fsn = NULL;
|
||||||
|
static FILE *fsw = NULL;
|
||||||
|
static FILE *few = NULL;
|
||||||
|
static FILE *fsw_ = NULL;
|
||||||
|
static FILE *fsoftdec = NULL;
|
||||||
|
static FILE *fmodel = NULL;
|
||||||
|
static FILE *fqmodel = NULL;
|
||||||
|
static FILE *fpwb = NULL;
|
||||||
|
static FILE *fpw = NULL;
|
||||||
|
static FILE *frw = NULL;
|
||||||
|
static FILE *flsp = NULL;
|
||||||
|
static FILE *fweights = NULL;
|
||||||
|
static FILE *flsp_ = NULL;
|
||||||
|
static FILE *fmel = NULL;
|
||||||
|
static FILE *fmel_indexes = NULL;
|
||||||
|
static FILE *fphase = NULL;
|
||||||
|
static FILE *fphase_ = NULL;
|
||||||
|
static FILE *ffw = NULL;
|
||||||
|
static FILE *fe = NULL;
|
||||||
|
static FILE *fsq = NULL;
|
||||||
|
static FILE *fdec = NULL;
|
||||||
|
static FILE *fsnr = NULL;
|
||||||
|
static FILE *flpcsnr = NULL;
|
||||||
|
static FILE *fak = NULL;
|
||||||
|
static FILE *fak_ = NULL;
|
||||||
|
static FILE *fbg = NULL;
|
||||||
|
static FILE *fE = NULL;
|
||||||
|
static FILE *frk = NULL;
|
||||||
|
static FILE *fhephase = NULL;
|
||||||
|
|
||||||
|
static char prefix[MAX_STR];
|
||||||
|
|
||||||
|
void dump_on(char p[]) {
|
||||||
|
dumpon = 1;
|
||||||
|
strcpy(prefix, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_off(){
|
||||||
|
if (fsn != NULL)
|
||||||
|
fclose(fsn);
|
||||||
|
if (fsw != NULL)
|
||||||
|
fclose(fsw);
|
||||||
|
if (fsw_ != NULL)
|
||||||
|
fclose(fsw_);
|
||||||
|
if (few != NULL)
|
||||||
|
fclose(few);
|
||||||
|
if (fmodel != NULL)
|
||||||
|
fclose(fmodel);
|
||||||
|
if (fsoftdec != NULL)
|
||||||
|
fclose(fsoftdec);
|
||||||
|
if (fqmodel != NULL)
|
||||||
|
fclose(fqmodel);
|
||||||
|
if (fpwb != NULL)
|
||||||
|
fclose(fpwb);
|
||||||
|
if (fpw != NULL)
|
||||||
|
fclose(fpw);
|
||||||
|
if (frw != NULL)
|
||||||
|
fclose(frw);
|
||||||
|
if (flsp != NULL)
|
||||||
|
fclose(flsp);
|
||||||
|
if (fweights != NULL)
|
||||||
|
fclose(fweights);
|
||||||
|
if (flsp_ != NULL)
|
||||||
|
fclose(flsp_);
|
||||||
|
if (fmel != NULL)
|
||||||
|
fclose(fmel);
|
||||||
|
if (fmel_indexes != NULL)
|
||||||
|
fclose(fmel_indexes);
|
||||||
|
if (fphase != NULL)
|
||||||
|
fclose(fphase);
|
||||||
|
if (fphase_ != NULL)
|
||||||
|
fclose(fphase_);
|
||||||
|
if (ffw != NULL)
|
||||||
|
fclose(ffw);
|
||||||
|
if (fe != NULL)
|
||||||
|
fclose(fe);
|
||||||
|
if (fsq != NULL)
|
||||||
|
fclose(fsq);
|
||||||
|
if (fdec != NULL)
|
||||||
|
fclose(fdec);
|
||||||
|
if (fsnr != NULL)
|
||||||
|
fclose(fsnr);
|
||||||
|
if (flpcsnr != NULL)
|
||||||
|
fclose(flpcsnr);
|
||||||
|
if (fak != NULL)
|
||||||
|
fclose(fak);
|
||||||
|
if (fak_ != NULL)
|
||||||
|
fclose(fak_);
|
||||||
|
if (fbg != NULL)
|
||||||
|
fclose(fbg);
|
||||||
|
if (fE != NULL)
|
||||||
|
fclose(fE);
|
||||||
|
if (frk != NULL)
|
||||||
|
fclose(frk);
|
||||||
|
if (fhephase != NULL)
|
||||||
|
fclose(fhephase);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_Sn(int m_pitch, float Sn[]) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fsn == NULL) {
|
||||||
|
sprintf(s,"%s_sn.txt", prefix);
|
||||||
|
fsn = fopen(s, "wt");
|
||||||
|
assert(fsn != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* split across two lines to avoid max line length problems */
|
||||||
|
/* reconstruct in Octave */
|
||||||
|
|
||||||
|
for(i=0; i<m_pitch/2; i++)
|
||||||
|
fprintf(fsn,"%f\t",Sn[i]);
|
||||||
|
fprintf(fsn,"\n");
|
||||||
|
for(i=m_pitch/2; i<m_pitch; i++)
|
||||||
|
fprintf(fsn,"%f\t",Sn[i]);
|
||||||
|
fprintf(fsn,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_Sw(COMP Sw[]) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fsw == NULL) {
|
||||||
|
sprintf(s,"%s_sw.txt", prefix);
|
||||||
|
fsw = fopen(s, "wt");
|
||||||
|
assert(fsw != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<FFT_ENC/2; i++)
|
||||||
|
fprintf(fsw,"%f\t",
|
||||||
|
10.0*log10(Sw[i].real*Sw[i].real + Sw[i].imag*Sw[i].imag));
|
||||||
|
fprintf(fsw,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_Sw_(COMP Sw_[]) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fsw_ == NULL) {
|
||||||
|
sprintf(s,"%s_sw_.txt", prefix);
|
||||||
|
fsw_ = fopen(s, "wt");
|
||||||
|
assert(fsw_ != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<FFT_ENC/2; i++)
|
||||||
|
fprintf(fsw_,"%f\t",
|
||||||
|
10.0*log10(Sw_[i].real*Sw_[i].real + Sw_[i].imag*Sw_[i].imag));
|
||||||
|
fprintf(fsw_,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_Ew(COMP Ew[]) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (few == NULL) {
|
||||||
|
sprintf(s,"%s_ew.txt", prefix);
|
||||||
|
few = fopen(s, "wt");
|
||||||
|
assert(few != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<FFT_ENC/2; i++)
|
||||||
|
fprintf(few,"%f\t",
|
||||||
|
10.0*log10(Ew[i].real*Ew[i].real + Ew[i].imag*Ew[i].imag));
|
||||||
|
fprintf(few,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_softdec(float *softdec, int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fsoftdec == NULL) {
|
||||||
|
sprintf(s,"%s_softdec.txt", prefix);
|
||||||
|
fsoftdec = fopen(s, "wt");
|
||||||
|
assert(fsoftdec != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<n; i++)
|
||||||
|
fprintf(fsoftdec,"%f\t", softdec[i]);
|
||||||
|
fprintf(fsoftdec,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_model(MODEL *model) {
|
||||||
|
int l;
|
||||||
|
char s[MAX_STR];
|
||||||
|
char line[MAX_STR*10];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fmodel == NULL) {
|
||||||
|
sprintf(s,"%s_model.txt", prefix);
|
||||||
|
fmodel = fopen(s, "wt");
|
||||||
|
assert(fmodel != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(line,"%12f %12d ", model->Wo, model->L);
|
||||||
|
for(l=1; l<=model->L; l++) {
|
||||||
|
sprintf(s,"%12f ",model->A[l]);
|
||||||
|
strcat(line, s);
|
||||||
|
assert(strlen(line) < MAX_STR*10);
|
||||||
|
}
|
||||||
|
for(l=model->L+1; l<=MAX_AMP; l++) {
|
||||||
|
sprintf(s,"%12f ", 0.0);
|
||||||
|
strcat(line,s);
|
||||||
|
assert(strlen(line) < MAX_STR*10);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(s,"%d\n",model->voiced);
|
||||||
|
strcat(line,s);
|
||||||
|
fprintf(fmodel,"%s",line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_quantised_model(MODEL *model) {
|
||||||
|
int l;
|
||||||
|
char s[MAX_STR];
|
||||||
|
char line[2048];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fqmodel == NULL) {
|
||||||
|
sprintf(s,"%s_qmodel.txt", prefix);
|
||||||
|
fqmodel = fopen(s, "wt");
|
||||||
|
assert(fqmodel != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(line,"%12f %12d ", model->Wo, model->L);
|
||||||
|
for(l=1; l<=model->L; l++) {
|
||||||
|
sprintf(s,"%12f ",model->A[l]);
|
||||||
|
strcat(line, s);
|
||||||
|
}
|
||||||
|
for(l=model->L+1; l<=MAX_AMP; l++) {
|
||||||
|
sprintf(s,"%12f ", 0.0);
|
||||||
|
strcat(line, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(s,"%d\n",model->voiced);
|
||||||
|
strcat(line, s);
|
||||||
|
fprintf(fqmodel, "%s", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_phase(float phase[], int L) {
|
||||||
|
int l;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fphase == NULL) {
|
||||||
|
sprintf(s,"%s_phase.txt", prefix);
|
||||||
|
fphase = fopen(s, "wt");
|
||||||
|
assert(fphase != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(l=1; l<=L; l++)
|
||||||
|
fprintf(fphase,"%f\t",phase[l]);
|
||||||
|
for(l=L+1; l<=MAX_AMP; l++)
|
||||||
|
fprintf(fphase,"%f\t",0.0);
|
||||||
|
fprintf(fphase,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_phase_(float phase_[], int L) {
|
||||||
|
int l;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fphase_ == NULL) {
|
||||||
|
sprintf(s,"%s_phase_.txt", prefix);
|
||||||
|
fphase_ = fopen(s, "wt");
|
||||||
|
assert(fphase_ != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(l=1; l<=L; l++)
|
||||||
|
fprintf(fphase_,"%f\t",phase_[l]);
|
||||||
|
for(l=L+1; l<MAX_AMP; l++)
|
||||||
|
fprintf(fphase_,"%f\t",0.0);
|
||||||
|
fprintf(fphase_,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dump_hephase(int ind[], int dim) {
|
||||||
|
int m;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fhephase == NULL) {
|
||||||
|
sprintf(s,"%s_hephase.txt", prefix);
|
||||||
|
fhephase = fopen(s, "wt");
|
||||||
|
assert(fhephase != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(m=0; m<dim; m++)
|
||||||
|
fprintf(fhephase,"%d\t",ind[m]);
|
||||||
|
fprintf(fhephase,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dump_snr(float snr) {
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fsnr == NULL) {
|
||||||
|
sprintf(s,"%s_snr.txt", prefix);
|
||||||
|
fsnr = fopen(s, "wt");
|
||||||
|
assert(fsnr != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fsnr,"%f\n",snr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_lpc_snr(float snr) {
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (flpcsnr == NULL) {
|
||||||
|
sprintf(s,"%s_lpc_snr.txt", prefix);
|
||||||
|
flpcsnr = fopen(s, "wt");
|
||||||
|
assert(flpcsnr != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(flpcsnr,"%f\n",snr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pw "before" post filter so we can plot before and after */
|
||||||
|
|
||||||
|
void dump_Pwb(float Pwb[]) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fpwb == NULL) {
|
||||||
|
sprintf(s,"%s_pwb.txt", prefix);
|
||||||
|
fpwb = fopen(s, "wt");
|
||||||
|
assert(fpwb != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<FFT_ENC/2; i++)
|
||||||
|
fprintf(fpwb,"%f\t",Pwb[i]);
|
||||||
|
fprintf(fpwb,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_Pw(float Pw[]) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fpw == NULL) {
|
||||||
|
sprintf(s,"%s_pw.txt", prefix);
|
||||||
|
fpw = fopen(s, "wt");
|
||||||
|
assert(fpw != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<FFT_ENC/2; i++)
|
||||||
|
fprintf(fpw,"%f\t",Pw[i]);
|
||||||
|
fprintf(fpw,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_Rw(float Rw[]) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (frw == NULL) {
|
||||||
|
sprintf(s,"%s_rw.txt", prefix);
|
||||||
|
frw = fopen(s, "wt");
|
||||||
|
assert(frw != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<FFT_ENC/2; i++)
|
||||||
|
fprintf(frw,"%f\t",Rw[i]);
|
||||||
|
fprintf(frw,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_weights(float w[], int order) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fweights == NULL) {
|
||||||
|
sprintf(s,"%s_weights.txt", prefix);
|
||||||
|
fweights = fopen(s, "wt");
|
||||||
|
assert(fweights != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<order; i++)
|
||||||
|
fprintf(fweights,"%f\t", w[i]);
|
||||||
|
fprintf(fweights,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_lsp(float lsp[]) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (flsp == NULL) {
|
||||||
|
sprintf(s,"%s_lsp.txt", prefix);
|
||||||
|
flsp = fopen(s, "wt");
|
||||||
|
assert(flsp != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<10; i++)
|
||||||
|
fprintf(flsp,"%f\t",lsp[i]);
|
||||||
|
fprintf(flsp,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_lsp_(float lsp_[]) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (flsp_ == NULL) {
|
||||||
|
sprintf(s,"%s_lsp_.txt", prefix);
|
||||||
|
flsp_ = fopen(s, "wt");
|
||||||
|
assert(flsp_ != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<10; i++)
|
||||||
|
fprintf(flsp_,"%f\t",lsp_[i]);
|
||||||
|
fprintf(flsp_,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_mel(float mel[], int order) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fmel == NULL) {
|
||||||
|
sprintf(s,"%s_mel.txt", prefix);
|
||||||
|
fmel = fopen(s, "wt");
|
||||||
|
assert(fmel != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<order; i++)
|
||||||
|
fprintf(fmel,"%f\t",mel[i]);
|
||||||
|
fprintf(fmel,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_mel_indexes(int mel_indexes[], int order) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fmel_indexes == NULL) {
|
||||||
|
sprintf(s,"%s_mel_indexes.txt", prefix);
|
||||||
|
fmel_indexes = fopen(s, "wt");
|
||||||
|
assert(fmel_indexes != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<order; i++)
|
||||||
|
fprintf(fmel_indexes,"%d\t",mel_indexes[i]);
|
||||||
|
fprintf(fmel_indexes,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_ak(float ak[], int order) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fak == NULL) {
|
||||||
|
sprintf(s,"%s_ak.txt", prefix);
|
||||||
|
fak = fopen(s, "wt");
|
||||||
|
assert(fak != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<=order; i++)
|
||||||
|
fprintf(fak,"%f\t",ak[i]);
|
||||||
|
fprintf(fak,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_ak_(float ak_[], int order) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fak_ == NULL) {
|
||||||
|
sprintf(s,"%s_ak_.txt", prefix);
|
||||||
|
fak_ = fopen(s, "wt");
|
||||||
|
assert(fak_ != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<=order; i++)
|
||||||
|
fprintf(fak_,"%f\t",ak_[i]);
|
||||||
|
fprintf(fak_,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_Fw(COMP Fw[]) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (ffw == NULL) {
|
||||||
|
sprintf(s,"%s_fw.txt", prefix);
|
||||||
|
ffw = fopen(s, "wt");
|
||||||
|
assert(ffw != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<256; i++)
|
||||||
|
fprintf(ffw,"%f\t",Fw[i].real);
|
||||||
|
fprintf(ffw,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_e(float e_hz[]) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fe == NULL) {
|
||||||
|
sprintf(s,"%s_e.txt", prefix);
|
||||||
|
fe = fopen(s, "wt");
|
||||||
|
assert(fe != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<500/2; i++)
|
||||||
|
fprintf(fe,"%f\t",e_hz[i]);
|
||||||
|
fprintf(fe,"\n");
|
||||||
|
for(i=500/2; i<500; i++)
|
||||||
|
fprintf(fe,"%f\t",e_hz[i]);
|
||||||
|
fprintf(fe,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_sq(int m_pitch, float sq[]) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fsq == NULL) {
|
||||||
|
sprintf(s,"%s_sq.txt", prefix);
|
||||||
|
fsq = fopen(s, "wt");
|
||||||
|
assert(fsq != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<m_pitch/2; i++)
|
||||||
|
fprintf(fsq,"%f\t",sq[i]);
|
||||||
|
fprintf(fsq,"\n");
|
||||||
|
for(i=m_pitch/2; i<m_pitch; i++)
|
||||||
|
fprintf(fsq,"%f\t",sq[i]);
|
||||||
|
fprintf(fsq,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_dec(COMP Fw[]) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fdec == NULL) {
|
||||||
|
sprintf(s,"%s_dec.txt", prefix);
|
||||||
|
fdec = fopen(s, "wt");
|
||||||
|
assert(fdec != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<320/5; i++)
|
||||||
|
fprintf(fdec,"%f\t",Fw[i].real);
|
||||||
|
fprintf(fdec,"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_bg(float e, float bg_est, float percent_uv) {
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fbg == NULL) {
|
||||||
|
sprintf(s,"%s_bg.txt", prefix);
|
||||||
|
fbg = fopen(s, "wt");
|
||||||
|
assert(fbg != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fbg,"%f\t%f\t%f\n", e, bg_est, percent_uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_E(float E) {
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (fE == NULL) {
|
||||||
|
sprintf(s,"%s_E.txt", prefix);
|
||||||
|
fE = fopen(s, "wt");
|
||||||
|
assert(fE != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fE,"%f\n", 10.0*log10(E));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void dump_Rk(float Rk[]) {
|
||||||
|
int i;
|
||||||
|
char s[MAX_STR];
|
||||||
|
|
||||||
|
if (!dumpon) return;
|
||||||
|
|
||||||
|
if (frk == NULL) {
|
||||||
|
sprintf(s,"%s_rk.txt", prefix);
|
||||||
|
frk = fopen(s, "wt");
|
||||||
|
assert(frk != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<P_MAX; i++)
|
||||||
|
fprintf(frk,"%f\t",Rk[i]);
|
||||||
|
fprintf(frk,"\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: dump.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 25/8/09
|
||||||
|
|
||||||
|
Routines to dump data to text files for Octave analysis.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DUMP__
|
||||||
|
#define __DUMP__
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
#include "comp.h"
|
||||||
|
#include "codec2_fft.h"
|
||||||
|
#include "codec2_internal.h"
|
||||||
|
|
||||||
|
void dump_on(char filename_prefix[]);
|
||||||
|
void dump_off();
|
||||||
|
|
||||||
|
void dump_Sn(int m_pitch, float Sn[]);
|
||||||
|
void dump_Sw(COMP Sw[]);
|
||||||
|
void dump_Sw_(COMP Sw_[]);
|
||||||
|
void dump_Ew(COMP Ew[]);
|
||||||
|
void dump_softdec(float *softdec, int n);
|
||||||
|
|
||||||
|
/* amplitude modelling */
|
||||||
|
|
||||||
|
void dump_model(MODEL *m);
|
||||||
|
void dump_quantised_model(MODEL *m);
|
||||||
|
void dump_Pwn(COMP Pw[]);
|
||||||
|
void dump_Pw(float Pw[]);
|
||||||
|
void dump_Rw(float Rw[]);
|
||||||
|
void dump_lsp(float lsp[]);
|
||||||
|
void dump_weights(float w[], int ndim);
|
||||||
|
void dump_lsp_(float lsp_[]);
|
||||||
|
void dump_mel(float mel[], int order);
|
||||||
|
void dump_mel_indexes(int mel_indexes[], int order);
|
||||||
|
void dump_ak(float ak[], int order);
|
||||||
|
void dump_ak_(float ak[], int order);
|
||||||
|
void dump_E(float E);
|
||||||
|
void dump_lpc_snr(float snr);
|
||||||
|
|
||||||
|
/* phase modelling */
|
||||||
|
|
||||||
|
void dump_snr(float snr);
|
||||||
|
void dump_phase(float phase[], int L);
|
||||||
|
void dump_phase_(float phase[], int L);
|
||||||
|
void dump_hephase(int ind[], int dim);
|
||||||
|
|
||||||
|
/* NLP states */
|
||||||
|
|
||||||
|
void dump_sq(int m_pitch, float sq[]);
|
||||||
|
void dump_dec(COMP Fw[]);
|
||||||
|
void dump_Fw(COMP Fw[]);
|
||||||
|
void dump_e(float e_hz[]);
|
||||||
|
#if 0
|
||||||
|
void dump_Rk(float Rk[]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* post filter */
|
||||||
|
|
||||||
|
void dump_bg(float e, float bg_est, float percent_uv);
|
||||||
|
void dump_Pwb(float Pwb[]);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: fdmdv_internal.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: April 16 2012
|
||||||
|
|
||||||
|
Header file for FDMDV internal functions, exposed via this header
|
||||||
|
file for testing.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2012 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FDMDV_INTERNAL__
|
||||||
|
#define __FDMDV_INTERNAL__
|
||||||
|
|
||||||
|
#include "comp.h"
|
||||||
|
#include "codec2_fdmdv.h"
|
||||||
|
#include "codec2_fft.h"
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
DEFINES
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef PI
|
||||||
|
#define PI 3.141592654
|
||||||
|
#endif
|
||||||
|
#define FS 8000 /* sample rate in Hz */
|
||||||
|
#define T (1.0/FS) /* sample period in seconds */
|
||||||
|
#define RS 50 /* symbol rate in Hz */
|
||||||
|
#define NC 20 /* max number of data carriers (plus one pilot in the centre) */
|
||||||
|
#define NB 2 /* Bits/symbol for QPSK modulation */
|
||||||
|
#define RB (NC*RS*NB) /* bit rate */
|
||||||
|
#define M_FAC (FS/RS) /* oversampling factor */
|
||||||
|
#define NSYM 6 /* number of symbols to filter over */
|
||||||
|
#define NFILTER (NSYM*M_FAC) /* size of tx/rx filters at sample rate M */
|
||||||
|
|
||||||
|
#define FSEP 75 /* Default separation between carriers (Hz) */
|
||||||
|
|
||||||
|
#define NT 5 /* number of symbols we estimate timing over */
|
||||||
|
#define P 4 /* oversample factor used for initial rx symbol filtering output */
|
||||||
|
#define Q (M_FAC/4) /* oversample factor used for initial rx symbol filtering input */
|
||||||
|
#define NRXDEC 31 /* number of taps in the rx decimation filter */
|
||||||
|
|
||||||
|
#define NPILOT_LUT (4*M_FAC) /* number of pilot look up table samples */
|
||||||
|
#define NPILOTCOEFF 30 /* number of FIR filter coeffs in LP filter */
|
||||||
|
#define NPILOTBASEBAND (NPILOTCOEFF+M_FAC+M_FAC/P) /* number of pilot baseband samples reqd for pilot LPF */
|
||||||
|
#define NPILOTLPF (4*M_FAC) /* number of samples we DFT pilot over, pilot est window */
|
||||||
|
#define MPILOTFFT 256
|
||||||
|
|
||||||
|
#define NSYNC_MEM 6
|
||||||
|
|
||||||
|
/* averaging filter coeffs */
|
||||||
|
|
||||||
|
#define TRACK_COEFF 0.5
|
||||||
|
#define SNR_COEFF 0.9 /* SNR est averaging filter coeff */
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
STRUCT for States
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
struct FDMDV {
|
||||||
|
|
||||||
|
int Nc;
|
||||||
|
float fsep;
|
||||||
|
|
||||||
|
/* test data (test frame) states */
|
||||||
|
|
||||||
|
int ntest_bits;
|
||||||
|
int current_test_bit;
|
||||||
|
int *rx_test_bits_mem;
|
||||||
|
|
||||||
|
/* Modulator */
|
||||||
|
|
||||||
|
int old_qpsk_mapping;
|
||||||
|
int tx_pilot_bit;
|
||||||
|
COMP prev_tx_symbols[NC+1];
|
||||||
|
COMP tx_filter_memory[NC+1][NSYM];
|
||||||
|
COMP phase_tx[NC+1];
|
||||||
|
COMP freq[NC+1];
|
||||||
|
float freq_pol[NC+1];
|
||||||
|
|
||||||
|
/* Pilot generation at demodulator */
|
||||||
|
|
||||||
|
COMP pilot_lut[NPILOT_LUT];
|
||||||
|
int pilot_lut_index;
|
||||||
|
int prev_pilot_lut_index;
|
||||||
|
|
||||||
|
/* freq offset estimation states */
|
||||||
|
|
||||||
|
codec2_fft_cfg fft_pilot_cfg;
|
||||||
|
COMP pilot_baseband1[NPILOTBASEBAND];
|
||||||
|
COMP pilot_baseband2[NPILOTBASEBAND];
|
||||||
|
COMP pilot_lpf1[NPILOTLPF];
|
||||||
|
COMP pilot_lpf2[NPILOTLPF];
|
||||||
|
COMP S1[MPILOTFFT];
|
||||||
|
COMP S2[MPILOTFFT];
|
||||||
|
|
||||||
|
/* baseband to low IF carrier states */
|
||||||
|
|
||||||
|
COMP fbb_rect;
|
||||||
|
float fbb_pol;
|
||||||
|
COMP fbb_phase_tx;
|
||||||
|
COMP fbb_phase_rx;
|
||||||
|
|
||||||
|
/* freq offset correction states */
|
||||||
|
|
||||||
|
float foff;
|
||||||
|
COMP foff_phase_rect;
|
||||||
|
float foff_filt;
|
||||||
|
|
||||||
|
/* Demodulator */
|
||||||
|
|
||||||
|
COMP rxdec_lpf_mem[NRXDEC-1+M_FAC];
|
||||||
|
COMP rx_fdm_mem[NFILTER+M_FAC];
|
||||||
|
COMP phase_rx[NC+1];
|
||||||
|
COMP rx_filter_mem_timing[NC+1][NT*P];
|
||||||
|
float rx_timing;
|
||||||
|
COMP phase_difference[NC+1];
|
||||||
|
COMP prev_rx_symbols[NC+1];
|
||||||
|
|
||||||
|
/* sync state machine */
|
||||||
|
|
||||||
|
int sync_mem[NSYNC_MEM];
|
||||||
|
int fest_state;
|
||||||
|
int sync;
|
||||||
|
int timer;
|
||||||
|
|
||||||
|
/* SNR estimation states */
|
||||||
|
|
||||||
|
float sig_est[NC+1];
|
||||||
|
float noise_est[NC+1];
|
||||||
|
|
||||||
|
/* channel simulation */
|
||||||
|
|
||||||
|
float sig_pwr_av;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FUNCTION PROTOTYPES
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void bits_to_dqpsk_symbols(COMP tx_symbols[], int Nc, COMP prev_tx_symbols[], int tx_bits[], int *pilot_bit, int old_qpsk_mapping);
|
||||||
|
void tx_filter(COMP tx_baseband[NC+1][M_FAC], int Nc, COMP tx_symbols[], COMP tx_filter_memory[NC+1][NSYM]);
|
||||||
|
void fdm_upconvert(COMP tx_fdm[], int Nc, COMP tx_baseband[NC+1][M_FAC], COMP phase_tx[], COMP freq_tx[],
|
||||||
|
COMP *fbb_phase, COMP fbb_rect);
|
||||||
|
void tx_filter_and_upconvert(COMP tx_fdm[], int Nc, COMP tx_symbols[],
|
||||||
|
COMP tx_filter_memory[NC+1][NSYM],
|
||||||
|
COMP phase_tx[], COMP freq[], COMP *fbb_phase, COMP fbb_rect);
|
||||||
|
void generate_pilot_fdm(COMP *pilot_fdm, int *bit, float *symbol, float *filter_mem, COMP *phase, COMP *freq);
|
||||||
|
void generate_pilot_lut(COMP pilot_lut[], COMP *pilot_freq);
|
||||||
|
float rx_est_freq_offset(struct FDMDV *f, COMP rx_fdm[], int nin, int do_fft);
|
||||||
|
void lpf_peak_pick(float *foff, float *max, COMP pilot_baseband[], COMP pilot_lpf[], codec2_fft_cfg fft_pilot_cfg, COMP S[], int nin, int do_fft);
|
||||||
|
void fdm_downconvert(COMP rx_baseband[NC+1][M_FAC+M_FAC/P], int Nc, COMP rx_fdm[], COMP phase_rx[], COMP freq[], int nin);
|
||||||
|
void rxdec_filter(COMP rx_fdm_filter[], COMP rx_fdm[], COMP rxdec_lpf_mem[], int nin);
|
||||||
|
void rx_filter(COMP rx_filt[NC+1][P+1], int Nc, COMP rx_baseband[NC+1][M_FAC+M_FAC/P], COMP rx_filter_memory[NC+1][NFILTER], int nin);
|
||||||
|
void down_convert_and_rx_filter(COMP rx_filt[NC+1][P+1], int Nc, COMP rx_fdm[],
|
||||||
|
COMP rx_fdm_mem[], COMP phase_rx[], COMP freq[],
|
||||||
|
float freq_pol[], int nin, int dec_rate);
|
||||||
|
float rx_est_timing(COMP rx_symbols[], int Nc,
|
||||||
|
COMP rx_filt[NC+1][P+1],
|
||||||
|
COMP rx_filter_mem_timing[NC+1][NT*P],
|
||||||
|
float env[],
|
||||||
|
int nin,
|
||||||
|
int m);
|
||||||
|
float qpsk_to_bits(int rx_bits[], int *sync_bit, int Nc, COMP phase_difference[], COMP prev_rx_symbols[], COMP rx_symbols[], int old_qpsk_mapping);
|
||||||
|
void snr_update(float sig_est[], float noise_est[], int Nc, COMP phase_difference[]);
|
||||||
|
int freq_state(int *reliable_sync_bit, int sync_bit, int *state, int *timer, int *sync_mem);
|
||||||
|
float calc_snr(int Nc, float sig_est[], float noise_est[]);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,413 @@
|
|||||||
|
/* Generated by fm_fir_coeff_file() Octave function in fm.m */
|
||||||
|
|
||||||
|
const float bin[]={
|
||||||
|
4.79309e-05,
|
||||||
|
1.1306e-05,
|
||||||
|
-5.5983e-05,
|
||||||
|
-7.01194e-05,
|
||||||
|
7.06484e-06,
|
||||||
|
9.92193e-05,
|
||||||
|
8.58591e-05,
|
||||||
|
-4.54326e-05,
|
||||||
|
-0.000152003,
|
||||||
|
-8.65645e-05,
|
||||||
|
0.000107704,
|
||||||
|
0.000207915,
|
||||||
|
6.24307e-05,
|
||||||
|
-0.000194905,
|
||||||
|
-0.000256788,
|
||||||
|
-3.72067e-06,
|
||||||
|
0.000303862,
|
||||||
|
0.000285027,
|
||||||
|
-9.75377e-05,
|
||||||
|
-0.000426141,
|
||||||
|
-0.000276571,
|
||||||
|
0.000245596,
|
||||||
|
0.00054748,
|
||||||
|
0.000214543,
|
||||||
|
-0.000438995,
|
||||||
|
-0.000647904,
|
||||||
|
-8.35097e-05,
|
||||||
|
0.000668808,
|
||||||
|
0.000702715,
|
||||||
|
-0.000127804,
|
||||||
|
-0.000917433,
|
||||||
|
-0.000684399,
|
||||||
|
0.000423605,
|
||||||
|
0.00115821,
|
||||||
|
0.000565432,
|
||||||
|
-0.000798262,
|
||||||
|
-0.00135608,
|
||||||
|
-0.000321829,
|
||||||
|
0.00123404,
|
||||||
|
0.00146953,
|
||||||
|
-6.28411e-05,
|
||||||
|
-0.00169975,
|
||||||
|
-0.00145365,
|
||||||
|
0.000593351,
|
||||||
|
0.00215057,
|
||||||
|
0.00126444,
|
||||||
|
-0.00125906,
|
||||||
|
-0.00252937,
|
||||||
|
-0.000863858,
|
||||||
|
0.00203097,
|
||||||
|
0.00276961,
|
||||||
|
0.000225378,
|
||||||
|
-0.00286002,
|
||||||
|
-0.00279968,
|
||||||
|
0.00066048,
|
||||||
|
0.00367697,
|
||||||
|
0.00254856,
|
||||||
|
-0.00178121,
|
||||||
|
-0.00439398,
|
||||||
|
-0.00195226,
|
||||||
|
0.00309842,
|
||||||
|
0.00490791,
|
||||||
|
0.000960678,
|
||||||
|
-0.0045454,
|
||||||
|
-0.00510509,
|
||||||
|
0.000456067,
|
||||||
|
0.00602631,
|
||||||
|
0.00486678,
|
||||||
|
-0.00230217,
|
||||||
|
-0.00741688,
|
||||||
|
-0.00407467,
|
||||||
|
0.00455244,
|
||||||
|
0.00856596,
|
||||||
|
0.0026148,
|
||||||
|
-0.00715072,
|
||||||
|
-0.0092966,
|
||||||
|
-0.000377815,
|
||||||
|
0.0100109,
|
||||||
|
0.00940383,
|
||||||
|
-0.00274808,
|
||||||
|
-0.0130204,
|
||||||
|
-0.00864357,
|
||||||
|
0.00689875,
|
||||||
|
0.0160465,
|
||||||
|
0.0066998,
|
||||||
|
-0.0122874,
|
||||||
|
-0.0189444,
|
||||||
|
-0.0030966,
|
||||||
|
0.0193367,
|
||||||
|
0.0215669,
|
||||||
|
-0.00304913,
|
||||||
|
-0.0290487,
|
||||||
|
-0.0237748,
|
||||||
|
0.0138493,
|
||||||
|
0.0443198,
|
||||||
|
0.0254471,
|
||||||
|
-0.0364426,
|
||||||
|
-0.0771407,
|
||||||
|
-0.0264901,
|
||||||
|
0.120993,
|
||||||
|
0.285249,
|
||||||
|
0.366844,
|
||||||
|
0.285249,
|
||||||
|
0.120993,
|
||||||
|
-0.0264901,
|
||||||
|
-0.0771407,
|
||||||
|
-0.0364426,
|
||||||
|
0.0254471,
|
||||||
|
0.0443198,
|
||||||
|
0.0138493,
|
||||||
|
-0.0237748,
|
||||||
|
-0.0290487,
|
||||||
|
-0.00304913,
|
||||||
|
0.0215669,
|
||||||
|
0.0193367,
|
||||||
|
-0.0030966,
|
||||||
|
-0.0189444,
|
||||||
|
-0.0122874,
|
||||||
|
0.0066998,
|
||||||
|
0.0160465,
|
||||||
|
0.00689875,
|
||||||
|
-0.00864357,
|
||||||
|
-0.0130204,
|
||||||
|
-0.00274808,
|
||||||
|
0.00940383,
|
||||||
|
0.0100109,
|
||||||
|
-0.000377815,
|
||||||
|
-0.0092966,
|
||||||
|
-0.00715072,
|
||||||
|
0.0026148,
|
||||||
|
0.00856596,
|
||||||
|
0.00455244,
|
||||||
|
-0.00407467,
|
||||||
|
-0.00741688,
|
||||||
|
-0.00230217,
|
||||||
|
0.00486678,
|
||||||
|
0.00602631,
|
||||||
|
0.000456067,
|
||||||
|
-0.00510509,
|
||||||
|
-0.0045454,
|
||||||
|
0.000960678,
|
||||||
|
0.00490791,
|
||||||
|
0.00309842,
|
||||||
|
-0.00195226,
|
||||||
|
-0.00439398,
|
||||||
|
-0.00178121,
|
||||||
|
0.00254856,
|
||||||
|
0.00367697,
|
||||||
|
0.00066048,
|
||||||
|
-0.00279968,
|
||||||
|
-0.00286002,
|
||||||
|
0.000225378,
|
||||||
|
0.00276961,
|
||||||
|
0.00203097,
|
||||||
|
-0.000863858,
|
||||||
|
-0.00252937,
|
||||||
|
-0.00125906,
|
||||||
|
0.00126444,
|
||||||
|
0.00215057,
|
||||||
|
0.000593351,
|
||||||
|
-0.00145365,
|
||||||
|
-0.00169975,
|
||||||
|
-6.28411e-05,
|
||||||
|
0.00146953,
|
||||||
|
0.00123404,
|
||||||
|
-0.000321829,
|
||||||
|
-0.00135608,
|
||||||
|
-0.000798262,
|
||||||
|
0.000565432,
|
||||||
|
0.00115821,
|
||||||
|
0.000423605,
|
||||||
|
-0.000684399,
|
||||||
|
-0.000917433,
|
||||||
|
-0.000127804,
|
||||||
|
0.000702715,
|
||||||
|
0.000668808,
|
||||||
|
-8.35097e-05,
|
||||||
|
-0.000647904,
|
||||||
|
-0.000438995,
|
||||||
|
0.000214543,
|
||||||
|
0.00054748,
|
||||||
|
0.000245596,
|
||||||
|
-0.000276571,
|
||||||
|
-0.000426141,
|
||||||
|
-9.75377e-05,
|
||||||
|
0.000285027,
|
||||||
|
0.000303862,
|
||||||
|
-3.72067e-06,
|
||||||
|
-0.000256788,
|
||||||
|
-0.000194905,
|
||||||
|
6.24307e-05,
|
||||||
|
0.000207915,
|
||||||
|
0.000107704,
|
||||||
|
-8.65645e-05,
|
||||||
|
-0.000152003,
|
||||||
|
-4.54326e-05,
|
||||||
|
8.58591e-05,
|
||||||
|
9.92193e-05,
|
||||||
|
7.06484e-06,
|
||||||
|
-7.01194e-05,
|
||||||
|
-5.5983e-05,
|
||||||
|
1.1306e-05,
|
||||||
|
4.79309e-05
|
||||||
|
};
|
||||||
|
|
||||||
|
const float bout[]={
|
||||||
|
-0.000901664,
|
||||||
|
-0.00105423,
|
||||||
|
-0.00102202,
|
||||||
|
-0.000796428,
|
||||||
|
-0.0004047,
|
||||||
|
9.24929e-05,
|
||||||
|
0.000610043,
|
||||||
|
0.00105267,
|
||||||
|
0.00133217,
|
||||||
|
0.00138452,
|
||||||
|
0.00118367,
|
||||||
|
0.000749102,
|
||||||
|
0.000145346,
|
||||||
|
-0.000527025,
|
||||||
|
-0.00114777,
|
||||||
|
-0.00159812,
|
||||||
|
-0.00178311,
|
||||||
|
-0.00165083,
|
||||||
|
-0.00120494,
|
||||||
|
-0.000507584,
|
||||||
|
0.000328412,
|
||||||
|
0.0011573,
|
||||||
|
0.00182538,
|
||||||
|
0.00219909,
|
||||||
|
0.00219097,
|
||||||
|
0.00177877,
|
||||||
|
0.00101358,
|
||||||
|
1.48175e-05,
|
||||||
|
-0.00104765,
|
||||||
|
-0.00198192,
|
||||||
|
-0.00260813,
|
||||||
|
-0.00279243,
|
||||||
|
-0.00247437,
|
||||||
|
-0.00168247,
|
||||||
|
-0.000534171,
|
||||||
|
0.000780521,
|
||||||
|
0.00202976,
|
||||||
|
0.00298006,
|
||||||
|
0.00343915,
|
||||||
|
0.00329371,
|
||||||
|
0.00253482,
|
||||||
|
0.00126569,
|
||||||
|
-0.000310763,
|
||||||
|
-0.00192329,
|
||||||
|
-0.00327808,
|
||||||
|
-0.0041113,
|
||||||
|
-0.00423916,
|
||||||
|
-0.00359628,
|
||||||
|
-0.00225463,
|
||||||
|
-0.000418452,
|
||||||
|
0.00160526,
|
||||||
|
0.00345676,
|
||||||
|
0.00478613,
|
||||||
|
0.00531776,
|
||||||
|
0.00490513,
|
||||||
|
0.00356541,
|
||||||
|
0.00148629,
|
||||||
|
-0.000997692,
|
||||||
|
-0.00345694,
|
||||||
|
-0.0054391,
|
||||||
|
-0.00654985,
|
||||||
|
-0.00652835,
|
||||||
|
-0.00530323,
|
||||||
|
-0.00301796,
|
||||||
|
-1.90046e-05,
|
||||||
|
0.00319335,
|
||||||
|
0.00604515,
|
||||||
|
0.00798756,
|
||||||
|
0.00859787,
|
||||||
|
0.00766479,
|
||||||
|
0.00524199,
|
||||||
|
0.001658,
|
||||||
|
-0.00252213,
|
||||||
|
-0.00658004,
|
||||||
|
-0.00976079,
|
||||||
|
-0.011405,
|
||||||
|
-0.0110744,
|
||||||
|
-0.00864874,
|
||||||
|
-0.00437487,
|
||||||
|
0.00114403,
|
||||||
|
0.00702171,
|
||||||
|
0.0122173,
|
||||||
|
0.0157018,
|
||||||
|
0.0166372,
|
||||||
|
0.0145415,
|
||||||
|
0.00940928,
|
||||||
|
0.00176699,
|
||||||
|
-0.00735151,
|
||||||
|
-0.0165112,
|
||||||
|
-0.0240533,
|
||||||
|
-0.0283208,
|
||||||
|
-0.027902,
|
||||||
|
-0.0218568,
|
||||||
|
-0.00988994,
|
||||||
|
0.0075553,
|
||||||
|
0.0293009,
|
||||||
|
0.0535398,
|
||||||
|
0.0780316,
|
||||||
|
0.100365,
|
||||||
|
0.118251,
|
||||||
|
0.129808,
|
||||||
|
0.143804,
|
||||||
|
0.129808,
|
||||||
|
0.118251,
|
||||||
|
0.100365,
|
||||||
|
0.0780316,
|
||||||
|
0.0535398,
|
||||||
|
0.0293009,
|
||||||
|
0.0075553,
|
||||||
|
-0.00988994,
|
||||||
|
-0.0218568,
|
||||||
|
-0.027902,
|
||||||
|
-0.0283208,
|
||||||
|
-0.0240533,
|
||||||
|
-0.0165112,
|
||||||
|
-0.00735151,
|
||||||
|
0.00176699,
|
||||||
|
0.00940928,
|
||||||
|
0.0145415,
|
||||||
|
0.0166372,
|
||||||
|
0.0157018,
|
||||||
|
0.0122173,
|
||||||
|
0.00702171,
|
||||||
|
0.00114403,
|
||||||
|
-0.00437487,
|
||||||
|
-0.00864874,
|
||||||
|
-0.0110744,
|
||||||
|
-0.011405,
|
||||||
|
-0.00976079,
|
||||||
|
-0.00658004,
|
||||||
|
-0.00252213,
|
||||||
|
0.001658,
|
||||||
|
0.00524199,
|
||||||
|
0.00766479,
|
||||||
|
0.00859787,
|
||||||
|
0.00798756,
|
||||||
|
0.00604515,
|
||||||
|
0.00319335,
|
||||||
|
-1.90046e-05,
|
||||||
|
-0.00301796,
|
||||||
|
-0.00530323,
|
||||||
|
-0.00652835,
|
||||||
|
-0.00654985,
|
||||||
|
-0.0054391,
|
||||||
|
-0.00345694,
|
||||||
|
-0.000997692,
|
||||||
|
0.00148629,
|
||||||
|
0.00356541,
|
||||||
|
0.00490513,
|
||||||
|
0.00531776,
|
||||||
|
0.00478613,
|
||||||
|
0.00345676,
|
||||||
|
0.00160526,
|
||||||
|
-0.000418452,
|
||||||
|
-0.00225463,
|
||||||
|
-0.00359628,
|
||||||
|
-0.00423916,
|
||||||
|
-0.0041113,
|
||||||
|
-0.00327808,
|
||||||
|
-0.00192329,
|
||||||
|
-0.000310763,
|
||||||
|
0.00126569,
|
||||||
|
0.00253482,
|
||||||
|
0.00329371,
|
||||||
|
0.00343915,
|
||||||
|
0.00298006,
|
||||||
|
0.00202976,
|
||||||
|
0.000780521,
|
||||||
|
-0.000534171,
|
||||||
|
-0.00168247,
|
||||||
|
-0.00247437,
|
||||||
|
-0.00279243,
|
||||||
|
-0.00260813,
|
||||||
|
-0.00198192,
|
||||||
|
-0.00104765,
|
||||||
|
1.48175e-05,
|
||||||
|
0.00101358,
|
||||||
|
0.00177877,
|
||||||
|
0.00219097,
|
||||||
|
0.00219909,
|
||||||
|
0.00182538,
|
||||||
|
0.0011573,
|
||||||
|
0.000328412,
|
||||||
|
-0.000507584,
|
||||||
|
-0.00120494,
|
||||||
|
-0.00165083,
|
||||||
|
-0.00178311,
|
||||||
|
-0.00159812,
|
||||||
|
-0.00114777,
|
||||||
|
-0.000527025,
|
||||||
|
0.000145346,
|
||||||
|
0.000749102,
|
||||||
|
0.00118367,
|
||||||
|
0.00138452,
|
||||||
|
0.00133217,
|
||||||
|
0.00105267,
|
||||||
|
0.000610043,
|
||||||
|
9.24929e-05,
|
||||||
|
-0.0004047,
|
||||||
|
-0.000796428,
|
||||||
|
-0.00102202,
|
||||||
|
-0.00105423,
|
||||||
|
-0.000901664
|
||||||
|
};
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: fmfsk.h
|
||||||
|
AUTHOR......: Brady O'Brien
|
||||||
|
DATE CREATED: 6 February 2016
|
||||||
|
|
||||||
|
C Implementation of 2FSK+Manchester over FM modulator/demodulator, based
|
||||||
|
on mancyfsk.m and fmfsk.m
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2016 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __C2FMFSK_H
|
||||||
|
#define __C2FMFSK_H
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "comp.h"
|
||||||
|
#include "modem_stats.h"
|
||||||
|
|
||||||
|
#define FMFSK_SCALE 16383
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fm-me-2fsk state
|
||||||
|
*/
|
||||||
|
struct FMFSK{
|
||||||
|
/* Static fmfsk parameters */
|
||||||
|
int Rb; /* Manchester-encoded bitrate */
|
||||||
|
int Rs; /* Raw modem symbol rate */
|
||||||
|
int Fs; /* Sample rate */
|
||||||
|
int Ts; /* Samples-per-symbol */
|
||||||
|
int N; /* Sample processing buffer size */
|
||||||
|
int nsym; /* Number of raw modem symbols processed per demod call */
|
||||||
|
int nbit; /* Number of bits spit out per demod call */
|
||||||
|
int nmem; /* Number of samples kept around between demod calls */
|
||||||
|
|
||||||
|
/* State kept by demod */
|
||||||
|
int nin; /* Number of samples to be demod-ed the next cycle */
|
||||||
|
int lodd; /* Last integrated sample for odd bitstream generation */
|
||||||
|
float * oldsamps; /* Memory of old samples to make clock-offset-tolerance possible */
|
||||||
|
|
||||||
|
/* Stats generated by demod */
|
||||||
|
float norm_rx_timing; /* RX Timing, used to calculate clock offset */
|
||||||
|
int ppm; /* Clock offset in parts-per-million */
|
||||||
|
float snr_mean;
|
||||||
|
|
||||||
|
/* Modem stat structure */
|
||||||
|
struct MODEM_STATS * stats;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new fmfsk modem instance.
|
||||||
|
*
|
||||||
|
* int Fs - sample rate
|
||||||
|
* int Rb - non-manchester bitrate
|
||||||
|
* returns - new struct FMFSK on sucess, NULL on failure
|
||||||
|
*/
|
||||||
|
struct FMFSK * fmfsk_create(int Fs,int Rb);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destroys an fmfsk modem and deallocates memory
|
||||||
|
*/
|
||||||
|
void fmfsk_destroy(struct FMFSK *fmfsk);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deposit demod statistics into a MODEM_STATS struct
|
||||||
|
*/
|
||||||
|
void fmfsk_get_demod_stats(struct FMFSK *fmfsk,struct MODEM_STATS *stats);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the number of samples that must be fed to fmfsk_demod the next
|
||||||
|
* cycle
|
||||||
|
*/
|
||||||
|
uint32_t fmfsk_nin(struct FMFSK *fmfsk);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modulates nbit bits into N samples to be sent through an FM radio
|
||||||
|
*
|
||||||
|
* struct FSK *fsk - FSK config/state struct, set up by fsk_create
|
||||||
|
* float mod_out[] - Buffer for N samples of modulated FMFSK
|
||||||
|
* uint8_t tx_bits[] - Buffer containing Nbits unpacked bits
|
||||||
|
*/
|
||||||
|
void fmfsk_mod(struct FMFSK *fmfsk, float fmfsk_out[],uint8_t bits_in[]);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Demodulate some number of FMFSK samples. The number of samples to be
|
||||||
|
* demodulated can be found by calling fmfsk_nin().
|
||||||
|
*
|
||||||
|
* struct FMFSK *fsk - FMFSK config/state struct, set up by fsk_create
|
||||||
|
* uint8_t rx_bits[] - Buffer for nbit unpacked bits to be written
|
||||||
|
* float fsk_in[] - nin samples of modualted FMFSK from an FM radio
|
||||||
|
*/
|
||||||
|
void fmfsk_demod(struct FMFSK *fmfsk, uint8_t rx_bits[],float fmfsk_in[]);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: freedv_api.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: August 2014
|
||||||
|
|
||||||
|
Library of API functions that implement FreeDV "modes", useful for
|
||||||
|
embedding FreeDV in other programs. Please see the documentation
|
||||||
|
for each function in freedv_api.c, and the sample freedv_tx.c and
|
||||||
|
freedv_rx.c programs.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2014 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __FREEDV__
|
||||||
|
|
||||||
|
// This declares a single-precision (float) complex number
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "comp.h"
|
||||||
|
|
||||||
|
#define FREEDV_MODE_1600 0
|
||||||
|
#define FREEDV_MODE_700 1
|
||||||
|
#define FREEDV_MODE_700B 2
|
||||||
|
#define FREEDV_MODE_2400A 3
|
||||||
|
#define FREEDV_MODE_2400B 4
|
||||||
|
#define FREEDV_MODE_800XA 5
|
||||||
|
#define FREEDV_MODE_700C 6
|
||||||
|
|
||||||
|
struct freedv;
|
||||||
|
|
||||||
|
/* Called when text message char is decoded */
|
||||||
|
typedef void (*freedv_callback_rx)(void *, char);
|
||||||
|
/* Called when new text message char is needed */
|
||||||
|
typedef char (*freedv_callback_tx)(void *);
|
||||||
|
typedef void (*freedv_calback_error_pattern)
|
||||||
|
(void *error_pattern_callback_state, short error_pattern[], int sz_error_pattern);
|
||||||
|
|
||||||
|
/* Protocol bits are packed MSB-first */
|
||||||
|
/* Called when a frame containing protocol data is decoded */
|
||||||
|
typedef void (*freedv_callback_protorx)(void *, char *);
|
||||||
|
/* Called when a frame containing protocol data is to be sent */
|
||||||
|
typedef void (*freedv_callback_prototx)(void *, char *);
|
||||||
|
|
||||||
|
/* Data packet callbacks */
|
||||||
|
/* Called when a packet has been received */
|
||||||
|
typedef void (*freedv_callback_datarx)(void *, unsigned char *packet, size_t size);
|
||||||
|
/* Called when a new packet can be send */
|
||||||
|
typedef void (*freedv_callback_datatx)(void *, unsigned char *packet, size_t *size);
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FreeDV API functions
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// open, close ----------------------------------------------------------------
|
||||||
|
|
||||||
|
struct freedv *freedv_open(int mode);
|
||||||
|
void freedv_close (struct freedv *freedv);
|
||||||
|
|
||||||
|
// Transmit -------------------------------------------------------------------
|
||||||
|
|
||||||
|
void freedv_tx (struct freedv *freedv, short mod_out[], short speech_in[]);
|
||||||
|
void freedv_comptx (struct freedv *freedv, COMP mod_out[], short speech_in[]);
|
||||||
|
void freedv_codectx (struct freedv *f, short mod_out[], unsigned char *packed_codec_bits);
|
||||||
|
void freedv_datatx (struct freedv *f, short mod_out[]);
|
||||||
|
int freedv_data_ntxframes (struct freedv *freedv);
|
||||||
|
|
||||||
|
// Receive -------------------------------------------------------------------
|
||||||
|
|
||||||
|
int freedv_nin (struct freedv *freedv);
|
||||||
|
int freedv_rx (struct freedv *freedv, short speech_out[], short demod_in[]);
|
||||||
|
int freedv_floatrx (struct freedv *freedv, short speech_out[], float demod_in[]);
|
||||||
|
int freedv_comprx (struct freedv *freedv, short speech_out[], COMP demod_in[]);
|
||||||
|
int freedv_codecrx (struct freedv *freedv, unsigned char *packed_codec_bits, short demod_in[]);
|
||||||
|
|
||||||
|
// Set parameters ------------------------------------------------------------
|
||||||
|
|
||||||
|
void freedv_set_callback_txt (struct freedv *freedv, freedv_callback_rx rx, freedv_callback_tx tx, void *callback_state);
|
||||||
|
void freedv_set_callback_protocol (struct freedv *freedv, freedv_callback_protorx rx, freedv_callback_prototx tx, void *callback_state);
|
||||||
|
void freedv_set_callback_data (struct freedv *freedv, freedv_callback_datarx datarx, freedv_callback_datatx datatx, void *callback_state);
|
||||||
|
void freedv_set_test_frames (struct freedv *freedv, int test_frames);
|
||||||
|
void freedv_set_test_frames_diversity (struct freedv *freedv, int test_frames_diversity);
|
||||||
|
void freedv_set_smooth_symbols (struct freedv *freedv, int smooth_symbols);
|
||||||
|
void freedv_set_squelch_en (struct freedv *freedv, int squelch_en);
|
||||||
|
void freedv_set_snr_squelch_thresh (struct freedv *freedv, float snr_squelch_thresh);
|
||||||
|
void freedv_set_clip (struct freedv *freedv, int val);
|
||||||
|
void freedv_set_total_bit_errors (struct freedv *freedv, int val);
|
||||||
|
void freedv_set_total_bits (struct freedv *freedv, int val);
|
||||||
|
void freedv_set_callback_error_pattern (struct freedv *freedv, freedv_calback_error_pattern cb, void *state);
|
||||||
|
void freedv_set_varicode_code_num (struct freedv *freedv, int val);
|
||||||
|
void freedv_set_data_header (struct freedv *freedv, unsigned char *header);
|
||||||
|
int freedv_set_alt_modem_samp_rate (struct freedv *freedv, int samp_rate);
|
||||||
|
void freedv_set_carrier_ampl (struct freedv *freedv, int c, float ampl);
|
||||||
|
|
||||||
|
// Get parameters -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct MODEM_STATS;
|
||||||
|
int freedv_get_version(void);
|
||||||
|
int freedv_get_mode (struct freedv *freedv);
|
||||||
|
void freedv_get_modem_stats (struct freedv *freedv, int *sync, float *snr_est);
|
||||||
|
void freedv_get_modem_extended_stats(struct freedv *freedv, struct MODEM_STATS *stats);
|
||||||
|
int freedv_get_test_frames (struct freedv *freedv);
|
||||||
|
int freedv_get_n_speech_samples (struct freedv *freedv);
|
||||||
|
int freedv_get_modem_sample_rate (struct freedv *freedv);
|
||||||
|
int freedv_get_n_max_modem_samples (struct freedv *freedv);
|
||||||
|
int freedv_get_n_nom_modem_samples (struct freedv *freedv);
|
||||||
|
int freedv_get_total_bits (struct freedv *freedv);
|
||||||
|
int freedv_get_total_bit_errors (struct freedv *freedv);
|
||||||
|
int freedv_get_sync (struct freedv *freedv);
|
||||||
|
struct FSK * freedv_get_fsk(struct freedv *f);
|
||||||
|
struct CODEC2 *freedv_get_codec2 (struct freedv *freedv);
|
||||||
|
int freedv_get_n_codec_bits (struct freedv *freedv);
|
||||||
|
int freedv_get_sz_error_pattern (struct freedv *freedv);
|
||||||
|
int freedv_get_protocol_bits (struct freedv *freedv);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,241 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: freedv_api_internal.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: August 2014
|
||||||
|
|
||||||
|
This declares the structure freedv. A pointer to this structure is
|
||||||
|
returned by the FreeDV API freedv_open() function. The pointer is used
|
||||||
|
by the other FreeDV API functions declared in freedv_api.h. This
|
||||||
|
structure is intended to be internal to the FreeDV API. The public
|
||||||
|
functions are declared in freedv_api.h. Changes to this structure
|
||||||
|
are expected. Changes (except additions) to freedv_api.h are
|
||||||
|
discouraged.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2014 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __FREEDV__
|
||||||
|
|
||||||
|
#include "varicode.h"
|
||||||
|
#include "fsk.h"
|
||||||
|
#include "fmfsk.h"
|
||||||
|
#include "codec2_fdmdv.h"
|
||||||
|
#include "codec2_cohpsk.h"
|
||||||
|
|
||||||
|
struct quisk_cfFilter { // Structure to hold the static data for FIR filters
|
||||||
|
float * dCoefs; // filter coefficients
|
||||||
|
int nBuf; // dimension of cBuf
|
||||||
|
int nTaps; // dimension of dSamples, cSamples, dCoefs
|
||||||
|
int decim_index; // index of next sample for decimation
|
||||||
|
COMP * cSamples; // storage for old samples
|
||||||
|
COMP * ptcSamp; // next available position in cSamples
|
||||||
|
COMP * cBuf; // auxillary buffer for interpolation
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static int quisk_cfInterpDecim(COMP *, int, struct quisk_cfFilter *, int, int);
|
||||||
|
static void quisk_filt_cfInit(struct quisk_cfFilter *, float *, int);
|
||||||
|
static void quisk_filt_destroy(struct quisk_cfFilter *);
|
||||||
|
static float quiskFilt120t480[480];
|
||||||
|
|
||||||
|
struct freedv {
|
||||||
|
int mode;
|
||||||
|
|
||||||
|
struct CODEC2 *codec2;
|
||||||
|
struct FDMDV *fdmdv;
|
||||||
|
struct MODEM_STATS stats;
|
||||||
|
struct COHPSK *cohpsk;
|
||||||
|
struct FSK *fsk;
|
||||||
|
struct FMFSK *fmfsk;
|
||||||
|
|
||||||
|
struct freedv_vhf_deframer * deframer; //Extracts frames from VHF stream
|
||||||
|
|
||||||
|
struct quisk_cfFilter * ptFilter7500to8000; // Filters to change to/from 7500 and 8000 sps
|
||||||
|
struct quisk_cfFilter * ptFilter8000to7500;
|
||||||
|
|
||||||
|
int n_speech_samples;
|
||||||
|
int n_nom_modem_samples; // size of tx and most rx modem sample buffers
|
||||||
|
int n_max_modem_samples; // make your rx modem sample buffers this big
|
||||||
|
int n_nat_modem_samples; // tx modem sample block length as used by the modem before interpolation to output
|
||||||
|
|
||||||
|
int modem_sample_rate; // ATM caller is responsible for meeting this (TBC)
|
||||||
|
int clip; // non-zero for cohpsk modem output clipping for low PAPR
|
||||||
|
|
||||||
|
unsigned char *packed_codec_bits;
|
||||||
|
int *codec_bits;
|
||||||
|
int *tx_bits;
|
||||||
|
int *fdmdv_bits;
|
||||||
|
int *rx_bits;
|
||||||
|
int tx_sync_bit;
|
||||||
|
int smooth_symbols;
|
||||||
|
float *prev_rx_bits;
|
||||||
|
int n_codec_bits; // amount of codec bits in a frame
|
||||||
|
|
||||||
|
int *ptest_bits_coh;
|
||||||
|
int *ptest_bits_coh_end;
|
||||||
|
|
||||||
|
int test_frames; // set this baby for 1 to tx/rx test frames to look at bit error stats
|
||||||
|
int test_frames_diversity; // 1 -> used combined carriers for error counting on 700 waveforms
|
||||||
|
int test_frame_sync_state;
|
||||||
|
int test_frame_sync_state_upper; // when test_frames_diveristy==0 we need extra states for upper carriers
|
||||||
|
int test_frame_count;
|
||||||
|
int total_bits;
|
||||||
|
int total_bit_errors;
|
||||||
|
int sz_error_pattern;
|
||||||
|
|
||||||
|
/* optional user defined function to pass error pattern when a test frame is received */
|
||||||
|
|
||||||
|
void *error_pattern_callback_state;
|
||||||
|
void (*freedv_put_error_pattern)(void *error_pattern_callback_state, short error_pattern[], int sz_error_pattern);
|
||||||
|
|
||||||
|
int sync;
|
||||||
|
int evenframe;
|
||||||
|
float snr_est;
|
||||||
|
float snr_squelch_thresh;
|
||||||
|
int squelch_en;
|
||||||
|
int nin;
|
||||||
|
|
||||||
|
struct VARICODE_DEC varicode_dec_states;
|
||||||
|
short tx_varicode_bits[VARICODE_MAX_BITS];
|
||||||
|
int nvaricode_bits;
|
||||||
|
int varicode_bit_index;
|
||||||
|
|
||||||
|
/* user defined function ptrs to produce and consume ASCII
|
||||||
|
characters using aux txt channel */
|
||||||
|
|
||||||
|
char (*freedv_get_next_tx_char)(void *callback_state);
|
||||||
|
void (*freedv_put_next_rx_char)(void *callback_state, char c);
|
||||||
|
void *callback_state;
|
||||||
|
|
||||||
|
/* user defined functions to produce and consume protocol bits */
|
||||||
|
/* Protocol bits are packed MSB-first */
|
||||||
|
void (*freedv_put_next_proto)(void *callback_state, char *proto_bits_packed);
|
||||||
|
void (*freedv_get_next_proto)(void *callback_state, char *proto_bits_packed);
|
||||||
|
void *proto_callback_state;
|
||||||
|
int n_protocol_bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIR filter suitable for changing rates 7500 to/from 8000
|
||||||
|
// Sample 120000 Hz, pass 2700, stop 3730, ripple 0.1dB, atten 100 dB. Stop 0.03108.
|
||||||
|
static float quiskFilt120t480[480] = { -0.000005050567303837, -0.000000267011791999, 0.000000197734700398, 0.000001038946634000,
|
||||||
|
0.000002322193058869, 0.000004115682735322, 0.000006499942123311, 0.000009551098482930, 0.000013350669444763,
|
||||||
|
0.000017966192635412, 0.000023463361155584, 0.000029885221425020, 0.000037271082107518, 0.000045630720487935,
|
||||||
|
0.000054970017069384, 0.000065233162392019, 0.000076360900545177, 0.000088271373315159, 0.000100818605854714,
|
||||||
|
0.000113853476544409, 0.000127174196746337, 0.000140558396336177, 0.000153744508371709, 0.000166450784469067,
|
||||||
|
0.000178368313347299, 0.000189176709991702, 0.000198541881389953, 0.000206128795372885, 0.000211604878787747,
|
||||||
|
0.000214655997661182, 0.000214994859281552, 0.000212358734245594, 0.000206539880117977, 0.000197379393194548,
|
||||||
|
0.000184780318878738, 0.000168719942655099, 0.000149250512353807, 0.000126511346757621, 0.000100726393185629,
|
||||||
|
0.000072210925236429, 0.000041365841965015, 0.000008680571408025, -0.000025277165852799, -0.000059865389594949,
|
||||||
|
-0.000094384355854646, -0.000128080670195777, -0.000160170174848483, -0.000189854272533545, -0.000216333899003825,
|
||||||
|
-0.000238836419299503, -0.000256632149501508, -0.000269058714331757, -0.000275541485292432, -0.000275614059005332,
|
||||||
|
-0.000268937472718753, -0.000255317038867589, -0.000234717772155001, -0.000207273956099563, -0.000173297342436372,
|
||||||
|
-0.000133280012107173, -0.000087895370243821, -0.000037986085678081, 0.000015440388211825, 0.000071232572821451,
|
||||||
|
0.000128114399130489, 0.000184710477990398, 0.000239577162514028, 0.000291234779803098, 0.000338204791740229,
|
||||||
|
0.000379047713684221, 0.000412403761615261, 0.000437031818051652, 0.000451848709179591, 0.000455966225408344,
|
||||||
|
0.000448726371643413, 0.000429729020814434, 0.000398857326863837, 0.000356297600912998, 0.000302547334727027,
|
||||||
|
0.000238422248479072, 0.000165048886226905, 0.000083853091464077, -0.000003462782744354, -0.000094949813106744,
|
||||||
|
-0.000188451833293202, -0.000281651282503015, -0.000372121907291206, -0.000457387566635848, -0.000534985542936898,
|
||||||
|
-0.000602532044011899, -0.000657788245032425, -0.000698728981427767, -0.000723604675185869, -0.000731002305621048,
|
||||||
|
-0.000719899536922384, -0.000689709694056092, -0.000640319946685634, -0.000572115873292030, -0.000485996080304965,
|
||||||
|
-0.000383371840261246, -0.000266155252511831, -0.000136731311264191, 0.000002082667095075, 0.000147092077716480,
|
||||||
|
0.000294790953130229, 0.000441441918072383, 0.000583164190168290, 0.000716029226064227, 0.000836164238172957,
|
||||||
|
0.000939856052624227, 0.001023657909064450, 0.001084492755093968, 0.001119751426837743, 0.001127383039339373,
|
||||||
|
0.001105974243787613, 0.001054815583369999, 0.000973950761085690, 0.000864209315714227, 0.000727219011746881,
|
||||||
|
0.000565398080608305, 0.000381924396468366, 0.000180685902835315, -0.000033793183292569, -0.000256444114966522,
|
||||||
|
-0.000481764526566339, -0.000703946352348464, -0.000917016099829735, -0.001114986581270253, -0.001292014799874503,
|
||||||
|
-0.001442563411804926, -0.001561559957317790, -0.001644551048567398, -0.001687846581475964, -0.001688649703502788,
|
||||||
|
-0.001645167889846890, -0.001556702802350076, -0.001423714708648073, -0.001247857669697092, -0.001031986722557201,
|
||||||
|
-0.000780131048444402, -0.000497436825078657, -0.000190077210351809, 0.000134868279325909, 0.000469563533327739,
|
||||||
|
0.000805591531546815, 0.001134152328775355, 0.001446279849797673, 0.001733071409562941, 0.001985924997799762,
|
||||||
|
0.002196778054604388, 0.002358342626407065, 0.002464328098407475, 0.002509648218888532, 0.002490604086803692,
|
||||||
|
0.002405037734357425, 0.002252452724297770, 0.002034094661603120, 0.001752990365583534, 0.001413941154886139,
|
||||||
|
0.001023470495638453, 0.000589723521647734, 0.000122320866350319, -0.000367832138027160, -0.000868777013398284,
|
||||||
|
-0.001367771151677059, -0.001851587344265625, -0.002306838088978190, -0.002720317947026380, -0.003079353614002113,
|
||||||
|
-0.003372155891804708, -0.003588162376578369, -0.003718362558663737, -0.003755596511143005, -0.003694818131674599,
|
||||||
|
-0.003533315298404129, -0.003270878754553819, -0.002909914962857412, -0.002455496391464944, -0.001915346645364514,
|
||||||
|
-0.001299757227227888, -0.000621437066532776, 0.000104706515738248, 0.000861849931067767, 0.001631595707499856,
|
||||||
|
0.002394368911341672, 0.003129858565588139, 0.003817496679992245, 0.004436963307209760, 0.004968707287606522,
|
||||||
|
0.005394469536085115, 0.005697797543539088, 0.005864537618023589, 0.005883292537600076, 0.005745832319314692,
|
||||||
|
0.005447447099071761, 0.004987231255534477, 0.004368289529377007, 0.003597859022418248, 0.002687338851256991,
|
||||||
|
0.001652226293162047, 0.000511956075882180, -0.000710356149138656, -0.001988263330091648, -0.003292424566049982,
|
||||||
|
-0.004591123342747130, -0.005850857852106148, -0.007036991266043732, -0.008114450164977267, -0.009048456200082230,
|
||||||
|
-0.009805276478965942, -0.010352975302354198, -0.010662152577592631, -0.010706650669328861, -0.010464214075017983,
|
||||||
|
-0.009917087295446811, -0.009052534679222271, -0.007863270920348924, -0.006347789704693751, -0.004510582323649121,
|
||||||
|
-0.002362238055733795, 0.000080576968834213, 0.002795265196543707, 0.005753566158586979, 0.008921944932552510,
|
||||||
|
0.012262093950265378, 0.015731539846483594, 0.019284344624007944, 0.022871886384520687, 0.026443706729191677,
|
||||||
|
0.029948406200633094, 0.033334570666910354, 0.036551709955124537, 0.039551189200810140, 0.042287133974308874,
|
||||||
|
0.044717290029466283, 0.046803820535016104, 0.048514022996355009, 0.049820951883635139, 0.050703932928426454,
|
||||||
|
0.051148959210315710, 0.051148959210315710, 0.050703932928426454, 0.049820951883635139, 0.048514022996355009,
|
||||||
|
0.046803820535016104, 0.044717290029466283, 0.042287133974308874, 0.039551189200810140, 0.036551709955124537,
|
||||||
|
0.033334570666910354, 0.029948406200633094, 0.026443706729191677, 0.022871886384520687, 0.019284344624007944,
|
||||||
|
0.015731539846483594, 0.012262093950265378, 0.008921944932552510, 0.005753566158586979, 0.002795265196543707,
|
||||||
|
0.000080576968834213, -0.002362238055733795, -0.004510582323649121, -0.006347789704693751, -0.007863270920348924,
|
||||||
|
-0.009052534679222271, -0.009917087295446811, -0.010464214075017983, -0.010706650669328861, -0.010662152577592631,
|
||||||
|
-0.010352975302354198, -0.009805276478965942, -0.009048456200082230, -0.008114450164977267, -0.007036991266043732,
|
||||||
|
-0.005850857852106148, -0.004591123342747130, -0.003292424566049982, -0.001988263330091648, -0.000710356149138656,
|
||||||
|
0.000511956075882180, 0.001652226293162047, 0.002687338851256991, 0.003597859022418248, 0.004368289529377007,
|
||||||
|
0.004987231255534477, 0.005447447099071761, 0.005745832319314692, 0.005883292537600076, 0.005864537618023589,
|
||||||
|
0.005697797543539088, 0.005394469536085115, 0.004968707287606522, 0.004436963307209760, 0.003817496679992245,
|
||||||
|
0.003129858565588139, 0.002394368911341672, 0.001631595707499856, 0.000861849931067767, 0.000104706515738248,
|
||||||
|
-0.000621437066532776, -0.001299757227227888, -0.001915346645364514, -0.002455496391464944, -0.002909914962857412,
|
||||||
|
-0.003270878754553819, -0.003533315298404129, -0.003694818131674599, -0.003755596511143005, -0.003718362558663737,
|
||||||
|
-0.003588162376578369, -0.003372155891804708, -0.003079353614002113, -0.002720317947026380, -0.002306838088978190,
|
||||||
|
-0.001851587344265625, -0.001367771151677059, -0.000868777013398284, -0.000367832138027160, 0.000122320866350319,
|
||||||
|
0.000589723521647734, 0.001023470495638453, 0.001413941154886139, 0.001752990365583534, 0.002034094661603120,
|
||||||
|
0.002252452724297770, 0.002405037734357425, 0.002490604086803692, 0.002509648218888532, 0.002464328098407475,
|
||||||
|
0.002358342626407065, 0.002196778054604388, 0.001985924997799762, 0.001733071409562941, 0.001446279849797673,
|
||||||
|
0.001134152328775355, 0.000805591531546815, 0.000469563533327739, 0.000134868279325909, -0.000190077210351809,
|
||||||
|
-0.000497436825078657, -0.000780131048444402, -0.001031986722557201, -0.001247857669697092, -0.001423714708648073,
|
||||||
|
-0.001556702802350076, -0.001645167889846890, -0.001688649703502788, -0.001687846581475964, -0.001644551048567398,
|
||||||
|
-0.001561559957317790, -0.001442563411804926, -0.001292014799874503, -0.001114986581270253, -0.000917016099829735,
|
||||||
|
-0.000703946352348464, -0.000481764526566339, -0.000256444114966522, -0.000033793183292569, 0.000180685902835315,
|
||||||
|
0.000381924396468366, 0.000565398080608305, 0.000727219011746881, 0.000864209315714227, 0.000973950761085690,
|
||||||
|
0.001054815583369999, 0.001105974243787613, 0.001127383039339373, 0.001119751426837743, 0.001084492755093968,
|
||||||
|
0.001023657909064450, 0.000939856052624227, 0.000836164238172957, 0.000716029226064227, 0.000583164190168290,
|
||||||
|
0.000441441918072383, 0.000294790953130229, 0.000147092077716480, 0.000002082667095075, -0.000136731311264191,
|
||||||
|
-0.000266155252511831, -0.000383371840261246, -0.000485996080304965, -0.000572115873292030, -0.000640319946685634,
|
||||||
|
-0.000689709694056092, -0.000719899536922384, -0.000731002305621048, -0.000723604675185869, -0.000698728981427767,
|
||||||
|
-0.000657788245032425, -0.000602532044011899, -0.000534985542936898, -0.000457387566635848, -0.000372121907291206,
|
||||||
|
-0.000281651282503015, -0.000188451833293202, -0.000094949813106744, -0.000003462782744354, 0.000083853091464077,
|
||||||
|
0.000165048886226905, 0.000238422248479072, 0.000302547334727027, 0.000356297600912998, 0.000398857326863837,
|
||||||
|
0.000429729020814434, 0.000448726371643413, 0.000455966225408344, 0.000451848709179591, 0.000437031818051652,
|
||||||
|
0.000412403761615261, 0.000379047713684221, 0.000338204791740229, 0.000291234779803098, 0.000239577162514028,
|
||||||
|
0.000184710477990398, 0.000128114399130489, 0.000071232572821451, 0.000015440388211825, -0.000037986085678081,
|
||||||
|
-0.000087895370243821, -0.000133280012107173, -0.000173297342436372, -0.000207273956099563, -0.000234717772155001,
|
||||||
|
-0.000255317038867589, -0.000268937472718753, -0.000275614059005332, -0.000275541485292432, -0.000269058714331757,
|
||||||
|
-0.000256632149501508, -0.000238836419299503, -0.000216333899003825, -0.000189854272533545, -0.000160170174848483,
|
||||||
|
-0.000128080670195777, -0.000094384355854646, -0.000059865389594949, -0.000025277165852799, 0.000008680571408025,
|
||||||
|
0.000041365841965015, 0.000072210925236429, 0.000100726393185629, 0.000126511346757621, 0.000149250512353807,
|
||||||
|
0.000168719942655099, 0.000184780318878738, 0.000197379393194548, 0.000206539880117977, 0.000212358734245594,
|
||||||
|
0.000214994859281552, 0.000214655997661182, 0.000211604878787747, 0.000206128795372885, 0.000198541881389953,
|
||||||
|
0.000189176709991702, 0.000178368313347299, 0.000166450784469067, 0.000153744508371709, 0.000140558396336177,
|
||||||
|
0.000127174196746337, 0.000113853476544409, 0.000100818605854714, 0.000088271373315159, 0.000076360900545177,
|
||||||
|
0.000065233162392019, 0.000054970017069384, 0.000045630720487935, 0.000037271082107518, 0.000029885221425020,
|
||||||
|
0.000023463361155584, 0.000017966192635412, 0.000013350669444763, 0.000009551098482930, 0.000006499942123311,
|
||||||
|
0.000004115682735322, 0.000002322193058869, 0.000001038946634000, 0.000000197734700398, -0.000000267011791999,
|
||||||
|
-0.000005050567303837 };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: freedv_data_channel.h
|
||||||
|
AUTHOR......: Jeroen Vreeken
|
||||||
|
DATE CREATED: 03 March 2016
|
||||||
|
|
||||||
|
Data channel for ethernet like packets in freedv VHF frames.
|
||||||
|
Currently designed for-
|
||||||
|
* 2 control bits per frame
|
||||||
|
* 4 byte counter bits per frame
|
||||||
|
* 64 bits of data per frame
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2016 Jeroen Vreeken
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FREEDV_DATA_CHANNEL_H
|
||||||
|
#define _FREEDV_DATA_CHANNEL_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define FREEDV_DATA_CHANNEL_PACKET_MAX 2048
|
||||||
|
|
||||||
|
typedef void (*freedv_data_callback_rx)(void *, unsigned char *packet, size_t size);
|
||||||
|
typedef void (*freedv_data_callback_tx)(void *, unsigned char *packet, size_t *size);
|
||||||
|
|
||||||
|
struct freedv_data_channel {
|
||||||
|
freedv_data_callback_rx cb_rx;
|
||||||
|
void *cb_rx_state;
|
||||||
|
freedv_data_callback_tx cb_tx;
|
||||||
|
void *cb_tx_state;
|
||||||
|
|
||||||
|
unsigned char rx_header[8];
|
||||||
|
unsigned char packet_rx[FREEDV_DATA_CHANNEL_PACKET_MAX + 2];
|
||||||
|
int packet_rx_cnt;
|
||||||
|
|
||||||
|
unsigned char tx_header[8];
|
||||||
|
unsigned char packet_tx[FREEDV_DATA_CHANNEL_PACKET_MAX + 2];
|
||||||
|
int packet_tx_cnt;
|
||||||
|
size_t packet_tx_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct freedv_data_channel *freedv_data_channel_create(void);
|
||||||
|
void freedv_data_channel_destroy(struct freedv_data_channel *fdc);
|
||||||
|
|
||||||
|
void freedv_data_set_cb_rx(struct freedv_data_channel *fdc, freedv_data_callback_rx cb, void *state);
|
||||||
|
void freedv_data_set_cb_tx(struct freedv_data_channel *fdc, freedv_data_callback_tx cb, void *state);
|
||||||
|
|
||||||
|
void freedv_data_channel_rx_frame(struct freedv_data_channel *fdc, unsigned char *data, size_t size, int from_bit, int bcast_bit, int crc_bit, int end_bits);
|
||||||
|
void freedv_data_channel_tx_frame(struct freedv_data_channel *fdc, unsigned char *data, size_t size, int *from_bit, int *bcast_bit, int *crc_bit, int *end_bits);
|
||||||
|
|
||||||
|
void freedv_data_set_header(struct freedv_data_channel *fdc, unsigned char *header);
|
||||||
|
int freedv_data_get_n_tx_frames(struct freedv_data_channel *fdc, size_t size);
|
||||||
|
|
||||||
|
#endif /* _FREEDV_DATA_CHANNEL_H */
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: freedv_vhf_framing.h
|
||||||
|
AUTHOR......: Brady O'Brien
|
||||||
|
DATE CREATED: 11 February 2016
|
||||||
|
|
||||||
|
Framer and deframer for VHF FreeDV modes 'A' and 'B'
|
||||||
|
Currently designed for-
|
||||||
|
* 40ms ota modem frames
|
||||||
|
* 40ms Codec2 1300 frames
|
||||||
|
* 52 bits of Codec2 per frame
|
||||||
|
* 16 bits of unique word per frame
|
||||||
|
* 28 'spare' bits per frame
|
||||||
|
* - 4 spare bits at front and end of frame (8 total) for padding
|
||||||
|
* - 20 'protocol' bits, either for higher layers of 'protocol' or
|
||||||
|
* - 18 'protocol' bits and 2 vericode sidechannel bits
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2016 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FREEDV_VHF_FRAMING_H
|
||||||
|
#define _FREEDV_VHF_FRAMING_H
|
||||||
|
|
||||||
|
#include "freedv_data_channel.h"
|
||||||
|
|
||||||
|
/* Standard frame type */
|
||||||
|
#define FREEDV_VHF_FRAME_A 1 /* 2400A/B Frame */
|
||||||
|
#define FREEDV_HF_FRAME_B 2 /* 800XA Frame */
|
||||||
|
#define FREEDV_VHF_FRAME_AT 3 /* 4800T Frame */
|
||||||
|
|
||||||
|
struct freedv_vhf_deframer {
|
||||||
|
int ftype; /* Type of frame to be looking for */
|
||||||
|
int state; /* State of deframer */
|
||||||
|
uint8_t * bits; /* Bits currently being decanted */
|
||||||
|
uint8_t * invbits; /* Inversion of bits currently being decanted, for FMFSK */
|
||||||
|
|
||||||
|
int bitptr; /* Pointer into circular bit buffer */
|
||||||
|
int miss_cnt; /* How many UWs have been missed */
|
||||||
|
int last_uw; /* How many bits since the last UW? */
|
||||||
|
int frame_size; /* How big is a frame? */
|
||||||
|
int uw_size; /* How big is the UW */
|
||||||
|
int on_inv_bits; /* Are we using the inverted bits? */
|
||||||
|
int sym_size; /* How many bits in a modem symbol */
|
||||||
|
|
||||||
|
float ber_est; /* Bit error rate estimate */
|
||||||
|
int total_uw_bits; /* Total RX-ed bits of UW */
|
||||||
|
int total_uw_err; /* Total errors in UW bits */
|
||||||
|
|
||||||
|
struct freedv_data_channel *fdc;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Init and allocate memory for a freedv-vhf framer/deframer */
|
||||||
|
struct freedv_vhf_deframer * fvhff_create_deframer(uint8_t frame_type,int enable_bit_flip);
|
||||||
|
|
||||||
|
/* Get size of various frame parameters */
|
||||||
|
/* Frame size in bits */
|
||||||
|
int fvhff_get_frame_size(struct freedv_vhf_deframer * def);
|
||||||
|
/* Codec2 size in bytes */
|
||||||
|
int fvhff_get_codec2_size(struct freedv_vhf_deframer * def);
|
||||||
|
/* Protocol bits in bits */
|
||||||
|
int fvhff_get_proto_size(struct freedv_vhf_deframer * def);
|
||||||
|
/* Varicode bits in bits */
|
||||||
|
int fvhff_get_varicode_size(struct freedv_vhf_deframer * def);
|
||||||
|
|
||||||
|
/* Free the memory used by a freedv-vhf framer/deframer */
|
||||||
|
void fvhff_destroy_deframer(struct freedv_vhf_deframer * def);
|
||||||
|
|
||||||
|
/* Place codec and other bits into a frame */
|
||||||
|
void fvhff_frame_bits(int frame_type,uint8_t bits_out[],uint8_t codec2_in[],uint8_t proto_in[],uint8_t vc_in[]);
|
||||||
|
void fvhff_frame_data_bits(struct freedv_vhf_deframer * def, int frame_type,uint8_t bits_out[]);
|
||||||
|
|
||||||
|
/* Find and extract frames from a stream of bits */
|
||||||
|
int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[],uint8_t bits_in[]);
|
||||||
|
|
||||||
|
/* Is the de-framer synchronized? */
|
||||||
|
int fvhff_synchronized(struct freedv_vhf_deframer * def);
|
||||||
|
|
||||||
|
#endif //_FREEDV_VHF_FRAMING_H
|
||||||
@@ -0,0 +1,190 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: fsk.h
|
||||||
|
AUTHOR......: Brady O'Brien
|
||||||
|
DATE CREATED: 6 January 2016
|
||||||
|
|
||||||
|
C Implementation of 2FSK/4FSK modulator/demodulator, based on octave/fsk_horus.m
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2016 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __C2FSK_H
|
||||||
|
#define __C2FSK_H
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "comp.h"
|
||||||
|
#include "kiss_fftr.h"
|
||||||
|
#include "modem_stats.h"
|
||||||
|
|
||||||
|
#define MODE_2FSK 2
|
||||||
|
#define MODE_4FSK 4
|
||||||
|
|
||||||
|
#define MODE_M_MAX 4
|
||||||
|
|
||||||
|
#define FSK_SCALE 16383
|
||||||
|
|
||||||
|
struct FSK {
|
||||||
|
/* Static parameters set up by fsk_init */
|
||||||
|
int Ndft; /* buffer size for freq offset est fft */
|
||||||
|
int Fs; /* sample freq */
|
||||||
|
int N; /* processing buffer size */
|
||||||
|
int Rs; /* symbol rate */
|
||||||
|
int Ts; /* samples per symbol */
|
||||||
|
int Nmem; /* size of extra mem for timing adj */
|
||||||
|
int P; /* oversample rate for timing est/adj */
|
||||||
|
int Nsym; /* Number of symbols spat out in a processing frame */
|
||||||
|
int Nbits; /* Number of bits spat out in a processing frame */
|
||||||
|
int f1_tx; /* f1 for modulator */
|
||||||
|
int fs_tx; /* Space between TX freqs for modulatosr */
|
||||||
|
int mode; /* 2FSK or 4FSK */
|
||||||
|
int est_min; /* Minimum frequency for freq. estimator */
|
||||||
|
int est_max; /* Maximum frequency for freq. estimaotr */
|
||||||
|
int est_space; /* Minimum frequency spacing for freq. estimator */
|
||||||
|
float* hann_table; /* Precomputed or runtime computed hann window table */
|
||||||
|
|
||||||
|
/* Parameters used by demod */
|
||||||
|
COMP phi_c[MODE_M_MAX];
|
||||||
|
|
||||||
|
kiss_fft_cfg fft_cfg; /* Config for KISS FFT, used in freq est */
|
||||||
|
float norm_rx_timing; /* Normalized RX timing */
|
||||||
|
|
||||||
|
COMP* samp_old; /* Tail end of last batch of samples */
|
||||||
|
int nstash; /* How many elements are in there */
|
||||||
|
|
||||||
|
float* fft_est; /* Freq est FFT magnitude */
|
||||||
|
|
||||||
|
/* Memory used by demod but not important between demod frames */
|
||||||
|
|
||||||
|
/* Parameters used by mod */
|
||||||
|
COMP tx_phase_c; /* TX phase, but complex */
|
||||||
|
|
||||||
|
/* Statistics generated by demod */
|
||||||
|
float EbNodB; /* Estimated EbNo in dB */
|
||||||
|
float f_est[MODE_M_MAX];/* Estimated frequencies */
|
||||||
|
float ppm; /* Estimated PPM clock offset */
|
||||||
|
|
||||||
|
/* Parameters used by mod/demod and driving code */
|
||||||
|
int nin; /* Number of samples to feed the next demod cycle */
|
||||||
|
|
||||||
|
/* modem statistic struct */
|
||||||
|
struct MODEM_STATS *stats;
|
||||||
|
int normalise_eye; /* enables/disables normalisation of eye diagram */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an FSK config/state struct from a set of config parameters
|
||||||
|
*
|
||||||
|
* int Fs - Sample frequency
|
||||||
|
* int Rs - Symbol rate
|
||||||
|
* int tx_f1 - '0' frequency
|
||||||
|
* int tx_fs - frequency spacing
|
||||||
|
*/
|
||||||
|
struct FSK * fsk_create(int Fs, int Rs, int M, int tx_f1, int tx_fs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an FSK config/state struct from a set of config parameters
|
||||||
|
*
|
||||||
|
* int Fs - Sample frequency
|
||||||
|
* int Rs - Symbol rate
|
||||||
|
* int tx_f1 - '0' frequency
|
||||||
|
* int tx_fs - frequency spacing
|
||||||
|
*/
|
||||||
|
struct FSK * fsk_create_hbr(int Fs, int Rs, int P, int M, int tx_f1, int tx_fs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set a new number of symbols per processing frame
|
||||||
|
*/
|
||||||
|
void fsk_set_nsym(struct FSK *fsk,int nsym);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the minimum and maximum frequencies at which the freq. estimator can find tones
|
||||||
|
*/
|
||||||
|
void fsk_set_est_limits(struct FSK *fsk,int fmin, int fmax);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear the estimator states
|
||||||
|
*/
|
||||||
|
void fsk_clear_estimators(struct FSK *fsk);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fills MODEM_STATS struct with demod statistics
|
||||||
|
*/
|
||||||
|
void fsk_get_demod_stats(struct FSK *fsk, struct MODEM_STATS *stats);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destroy an FSK state struct and free it's memory
|
||||||
|
*
|
||||||
|
* struct FSK *fsk - FSK config/state struct to be destroyed
|
||||||
|
*/
|
||||||
|
void fsk_destroy(struct FSK *fsk);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modulates Nsym bits into N samples
|
||||||
|
*
|
||||||
|
* struct FSK *fsk - FSK config/state struct, set up by fsk_create
|
||||||
|
* float fsk_out[] - Buffer for N samples of modulated FSK
|
||||||
|
* uint8_t tx_bits[] - Buffer containing Nbits unpacked bits
|
||||||
|
*/
|
||||||
|
void fsk_mod(struct FSK *fsk, float fsk_out[], uint8_t tx_bits[]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modulates Nsym bits into N complex samples
|
||||||
|
*
|
||||||
|
* struct FSK *fsk - FSK config/state struct, set up by fsk_create
|
||||||
|
* comp fsk_out[] - Buffer for N samples of modulated FSK
|
||||||
|
* uint8_t tx_bits[] - Buffer containing Nbits unpacked bits
|
||||||
|
*/
|
||||||
|
void fsk_mod_c(struct FSK *fsk, COMP fsk_out[], uint8_t tx_bits[]);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the number of samples needed for the next fsk_demod() cycle
|
||||||
|
*
|
||||||
|
* struct FSK *fsk - FSK config/state struct, set up by fsk_create
|
||||||
|
* returns - number of samples to be fed into fsk_demod next cycle
|
||||||
|
*/
|
||||||
|
uint32_t fsk_nin(struct FSK *fsk);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Demodulate some number of FSK samples. The number of samples to be
|
||||||
|
* demodulated can be found by calling fsk_nin().
|
||||||
|
*
|
||||||
|
* struct FSK *fsk - FSK config/state struct, set up by fsk_create
|
||||||
|
* uint8_t rx_bits[] - Buffer for Nbits unpacked bits to be written
|
||||||
|
* float fsk_in[] - nin samples of modualted FSK
|
||||||
|
*/
|
||||||
|
void fsk_demod(struct FSK *fsk, uint8_t rx_bits[],COMP fsk_in[]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Demodulate some number of FSK samples. The number of samples to be
|
||||||
|
* demodulated can be found by calling fsk_nin().
|
||||||
|
*
|
||||||
|
* struct FSK *fsk - FSK config/state struct, set up by fsk_create
|
||||||
|
* float rx_bits[] - Buffer for Nbits soft decision bits to be written
|
||||||
|
* float fsk_in[] - nin samples of modualted FSK
|
||||||
|
*/
|
||||||
|
void fsk_demod_sd(struct FSK *fsk, float rx_bits[],COMP fsk_in[]);
|
||||||
|
|
||||||
|
/* enables/disables normalisation of eye diagram samples */
|
||||||
|
|
||||||
|
void fsk_stats_normalise_eye(struct FSK *fsk, int normalise_enable);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: golay23.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 3 March 2013
|
||||||
|
|
||||||
|
Header file for Golay FEC.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2013 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GOLAY23__
|
||||||
|
#define __GOLAY23__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void golay23_init(void);
|
||||||
|
int golay23_encode(int data);
|
||||||
|
int golay23_decode(int received_codeword);
|
||||||
|
int golay23_count_errors(int recd_codeword, int corrected_codeword);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,644 @@
|
|||||||
|
/* Generated by hanning_file() Octave function */
|
||||||
|
|
||||||
|
const float hanning[]={
|
||||||
|
0,
|
||||||
|
2.4171e-05,
|
||||||
|
9.66816e-05,
|
||||||
|
0.000217525,
|
||||||
|
0.000386689,
|
||||||
|
0.000604158,
|
||||||
|
0.00086991,
|
||||||
|
0.00118392,
|
||||||
|
0.00154616,
|
||||||
|
0.00195659,
|
||||||
|
0.00241517,
|
||||||
|
0.00292186,
|
||||||
|
0.00347661,
|
||||||
|
0.00407937,
|
||||||
|
0.00473008,
|
||||||
|
0.00542867,
|
||||||
|
0.00617507,
|
||||||
|
0.00696922,
|
||||||
|
0.00781104,
|
||||||
|
0.00870045,
|
||||||
|
0.00963736,
|
||||||
|
0.0106217,
|
||||||
|
0.0116533,
|
||||||
|
0.0127322,
|
||||||
|
0.0138581,
|
||||||
|
0.0150311,
|
||||||
|
0.0162509,
|
||||||
|
0.0175175,
|
||||||
|
0.0188308,
|
||||||
|
0.0201906,
|
||||||
|
0.0215968,
|
||||||
|
0.0230492,
|
||||||
|
0.0245478,
|
||||||
|
0.0260923,
|
||||||
|
0.0276826,
|
||||||
|
0.0293186,
|
||||||
|
0.0310001,
|
||||||
|
0.032727,
|
||||||
|
0.034499,
|
||||||
|
0.036316,
|
||||||
|
0.0381779,
|
||||||
|
0.0400844,
|
||||||
|
0.0420354,
|
||||||
|
0.0440307,
|
||||||
|
0.04607,
|
||||||
|
0.0481533,
|
||||||
|
0.0502802,
|
||||||
|
0.0524506,
|
||||||
|
0.0546643,
|
||||||
|
0.056921,
|
||||||
|
0.0592206,
|
||||||
|
0.0615627,
|
||||||
|
0.0639473,
|
||||||
|
0.0663741,
|
||||||
|
0.0688427,
|
||||||
|
0.0713531,
|
||||||
|
0.0739048,
|
||||||
|
0.0764978,
|
||||||
|
0.0791318,
|
||||||
|
0.0818064,
|
||||||
|
0.0845214,
|
||||||
|
0.0872767,
|
||||||
|
0.0900718,
|
||||||
|
0.0929066,
|
||||||
|
0.0957807,
|
||||||
|
0.0986939,
|
||||||
|
0.101646,
|
||||||
|
0.104636,
|
||||||
|
0.107665,
|
||||||
|
0.110732,
|
||||||
|
0.113836,
|
||||||
|
0.116978,
|
||||||
|
0.120156,
|
||||||
|
0.123372,
|
||||||
|
0.126624,
|
||||||
|
0.129912,
|
||||||
|
0.133235,
|
||||||
|
0.136594,
|
||||||
|
0.139989,
|
||||||
|
0.143418,
|
||||||
|
0.146881,
|
||||||
|
0.150379,
|
||||||
|
0.153911,
|
||||||
|
0.157476,
|
||||||
|
0.161074,
|
||||||
|
0.164705,
|
||||||
|
0.168368,
|
||||||
|
0.172063,
|
||||||
|
0.17579,
|
||||||
|
0.179549,
|
||||||
|
0.183338,
|
||||||
|
0.187158,
|
||||||
|
0.191008,
|
||||||
|
0.194888,
|
||||||
|
0.198798,
|
||||||
|
0.202737,
|
||||||
|
0.206704,
|
||||||
|
0.2107,
|
||||||
|
0.214724,
|
||||||
|
0.218775,
|
||||||
|
0.222854,
|
||||||
|
0.226959,
|
||||||
|
0.231091,
|
||||||
|
0.235249,
|
||||||
|
0.239432,
|
||||||
|
0.243641,
|
||||||
|
0.247874,
|
||||||
|
0.252132,
|
||||||
|
0.256414,
|
||||||
|
0.260719,
|
||||||
|
0.265047,
|
||||||
|
0.269398,
|
||||||
|
0.273772,
|
||||||
|
0.278167,
|
||||||
|
0.282584,
|
||||||
|
0.287021,
|
||||||
|
0.29148,
|
||||||
|
0.295958,
|
||||||
|
0.300456,
|
||||||
|
0.304974,
|
||||||
|
0.30951,
|
||||||
|
0.314065,
|
||||||
|
0.318638,
|
||||||
|
0.323228,
|
||||||
|
0.327835,
|
||||||
|
0.332459,
|
||||||
|
0.3371,
|
||||||
|
0.341756,
|
||||||
|
0.346427,
|
||||||
|
0.351113,
|
||||||
|
0.355814,
|
||||||
|
0.360528,
|
||||||
|
0.365256,
|
||||||
|
0.369997,
|
||||||
|
0.374751,
|
||||||
|
0.379516,
|
||||||
|
0.384293,
|
||||||
|
0.389082,
|
||||||
|
0.393881,
|
||||||
|
0.398691,
|
||||||
|
0.40351,
|
||||||
|
0.408338,
|
||||||
|
0.413176,
|
||||||
|
0.418022,
|
||||||
|
0.422876,
|
||||||
|
0.427737,
|
||||||
|
0.432605,
|
||||||
|
0.43748,
|
||||||
|
0.44236,
|
||||||
|
0.447247,
|
||||||
|
0.452138,
|
||||||
|
0.457034,
|
||||||
|
0.461935,
|
||||||
|
0.466839,
|
||||||
|
0.471746,
|
||||||
|
0.476655,
|
||||||
|
0.481568,
|
||||||
|
0.486481,
|
||||||
|
0.491397,
|
||||||
|
0.496313,
|
||||||
|
0.501229,
|
||||||
|
0.506145,
|
||||||
|
0.511061,
|
||||||
|
0.515976,
|
||||||
|
0.520889,
|
||||||
|
0.5258,
|
||||||
|
0.530708,
|
||||||
|
0.535614,
|
||||||
|
0.540516,
|
||||||
|
0.545414,
|
||||||
|
0.550308,
|
||||||
|
0.555197,
|
||||||
|
0.560081,
|
||||||
|
0.564958,
|
||||||
|
0.56983,
|
||||||
|
0.574695,
|
||||||
|
0.579552,
|
||||||
|
0.584402,
|
||||||
|
0.589244,
|
||||||
|
0.594077,
|
||||||
|
0.598901,
|
||||||
|
0.603715,
|
||||||
|
0.60852,
|
||||||
|
0.613314,
|
||||||
|
0.618097,
|
||||||
|
0.622868,
|
||||||
|
0.627628,
|
||||||
|
0.632375,
|
||||||
|
0.63711,
|
||||||
|
0.641831,
|
||||||
|
0.646538,
|
||||||
|
0.651232,
|
||||||
|
0.655911,
|
||||||
|
0.660574,
|
||||||
|
0.665222,
|
||||||
|
0.669855,
|
||||||
|
0.67447,
|
||||||
|
0.679069,
|
||||||
|
0.683651,
|
||||||
|
0.688215,
|
||||||
|
0.69276,
|
||||||
|
0.697287,
|
||||||
|
0.701795,
|
||||||
|
0.706284,
|
||||||
|
0.710752,
|
||||||
|
0.7152,
|
||||||
|
0.719627,
|
||||||
|
0.724033,
|
||||||
|
0.728418,
|
||||||
|
0.73278,
|
||||||
|
0.73712,
|
||||||
|
0.741437,
|
||||||
|
0.74573,
|
||||||
|
0.75,
|
||||||
|
0.754246,
|
||||||
|
0.758467,
|
||||||
|
0.762663,
|
||||||
|
0.766833,
|
||||||
|
0.770978,
|
||||||
|
0.775097,
|
||||||
|
0.779189,
|
||||||
|
0.783254,
|
||||||
|
0.787291,
|
||||||
|
0.791301,
|
||||||
|
0.795283,
|
||||||
|
0.799236,
|
||||||
|
0.80316,
|
||||||
|
0.807055,
|
||||||
|
0.810921,
|
||||||
|
0.814756,
|
||||||
|
0.81856,
|
||||||
|
0.822334,
|
||||||
|
0.826077,
|
||||||
|
0.829788,
|
||||||
|
0.833468,
|
||||||
|
0.837115,
|
||||||
|
0.840729,
|
||||||
|
0.844311,
|
||||||
|
0.847859,
|
||||||
|
0.851374,
|
||||||
|
0.854855,
|
||||||
|
0.858301,
|
||||||
|
0.861713,
|
||||||
|
0.86509,
|
||||||
|
0.868431,
|
||||||
|
0.871737,
|
||||||
|
0.875007,
|
||||||
|
0.87824,
|
||||||
|
0.881437,
|
||||||
|
0.884598,
|
||||||
|
0.887721,
|
||||||
|
0.890806,
|
||||||
|
0.893854,
|
||||||
|
0.896864,
|
||||||
|
0.899835,
|
||||||
|
0.902768,
|
||||||
|
0.905661,
|
||||||
|
0.908516,
|
||||||
|
0.911331,
|
||||||
|
0.914106,
|
||||||
|
0.916841,
|
||||||
|
0.919536,
|
||||||
|
0.92219,
|
||||||
|
0.924804,
|
||||||
|
0.927376,
|
||||||
|
0.929907,
|
||||||
|
0.932397,
|
||||||
|
0.934845,
|
||||||
|
0.93725,
|
||||||
|
0.939614,
|
||||||
|
0.941935,
|
||||||
|
0.944213,
|
||||||
|
0.946448,
|
||||||
|
0.94864,
|
||||||
|
0.950789,
|
||||||
|
0.952894,
|
||||||
|
0.954955,
|
||||||
|
0.956972,
|
||||||
|
0.958946,
|
||||||
|
0.960874,
|
||||||
|
0.962759,
|
||||||
|
0.964598,
|
||||||
|
0.966393,
|
||||||
|
0.968142,
|
||||||
|
0.969846,
|
||||||
|
0.971505,
|
||||||
|
0.973118,
|
||||||
|
0.974686,
|
||||||
|
0.976207,
|
||||||
|
0.977683,
|
||||||
|
0.979112,
|
||||||
|
0.980495,
|
||||||
|
0.981832,
|
||||||
|
0.983122,
|
||||||
|
0.984365,
|
||||||
|
0.985561,
|
||||||
|
0.986711,
|
||||||
|
0.987813,
|
||||||
|
0.988868,
|
||||||
|
0.989876,
|
||||||
|
0.990837,
|
||||||
|
0.99175,
|
||||||
|
0.992616,
|
||||||
|
0.993434,
|
||||||
|
0.994204,
|
||||||
|
0.994927,
|
||||||
|
0.995601,
|
||||||
|
0.996228,
|
||||||
|
0.996807,
|
||||||
|
0.997337,
|
||||||
|
0.99782,
|
||||||
|
0.998255,
|
||||||
|
0.998641,
|
||||||
|
0.998979,
|
||||||
|
0.999269,
|
||||||
|
0.999511,
|
||||||
|
0.999704,
|
||||||
|
0.999849,
|
||||||
|
0.999946,
|
||||||
|
0.999994,
|
||||||
|
0.999994,
|
||||||
|
0.999946,
|
||||||
|
0.999849,
|
||||||
|
0.999704,
|
||||||
|
0.999511,
|
||||||
|
0.999269,
|
||||||
|
0.998979,
|
||||||
|
0.998641,
|
||||||
|
0.998255,
|
||||||
|
0.99782,
|
||||||
|
0.997337,
|
||||||
|
0.996807,
|
||||||
|
0.996228,
|
||||||
|
0.995601,
|
||||||
|
0.994927,
|
||||||
|
0.994204,
|
||||||
|
0.993434,
|
||||||
|
0.992616,
|
||||||
|
0.99175,
|
||||||
|
0.990837,
|
||||||
|
0.989876,
|
||||||
|
0.988868,
|
||||||
|
0.987813,
|
||||||
|
0.986711,
|
||||||
|
0.985561,
|
||||||
|
0.984365,
|
||||||
|
0.983122,
|
||||||
|
0.981832,
|
||||||
|
0.980495,
|
||||||
|
0.979112,
|
||||||
|
0.977683,
|
||||||
|
0.976207,
|
||||||
|
0.974686,
|
||||||
|
0.973118,
|
||||||
|
0.971505,
|
||||||
|
0.969846,
|
||||||
|
0.968142,
|
||||||
|
0.966393,
|
||||||
|
0.964598,
|
||||||
|
0.962759,
|
||||||
|
0.960874,
|
||||||
|
0.958946,
|
||||||
|
0.956972,
|
||||||
|
0.954955,
|
||||||
|
0.952894,
|
||||||
|
0.950789,
|
||||||
|
0.94864,
|
||||||
|
0.946448,
|
||||||
|
0.944213,
|
||||||
|
0.941935,
|
||||||
|
0.939614,
|
||||||
|
0.93725,
|
||||||
|
0.934845,
|
||||||
|
0.932397,
|
||||||
|
0.929907,
|
||||||
|
0.927376,
|
||||||
|
0.924804,
|
||||||
|
0.92219,
|
||||||
|
0.919536,
|
||||||
|
0.916841,
|
||||||
|
0.914106,
|
||||||
|
0.911331,
|
||||||
|
0.908516,
|
||||||
|
0.905661,
|
||||||
|
0.902768,
|
||||||
|
0.899835,
|
||||||
|
0.896864,
|
||||||
|
0.893854,
|
||||||
|
0.890806,
|
||||||
|
0.887721,
|
||||||
|
0.884598,
|
||||||
|
0.881437,
|
||||||
|
0.87824,
|
||||||
|
0.875007,
|
||||||
|
0.871737,
|
||||||
|
0.868431,
|
||||||
|
0.86509,
|
||||||
|
0.861713,
|
||||||
|
0.858301,
|
||||||
|
0.854855,
|
||||||
|
0.851374,
|
||||||
|
0.847859,
|
||||||
|
0.844311,
|
||||||
|
0.840729,
|
||||||
|
0.837115,
|
||||||
|
0.833468,
|
||||||
|
0.829788,
|
||||||
|
0.826077,
|
||||||
|
0.822334,
|
||||||
|
0.81856,
|
||||||
|
0.814756,
|
||||||
|
0.810921,
|
||||||
|
0.807055,
|
||||||
|
0.80316,
|
||||||
|
0.799236,
|
||||||
|
0.795283,
|
||||||
|
0.791301,
|
||||||
|
0.787291,
|
||||||
|
0.783254,
|
||||||
|
0.779189,
|
||||||
|
0.775097,
|
||||||
|
0.770978,
|
||||||
|
0.766833,
|
||||||
|
0.762663,
|
||||||
|
0.758467,
|
||||||
|
0.754246,
|
||||||
|
0.75,
|
||||||
|
0.74573,
|
||||||
|
0.741437,
|
||||||
|
0.73712,
|
||||||
|
0.73278,
|
||||||
|
0.728418,
|
||||||
|
0.724033,
|
||||||
|
0.719627,
|
||||||
|
0.7152,
|
||||||
|
0.710752,
|
||||||
|
0.706284,
|
||||||
|
0.701795,
|
||||||
|
0.697287,
|
||||||
|
0.69276,
|
||||||
|
0.688215,
|
||||||
|
0.683651,
|
||||||
|
0.679069,
|
||||||
|
0.67447,
|
||||||
|
0.669855,
|
||||||
|
0.665222,
|
||||||
|
0.660574,
|
||||||
|
0.655911,
|
||||||
|
0.651232,
|
||||||
|
0.646538,
|
||||||
|
0.641831,
|
||||||
|
0.63711,
|
||||||
|
0.632375,
|
||||||
|
0.627628,
|
||||||
|
0.622868,
|
||||||
|
0.618097,
|
||||||
|
0.613314,
|
||||||
|
0.60852,
|
||||||
|
0.603715,
|
||||||
|
0.598901,
|
||||||
|
0.594077,
|
||||||
|
0.589244,
|
||||||
|
0.584402,
|
||||||
|
0.579552,
|
||||||
|
0.574695,
|
||||||
|
0.56983,
|
||||||
|
0.564958,
|
||||||
|
0.560081,
|
||||||
|
0.555197,
|
||||||
|
0.550308,
|
||||||
|
0.545414,
|
||||||
|
0.540516,
|
||||||
|
0.535614,
|
||||||
|
0.530708,
|
||||||
|
0.5258,
|
||||||
|
0.520889,
|
||||||
|
0.515976,
|
||||||
|
0.511061,
|
||||||
|
0.506145,
|
||||||
|
0.501229,
|
||||||
|
0.496313,
|
||||||
|
0.491397,
|
||||||
|
0.486481,
|
||||||
|
0.481568,
|
||||||
|
0.476655,
|
||||||
|
0.471746,
|
||||||
|
0.466839,
|
||||||
|
0.461935,
|
||||||
|
0.457034,
|
||||||
|
0.452138,
|
||||||
|
0.447247,
|
||||||
|
0.44236,
|
||||||
|
0.43748,
|
||||||
|
0.432605,
|
||||||
|
0.427737,
|
||||||
|
0.422876,
|
||||||
|
0.418022,
|
||||||
|
0.413176,
|
||||||
|
0.408338,
|
||||||
|
0.40351,
|
||||||
|
0.398691,
|
||||||
|
0.393881,
|
||||||
|
0.389082,
|
||||||
|
0.384293,
|
||||||
|
0.379516,
|
||||||
|
0.374751,
|
||||||
|
0.369997,
|
||||||
|
0.365256,
|
||||||
|
0.360528,
|
||||||
|
0.355814,
|
||||||
|
0.351113,
|
||||||
|
0.346427,
|
||||||
|
0.341756,
|
||||||
|
0.3371,
|
||||||
|
0.332459,
|
||||||
|
0.327835,
|
||||||
|
0.323228,
|
||||||
|
0.318638,
|
||||||
|
0.314065,
|
||||||
|
0.30951,
|
||||||
|
0.304974,
|
||||||
|
0.300456,
|
||||||
|
0.295958,
|
||||||
|
0.29148,
|
||||||
|
0.287021,
|
||||||
|
0.282584,
|
||||||
|
0.278167,
|
||||||
|
0.273772,
|
||||||
|
0.269398,
|
||||||
|
0.265047,
|
||||||
|
0.260719,
|
||||||
|
0.256414,
|
||||||
|
0.252132,
|
||||||
|
0.247874,
|
||||||
|
0.243641,
|
||||||
|
0.239432,
|
||||||
|
0.235249,
|
||||||
|
0.231091,
|
||||||
|
0.226959,
|
||||||
|
0.222854,
|
||||||
|
0.218775,
|
||||||
|
0.214724,
|
||||||
|
0.2107,
|
||||||
|
0.206704,
|
||||||
|
0.202737,
|
||||||
|
0.198798,
|
||||||
|
0.194888,
|
||||||
|
0.191008,
|
||||||
|
0.187158,
|
||||||
|
0.183338,
|
||||||
|
0.179549,
|
||||||
|
0.17579,
|
||||||
|
0.172063,
|
||||||
|
0.168368,
|
||||||
|
0.164705,
|
||||||
|
0.161074,
|
||||||
|
0.157476,
|
||||||
|
0.153911,
|
||||||
|
0.150379,
|
||||||
|
0.146881,
|
||||||
|
0.143418,
|
||||||
|
0.139989,
|
||||||
|
0.136594,
|
||||||
|
0.133235,
|
||||||
|
0.129912,
|
||||||
|
0.126624,
|
||||||
|
0.123372,
|
||||||
|
0.120156,
|
||||||
|
0.116978,
|
||||||
|
0.113836,
|
||||||
|
0.110732,
|
||||||
|
0.107665,
|
||||||
|
0.104636,
|
||||||
|
0.101646,
|
||||||
|
0.0986939,
|
||||||
|
0.0957807,
|
||||||
|
0.0929066,
|
||||||
|
0.0900718,
|
||||||
|
0.0872767,
|
||||||
|
0.0845214,
|
||||||
|
0.0818064,
|
||||||
|
0.0791318,
|
||||||
|
0.0764978,
|
||||||
|
0.0739048,
|
||||||
|
0.0713531,
|
||||||
|
0.0688427,
|
||||||
|
0.0663741,
|
||||||
|
0.0639473,
|
||||||
|
0.0615627,
|
||||||
|
0.0592206,
|
||||||
|
0.056921,
|
||||||
|
0.0546643,
|
||||||
|
0.0524506,
|
||||||
|
0.0502802,
|
||||||
|
0.0481533,
|
||||||
|
0.04607,
|
||||||
|
0.0440307,
|
||||||
|
0.0420354,
|
||||||
|
0.0400844,
|
||||||
|
0.0381779,
|
||||||
|
0.036316,
|
||||||
|
0.034499,
|
||||||
|
0.032727,
|
||||||
|
0.0310001,
|
||||||
|
0.0293186,
|
||||||
|
0.0276826,
|
||||||
|
0.0260923,
|
||||||
|
0.0245478,
|
||||||
|
0.0230492,
|
||||||
|
0.0215968,
|
||||||
|
0.0201906,
|
||||||
|
0.0188308,
|
||||||
|
0.0175175,
|
||||||
|
0.0162509,
|
||||||
|
0.0150311,
|
||||||
|
0.0138581,
|
||||||
|
0.0127322,
|
||||||
|
0.0116533,
|
||||||
|
0.0106217,
|
||||||
|
0.00963736,
|
||||||
|
0.00870045,
|
||||||
|
0.00781104,
|
||||||
|
0.00696922,
|
||||||
|
0.00617507,
|
||||||
|
0.00542867,
|
||||||
|
0.00473008,
|
||||||
|
0.00407937,
|
||||||
|
0.00347661,
|
||||||
|
0.00292186,
|
||||||
|
0.00241517,
|
||||||
|
0.00195659,
|
||||||
|
0.00154616,
|
||||||
|
0.00118392,
|
||||||
|
0.00086991,
|
||||||
|
0.000604158,
|
||||||
|
0.000386689,
|
||||||
|
0.000217525,
|
||||||
|
9.66816e-05,
|
||||||
|
2.4171e-05,
|
||||||
|
0
|
||||||
|
};
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: horus_l2.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: Dec 2015
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef __HORUS_L2__
|
||||||
|
#define __HORUS_L2__
|
||||||
|
|
||||||
|
int horus_l2_get_num_tx_data_bytes(int num_payload_data_bytes);
|
||||||
|
|
||||||
|
/* returns number of output bytes in output_tx_data */
|
||||||
|
int horus_l2_encode_tx_packet(unsigned char *output_tx_data,
|
||||||
|
unsigned char *input_payload_data,
|
||||||
|
int num_payload_data_bytes);
|
||||||
|
|
||||||
|
void horus_l2_decode_rx_packet(unsigned char *output_payload_data,
|
||||||
|
unsigned char *input_rx_data,
|
||||||
|
int num_payload_data_bytes);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/* Hilbert Transform FIR filter coeffs */
|
||||||
|
/* Generated by make_hilb Octave script */
|
||||||
|
|
||||||
|
#define HT_N 100
|
||||||
|
|
||||||
|
COMP ht_coeff[]={
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,-0.000001},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,-0.000017},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,-0.000079},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,-0.000217},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,-0.000461},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,-0.000842},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,-0.001391},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,-0.002140},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,-0.003121},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,-0.004371},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,-0.005928},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,-0.007839},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,-0.010159},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,-0.012957},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,-0.016327},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,-0.020399},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,-0.025364},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,-0.031512},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,-0.039319},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,-0.049610},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,-0.063952},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,-0.085722},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,-0.123718},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,-0.210249},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,-0.636250},
|
||||||
|
{0.999748,0.000000},
|
||||||
|
{0.000000,0.634969},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,0.208979},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,0.122467},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,0.084502},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,0.062771},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,0.048477},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,0.038242},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,0.030497},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,0.024418},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,0.019527},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,0.015532},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,0.012242},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,0.009524},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,0.007285},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,0.005454},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,0.003973},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,0.002796},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,0.001882},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,0.001196},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,0.000701},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,0.000367},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,0.000160},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,0.000051},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{-0.000000,0.000008},
|
||||||
|
{0.000000,0.000000},
|
||||||
|
{0.000000,0.000000}
|
||||||
|
};
|
||||||
@@ -0,0 +1,331 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: interp.c
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 9/10/09
|
||||||
|
|
||||||
|
Interpolation of 20ms frames to 10ms frames.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2009 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
#include "interp.h"
|
||||||
|
#include "lsp.h"
|
||||||
|
#include "quantise.h"
|
||||||
|
|
||||||
|
float sample_log_amp(MODEL *model, float w);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FUNCTION....: interp()
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 22/8/10
|
||||||
|
|
||||||
|
Given two frames decribed by model parameters 20ms apart, determines
|
||||||
|
the model parameters of the 10ms frame between them. Assumes
|
||||||
|
voicing is available for middle (interpolated) frame. Outputs are
|
||||||
|
amplitudes and Wo for the interpolated frame.
|
||||||
|
|
||||||
|
This version can interpolate the amplitudes between two frames of
|
||||||
|
different Wo and L.
|
||||||
|
|
||||||
|
This version works by log linear interpolation, but listening tests
|
||||||
|
showed it creates problems in background noise, e.g. hts2a and mmt1.
|
||||||
|
When this function is used (--dec mode) bg noise appears to be
|
||||||
|
amplitude modulated, and gets louder. The interp_lsp() function
|
||||||
|
below seems to do a better job.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void interpolate(
|
||||||
|
MODEL *interp, /* interpolated model params */
|
||||||
|
MODEL *prev, /* previous frames model params */
|
||||||
|
MODEL *next, /* next frames model params */
|
||||||
|
float Wo_min
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int l;
|
||||||
|
float w,log_amp;
|
||||||
|
|
||||||
|
/* Wo depends on voicing of this and adjacent frames */
|
||||||
|
|
||||||
|
if (interp->voiced) {
|
||||||
|
if (prev->voiced && next->voiced)
|
||||||
|
interp->Wo = (prev->Wo + next->Wo)/2.0;
|
||||||
|
if (!prev->voiced && next->voiced)
|
||||||
|
interp->Wo = next->Wo;
|
||||||
|
if (prev->voiced && !next->voiced)
|
||||||
|
interp->Wo = prev->Wo;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
interp->Wo = Wo_min;
|
||||||
|
}
|
||||||
|
interp->L = PI/interp->Wo;
|
||||||
|
|
||||||
|
/* Interpolate amplitudes using linear interpolation in log domain */
|
||||||
|
|
||||||
|
for(l=1; l<=interp->L; l++) {
|
||||||
|
w = l*interp->Wo;
|
||||||
|
log_amp = (sample_log_amp(prev, w) + sample_log_amp(next, w))/2.0;
|
||||||
|
interp->A[l] = powf(10.0, log_amp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FUNCTION....: sample_log_amp()
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 22/8/10
|
||||||
|
|
||||||
|
Samples the amplitude envelope at an arbitrary frequency w. Uses
|
||||||
|
linear interpolation in the log domain to sample between harmonic
|
||||||
|
amplitudes.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float sample_log_amp(MODEL *model, float w)
|
||||||
|
{
|
||||||
|
int m;
|
||||||
|
float f, log_amp;
|
||||||
|
|
||||||
|
assert(w > 0.0); assert (w <= PI);
|
||||||
|
|
||||||
|
m = floorf(w/model->Wo + 0.5);
|
||||||
|
f = (w - m*model->Wo)/w;
|
||||||
|
assert(f <= 1.0);
|
||||||
|
|
||||||
|
if (m < 1) {
|
||||||
|
log_amp = f*log10f(model->A[1] + 1E-6);
|
||||||
|
}
|
||||||
|
else if ((m+1) > model->L) {
|
||||||
|
log_amp = (1.0-f)*log10f(model->A[model->L] + 1E-6);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log_amp = (1.0-f)*log10f(model->A[m] + 1E-6) +
|
||||||
|
f*log10f(model->A[m+1] + 1E-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
return log_amp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NOT_NEEDED
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FUNCTION....: interp_lsp()
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 10 Nov 2010
|
||||||
|
|
||||||
|
Given two frames decribed by model parameters 20ms apart, determines
|
||||||
|
the model parameters of the 10ms frame between them. Assumes
|
||||||
|
voicing is available for middle (interpolated) frame. Outputs are
|
||||||
|
amplitudes and Wo for the interpolated frame.
|
||||||
|
|
||||||
|
This version uses interpolation of LSPs, seems to do a better job
|
||||||
|
with bg noise.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void interpolate_lsp(
|
||||||
|
codec2_fft_cfg fft_fwd_cfg,
|
||||||
|
MODEL *interp, /* interpolated model params */
|
||||||
|
MODEL *prev, /* previous frames model params */
|
||||||
|
MODEL *next, /* next frames model params */
|
||||||
|
float *prev_lsps, /* previous frames LSPs */
|
||||||
|
float prev_e, /* previous frames LPC energy */
|
||||||
|
float *next_lsps, /* next frames LSPs */
|
||||||
|
float next_e, /* next frames LPC energy */
|
||||||
|
float *ak_interp, /* interpolated aks for this frame */
|
||||||
|
float *lsps_interp, /* interpolated lsps for this frame */
|
||||||
|
float Wo_min
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
float e;
|
||||||
|
float snr;
|
||||||
|
|
||||||
|
/* trap corner case where V est is probably wrong */
|
||||||
|
|
||||||
|
if (interp->voiced && !prev->voiced && !next->voiced) {
|
||||||
|
interp->voiced = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wo depends on voicing of this and adjacent frames */
|
||||||
|
|
||||||
|
if (interp->voiced) {
|
||||||
|
if (prev->voiced && next->voiced)
|
||||||
|
interp->Wo = (prev->Wo + next->Wo)/2.0;
|
||||||
|
if (!prev->voiced && next->voiced)
|
||||||
|
interp->Wo = next->Wo;
|
||||||
|
if (prev->voiced && !next->voiced)
|
||||||
|
interp->Wo = prev->Wo;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
interp->Wo = Wo_min;
|
||||||
|
}
|
||||||
|
interp->L = PI/interp->Wo;
|
||||||
|
|
||||||
|
//printf(" interp: prev_v: %d next_v: %d prev_Wo: %f next_Wo: %f\n",
|
||||||
|
// prev->voiced, next->voiced, prev->Wo, next->Wo);
|
||||||
|
//printf(" interp: Wo: %1.5f L: %d\n", interp->Wo, interp->L);
|
||||||
|
|
||||||
|
/* interpolate LSPs */
|
||||||
|
|
||||||
|
for(i=0; i<LPC_ORD; i++) {
|
||||||
|
lsps_interp[i] = (prev_lsps[i] + next_lsps[i])/2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interpolate LPC energy in log domain */
|
||||||
|
|
||||||
|
e = powf(10.0, (log10f(prev_e) + log10f(next_e))/2.0);
|
||||||
|
//printf(" interp: e: %f\n", e);
|
||||||
|
|
||||||
|
/* convert back to amplitudes */
|
||||||
|
|
||||||
|
lsp_to_lpc(lsps_interp, ak_interp, LPC_ORD);
|
||||||
|
aks_to_M2(fft_fwd_cfg, ak_interp, LPC_ORD, interp, e, &snr, 0, 0, 1, 1, LPCPF_BETA, LPCPF_GAMMA);
|
||||||
|
//printf(" interp: ak[1]: %f A[1] %f\n", ak_interp[1], interp->A[1]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FUNCTION....: interp_Wo()
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 22 May 2012
|
||||||
|
|
||||||
|
Interpolates centre 10ms sample of Wo and L samples given two
|
||||||
|
samples 20ms apart. Assumes voicing is available for centre
|
||||||
|
(interpolated) frame.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void interp_Wo(
|
||||||
|
MODEL *interp, /* interpolated model params */
|
||||||
|
MODEL *prev, /* previous frames model params */
|
||||||
|
MODEL *next, /* next frames model params */
|
||||||
|
float Wo_min
|
||||||
|
)
|
||||||
|
{
|
||||||
|
interp_Wo2(interp, prev, next, 0.5, Wo_min);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FUNCTION....: interp_Wo2()
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 22 May 2012
|
||||||
|
|
||||||
|
Weighted interpolation of two Wo samples.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void interp_Wo2(
|
||||||
|
MODEL *interp, /* interpolated model params */
|
||||||
|
MODEL *prev, /* previous frames model params */
|
||||||
|
MODEL *next, /* next frames model params */
|
||||||
|
float weight,
|
||||||
|
float Wo_min
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* trap corner case where voicing est is probably wrong */
|
||||||
|
|
||||||
|
if (interp->voiced && !prev->voiced && !next->voiced) {
|
||||||
|
interp->voiced = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wo depends on voicing of this and adjacent frames */
|
||||||
|
|
||||||
|
if (interp->voiced) {
|
||||||
|
if (prev->voiced && next->voiced)
|
||||||
|
interp->Wo = (1.0 - weight)*prev->Wo + weight*next->Wo;
|
||||||
|
if (!prev->voiced && next->voiced)
|
||||||
|
interp->Wo = next->Wo;
|
||||||
|
if (prev->voiced && !next->voiced)
|
||||||
|
interp->Wo = prev->Wo;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
interp->Wo = Wo_min;
|
||||||
|
}
|
||||||
|
interp->L = PI/interp->Wo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FUNCTION....: interp_energy()
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 22 May 2012
|
||||||
|
|
||||||
|
Interpolates centre 10ms sample of energy given two samples 20ms
|
||||||
|
apart.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float interp_energy(float prev_e, float next_e)
|
||||||
|
{
|
||||||
|
//return powf(10.0, (log10f(prev_e) + log10f(next_e))/2.0);
|
||||||
|
return sqrtf(prev_e * next_e); //looks better is math. identical and faster math
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FUNCTION....: interp_energy2()
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 22 May 2012
|
||||||
|
|
||||||
|
Interpolates centre 10ms sample of energy given two samples 20ms
|
||||||
|
apart.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float interp_energy2(float prev_e, float next_e, float weight)
|
||||||
|
{
|
||||||
|
return powf(10.0, (1.0 - weight)*log10f(prev_e) + weight*log10f(next_e));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FUNCTION....: interpolate_lsp_ver2()
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 22 May 2012
|
||||||
|
|
||||||
|
Weighted interpolation of LSPs.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void interpolate_lsp_ver2(float interp[], float prev[], float next[], float weight, int order)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i<order; i++)
|
||||||
|
interp[i] = (1.0 - weight)*prev[i] + weight*next[i];
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: interp.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: 9/10/09
|
||||||
|
|
||||||
|
Interpolation of 20ms frames to 10ms frames.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2009 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __INTERP__
|
||||||
|
#define __INTERP__
|
||||||
|
|
||||||
|
#include "kiss_fft.h"
|
||||||
|
|
||||||
|
void interpolate(MODEL *interp, MODEL *prev, MODEL *next);
|
||||||
|
void interpolate_lsp(kiss_fft_cfg fft_dec_cfg,
|
||||||
|
MODEL *interp, MODEL *prev, MODEL *next,
|
||||||
|
float *prev_lsps, float prev_e,
|
||||||
|
float *next_lsps, float next_e,
|
||||||
|
float *ak_interp, float *lsps_interp, float Wo_min);
|
||||||
|
void interp_Wo(MODEL *interp, MODEL *prev, MODEL *next, float Wo_min);
|
||||||
|
void interp_Wo2(MODEL *interp, MODEL *prev, MODEL *next, float weight, float Wo_min);
|
||||||
|
float interp_energy(float prev, float next);
|
||||||
|
float interp_energy2(float prev, float next, float weight);
|
||||||
|
void interpolate_lsp_ver2(float interp[], float prev[], float next[], float weight, int order);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,408 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2003-2010, Mark Borgerding
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "_kiss_fft_guts.h"
|
||||||
|
/* The guts header contains all the multiplication and addition macros that are defined for
|
||||||
|
fixed or floating point complex numbers. It also delares the kf_ internal functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void kf_bfly2(
|
||||||
|
kiss_fft_cpx * Fout,
|
||||||
|
const size_t fstride,
|
||||||
|
const kiss_fft_cfg st,
|
||||||
|
int m
|
||||||
|
)
|
||||||
|
{
|
||||||
|
kiss_fft_cpx * Fout2;
|
||||||
|
kiss_fft_cpx * tw1 = st->twiddles;
|
||||||
|
kiss_fft_cpx t;
|
||||||
|
Fout2 = Fout + m;
|
||||||
|
do{
|
||||||
|
C_FIXDIV(*Fout,2); C_FIXDIV(*Fout2,2);
|
||||||
|
|
||||||
|
C_MUL (t, *Fout2 , *tw1);
|
||||||
|
tw1 += fstride;
|
||||||
|
C_SUB( *Fout2 , *Fout , t );
|
||||||
|
C_ADDTO( *Fout , t );
|
||||||
|
++Fout2;
|
||||||
|
++Fout;
|
||||||
|
}while (--m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kf_bfly4(
|
||||||
|
kiss_fft_cpx * Fout,
|
||||||
|
const size_t fstride,
|
||||||
|
const kiss_fft_cfg st,
|
||||||
|
const size_t m
|
||||||
|
)
|
||||||
|
{
|
||||||
|
kiss_fft_cpx *tw1,*tw2,*tw3;
|
||||||
|
kiss_fft_cpx scratch[6];
|
||||||
|
size_t k=m;
|
||||||
|
const size_t m2=2*m;
|
||||||
|
const size_t m3=3*m;
|
||||||
|
|
||||||
|
|
||||||
|
tw3 = tw2 = tw1 = st->twiddles;
|
||||||
|
|
||||||
|
do {
|
||||||
|
C_FIXDIV(*Fout,4); C_FIXDIV(Fout[m],4); C_FIXDIV(Fout[m2],4); C_FIXDIV(Fout[m3],4);
|
||||||
|
|
||||||
|
C_MUL(scratch[0],Fout[m] , *tw1 );
|
||||||
|
C_MUL(scratch[1],Fout[m2] , *tw2 );
|
||||||
|
C_MUL(scratch[2],Fout[m3] , *tw3 );
|
||||||
|
|
||||||
|
C_SUB( scratch[5] , *Fout, scratch[1] );
|
||||||
|
C_ADDTO(*Fout, scratch[1]);
|
||||||
|
C_ADD( scratch[3] , scratch[0] , scratch[2] );
|
||||||
|
C_SUB( scratch[4] , scratch[0] , scratch[2] );
|
||||||
|
C_SUB( Fout[m2], *Fout, scratch[3] );
|
||||||
|
tw1 += fstride;
|
||||||
|
tw2 += fstride*2;
|
||||||
|
tw3 += fstride*3;
|
||||||
|
C_ADDTO( *Fout , scratch[3] );
|
||||||
|
|
||||||
|
if(st->inverse) {
|
||||||
|
Fout[m].r = scratch[5].r - scratch[4].i;
|
||||||
|
Fout[m].i = scratch[5].i + scratch[4].r;
|
||||||
|
Fout[m3].r = scratch[5].r + scratch[4].i;
|
||||||
|
Fout[m3].i = scratch[5].i - scratch[4].r;
|
||||||
|
}else{
|
||||||
|
Fout[m].r = scratch[5].r + scratch[4].i;
|
||||||
|
Fout[m].i = scratch[5].i - scratch[4].r;
|
||||||
|
Fout[m3].r = scratch[5].r - scratch[4].i;
|
||||||
|
Fout[m3].i = scratch[5].i + scratch[4].r;
|
||||||
|
}
|
||||||
|
++Fout;
|
||||||
|
}while(--k);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kf_bfly3(
|
||||||
|
kiss_fft_cpx * Fout,
|
||||||
|
const size_t fstride,
|
||||||
|
const kiss_fft_cfg st,
|
||||||
|
size_t m
|
||||||
|
)
|
||||||
|
{
|
||||||
|
size_t k=m;
|
||||||
|
const size_t m2 = 2*m;
|
||||||
|
kiss_fft_cpx *tw1,*tw2;
|
||||||
|
kiss_fft_cpx scratch[5];
|
||||||
|
kiss_fft_cpx epi3;
|
||||||
|
epi3 = st->twiddles[fstride*m];
|
||||||
|
|
||||||
|
tw1=tw2=st->twiddles;
|
||||||
|
|
||||||
|
do{
|
||||||
|
C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3);
|
||||||
|
|
||||||
|
C_MUL(scratch[1],Fout[m] , *tw1);
|
||||||
|
C_MUL(scratch[2],Fout[m2] , *tw2);
|
||||||
|
|
||||||
|
C_ADD(scratch[3],scratch[1],scratch[2]);
|
||||||
|
C_SUB(scratch[0],scratch[1],scratch[2]);
|
||||||
|
tw1 += fstride;
|
||||||
|
tw2 += fstride*2;
|
||||||
|
|
||||||
|
Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
|
||||||
|
Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
|
||||||
|
|
||||||
|
C_MULBYSCALAR( scratch[0] , epi3.i );
|
||||||
|
|
||||||
|
C_ADDTO(*Fout,scratch[3]);
|
||||||
|
|
||||||
|
Fout[m2].r = Fout[m].r + scratch[0].i;
|
||||||
|
Fout[m2].i = Fout[m].i - scratch[0].r;
|
||||||
|
|
||||||
|
Fout[m].r -= scratch[0].i;
|
||||||
|
Fout[m].i += scratch[0].r;
|
||||||
|
|
||||||
|
++Fout;
|
||||||
|
}while(--k);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kf_bfly5(
|
||||||
|
kiss_fft_cpx * Fout,
|
||||||
|
const size_t fstride,
|
||||||
|
const kiss_fft_cfg st,
|
||||||
|
int m
|
||||||
|
)
|
||||||
|
{
|
||||||
|
kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
|
||||||
|
int u;
|
||||||
|
kiss_fft_cpx scratch[13];
|
||||||
|
kiss_fft_cpx * twiddles = st->twiddles;
|
||||||
|
kiss_fft_cpx *tw;
|
||||||
|
kiss_fft_cpx ya,yb;
|
||||||
|
ya = twiddles[fstride*m];
|
||||||
|
yb = twiddles[fstride*2*m];
|
||||||
|
|
||||||
|
Fout0=Fout;
|
||||||
|
Fout1=Fout0+m;
|
||||||
|
Fout2=Fout0+2*m;
|
||||||
|
Fout3=Fout0+3*m;
|
||||||
|
Fout4=Fout0+4*m;
|
||||||
|
|
||||||
|
tw=st->twiddles;
|
||||||
|
for ( u=0; u<m; ++u ) {
|
||||||
|
C_FIXDIV( *Fout0,5); C_FIXDIV( *Fout1,5); C_FIXDIV( *Fout2,5); C_FIXDIV( *Fout3,5); C_FIXDIV( *Fout4,5);
|
||||||
|
scratch[0] = *Fout0;
|
||||||
|
|
||||||
|
C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
|
||||||
|
C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
|
||||||
|
C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
|
||||||
|
C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
|
||||||
|
|
||||||
|
C_ADD( scratch[7],scratch[1],scratch[4]);
|
||||||
|
C_SUB( scratch[10],scratch[1],scratch[4]);
|
||||||
|
C_ADD( scratch[8],scratch[2],scratch[3]);
|
||||||
|
C_SUB( scratch[9],scratch[2],scratch[3]);
|
||||||
|
|
||||||
|
Fout0->r += scratch[7].r + scratch[8].r;
|
||||||
|
Fout0->i += scratch[7].i + scratch[8].i;
|
||||||
|
|
||||||
|
scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
|
||||||
|
scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
|
||||||
|
|
||||||
|
scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i);
|
||||||
|
scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i);
|
||||||
|
|
||||||
|
C_SUB(*Fout1,scratch[5],scratch[6]);
|
||||||
|
C_ADD(*Fout4,scratch[5],scratch[6]);
|
||||||
|
|
||||||
|
scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
|
||||||
|
scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
|
||||||
|
scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i);
|
||||||
|
scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i);
|
||||||
|
|
||||||
|
C_ADD(*Fout2,scratch[11],scratch[12]);
|
||||||
|
C_SUB(*Fout3,scratch[11],scratch[12]);
|
||||||
|
|
||||||
|
++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* perform the butterfly for one stage of a mixed radix FFT */
|
||||||
|
static void kf_bfly_generic(
|
||||||
|
kiss_fft_cpx * Fout,
|
||||||
|
const size_t fstride,
|
||||||
|
const kiss_fft_cfg st,
|
||||||
|
int m,
|
||||||
|
int p
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int u,k,q1,q;
|
||||||
|
kiss_fft_cpx * twiddles = st->twiddles;
|
||||||
|
kiss_fft_cpx t;
|
||||||
|
int Norig = st->nfft;
|
||||||
|
|
||||||
|
kiss_fft_cpx * scratch = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC(sizeof(kiss_fft_cpx)*p);
|
||||||
|
|
||||||
|
for ( u=0; u<m; ++u ) {
|
||||||
|
k=u;
|
||||||
|
for ( q1=0 ; q1<p ; ++q1 ) {
|
||||||
|
scratch[q1] = Fout[ k ];
|
||||||
|
C_FIXDIV(scratch[q1],p);
|
||||||
|
k += m;
|
||||||
|
}
|
||||||
|
|
||||||
|
k=u;
|
||||||
|
for ( q1=0 ; q1<p ; ++q1 ) {
|
||||||
|
int twidx=0;
|
||||||
|
Fout[ k ] = scratch[0];
|
||||||
|
for (q=1;q<p;++q ) {
|
||||||
|
twidx += fstride * k;
|
||||||
|
if (twidx>=Norig) twidx-=Norig;
|
||||||
|
C_MUL(t,scratch[q] , twiddles[twidx] );
|
||||||
|
C_ADDTO( Fout[ k ] ,t);
|
||||||
|
}
|
||||||
|
k += m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KISS_FFT_TMP_FREE(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void kf_work(
|
||||||
|
kiss_fft_cpx * Fout,
|
||||||
|
const kiss_fft_cpx * f,
|
||||||
|
const size_t fstride,
|
||||||
|
int in_stride,
|
||||||
|
int * factors,
|
||||||
|
const kiss_fft_cfg st
|
||||||
|
)
|
||||||
|
{
|
||||||
|
kiss_fft_cpx * Fout_beg=Fout;
|
||||||
|
const int p=*factors++; /* the radix */
|
||||||
|
const int m=*factors++; /* stage's fft length/p */
|
||||||
|
const kiss_fft_cpx * Fout_end = Fout + p*m;
|
||||||
|
|
||||||
|
#ifdef _OPENMP
|
||||||
|
// use openmp extensions at the
|
||||||
|
// top-level (not recursive)
|
||||||
|
if (fstride==1 && p<=5)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
|
// execute the p different work units in different threads
|
||||||
|
# pragma omp parallel for
|
||||||
|
for (k=0;k<p;++k)
|
||||||
|
kf_work( Fout +k*m, f+ fstride*in_stride*k,fstride*p,in_stride,factors,st);
|
||||||
|
// all threads have joined by this point
|
||||||
|
|
||||||
|
switch (p) {
|
||||||
|
case 2: kf_bfly2(Fout,fstride,st,m); break;
|
||||||
|
case 3: kf_bfly3(Fout,fstride,st,m); break;
|
||||||
|
case 4: kf_bfly4(Fout,fstride,st,m); break;
|
||||||
|
case 5: kf_bfly5(Fout,fstride,st,m); break;
|
||||||
|
default: kf_bfly_generic(Fout,fstride,st,m,p); break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (m==1) {
|
||||||
|
do{
|
||||||
|
*Fout = *f;
|
||||||
|
f += fstride*in_stride;
|
||||||
|
}while(++Fout != Fout_end );
|
||||||
|
}else{
|
||||||
|
do{
|
||||||
|
// recursive call:
|
||||||
|
// DFT of size m*p performed by doing
|
||||||
|
// p instances of smaller DFTs of size m,
|
||||||
|
// each one takes a decimated version of the input
|
||||||
|
kf_work( Fout , f, fstride*p, in_stride, factors,st);
|
||||||
|
f += fstride*in_stride;
|
||||||
|
}while( (Fout += m) != Fout_end );
|
||||||
|
}
|
||||||
|
|
||||||
|
Fout=Fout_beg;
|
||||||
|
|
||||||
|
// recombine the p smaller DFTs
|
||||||
|
switch (p) {
|
||||||
|
case 2: kf_bfly2(Fout,fstride,st,m); break;
|
||||||
|
case 3: kf_bfly3(Fout,fstride,st,m); break;
|
||||||
|
case 4: kf_bfly4(Fout,fstride,st,m); break;
|
||||||
|
case 5: kf_bfly5(Fout,fstride,st,m); break;
|
||||||
|
default: kf_bfly_generic(Fout,fstride,st,m,p); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* facbuf is populated by p1,m1,p2,m2, ...
|
||||||
|
where
|
||||||
|
p[i] * m[i] = m[i-1]
|
||||||
|
m0 = n */
|
||||||
|
static
|
||||||
|
void kf_factor(int n,int * facbuf)
|
||||||
|
{
|
||||||
|
int p=4;
|
||||||
|
double floor_sqrt;
|
||||||
|
floor_sqrt = floorf( sqrtf((double)n) );
|
||||||
|
|
||||||
|
/*factor out powers of 4, powers of 2, then any remaining primes */
|
||||||
|
do {
|
||||||
|
while (n % p) {
|
||||||
|
switch (p) {
|
||||||
|
case 4: p = 2; break;
|
||||||
|
case 2: p = 3; break;
|
||||||
|
default: p += 2; break;
|
||||||
|
}
|
||||||
|
if (p > floor_sqrt)
|
||||||
|
p = n; /* no more factors, skip to end */
|
||||||
|
}
|
||||||
|
n /= p;
|
||||||
|
*facbuf++ = p;
|
||||||
|
*facbuf++ = n;
|
||||||
|
} while (n > 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* User-callable function to allocate all necessary storage space for the fft.
|
||||||
|
*
|
||||||
|
* The return value is a contiguous block of memory, allocated with malloc. As such,
|
||||||
|
* It can be freed with free(), rather than a kiss_fft-specific function.
|
||||||
|
* */
|
||||||
|
kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem )
|
||||||
|
{
|
||||||
|
kiss_fft_cfg st=NULL;
|
||||||
|
size_t memneeded = sizeof(struct kiss_fft_state)
|
||||||
|
+ sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/
|
||||||
|
|
||||||
|
if ( lenmem==NULL ) {
|
||||||
|
st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded );
|
||||||
|
}else{
|
||||||
|
if (mem != NULL && *lenmem >= memneeded)
|
||||||
|
st = (kiss_fft_cfg)mem;
|
||||||
|
*lenmem = memneeded;
|
||||||
|
}
|
||||||
|
if (st) {
|
||||||
|
int i;
|
||||||
|
st->nfft=nfft;
|
||||||
|
st->inverse = inverse_fft;
|
||||||
|
|
||||||
|
for (i=0;i<nfft;++i) {
|
||||||
|
const double pi=3.141592653589793238462643383279502884197169399375105820974944;
|
||||||
|
double phase = -2*pi*i / nfft;
|
||||||
|
if (st->inverse)
|
||||||
|
phase *= -1;
|
||||||
|
kf_cexp(st->twiddles+i, phase );
|
||||||
|
}
|
||||||
|
|
||||||
|
kf_factor(nfft,st->factors);
|
||||||
|
}
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
|
||||||
|
{
|
||||||
|
if (fin == fout) {
|
||||||
|
//NOTE: this is not really an in-place FFT algorithm.
|
||||||
|
//It just performs an out-of-place FFT into a temp buffer
|
||||||
|
kiss_fft_cpx * tmpbuf = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC( sizeof(kiss_fft_cpx)*st->nfft);
|
||||||
|
kf_work(tmpbuf,fin,1,in_stride, st->factors,st);
|
||||||
|
memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft);
|
||||||
|
KISS_FFT_TMP_FREE(tmpbuf);
|
||||||
|
}else{
|
||||||
|
kf_work( fout, fin, 1,in_stride, st->factors,st );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
|
||||||
|
{
|
||||||
|
kiss_fft_stride(cfg,fin,fout,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void kiss_fft_cleanup(void)
|
||||||
|
{
|
||||||
|
// nothing needed any more
|
||||||
|
}
|
||||||
|
|
||||||
|
int kiss_fft_next_fast_size(int n)
|
||||||
|
{
|
||||||
|
while(1) {
|
||||||
|
int m=n;
|
||||||
|
while ( (m%2) == 0 ) m/=2;
|
||||||
|
while ( (m%3) == 0 ) m/=3;
|
||||||
|
while ( (m%5) == 0 ) m/=5;
|
||||||
|
if (m<=1)
|
||||||
|
break; /* n is completely factorable by twos, threes, and fives */
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
#ifndef KISS_FFT_H
|
||||||
|
#define KISS_FFT_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
ATTENTION!
|
||||||
|
If you would like a :
|
||||||
|
-- a utility that will handle the caching of fft objects
|
||||||
|
-- real-only (no imaginary time component ) FFT
|
||||||
|
-- a multi-dimensional FFT
|
||||||
|
-- a command-line utility to perform ffts
|
||||||
|
-- a command-line utility to perform fast-convolution filtering
|
||||||
|
|
||||||
|
Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c
|
||||||
|
in the tools/ directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_SIMD
|
||||||
|
# include <xmmintrin.h>
|
||||||
|
# define kiss_fft_scalar __m128
|
||||||
|
#define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16)
|
||||||
|
#define KISS_FFT_FREE _mm_free
|
||||||
|
#else
|
||||||
|
#define KISS_FFT_MALLOC malloc
|
||||||
|
#define KISS_FFT_FREE free
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef FIXED_POINT
|
||||||
|
#include <sys/types.h>
|
||||||
|
# if (FIXED_POINT == 32)
|
||||||
|
# define kiss_fft_scalar int32_t
|
||||||
|
# else
|
||||||
|
# define kiss_fft_scalar int16_t
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# ifndef kiss_fft_scalar
|
||||||
|
/* default is float */
|
||||||
|
# define kiss_fft_scalar float
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
kiss_fft_scalar r;
|
||||||
|
kiss_fft_scalar i;
|
||||||
|
}kiss_fft_cpx;
|
||||||
|
|
||||||
|
typedef struct kiss_fft_state* kiss_fft_cfg;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* kiss_fft_alloc
|
||||||
|
*
|
||||||
|
* Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
|
||||||
|
*
|
||||||
|
* typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL);
|
||||||
|
*
|
||||||
|
* The return value from fft_alloc is a cfg buffer used internally
|
||||||
|
* by the fft routine or NULL.
|
||||||
|
*
|
||||||
|
* If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc.
|
||||||
|
* The returned value should be free()d when done to avoid memory leaks.
|
||||||
|
*
|
||||||
|
* The state can be placed in a user supplied buffer 'mem':
|
||||||
|
* If lenmem is not NULL and mem is not NULL and *lenmem is large enough,
|
||||||
|
* then the function places the cfg in mem and the size used in *lenmem
|
||||||
|
* and returns mem.
|
||||||
|
*
|
||||||
|
* If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough),
|
||||||
|
* then the function returns NULL and places the minimum cfg
|
||||||
|
* buffer size in *lenmem.
|
||||||
|
* */
|
||||||
|
|
||||||
|
kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* kiss_fft(cfg,in_out_buf)
|
||||||
|
*
|
||||||
|
* Perform an FFT on a complex input buffer.
|
||||||
|
* for a forward FFT,
|
||||||
|
* fin should be f[0] , f[1] , ... ,f[nfft-1]
|
||||||
|
* fout will be F[0] , F[1] , ... ,F[nfft-1]
|
||||||
|
* Note that each element is complex and can be accessed like
|
||||||
|
f[k].r and f[k].i
|
||||||
|
* */
|
||||||
|
void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
|
||||||
|
|
||||||
|
/*
|
||||||
|
A more generic version of the above function. It reads its input from every Nth sample.
|
||||||
|
* */
|
||||||
|
void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride);
|
||||||
|
|
||||||
|
/* If kiss_fft_alloc allocated a buffer, it is one contiguous
|
||||||
|
buffer and can be simply free()d when no longer needed*/
|
||||||
|
#define kiss_fft_free free
|
||||||
|
|
||||||
|
/*
|
||||||
|
Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up
|
||||||
|
your compiler output to call this before you exit.
|
||||||
|
*/
|
||||||
|
void kiss_fft_cleanup(void);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5)
|
||||||
|
*/
|
||||||
|
int kiss_fft_next_fast_size(int n);
|
||||||
|
|
||||||
|
/* for real ffts, we need an even size */
|
||||||
|
#define kiss_fftr_next_fast_size_real(n) \
|
||||||
|
(kiss_fft_next_fast_size( ((n)+1)>>1)<<1)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2003-2004, Mark Borgerding
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kiss_fftr.h"
|
||||||
|
#include "_kiss_fft_guts.h"
|
||||||
|
#include "assert.h"
|
||||||
|
|
||||||
|
struct kiss_fftr_state{
|
||||||
|
kiss_fft_cfg substate;
|
||||||
|
kiss_fft_cpx * tmpbuf;
|
||||||
|
kiss_fft_cpx * super_twiddles;
|
||||||
|
#ifdef USE_SIMD
|
||||||
|
void * pad;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
kiss_fftr_cfg st = NULL;
|
||||||
|
size_t subsize, memneeded;
|
||||||
|
|
||||||
|
if (nfft & 1) {
|
||||||
|
fprintf(stderr,"Real FFT optimization must be even.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
nfft >>= 1;
|
||||||
|
|
||||||
|
kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize);
|
||||||
|
memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 3 / 2);
|
||||||
|
|
||||||
|
if (lenmem == NULL) {
|
||||||
|
st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded);
|
||||||
|
} else {
|
||||||
|
if (*lenmem >= memneeded)
|
||||||
|
st = (kiss_fftr_cfg) mem;
|
||||||
|
*lenmem = memneeded;
|
||||||
|
}
|
||||||
|
if (!st)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */
|
||||||
|
st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize);
|
||||||
|
st->super_twiddles = st->tmpbuf + nfft;
|
||||||
|
kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize);
|
||||||
|
|
||||||
|
for (i = 0; i < nfft/2; ++i) {
|
||||||
|
double phase =
|
||||||
|
-3.14159265358979323846264338327 * ((double) (i+1) / nfft + .5);
|
||||||
|
if (inverse_fft)
|
||||||
|
phase *= -1;
|
||||||
|
kf_cexp (st->super_twiddles+i,phase);
|
||||||
|
}
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata)
|
||||||
|
{
|
||||||
|
/* input buffer timedata is stored row-wise */
|
||||||
|
int k,ncfft;
|
||||||
|
kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc;
|
||||||
|
|
||||||
|
assert(st->substate->inverse==0);
|
||||||
|
|
||||||
|
ncfft = st->substate->nfft;
|
||||||
|
|
||||||
|
/*perform the parallel fft of two real signals packed in real,imag*/
|
||||||
|
kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf );
|
||||||
|
/* The real part of the DC element of the frequency spectrum in st->tmpbuf
|
||||||
|
* contains the sum of the even-numbered elements of the input time sequence
|
||||||
|
* The imag part is the sum of the odd-numbered elements
|
||||||
|
*
|
||||||
|
* The sum of tdc.r and tdc.i is the sum of the input time sequence.
|
||||||
|
* yielding DC of input time sequence
|
||||||
|
* The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1...
|
||||||
|
* yielding Nyquist bin of input time sequence
|
||||||
|
*/
|
||||||
|
|
||||||
|
tdc.r = st->tmpbuf[0].r;
|
||||||
|
tdc.i = st->tmpbuf[0].i;
|
||||||
|
C_FIXDIV(tdc,2);
|
||||||
|
CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i);
|
||||||
|
CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i);
|
||||||
|
freqdata[0].r = tdc.r + tdc.i;
|
||||||
|
freqdata[ncfft].r = tdc.r - tdc.i;
|
||||||
|
#ifdef USE_SIMD
|
||||||
|
freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0);
|
||||||
|
#else
|
||||||
|
freqdata[ncfft].i = freqdata[0].i = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for ( k=1;k <= ncfft/2 ; ++k ) {
|
||||||
|
fpk = st->tmpbuf[k];
|
||||||
|
fpnk.r = st->tmpbuf[ncfft-k].r;
|
||||||
|
fpnk.i = - st->tmpbuf[ncfft-k].i;
|
||||||
|
C_FIXDIV(fpk,2);
|
||||||
|
C_FIXDIV(fpnk,2);
|
||||||
|
|
||||||
|
C_ADD( f1k, fpk , fpnk );
|
||||||
|
C_SUB( f2k, fpk , fpnk );
|
||||||
|
C_MUL( tw , f2k , st->super_twiddles[k-1]);
|
||||||
|
|
||||||
|
freqdata[k].r = HALF_OF(f1k.r + tw.r);
|
||||||
|
freqdata[k].i = HALF_OF(f1k.i + tw.i);
|
||||||
|
freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r);
|
||||||
|
freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata)
|
||||||
|
{
|
||||||
|
/* input buffer timedata is stored row-wise */
|
||||||
|
int k, ncfft;
|
||||||
|
|
||||||
|
assert(st->substate->inverse == 1);
|
||||||
|
|
||||||
|
ncfft = st->substate->nfft;
|
||||||
|
|
||||||
|
st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r;
|
||||||
|
st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r;
|
||||||
|
C_FIXDIV(st->tmpbuf[0],2);
|
||||||
|
|
||||||
|
for (k = 1; k <= ncfft / 2; ++k) {
|
||||||
|
kiss_fft_cpx fk, fnkc, fek, fok, tmp;
|
||||||
|
fk = freqdata[k];
|
||||||
|
fnkc.r = freqdata[ncfft - k].r;
|
||||||
|
fnkc.i = -freqdata[ncfft - k].i;
|
||||||
|
C_FIXDIV( fk , 2 );
|
||||||
|
C_FIXDIV( fnkc , 2 );
|
||||||
|
|
||||||
|
C_ADD (fek, fk, fnkc);
|
||||||
|
C_SUB (tmp, fk, fnkc);
|
||||||
|
C_MUL (fok, tmp, st->super_twiddles[k-1]);
|
||||||
|
C_ADD (st->tmpbuf[k], fek, fok);
|
||||||
|
C_SUB (st->tmpbuf[ncfft - k], fek, fok);
|
||||||
|
#ifdef USE_SIMD
|
||||||
|
st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0);
|
||||||
|
#else
|
||||||
|
st->tmpbuf[ncfft - k].i *= -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata);
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef KISS_FTR_H
|
||||||
|
#define KISS_FTR_H
|
||||||
|
|
||||||
|
#include "kiss_fft.h"
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Real optimized version can save about 45% cpu time vs. complex fft of a real seq.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct kiss_fftr_state *kiss_fftr_cfg;
|
||||||
|
|
||||||
|
|
||||||
|
kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem);
|
||||||
|
/*
|
||||||
|
nfft must be even
|
||||||
|
|
||||||
|
If you don't care to allocate space, use mem = lenmem = NULL
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
void kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata);
|
||||||
|
/*
|
||||||
|
input timedata has nfft scalar points
|
||||||
|
output freqdata has nfft/2+1 complex points
|
||||||
|
*/
|
||||||
|
|
||||||
|
void kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata);
|
||||||
|
/*
|
||||||
|
input freqdata has nfft/2+1 complex points
|
||||||
|
output timedata has nfft scalar points
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define kiss_fftr_free free
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: linreg.c
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: April 2015
|
||||||
|
|
||||||
|
Linear regression C module based on:
|
||||||
|
|
||||||
|
http://stackoverflow.com/questions/5083465/fast-efficient-least-squares-fit-algorithm-in-c
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
$ gcc linreg.c -o linreg -D__UNITTEST__ -Wall
|
||||||
|
$ ./linreg
|
||||||
|
|
||||||
|
Then compare yfit results with octave/tlinreg.m
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2015 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "linreg.h"
|
||||||
|
#include "comp_prim.h"
|
||||||
|
|
||||||
|
|
||||||
|
void linreg(COMP *m, COMP *b, float x[], COMP y[], int n)
|
||||||
|
{
|
||||||
|
float sumx = 0.0; /* sum of x */
|
||||||
|
float sumx2 = 0.0; /* sum of x^2 */
|
||||||
|
COMP sumxy = {0.0,0.0}; /* sum of x * y */
|
||||||
|
COMP sumy = {0.0,0.0}; /* sum of y */
|
||||||
|
COMP sumy2 = {0.0,0.0}; /* sum of y**2 */
|
||||||
|
float denom;
|
||||||
|
COMP zero;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<n; i++) {
|
||||||
|
sumx += x[i];
|
||||||
|
sumx2 += x[i]*x[i];
|
||||||
|
sumxy = cadd(sumxy, fcmult(x[i], y[i]));
|
||||||
|
sumy = cadd(sumy, y[i]);
|
||||||
|
sumy2 = cadd(sumy2, cmult(y[i],y[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
denom = (n * sumx2 - sumx*sumx);
|
||||||
|
|
||||||
|
if (denom == 0) {
|
||||||
|
/* singular matrix. can't solve the problem */
|
||||||
|
zero.real = 0.0; zero.imag = 0.0;
|
||||||
|
*m = zero;
|
||||||
|
*b = zero;
|
||||||
|
} else {
|
||||||
|
*m = fcmult(1.0/denom, cadd(fcmult(n, sumxy), cneg(fcmult(sumx,sumy))));
|
||||||
|
*b = fcmult(1.0/denom, cadd(fcmult(sumx2,sumy), cneg(fcmult(sumx, sumxy))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __UNITTEST__
|
||||||
|
|
||||||
|
|
||||||
|
static float x[] = {1, 2, 7, 8};
|
||||||
|
|
||||||
|
static COMP y[] = {
|
||||||
|
{-0.70702, 0.70708},
|
||||||
|
{-0.77314, 0.63442},
|
||||||
|
{-0.98083, 0.19511},
|
||||||
|
{-0.99508, 0.09799}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
float x1;
|
||||||
|
COMP m,b,yfit;
|
||||||
|
|
||||||
|
linreg(&m, &b, x, y, sizeof(x)/sizeof(float));
|
||||||
|
|
||||||
|
for (x1=1; x1<=8; x1++) {
|
||||||
|
yfit = cadd(fcmult(x1, m),b);
|
||||||
|
printf("%f %f\n", yfit.real, yfit.imag);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
|
||||||
|
FILE........: linreg.h
|
||||||
|
AUTHOR......: David Rowe
|
||||||
|
DATE CREATED: April 2015
|
||||||
|
|
||||||
|
Linear regression C module based
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (C) 2015 David Rowe
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||||
|
published by the Free Software Foundation. This program is
|
||||||
|
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LINREG__
|
||||||
|
#define __LINREG__
|
||||||
|
|
||||||
|
#include "comp.h"
|
||||||
|
|
||||||
|
void linreg(COMP *m, COMP *b, float x[], COMP y[], int n);
|
||||||
|
|
||||||
|
#endif
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user