mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-11 12:27:28 +00:00
Compare commits
194 Commits
d4b44b1c63
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8ddda6f0d | ||
|
|
6f62748916 | ||
|
|
05bb43189e | ||
|
|
5dba5c82c0 | ||
|
|
727b1b3e85 | ||
|
|
c45c217743 | ||
|
|
c520d3aae7 | ||
|
|
acb6eb704b | ||
|
|
04e755aa48 | ||
|
|
9e96b0ace8 | ||
|
|
be024d8d4e | ||
|
|
b6512d3de1 | ||
|
|
214c76ce1b | ||
|
|
b002844aa0 | ||
|
|
925381ef7b | ||
|
|
ff8d6aa9c3 | ||
|
|
b12acba44f | ||
|
|
6b8e5e9d7b | ||
|
|
489de09375 | ||
|
|
390f0c8248 | ||
|
|
792e930e45 | ||
|
|
5fab45c133 | ||
|
|
c6e070461a | ||
|
|
f289b78061 | ||
|
|
b4369b2730 | ||
|
|
29d0d5e559 | ||
|
|
6e110788fd | ||
|
|
86326f294d | ||
|
|
fb7af18f4f | ||
|
|
4d303c95d1 | ||
|
|
1a6cbb5caa | ||
|
|
a6c4683ddc | ||
|
|
70f909d718 | ||
|
|
9c1d55c844 | ||
|
|
ba9d0e6fa3 | ||
|
|
da11cc739d | ||
|
|
9f5170a0bc | ||
|
|
594f27c3ff | ||
|
|
e648e26c17 | ||
|
|
1669a027e6 | ||
|
|
105d657359 | ||
|
|
37ab800500 | ||
|
|
0c553c40d4 | ||
|
|
17b075a11c | ||
|
|
15f5b35859 | ||
|
|
25bdefecb2 | ||
|
|
beb268ff25 | ||
|
|
0d11331d18 | ||
|
|
21ca25404a | ||
|
|
abab6ce815 | ||
|
|
52907e4c44 | ||
|
|
3a90781e1b | ||
|
|
f63dadd19e | ||
|
|
9313d465f6 | ||
|
|
004746683e | ||
|
|
1e914140ca | ||
|
|
caceaf424a | ||
|
|
75144d2028 | ||
|
|
b5e952b008 | ||
|
|
27b522b55a | ||
|
|
11b5f1a4fe | ||
|
|
f9c9350f45 | ||
|
|
a2ce4c7f18 | ||
|
|
45335532ca | ||
|
|
a5b2d4a9d5 | ||
|
|
7fb95841e4 | ||
|
|
4f1a56d480 | ||
|
|
eaab8f04b5 | ||
|
|
25acce2a8d | ||
|
|
da9d71190f | ||
|
|
1443a32f1b | ||
|
|
9058ccecf9 | ||
|
|
1b83501ee2 | ||
|
|
1b2dc10e77 | ||
|
|
ac571d5dd2 | ||
|
|
ef30fd850d | ||
|
|
3a723ceae8 | ||
|
|
dc36f5df7a | ||
|
|
b9a0015149 | ||
|
|
9673cfb0b2 | ||
|
|
757f7b68d6 | ||
|
|
63aadba526 | ||
|
|
759a972f77 | ||
|
|
d1db4433f4 | ||
|
|
2c68710e8c | ||
|
|
5510dae8d3 | ||
|
|
52fd362720 | ||
|
|
9f8f4471aa | ||
|
|
cf03caff10 | ||
|
|
ac937766cd | ||
|
|
9e215213a7 | ||
|
|
4fbe5356ca | ||
|
|
e899e84ef9 | ||
|
|
69c3c0151f | ||
|
|
2b977b4830 | ||
|
|
b88a8bf968 | ||
|
|
514f8590fe | ||
|
|
cbd40faa89 | ||
|
|
7dd9c8b223 | ||
|
|
3473c32e81 | ||
|
|
33e1f58f6e | ||
|
|
db2224ed0e | ||
|
|
29c5713a7e | ||
|
|
82cf2bf16a | ||
|
|
9dc7ef612e | ||
|
|
ef530db44c | ||
|
|
b2c82bdc41 | ||
|
|
9da4396c6f | ||
|
|
e5c3eda2a2 | ||
|
|
54a928f47f | ||
|
|
33f18659c8 | ||
|
|
3b968c1d58 | ||
|
|
d7f0625ada | ||
|
|
3a7093a973 | ||
|
|
a4f6f4515a | ||
|
|
89c5e4034b | ||
|
|
d609d05698 | ||
|
|
5a3855b208 | ||
|
|
8fdba1f1e2 | ||
|
|
db64a5b51e | ||
|
|
3371d3372c | ||
|
|
83c6161ac6 | ||
|
|
d93d68d31e | ||
|
|
d97e38bafc | ||
|
|
cadf151826 | ||
|
|
4fe1c87e54 | ||
|
|
1021d967da | ||
|
|
4f94354f60 | ||
|
|
6a93cb7b69 | ||
|
|
b11f292cc4 | ||
|
|
217abc4c10 | ||
|
|
e6af68bd14 | ||
|
|
530f0135ee | ||
|
|
208a873c4c | ||
|
|
f57eb6f27d | ||
|
|
155cdf9f9d | ||
|
|
661f49ad7a | ||
|
|
31e55d0b66 | ||
|
|
ee6449746b | ||
|
|
85aba3a4f7 | ||
|
|
5262233b2d | ||
|
|
e9db03d185 | ||
|
|
176d8def48 | ||
|
|
5b299f3ede | ||
|
|
96c42229b0 | ||
|
|
40f1f91c0d | ||
|
|
269dee7a2d | ||
|
|
f1aefc4eef | ||
|
|
203826374c | ||
|
|
8e0547e76d | ||
|
|
8a48321555 | ||
|
|
917794ebab | ||
|
|
ed77ba5612 | ||
|
|
eafa8c7b47 | ||
|
|
aa8bb6c6f1 | ||
|
|
1952982896 | ||
|
|
024ac74f5c | ||
|
|
de2b9632bb | ||
|
|
c2b7dc2641 | ||
|
|
d0d375f1ff | ||
|
|
e8ebfc0513 | ||
|
|
bf32f17f28 | ||
|
|
b74238194b | ||
|
|
5d5819b876 | ||
|
|
f127702bef | ||
|
|
cce8cbfe34 | ||
|
|
a4a6c3509a | ||
|
|
68250dc937 | ||
|
|
c8628b3422 | ||
|
|
2ac74d6677 | ||
|
|
9d487ddc0d | ||
|
|
bcfe069997 | ||
|
|
4fc96bdf83 | ||
|
|
4ef943f204 | ||
|
|
a8fa5f25cb | ||
|
|
3b2a1547de | ||
|
|
6f725a1996 | ||
|
|
467c042bf7 | ||
|
|
cc4c41167c | ||
|
|
fff2bbf4a0 | ||
|
|
fba92229a6 | ||
|
|
ff0a4ea320 | ||
|
|
83b603827c | ||
|
|
2032ff1c32 | ||
|
|
5910cc2e26 | ||
|
|
ee80ec7b68 | ||
|
|
aa72e397f2 | ||
|
|
ec0dfb7337 | ||
|
|
c55bea8460 | ||
|
|
aa605fc4a2 | ||
|
|
d75680a2dd | ||
|
|
817f3b9ec8 | ||
|
|
0726bb4b56 | ||
|
|
6b11991be0 |
1
.github/actionlint.yaml
vendored
1
.github/actionlint.yaml
vendored
@@ -2,4 +2,5 @@
|
||||
self-hosted-runner:
|
||||
# Labels of self-hosted runner in array of strings.
|
||||
labels:
|
||||
- arctastic
|
||||
- test-runner
|
||||
|
||||
4
.github/actions/build-variant/action.yml
vendored
4
.github/actions/build-variant/action.yml
vendored
@@ -76,7 +76,7 @@ runs:
|
||||
done
|
||||
|
||||
- name: PlatformIO ${{ inputs.arch }} download cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ~/.platformio/.cache
|
||||
key: pio-cache-${{ inputs.arch }}-${{ hashFiles('.github/actions/**', '**.ini') }}
|
||||
@@ -100,7 +100,7 @@ runs:
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: firmware-${{ inputs.arch }}-${{ inputs.board }}-${{ steps.version.outputs.long }}
|
||||
overwrite: true
|
||||
|
||||
314
.github/copilot-instructions.md
vendored
Normal file
314
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,314 @@
|
||||
# Meshtastic Firmware - Copilot Instructions
|
||||
|
||||
This document provides context and guidelines for AI assistants working with the Meshtastic firmware codebase.
|
||||
|
||||
## Project Overview
|
||||
|
||||
Meshtastic is an open-source LoRa mesh networking project for long-range, low-power communication without relying on internet or cellular infrastructure. The firmware enables text messaging, location sharing, and telemetry over a decentralized mesh network.
|
||||
|
||||
### Supported Hardware Platforms
|
||||
|
||||
- **ESP32** (ESP32, ESP32-S3, ESP32-C3) - Most common platform
|
||||
- **nRF52** (nRF52840, nRF52833) - Low power Nordic chips
|
||||
- **RP2040/RP2350** - Raspberry Pi Pico variants
|
||||
- **STM32WL** - STM32 with integrated LoRa
|
||||
- **Linux/Portduino** - Native Linux builds (Raspberry Pi, etc.)
|
||||
|
||||
### Supported Radio Chips
|
||||
|
||||
- **SX1262/SX1268** - Sub-GHz LoRa (868/915 MHz regions)
|
||||
- **SX1280** - 2.4 GHz LoRa
|
||||
- **LR1110/LR1120/LR1121** - Wideband radios (sub-GHz and 2.4 GHz capable, but not simultaneously)
|
||||
- **RF95** - Legacy RFM95 modules
|
||||
- **LLCC68** - Low-cost LoRa
|
||||
|
||||
### MQTT Integration
|
||||
|
||||
MQTT provides a bridge between Meshtastic mesh networks and the internet, enabling nodes with network connectivity to share messages with remote meshes or external services.
|
||||
|
||||
#### Key Components
|
||||
|
||||
- **`src/mqtt/MQTT.cpp`** - Main MQTT client singleton, handles connection and message routing
|
||||
- **`src/mqtt/ServiceEnvelope.cpp`** - Protobuf wrapper for mesh packets sent over MQTT
|
||||
- **`moduleConfig.mqtt`** - MQTT module configuration
|
||||
|
||||
#### MQTT Topic Structure
|
||||
|
||||
Messages are published/subscribed using a hierarchical topic format:
|
||||
|
||||
```
|
||||
{root}/{channel_id}/{gateway_id}
|
||||
```
|
||||
|
||||
- `root` - Configurable prefix (default: `msh`)
|
||||
- `channel_id` - Channel name/identifier
|
||||
- `gateway_id` - Node ID of the publishing gateway
|
||||
|
||||
#### Configuration Defaults (from `Default.h`)
|
||||
|
||||
```cpp
|
||||
#define default_mqtt_address "mqtt.meshtastic.org"
|
||||
#define default_mqtt_username "meshdev"
|
||||
#define default_mqtt_password "large4cats"
|
||||
#define default_mqtt_root "msh"
|
||||
#define default_mqtt_encryption_enabled true
|
||||
#define default_mqtt_tls_enabled false
|
||||
```
|
||||
|
||||
#### Key Concepts
|
||||
|
||||
- **Uplink** - Mesh packets sent TO the MQTT broker (controlled by `uplink_enabled` per channel)
|
||||
- **Downlink** - MQTT messages received and injected INTO the mesh (controlled by `downlink_enabled` per channel)
|
||||
- **Encryption** - When `encryption_enabled` is true, only encrypted packets are sent; plaintext JSON is disabled
|
||||
- **ServiceEnvelope** - Protobuf wrapper containing packet + channel_id + gateway_id for routing
|
||||
- **JSON Support** - Optional JSON encoding for integration with external systems (disabled on nRF52 by default)
|
||||
|
||||
#### PKI Messages
|
||||
|
||||
PKI (Public Key Infrastructure) messages have special handling:
|
||||
|
||||
- Accepted on a special "PKI" channel
|
||||
- Allow encrypted DMs between nodes that discovered each other on downlink-enabled channels
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
firmware/
|
||||
├── src/ # Main source code
|
||||
│ ├── main.cpp # Application entry point
|
||||
│ ├── mesh/ # Core mesh networking
|
||||
│ │ ├── NodeDB.* # Node database management
|
||||
│ │ ├── Router.* # Packet routing
|
||||
│ │ ├── Channels.* # Channel management
|
||||
│ │ ├── *Interface.* # Radio interface implementations
|
||||
│ │ └── generated/ # Protobuf generated code
|
||||
│ ├── modules/ # Feature modules (Position, Telemetry, etc.)
|
||||
│ ├── gps/ # GPS handling
|
||||
│ ├── graphics/ # Display drivers and UI
|
||||
│ ├── platform/ # Platform-specific code
|
||||
│ ├── input/ # Input device handling
|
||||
│ └── concurrency/ # Threading utilities
|
||||
├── variants/ # Hardware variant definitions
|
||||
│ ├── esp32/ # ESP32 variants
|
||||
│ ├── esp32s3/ # ESP32-S3 variants
|
||||
│ ├── nrf52/ # nRF52 variants
|
||||
│ └── rp2xxx/ # RP2040/RP2350 variants
|
||||
├── protobufs/ # Protocol buffer definitions
|
||||
├── boards/ # Custom PlatformIO board definitions
|
||||
└── bin/ # Build and utility scripts
|
||||
```
|
||||
|
||||
## Coding Conventions
|
||||
|
||||
### General Style
|
||||
|
||||
- Follow existing code style - run `trunk fmt` before commits
|
||||
- Prefer `LOG_DEBUG`, `LOG_INFO`, `LOG_WARN`, `LOG_ERROR` for logging
|
||||
- Use `assert()` for invariants that should never fail
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
- Classes: `PascalCase` (e.g., `PositionModule`, `NodeDB`)
|
||||
- Functions/Methods: `camelCase` (e.g., `sendOurPosition`, `getNodeNum`)
|
||||
- Constants/Defines: `UPPER_SNAKE_CASE` (e.g., `MAX_INTERVAL`, `ONE_DAY`)
|
||||
- Member variables: `camelCase` (e.g., `lastGpsSend`, `nodeDB`)
|
||||
- Config defines: `USERPREFS_*` for user-configurable options
|
||||
|
||||
### Key Patterns
|
||||
|
||||
#### Module System
|
||||
|
||||
Modules inherit from `MeshModule` or `ProtobufModule<T>` and implement:
|
||||
|
||||
- `handleReceivedProtobuf()` - Process incoming packets
|
||||
- `allocReply()` - Generate response packets
|
||||
- `runOnce()` - Periodic task execution (returns next run interval in ms)
|
||||
|
||||
```cpp
|
||||
class MyModule : public ProtobufModule<meshtastic_MyMessage>
|
||||
{
|
||||
protected:
|
||||
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_MyMessage *msg) override;
|
||||
virtual int32_t runOnce() override;
|
||||
};
|
||||
```
|
||||
|
||||
#### Configuration Access
|
||||
|
||||
- `config.*` - Device configuration (LoRa, position, power, etc.)
|
||||
- `moduleConfig.*` - Module-specific configuration
|
||||
- `channels.*` - Channel configuration and management
|
||||
|
||||
#### Default Values
|
||||
|
||||
Use the `Default` class helpers in `src/mesh/Default.h`:
|
||||
|
||||
- `Default::getConfiguredOrDefaultMs(configured, default)` - Returns ms, using default if configured is 0
|
||||
- `Default::getConfiguredOrMinimumValue(configured, min)` - Enforces minimum values
|
||||
- `Default::getConfiguredOrDefaultMsScaled(configured, default, numNodes)` - Scales based on network size
|
||||
|
||||
#### Thread Safety
|
||||
|
||||
- Use `concurrency::Lock` for mutex protection
|
||||
- Radio SPI access uses `SPILock`
|
||||
- Prefer `OSThread` for background tasks
|
||||
|
||||
### Hardware Variants
|
||||
|
||||
Each hardware variant has:
|
||||
|
||||
- `variant.h` - Pin definitions and hardware capabilities
|
||||
- `platformio.ini` - Build configuration
|
||||
- Optional: `pins_arduino.h`, `rfswitch.h`
|
||||
|
||||
Key defines in variant.h:
|
||||
|
||||
```cpp
|
||||
#define USE_SX1262 // Radio chip selection
|
||||
#define HAS_GPS 1 // Hardware capabilities
|
||||
#define LORA_CS 36 // Pin assignments
|
||||
#define SX126X_DIO1 14 // Radio-specific pins
|
||||
```
|
||||
|
||||
### Protobuf Messages
|
||||
|
||||
- Defined in `protobufs/meshtastic/*.proto`
|
||||
- Generated code in `src/mesh/generated/`
|
||||
- Regenerate with `bin/regen-protos.sh`
|
||||
- Message types prefixed with `meshtastic_`
|
||||
|
||||
### Conditional Compilation
|
||||
|
||||
```cpp
|
||||
#if !MESHTASTIC_EXCLUDE_GPS // Feature exclusion
|
||||
#ifdef ARCH_ESP32 // Architecture-specific
|
||||
#if defined(USE_SX1262) // Radio-specific
|
||||
#ifdef HAS_SCREEN // Hardware capability
|
||||
#if USERPREFS_EVENT_MODE // User preferences
|
||||
```
|
||||
|
||||
## Build System
|
||||
|
||||
Uses **PlatformIO** with custom scripts:
|
||||
|
||||
- `bin/platformio-pre.py` - Pre-build script
|
||||
- `bin/platformio-custom.py` - Custom build logic
|
||||
|
||||
Build commands:
|
||||
|
||||
```bash
|
||||
pio run -e tbeam # Build specific target
|
||||
pio run -e tbeam -t upload # Build and upload
|
||||
pio run -e native # Build native/Linux version
|
||||
```
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Adding a New Module
|
||||
|
||||
1. Create `src/modules/MyModule.cpp` and `.h`
|
||||
2. Inherit from appropriate base class
|
||||
3. Register in `src/modules/Modules.cpp`
|
||||
4. Add protobuf messages if needed in `protobufs/`
|
||||
|
||||
### Adding a New Hardware Variant
|
||||
|
||||
1. Create directory under `variants/<arch>/<name>/`
|
||||
2. Add `variant.h` with pin definitions
|
||||
3. Add `platformio.ini` with build config
|
||||
4. Reference common configs with `extends`
|
||||
|
||||
### Modifying Configuration Defaults
|
||||
|
||||
- Check `src/mesh/Default.h` for default value defines
|
||||
- Check `src/mesh/NodeDB.cpp` for initialization logic
|
||||
- Consider `isDefaultChannel()` checks for public channel restrictions
|
||||
|
||||
## Important Considerations
|
||||
|
||||
### Traffic Management
|
||||
|
||||
The mesh network has limited bandwidth. When modifying broadcast intervals:
|
||||
|
||||
- Respect minimum intervals on default/public channels
|
||||
- Use `Default::getConfiguredOrMinimumValue()` to enforce minimums
|
||||
- Consider `numOnlineNodes` scaling for congestion control
|
||||
|
||||
### Power Management
|
||||
|
||||
Many devices are battery-powered:
|
||||
|
||||
- Use `IF_ROUTER(routerVal, normalVal)` for role-based defaults
|
||||
- Check `config.power.is_power_saving` for power-saving modes
|
||||
- Implement proper `sleep()` methods in radio interfaces
|
||||
|
||||
### Channel Security
|
||||
|
||||
- `channels.isDefaultChannel(index)` - Check if using default/public settings
|
||||
- Default channels get stricter rate limits to prevent abuse
|
||||
- Private channels may have relaxed limits
|
||||
|
||||
## GitHub Actions CI/CD
|
||||
|
||||
The project uses GitHub Actions extensively for CI/CD. Key workflows are in `.github/workflows/`:
|
||||
|
||||
### Core CI Workflows
|
||||
|
||||
- **`main_matrix.yml`** - Main CI pipeline, runs on push to `master`/`develop` and PRs
|
||||
- Uses `bin/generate_ci_matrix.py` to dynamically generate build targets
|
||||
- Builds all supported hardware variants
|
||||
- PRs build a subset (`--level pr`) for faster feedback
|
||||
|
||||
- **`trunk_check.yml`** - Code quality checks on PRs
|
||||
- Runs Trunk.io for linting and formatting
|
||||
- Must pass before merge
|
||||
|
||||
- **`tests.yml`** - End-to-end and hardware tests
|
||||
- Runs daily on schedule
|
||||
- Includes native tests and hardware-in-the-loop testing
|
||||
|
||||
- **`test_native.yml`** - Native platform unit tests
|
||||
- Runs `pio test -e native`
|
||||
|
||||
### Release Workflows
|
||||
|
||||
- **`release_channels.yml`** - Triggered on GitHub release publish
|
||||
- Builds Docker images
|
||||
- Packages for PPA (Ubuntu), OBS (openSUSE), and COPR (Fedora)
|
||||
- Handles Alpha/Beta/Stable release channels
|
||||
|
||||
- **`nightly.yml`** - Nightly builds from develop branch
|
||||
|
||||
- **`docker_build.yml`** / **`docker_manifest.yml`** - Docker image builds
|
||||
|
||||
### Build Matrix Generation
|
||||
|
||||
The CI uses `bin/generate_ci_matrix.py` to dynamically select which targets to build:
|
||||
|
||||
```bash
|
||||
# Generate full build matrix
|
||||
./bin/generate_ci_matrix.py all
|
||||
|
||||
# Generate PR-level matrix (subset for faster builds)
|
||||
./bin/generate_ci_matrix.py all --level pr
|
||||
```
|
||||
|
||||
Variants can specify their support level in `platformio.ini`:
|
||||
|
||||
- `custom_meshtastic_support_level = 1` - Actively supported, built on every PR
|
||||
- `custom_meshtastic_support_level = 2` - Supported, built on merge to main branches
|
||||
- `board_level = extra` - Extra builds, only on full releases
|
||||
|
||||
### Running Workflows Locally
|
||||
|
||||
Most workflows can be triggered manually via `workflow_dispatch` for testing.
|
||||
|
||||
## Testing
|
||||
|
||||
- Unit tests in `test/` directory
|
||||
- Run with `pio test -e native`
|
||||
- Use `bin/test-simulator.sh` for simulation testing
|
||||
|
||||
## Resources
|
||||
|
||||
- [Documentation](https://meshtastic.org/docs/)
|
||||
2
.github/workflows/build_debian_src.yml
vendored
2
.github/workflows/build_debian_src.yml
vendored
@@ -64,7 +64,7 @@ jobs:
|
||||
PKG_VERSION: ${{ steps.version.outputs.deb }}
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
|
||||
overwrite: true
|
||||
|
||||
26
.github/workflows/build_firmware.yml
vendored
26
.github/workflows/build_firmware.yml
vendored
@@ -18,9 +18,10 @@ permissions: read-all
|
||||
jobs:
|
||||
pio-build:
|
||||
name: build-${{ inputs.platform }}
|
||||
runs-on: ubuntu-24.04
|
||||
# Use 'arctastic' self-hosted runner pool when building in the main repo
|
||||
runs-on: ${{ github.repository_owner == 'meshtastic' && 'arctastic' || 'ubuntu-latest' }}
|
||||
outputs:
|
||||
artifact-id: ${{ steps.upload.outputs.artifact-id }}
|
||||
artifact-id: ${{ steps.upload-firmware.outputs.artifact-id }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
@@ -55,20 +56,22 @@ jobs:
|
||||
ota_firmware_source: ${{ steps.ota_dir.outputs.src || '' }}
|
||||
ota_firmware_target: ${{ steps.ota_dir.outputs.tgt || '' }}
|
||||
|
||||
- name: Echo manifest from release/firmware-*.mt.json to job summary
|
||||
if: ${{ always() }}
|
||||
- name: Job summary
|
||||
env:
|
||||
PIO_ENV: ${{ inputs.pio_env }}
|
||||
run: |
|
||||
echo "## Manifest: \`$PIO_ENV\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "## $PIO_ENV" >> $GITHUB_STEP_SUMMARY
|
||||
echo "<details><summary><strong>Manifest</strong></summary>" >> $GITHUB_STEP_SUMMARY
|
||||
echo '' >> $GITHUB_STEP_SUMMARY
|
||||
echo '```json' >> $GITHUB_STEP_SUMMARY
|
||||
cat release/firmware-*.mt.json >> $GITHUB_STEP_SUMMARY
|
||||
echo '' >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
echo "</details>" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v5
|
||||
id: upload
|
||||
uses: actions/upload-artifact@v6
|
||||
id: upload-firmware
|
||||
with:
|
||||
name: firmware-${{ inputs.platform }}-${{ inputs.pio_env }}-${{ inputs.version }}
|
||||
overwrite: true
|
||||
@@ -81,3 +84,12 @@ jobs:
|
||||
release/*.zip
|
||||
release/device-*.sh
|
||||
release/device-*.bat
|
||||
|
||||
- name: Store manifests as an artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
id: upload-manifest
|
||||
with:
|
||||
name: manifest-${{ inputs.platform }}-${{ inputs.pio_env }}-${{ inputs.version }}
|
||||
overwrite: true
|
||||
path: |
|
||||
release/*.mt.json
|
||||
|
||||
8
.github/workflows/build_one_target.yml
vendored
8
.github/workflows/build_one_target.yml
vendored
@@ -98,7 +98,7 @@ jobs:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
path: ./
|
||||
pattern: firmware-*-*
|
||||
@@ -111,7 +111,7 @@ jobs:
|
||||
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
|
||||
|
||||
- name: Repackage in single firmware zip
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: firmware-${{inputs.target}}-${{ needs.version.outputs.long }}
|
||||
overwrite: true
|
||||
@@ -127,7 +127,7 @@ jobs:
|
||||
./Meshtastic_nRF52_factory_erase*.uf2
|
||||
retention-days: 30
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
pattern: firmware-*-${{ needs.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
@@ -146,7 +146,7 @@ jobs:
|
||||
run: zip -j -9 -r ./firmware-${{inputs.target}}-${{ needs.version.outputs.long }}.zip ./output
|
||||
|
||||
- name: Repackage in single elfs zip
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: debug-elfs-${{inputs.target}}-${{ needs.version.outputs.long }}.zip
|
||||
overwrite: true
|
||||
|
||||
47
.github/workflows/first_time_contributor.yml
vendored
Normal file
47
.github/workflows/first_time_contributor.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
name: Welcome First-Time Contributor
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: opened
|
||||
pull_request_target:
|
||||
types: opened
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
welcome:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write # Required to post comments and labels on issues
|
||||
pull-requests: write # Required to post comments and labels on PRs
|
||||
steps:
|
||||
- uses: plbstl/first-contribution@v4
|
||||
with:
|
||||
labels: first-contribution
|
||||
issue-opened-msg: |
|
||||
### @{fc-author}, Welcome to Meshtastic! :wave:
|
||||
|
||||
Thanks for opening your first issue. If it's helpful, an easy way
|
||||
to get logs is the "Open Serial Monitor" button on the [Web Flasher](https://flasher.meshtastic.org).
|
||||
|
||||
If you have ideas for features, note that we often debate big ideas
|
||||
in the [discussions tab](https://github.com/meshtastic/firmware/discussions/categories/ideas)
|
||||
first. This tracker tends to be for ideas that have community
|
||||
consensus and a clear implementation.
|
||||
|
||||
We're very active [on discord](https://discord.com/invite/meshtastic),
|
||||
especially the \#firmware and \#alphanauts-testing channels. If you'll
|
||||
be around for a while, we'd love to see you there!
|
||||
|
||||
Welcome to the community! :heart:
|
||||
|
||||
pr-opened-msg: |
|
||||
### @{fc-author}, Welcome to Meshtastic!
|
||||
|
||||
Thanks for opening your first pull request. We really appreciate it.
|
||||
|
||||
We discuss work as a team in discord, please join us in the [#firmware channel](https://discord.com/invite/meshtastic).
|
||||
There's a big backlog of patches at the moment. If you have time,
|
||||
please help us with some code review and testing of [other PRs](https://github.com/meshtastic/firmware/pulls)!
|
||||
|
||||
Welcome to the team :smile:
|
||||
89
.github/workflows/main_matrix.yml
vendored
89
.github/workflows/main_matrix.yml
vendored
@@ -8,7 +8,9 @@ on:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- pioarduino # Remove when merged // use `feature/` in the future.
|
||||
- event/*
|
||||
- feature/*
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
- version.properties
|
||||
@@ -18,7 +20,9 @@ on:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- pioarduino # Remove when merged // use `feature/` in the future.
|
||||
- event/*
|
||||
- feature/*
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
#- "**.yml"
|
||||
@@ -77,16 +81,21 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
check: ${{ fromJson(needs.setup.outputs.check) }}
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
# Use 'arctastic' self-hosted runner pool when checking in the main repo
|
||||
runs-on: ${{ github.repository_owner == 'meshtastic' && 'arctastic' || 'ubuntu-latest' }}
|
||||
if: ${{ github.event_name != 'workflow_dispatch' && github.repository == 'meshtastic/firmware' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
- name: Check ${{ matrix.check.board }}
|
||||
run: bin/check-all.sh ${{ matrix.check.board }}
|
||||
uses: meshtastic/gh-action-firmware@main
|
||||
with:
|
||||
pio_platform: ${{ matrix.check.platform }}
|
||||
pio_env: ${{ matrix.check.board }}
|
||||
pio_target: check
|
||||
|
||||
build:
|
||||
needs: [setup, version]
|
||||
@@ -168,7 +177,7 @@ jobs:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
path: ./
|
||||
pattern: firmware-${{matrix.arch}}-*
|
||||
@@ -178,7 +187,7 @@ jobs:
|
||||
run: ls -R
|
||||
|
||||
- name: Repackage in single firmware zip
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
overwrite: true
|
||||
@@ -195,7 +204,7 @@ jobs:
|
||||
./Meshtastic_nRF52_factory_erase*.uf2
|
||||
retention-days: 30
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
@@ -214,7 +223,7 @@ jobs:
|
||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
|
||||
|
||||
- name: Repackage in single elfs zip
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
overwrite: true
|
||||
@@ -228,6 +237,48 @@ jobs:
|
||||
description: "Download firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip. This artifact will be available for 90 days from creation"
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
shame:
|
||||
if: github.repository == 'meshtastic/firmware'
|
||||
continue-on-error: true
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
if: github.event_name == 'pull_request_target'
|
||||
with:
|
||||
filter: blob:none # means we download all the git history but none of the commit (except ones with checkout like the head)
|
||||
fetch-depth: 0
|
||||
- name: Download the current manifests
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
path: ./manifests-new/
|
||||
pattern: manifest-*
|
||||
merge-multiple: true
|
||||
- name: Upload combined manifests for later commit and global stats crunching.
|
||||
uses: actions/upload-artifact@v6
|
||||
id: upload-manifest
|
||||
with:
|
||||
name: manifests-${{ github.sha }}
|
||||
overwrite: true
|
||||
path: manifests-new/*.mt.json
|
||||
- name: Find the merge base
|
||||
if: github.event_name == 'pull_request_target'
|
||||
run: echo "MERGE_BASE=$(git merge-base "origin/$base" "$head")" >> $GITHUB_ENV
|
||||
env:
|
||||
base: ${{ github.base_ref }}
|
||||
head: ${{ github.sha }}
|
||||
# Currently broken (for-loop through EVERY artifact -- rate limiting)
|
||||
# - name: Download the old manifests
|
||||
# if: github.event_name == 'pull_request_target'
|
||||
# run: gh run download -R "$repo" --name "manifests-$merge_base" --dir manifest-old/
|
||||
# env:
|
||||
# GH_TOKEN: ${{ github.token }}
|
||||
# merge_base: ${{ env.MERGE_BASE }}
|
||||
# repo: ${{ github.repository }}
|
||||
# - name: Do scan and post comment
|
||||
# if: github.event_name == 'pull_request_target'
|
||||
# run: python3 bin/shame.py ${{ github.event.pull_request.number }} manifests-old/ manifests-new/
|
||||
|
||||
release-artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'meshtastic/firmware' }}
|
||||
@@ -255,14 +306,14 @@ jobs:
|
||||
Autogenerated by github action, developer should edit as required before publishing...
|
||||
|
||||
- name: Download source deb
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
pattern: firmware-debian-${{ needs.version.outputs.deb }}~UNRELEASED-src
|
||||
merge-multiple: true
|
||||
path: ./output/debian-src
|
||||
|
||||
- name: Download `native-tft` pio deps
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
pattern: platformio-deps-native-tft-${{ needs.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
@@ -280,13 +331,13 @@ jobs:
|
||||
|
||||
- name: Generate Release manifest
|
||||
run: |
|
||||
jq -n --arg ver "${{ needs.version.outputs.long }}" --arg targets "${{ toJson(needs.setup.outputs.all) }}" '{
|
||||
jq -n --arg ver "${{ needs.version.outputs.long }}" --argjson targets ${{ toJson(needs.setup.outputs.all) }} '{
|
||||
"version": $ver,
|
||||
"targets": ($targets | fromjson)
|
||||
"targets": $targets
|
||||
}' > firmware-${{ needs.version.outputs.long }}.json
|
||||
|
||||
- name: Save Release manifest artifact
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: manifest-${{ needs.version.outputs.long }}
|
||||
overwrite: true
|
||||
@@ -327,7 +378,7 @@ jobs:
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
pattern: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
@@ -344,7 +395,7 @@ jobs:
|
||||
- name: Zip firmware
|
||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
@@ -383,14 +434,14 @@ jobs:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Get firmware artifacts
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
path: ./publish
|
||||
|
||||
- name: Get manifest artifact
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
pattern: manifest-${{ needs.version.outputs.long }}
|
||||
path: ./publish
|
||||
|
||||
18
.github/workflows/merge_queue.yml
vendored
18
.github/workflows/merge_queue.yml
vendored
@@ -147,7 +147,7 @@ jobs:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
path: ./
|
||||
pattern: firmware-${{matrix.arch}}-*
|
||||
@@ -160,7 +160,7 @@ jobs:
|
||||
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
|
||||
|
||||
- name: Repackage in single firmware zip
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
overwrite: true
|
||||
@@ -176,7 +176,7 @@ jobs:
|
||||
./Meshtastic_nRF52_factory_erase*.uf2
|
||||
retention-days: 30
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
@@ -195,7 +195,7 @@ jobs:
|
||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
|
||||
|
||||
- name: Repackage in single elfs zip
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
overwrite: true
|
||||
@@ -235,14 +235,14 @@ jobs:
|
||||
Autogenerated by github action, developer should edit as required before publishing...
|
||||
|
||||
- name: Download source deb
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
pattern: firmware-debian-${{ needs.version.outputs.deb }}~UNRELEASED-src
|
||||
merge-multiple: true
|
||||
path: ./output/debian-src
|
||||
|
||||
- name: Download `native-tft` pio deps
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
pattern: platformio-deps-native-tft-${{ needs.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
@@ -292,7 +292,7 @@ jobs:
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
pattern: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
@@ -309,7 +309,7 @@ jobs:
|
||||
- name: Zip firmware
|
||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
@@ -347,7 +347,7 @@ jobs:
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- uses: actions/download-artifact@v6
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
|
||||
2
.github/workflows/package_obs.yml
vendored
2
.github/workflows/package_obs.yml
vendored
@@ -58,7 +58,7 @@ jobs:
|
||||
id: version
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
|
||||
merge-multiple: true
|
||||
|
||||
2
.github/workflows/package_pio_deps.yml
vendored
2
.github/workflows/package_pio_deps.yml
vendored
@@ -56,7 +56,7 @@ jobs:
|
||||
PLATFORMIO_CORE_DIR: pio/core
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: platformio-deps-${{ inputs.pio_env }}-${{ steps.version.outputs.long }}
|
||||
overwrite: true
|
||||
|
||||
2
.github/workflows/package_ppa.yml
vendored
2
.github/workflows/package_ppa.yml
vendored
@@ -60,7 +60,7 @@ jobs:
|
||||
id: version
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
|
||||
merge-multiple: true
|
||||
|
||||
2
.github/workflows/pr_tests.yml
vendored
2
.github/workflows/pr_tests.yml
vendored
@@ -50,7 +50,7 @@ jobs:
|
||||
|
||||
- name: Download test artifacts
|
||||
if: needs.native-tests.result != 'skipped'
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: platformio-test-report-${{ steps.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
|
||||
2
.github/workflows/release_channels.yml
vendored
2
.github/workflows/release_channels.yml
vendored
@@ -102,7 +102,7 @@ jobs:
|
||||
PIP_DISABLE_PIP_VERSION_CHECK: 1
|
||||
|
||||
- name: Create Bumps pull request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
with:
|
||||
base: ${{ github.event.repository.default_branch }}
|
||||
branch: create-pull-request/bump-version
|
||||
|
||||
2
.github/workflows/sec_sast_semgrep_cron.yml
vendored
2
.github/workflows/sec_sast_semgrep_cron.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
|
||||
# step 3
|
||||
- name: save report as pipeline artifact
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: report.sarif
|
||||
overwrite: true
|
||||
|
||||
4
.github/workflows/stale_bot.yml
vendored
4
.github/workflows/stale_bot.yml
vendored
@@ -22,5 +22,5 @@ jobs:
|
||||
days-before-stale: 45
|
||||
stale-issue-message: This issue has not had any comment or update in the last month. If it is still relevant, please post update comments. If no comments are made, this issue will be closed automagically in 7 days.
|
||||
close-issue-message: This issue has not had any comment since the last notice. It has been closed automatically. If this is incorrect, or the issue becomes relevant again, please request that it is reopened.
|
||||
exempt-issue-labels: pinned,3.0
|
||||
exempt-pr-labels: pinned,3.0
|
||||
exempt-issue-labels: pinned,3.0,triaged,backlog
|
||||
exempt-pr-labels: pinned,3.0,triaged,backlog
|
||||
|
||||
14
.github/workflows/test_native.yml
vendored
14
.github/workflows/test_native.yml
vendored
@@ -59,7 +59,7 @@ jobs:
|
||||
id: version
|
||||
|
||||
- name: Save coverage information
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
if: always() # run this step even if previous step failed
|
||||
with:
|
||||
name: lcov-coverage-info-native-simulator-test-${{ steps.version.outputs.long }}
|
||||
@@ -94,7 +94,7 @@ jobs:
|
||||
|
||||
- name: Save test results
|
||||
if: always() # run this step even if previous step failed
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: platformio-test-report-${{ steps.version.outputs.long }}
|
||||
overwrite: true
|
||||
@@ -108,7 +108,7 @@ jobs:
|
||||
sed -i -e "s#${PWD}#.#" coverage_tests.info # Make paths relative.
|
||||
|
||||
- name: Save coverage information
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
if: always() # run this step even if previous step failed
|
||||
with:
|
||||
name: lcov-coverage-info-native-platformio-tests-${{ steps.version.outputs.long }}
|
||||
@@ -137,20 +137,20 @@ jobs:
|
||||
id: version
|
||||
|
||||
- name: Download test artifacts
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: platformio-test-report-${{ steps.version.outputs.long }}
|
||||
merge-multiple: true
|
||||
|
||||
- name: Test Report
|
||||
uses: dorny/test-reporter@v2.3.0
|
||||
uses: dorny/test-reporter@v2.5.0
|
||||
with:
|
||||
name: PlatformIO Tests
|
||||
path: testreport.xml
|
||||
reporter: java-junit
|
||||
|
||||
- name: Download coverage artifacts
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.long }}
|
||||
path: code-coverage-report
|
||||
@@ -163,7 +163,7 @@ jobs:
|
||||
genhtml --quiet --legend --prefix "${PWD}" code-coverage-report/coverage_src.info --output-directory code-coverage-report
|
||||
|
||||
- name: Save Code Coverage Report
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: code-coverage-report-${{ steps.version.outputs.long }}
|
||||
path: code-coverage-report
|
||||
|
||||
51
.github/workflows/trunk_format_pr.yml
vendored
51
.github/workflows/trunk_format_pr.yml
vendored
@@ -1,51 +0,0 @@
|
||||
name: Run Trunk Fmt on PR Comment
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
trunk-fmt:
|
||||
if: github.event.issue.pull_request != null && contains(github.event.comment.body, 'trunk fmt')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Install trunk
|
||||
run: curl https://get.trunk.io -fsSL | bash
|
||||
|
||||
- name: Run Trunk Fmt
|
||||
run: trunk fmt
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Commit and push changes
|
||||
run: |
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add .
|
||||
git commit -m "Add firmware version ${{ steps.version.outputs.long }}"
|
||||
git push
|
||||
|
||||
- name: Comment on PR
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
github.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: '`trunk fmt` has been run on this PR.'
|
||||
})
|
||||
4
.github/workflows/update_protobufs.yml
vendored
4
.github/workflows/update_protobufs.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
submodules: true
|
||||
|
||||
- name: Update submodule
|
||||
if: ${{ github.ref == 'refs/heads/master' }}
|
||||
if: ${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop' }}
|
||||
run: |
|
||||
git submodule update --remote protobufs
|
||||
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
./bin/regen-protos.sh
|
||||
|
||||
- name: Create pull request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
with:
|
||||
branch: create-pull-request/update-protobufs
|
||||
labels: submodules
|
||||
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -41,3 +41,12 @@ src/mesh/raspihttp/private_key.pem
|
||||
|
||||
# Ignore logo (set at build time with platformio-custom.py)
|
||||
data/boot/logo.*
|
||||
|
||||
# pioarduino platform
|
||||
managed_components/*
|
||||
arduino-lib-builder*
|
||||
dependencies.lock
|
||||
idf_component.yml
|
||||
CMakeLists.txt
|
||||
sdkconfig.*
|
||||
.dummy/*
|
||||
|
||||
@@ -8,25 +8,25 @@ plugins:
|
||||
uri: https://github.com/trunk-io/plugins
|
||||
lint:
|
||||
enabled:
|
||||
- checkov@3.2.495
|
||||
- renovate@42.30.4
|
||||
- checkov@3.2.497
|
||||
- renovate@42.75.0
|
||||
- prettier@3.7.4
|
||||
- trufflehog@3.91.2
|
||||
- trufflehog@3.92.4
|
||||
- yamllint@1.37.1
|
||||
- bandit@1.9.2
|
||||
- trivy@0.67.2
|
||||
- trivy@0.68.2
|
||||
- taplo@0.10.0
|
||||
- ruff@0.14.7
|
||||
- ruff@0.14.11
|
||||
- isort@7.0.0
|
||||
- markdownlint@0.46.0
|
||||
- oxipng@9.1.5
|
||||
- markdownlint@0.47.0
|
||||
- oxipng@10.0.0
|
||||
- svgo@4.0.0
|
||||
- actionlint@1.7.9
|
||||
- actionlint@1.7.10
|
||||
- flake8@7.3.0
|
||||
- hadolint@2.14.0
|
||||
- shfmt@3.6.0
|
||||
- shellcheck@0.11.0
|
||||
- black@25.11.0
|
||||
- black@25.12.0
|
||||
- git-diff-check
|
||||
- gitleaks@8.30.0
|
||||
- clang-format@16.0.3
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
| Firmware Version | Supported |
|
||||
| ---------------- | ------------------ |
|
||||
| 2.6.x | :white_check_mark: |
|
||||
| <= 2.5.x | :x: |
|
||||
| 2.7.x | :white_check_mark: |
|
||||
| <= 2.6.x | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ export APP_VERSION=$VERSION
|
||||
|
||||
basename=firmware-$1-$VERSION
|
||||
|
||||
pio run --environment $1 # -v
|
||||
pio run --environment $1 -t mtjson # -v
|
||||
|
||||
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
|
||||
|
||||
@@ -32,20 +32,10 @@ cp $BUILDDIR/$basename.factory.bin $OUTDIR/$basename.factory.bin
|
||||
echo "Copying ESP32 update bin file"
|
||||
cp $BUILDDIR/$basename.bin $OUTDIR/$basename.bin
|
||||
|
||||
echo "Building Filesystem for ESP32 targets"
|
||||
# If you want to build the webui, uncomment the following lines
|
||||
# pio run --environment $1 -t buildfs
|
||||
# cp .pio/build/$1/littlefs.bin $OUTDIR/littlefswebui-$1-$VERSION.bin
|
||||
# # Remove webserver files from the filesystem and rebuild
|
||||
# ls -l data/static # Diagnostic list of files
|
||||
# rm -rf data/static
|
||||
pio run --environment $1 -t buildfs --disable-auto-clean
|
||||
echo "Copying Filesystem for ESP32 targets"
|
||||
cp $BUILDDIR/littlefs-$1-$VERSION.bin $OUTDIR/littlefs-$1-$VERSION.bin
|
||||
cp bin/device-install.* $OUTDIR/
|
||||
cp bin/device-update.* $OUTDIR/
|
||||
|
||||
# Generate the manifest file
|
||||
echo "Generating Meshtastic manifest"
|
||||
TIMEFORMAT="Generated manifest in %E seconds"
|
||||
time pio run --environment $1 -t mtjson --silent --disable-auto-clean
|
||||
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json
|
||||
echo "Copying manifest"
|
||||
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json || true
|
||||
|
||||
@@ -21,13 +21,14 @@ rm -f $BUILDDIR/firmware*
|
||||
export APP_VERSION=$VERSION
|
||||
|
||||
basename=firmware-$1-$VERSION
|
||||
ota_basename=${basename}-ota
|
||||
|
||||
pio run --environment $1 # -v
|
||||
pio run --environment $1 -t mtjson # -v
|
||||
|
||||
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
|
||||
|
||||
echo "Copying NRF52 dfu (OTA) file"
|
||||
cp $BUILDDIR/$basename.zip $OUTDIR/$basename.zip
|
||||
cp $BUILDDIR/$basename.zip $OUTDIR/$ota_basename.zip
|
||||
|
||||
echo "Copying NRF52 UF2 file"
|
||||
cp $BUILDDIR/$basename.uf2 $OUTDIR/$basename.uf2
|
||||
@@ -47,8 +48,5 @@ if (echo $1 | grep -q "rak4631"); then
|
||||
cp $SRCHEX $OUTDIR/
|
||||
fi
|
||||
|
||||
# Generate the manifest file
|
||||
echo "Generating Meshtastic manifest"
|
||||
TIMEFORMAT="Generated manifest in %E seconds"
|
||||
time pio run --environment $1 -t mtjson --silent --disable-auto-clean
|
||||
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json
|
||||
echo "Copying manifest"
|
||||
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json || true
|
||||
|
||||
@@ -22,15 +22,12 @@ export APP_VERSION=$VERSION
|
||||
|
||||
basename=firmware-$1-$VERSION
|
||||
|
||||
pio run --environment $1 # -v
|
||||
pio run --environment $1 -t mtjson # -v
|
||||
|
||||
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
|
||||
|
||||
echo "Copying uf2 file"
|
||||
cp $BUILDDIR/$basename.uf2 $OUTDIR/$basename.uf2
|
||||
|
||||
# Generate the manifest file
|
||||
echo "Generating Meshtastic manifest"
|
||||
TIMEFORMAT="Generated manifest in %E seconds"
|
||||
time pio run --environment $1 -t mtjson --silent --disable-auto-clean
|
||||
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json
|
||||
echo "Copying manifest"
|
||||
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json || true
|
||||
|
||||
@@ -22,15 +22,12 @@ export APP_VERSION=$VERSION
|
||||
|
||||
basename=firmware-$1-$VERSION
|
||||
|
||||
pio run --environment $1 # -v
|
||||
pio run --environment $1 -t mtjson # -v
|
||||
|
||||
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
|
||||
|
||||
echo "Copying STM32 bin file"
|
||||
cp $BUILDDIR/$basename.bin $OUTDIR/$basename.bin
|
||||
|
||||
# Generate the manifest file
|
||||
echo "Generating Meshtastic manifest"
|
||||
TIMEFORMAT="Generated manifest in %E seconds"
|
||||
time pio run --environment $1 -t mtjson --silent --disable-auto-clean
|
||||
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json
|
||||
echo "Copying manifest"
|
||||
cp $BUILDDIR/$basename.mt.json $OUTDIR/$basename.mt.json || true
|
||||
|
||||
@@ -184,6 +184,8 @@ Input:
|
||||
Logging:
|
||||
LogLevel: info # debug, info, warn, error
|
||||
# TraceFile: /var/log/meshtasticd.json
|
||||
# JSONFile: /packets.json # File location for JSON output of decoded packets
|
||||
# JSONFilter: position # filter for packets to save to JSON file
|
||||
# AsciiLogs: true # default if not specified is !isatty() on stdout
|
||||
|
||||
Webserver:
|
||||
|
||||
11
bin/config.d/lora-hat-rak-6421-pi-hat.yaml
Normal file
11
bin/config.d/lora-hat-rak-6421-pi-hat.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
Lora:
|
||||
|
||||
### RAK13300in Slot 1
|
||||
Module: sx1262
|
||||
IRQ: 22 #IO6
|
||||
Reset: 16 # IO4
|
||||
Busy: 24 # IO5
|
||||
# Ant_sw: 13 # IO3
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: spidev0.0
|
||||
14
bin/config.d/lora-usb-meshstick-1262.yaml
Normal file
14
bin/config.d/lora-usb-meshstick-1262.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
Lora:
|
||||
Module: sx1262
|
||||
CS: 0
|
||||
IRQ: 6
|
||||
Reset: 2
|
||||
Busy: 4
|
||||
RXen: 1
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
spidev: ch341
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
# USB_Serialnum: 12345678
|
||||
USB_PID: 0x5512
|
||||
USB_VID: 0x1A86
|
||||
SX126X_MAX_POWER: 22
|
||||
@@ -75,7 +75,7 @@ TOOLS = {
|
||||
}
|
||||
|
||||
BACKTRACE_REGEX = re.compile(
|
||||
r"(?:\s+(0x40[0-2](?:\d|[a-f]|[A-F]){5}):0x(?:\d|[a-f]|[A-F]){8})\b"
|
||||
r"\b(0x4[0-9a-fA-F]{7,8}):0x[0-9a-fA-F]{8}\b"
|
||||
)
|
||||
EXCEPTION_REGEX = re.compile("^Exception \\((?P<exc>[0-9]*)\\):$")
|
||||
COUNTER_REGEX = re.compile(
|
||||
@@ -89,7 +89,7 @@ POINTER_REGEX = re.compile(
|
||||
STACK_BEGIN = ">>>stack>>>"
|
||||
STACK_END = "<<<stack<<<"
|
||||
STACK_REGEX = re.compile(
|
||||
"^(?P<off>[0-9a-f]+):\W+(?P<c1>[0-9a-f]+) (?P<c2>[0-9a-f]+) (?P<c3>[0-9a-f]+) (?P<c4>[0-9a-f]+)(\W.*)?$"
|
||||
r"^(?P<off>[0-9a-f]+):\W+(?P<c1>[0-9a-f]+) (?P<c2>[0-9a-f]+) (?P<c3>[0-9a-f]+) (?P<c4>[0-9a-f]+)(\W.*)?$"
|
||||
)
|
||||
|
||||
StackLine = namedtuple("StackLine", ["offset", "content"])
|
||||
@@ -223,7 +223,7 @@ class AddressResolver(object):
|
||||
if match is None:
|
||||
if last is not None and line.startswith("(inlined by)"):
|
||||
line = line[12:].strip()
|
||||
self._address_map[last] += "\n \-> inlined by: " + line
|
||||
self._address_map[last] += "\n \\-> inlined by: " + line
|
||||
continue
|
||||
|
||||
if match.group("result") == "?? ??:0":
|
||||
|
||||
32
bin/meshtasticd-start.sh
Executable file
32
bin/meshtasticd-start.sh
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
INSTANCE=$1
|
||||
CONF_DIR="/etc/meshtasticd/config.d"
|
||||
VFS_DIR="/var/lib"
|
||||
|
||||
# If no instance ID provided, start bare daemon and exit
|
||||
echo "no instance ID provided, starting bare meshtasticd service"
|
||||
if [ -z "${INSTANCE}" ]; then
|
||||
/usr/bin/meshtasticd
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Make VFS dir if it does not exist
|
||||
if [ ! -d "${VFS_DIR}/meshtasticd-${INSTANCE}" ]; then
|
||||
echo "vfs for ${INSTANCE} does not exist, creating it."
|
||||
mkdir "${VFS_DIR}/meshtasticd-${INSTANCE}"
|
||||
fi
|
||||
|
||||
# Abort if config for $INSTANCE does not exist
|
||||
if [ ! -f "${CONF_DIR}/config-${INSTANCE}.yaml" ]; then
|
||||
echo "no config for ${INSTANCE} found in ${CONF_DIR}. refusing to start" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Start meshtasticd with instance parameters
|
||||
printf "starting meshtasticd-%s..., ${INSTANCE}"
|
||||
if /usr/bin/meshtasticd --config="${CONF_DIR}/config-${INSTANCE}.yaml" --fsdir="${VFS_DIR}/meshtasticd-${INSTANCE}"; then
|
||||
echo "ok"
|
||||
else
|
||||
echo "failed"
|
||||
fi
|
||||
@@ -1,5 +1,5 @@
|
||||
[Unit]
|
||||
Description=Meshtastic Native Daemon
|
||||
Description=Meshtastic %i Daemon
|
||||
After=network-online.target
|
||||
StartLimitInterval=200
|
||||
StartLimitBurst=5
|
||||
@@ -9,7 +9,7 @@ AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
User=meshtasticd
|
||||
Group=meshtasticd
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/meshtasticd
|
||||
ExecStart=/usr/bin/meshtasticd-start.sh %i
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cp "release/meshtasticd_linux_$(uname -m)" /usr/bin/meshtasticd
|
||||
cp "bin/meshtasticd-start.sh" /usr/bin/meshtasticd-start.sh
|
||||
mkdir -p /etc/meshtasticd
|
||||
if [[ -f "/etc/meshtasticd/config.yaml" ]]; then
|
||||
cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml
|
||||
|
||||
@@ -87,6 +87,9 @@
|
||||
</screenshots>
|
||||
|
||||
<releases>
|
||||
<release version="2.7.18" date="2026-01-02">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.18</url>
|
||||
</release>
|
||||
<release version="2.7.17" date="2025-11-28">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.17</url>
|
||||
</release>
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
# trunk-ignore-all(ruff/F821)
|
||||
# trunk-ignore-all(flake8/F821): For SConstruct imports
|
||||
import sys
|
||||
from os.path import join, basename, isfile
|
||||
from os.path import join
|
||||
import subprocess
|
||||
import json
|
||||
import re
|
||||
from datetime import datetime
|
||||
from typing import Dict
|
||||
|
||||
from readprops import readProps
|
||||
|
||||
@@ -14,9 +15,50 @@ Import("env")
|
||||
platform = env.PioPlatform()
|
||||
progname = env.get("PROGNAME")
|
||||
lfsbin = f"{progname.replace('firmware-', 'littlefs-')}.bin"
|
||||
manifest_ran = False
|
||||
|
||||
def infer_architecture(board_cfg):
|
||||
try:
|
||||
mcu = board_cfg.get("build.mcu") if board_cfg else None
|
||||
except KeyError:
|
||||
mcu = None
|
||||
except Exception:
|
||||
mcu = None
|
||||
if not mcu:
|
||||
return None
|
||||
mcu_l = str(mcu).lower()
|
||||
if "esp32s3" in mcu_l:
|
||||
return "esp32-s3"
|
||||
if "esp32c6" in mcu_l:
|
||||
return "esp32-c6"
|
||||
if "esp32c3" in mcu_l:
|
||||
return "esp32-c3"
|
||||
if "esp32" in mcu_l:
|
||||
return "esp32"
|
||||
if "rp2040" in mcu_l:
|
||||
return "rp2040"
|
||||
if "rp2350" in mcu_l:
|
||||
return "rp2350"
|
||||
if "nrf52" in mcu_l or "nrf52840" in mcu_l:
|
||||
return "nrf52840"
|
||||
if "stm32" in mcu_l:
|
||||
return "stm32"
|
||||
return None
|
||||
|
||||
def manifest_gather(source, target, env):
|
||||
global manifest_ran
|
||||
if manifest_ran:
|
||||
return
|
||||
# Skip manifest generation if we cannot determine architecture (host/native builds)
|
||||
board_arch = infer_architecture(env.BoardConfig())
|
||||
if not board_arch:
|
||||
print(f"Skipping mtjson generation for unknown architecture (env={env.get('PIOENV')})")
|
||||
manifest_ran = True
|
||||
return
|
||||
manifest_ran = True
|
||||
out = []
|
||||
board_platform = env.BoardConfig().get("platform")
|
||||
needs_ota_suffix = board_platform == "nordicnrf52"
|
||||
check_paths = [
|
||||
progname,
|
||||
f"{progname}.elf",
|
||||
@@ -32,8 +74,11 @@ def manifest_gather(source, target, env):
|
||||
for p in check_paths:
|
||||
f = env.File(env.subst(f"$BUILD_DIR/{p}"))
|
||||
if f.exists():
|
||||
manifest_name = p
|
||||
if needs_ota_suffix and p == f"{progname}.zip":
|
||||
manifest_name = f"{progname}-ota.zip"
|
||||
d = {
|
||||
"name": p,
|
||||
"name": manifest_name,
|
||||
"md5": f.get_content_hash(), # Returns MD5 hash
|
||||
"bytes": f.get_size() # Returns file size in bytes
|
||||
}
|
||||
@@ -42,14 +87,39 @@ def manifest_gather(source, target, env):
|
||||
manifest_write(out, env)
|
||||
|
||||
def manifest_write(files, env):
|
||||
# Defensive: also skip manifest writing if we cannot determine architecture
|
||||
def get_project_option(name):
|
||||
try:
|
||||
return env.GetProjectOption(name)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def get_project_option_any(names):
|
||||
for name in names:
|
||||
val = get_project_option(name)
|
||||
if val is not None:
|
||||
return val
|
||||
return None
|
||||
|
||||
def as_bool(val):
|
||||
return str(val).strip().lower() in ("1", "true", "yes", "on")
|
||||
|
||||
def as_int(val):
|
||||
try:
|
||||
return int(str(val), 10)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
def as_list(val):
|
||||
return [item.strip() for item in str(val).split(",") if item.strip()]
|
||||
|
||||
manifest = {
|
||||
"version": verObj["long"],
|
||||
"build_epoch": build_epoch,
|
||||
"board": env.get("PIOENV"),
|
||||
"platformioTarget": env.get("PIOENV"),
|
||||
"mcu": env.get("BOARD_MCU"),
|
||||
"repo": repo_owner,
|
||||
"files": files,
|
||||
"part": None,
|
||||
"has_mui": False,
|
||||
"has_inkhud": False,
|
||||
}
|
||||
@@ -64,6 +134,51 @@ def manifest_write(files, env):
|
||||
if "MESHTASTIC_INCLUDE_INKHUD" in env.get("CPPDEFINES", []):
|
||||
manifest["has_inkhud"] = True
|
||||
|
||||
pioenv = env.get("PIOENV")
|
||||
device_meta = {}
|
||||
device_meta_fields = [
|
||||
("hwModel", ["custom_meshtastic_hw_model"], as_int),
|
||||
("hwModelSlug", ["custom_meshtastic_hw_model_slug"], str),
|
||||
("architecture", ["custom_meshtastic_architecture"], str),
|
||||
("activelySupported", ["custom_meshtastic_actively_supported"], as_bool),
|
||||
("displayName", ["custom_meshtastic_display_name"], str),
|
||||
("supportLevel", ["custom_meshtastic_support_level"], as_int),
|
||||
("images", ["custom_meshtastic_images"], as_list),
|
||||
("tags", ["custom_meshtastic_tags"], as_list),
|
||||
("requiresDfu", ["custom_meshtastic_requires_dfu"], as_bool),
|
||||
("partitionScheme", ["custom_meshtastic_partition_scheme"], str),
|
||||
("url", ["custom_meshtastic_url"], str),
|
||||
("key", ["custom_meshtastic_key"], str),
|
||||
("variant", ["custom_meshtastic_variant"], str),
|
||||
]
|
||||
|
||||
|
||||
for manifest_key, option_keys, caster in device_meta_fields:
|
||||
raw_val = get_project_option_any(option_keys)
|
||||
if raw_val is None:
|
||||
continue
|
||||
parsed = caster(raw_val) if callable(caster) else raw_val
|
||||
if parsed is not None and parsed != "":
|
||||
device_meta[manifest_key] = parsed
|
||||
|
||||
# Determine architecture once; if we can't infer it, skip manifest generation
|
||||
board_arch = device_meta.get("architecture") or infer_architecture(env.BoardConfig())
|
||||
if not board_arch:
|
||||
print(f"Skipping mtjson write for unknown architecture (env={env.get('PIOENV')})")
|
||||
return
|
||||
|
||||
device_meta["architecture"] = board_arch
|
||||
|
||||
# Always set requiresDfu: true for nrf52840 targets
|
||||
if board_arch == "nrf52840":
|
||||
device_meta["requiresDfu"] = True
|
||||
|
||||
device_meta.setdefault("displayName", pioenv)
|
||||
device_meta.setdefault("activelySupported", False)
|
||||
|
||||
if device_meta:
|
||||
manifest.update(device_meta)
|
||||
|
||||
# Write the manifest to the build directory
|
||||
with open(env.subst("$BUILD_DIR/${PROGNAME}.mt.json"), "w") as f:
|
||||
json.dump(manifest, f, indent=2)
|
||||
@@ -159,20 +274,42 @@ def load_boot_logo(source, target, env):
|
||||
|
||||
# Load the boot logo on TFT builds
|
||||
if ("HAS_TFT", 1) in env.get("CPPDEFINES", []):
|
||||
env.AddPreAction('$BUILD_DIR/littlefs.bin', load_boot_logo)
|
||||
env.AddPreAction(f"$BUILD_DIR/{lfsbin}", load_boot_logo)
|
||||
|
||||
# Rename (mv) littlefs.bin to include the PROGNAME
|
||||
# This ensures the littlefs.bin is named consistently with the firmware
|
||||
env.AddPostAction('$BUILD_DIR/littlefs.bin', env.VerboseAction(
|
||||
f'mv $BUILD_DIR/littlefs.bin $BUILD_DIR/{lfsbin}',
|
||||
f'Renaming littlefs.bin to {lfsbin}'
|
||||
))
|
||||
board_arch = infer_architecture(env.BoardConfig())
|
||||
should_skip_manifest = board_arch is None
|
||||
|
||||
env.AddCustomTarget(
|
||||
name="mtjson",
|
||||
dependencies=None,
|
||||
actions=[manifest_gather],
|
||||
title="Meshtastic Manifest",
|
||||
description="Generating Meshtastic manifest JSON + Checksums",
|
||||
always_build=True,
|
||||
)
|
||||
# For host/native envs, avoid depending on 'buildprog' (some targets don't define it)
|
||||
mtjson_deps = [] if should_skip_manifest else ["buildprog"]
|
||||
if not should_skip_manifest and platform.name == "espressif32":
|
||||
# Build littlefs image as part of mtjson target
|
||||
# Equivalent to `pio run -t buildfs`
|
||||
target_lfs = env.DataToBin(
|
||||
join("$BUILD_DIR", "${ESP32_FS_IMAGE_NAME}"), "$PROJECT_DATA_DIR"
|
||||
)
|
||||
mtjson_deps.append(target_lfs)
|
||||
|
||||
if should_skip_manifest:
|
||||
def skip_manifest(source, target, env):
|
||||
print(f"mtjson: skipped for native environment: {env.get('PIOENV')}")
|
||||
|
||||
env.AddCustomTarget(
|
||||
name="mtjson",
|
||||
dependencies=mtjson_deps,
|
||||
actions=[skip_manifest],
|
||||
title="Meshtastic Manifest (skipped)",
|
||||
description="mtjson generation is skipped for native environments",
|
||||
always_build=True,
|
||||
)
|
||||
else:
|
||||
env.AddCustomTarget(
|
||||
name="mtjson",
|
||||
dependencies=mtjson_deps,
|
||||
actions=[manifest_gather],
|
||||
title="Meshtastic Manifest",
|
||||
description="Generating Meshtastic manifest JSON + Checksums",
|
||||
always_build=True,
|
||||
)
|
||||
|
||||
# Run manifest generation as part of the default build pipeline for non-native builds.
|
||||
env.Default("mtjson")
|
||||
|
||||
@@ -11,6 +11,9 @@ else:
|
||||
prefsLoc = env["PROJECT_DIR"] + "/version.properties"
|
||||
verObj = readProps(prefsLoc)
|
||||
env.Replace(PROGNAME=f"firmware-{env.get('PIOENV')}-{verObj['long']}")
|
||||
env.Replace(ESP32_FS_IMAGE_NAME=f"littlefs-{env.get('PIOENV')}-{verObj['long']}")
|
||||
|
||||
# Print the new program name for verification
|
||||
print(f"PROGNAME: {env.get('PROGNAME')}")
|
||||
if platform.name == "espressif32":
|
||||
print(f"ESP32_FS_IMAGE_NAME: {env.get('ESP32_FS_IMAGE_NAME')}")
|
||||
|
||||
@@ -18,8 +18,9 @@ def readProps(prefsLoc):
|
||||
|
||||
# Try to find current build SHA if if the workspace is clean. This could fail if git is not installed
|
||||
try:
|
||||
# Pin abbreviation length to keep local builds and CI matching (avoid auto-shortening)
|
||||
sha = (
|
||||
subprocess.check_output(["git", "rev-parse", "--short", "HEAD"])
|
||||
subprocess.check_output(["git", "rev-parse", "--short=7", "HEAD"])
|
||||
.decode("utf-8")
|
||||
.strip()
|
||||
)
|
||||
|
||||
95
bin/shame.py
Normal file
95
bin/shame.py
Normal file
@@ -0,0 +1,95 @@
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
from github import Github
|
||||
|
||||
def parseFile(path):
|
||||
with open(path, "r") as f:
|
||||
data = json.loads(f)
|
||||
for file in data["files"]:
|
||||
if file["name"].endswith(".bin"):
|
||||
return file["name"], file["bytes"]
|
||||
|
||||
if len(sys.argv) != 4:
|
||||
print(f"expected usage: {sys.argv[0]} <PR number> <path to old-manifests> <path to new-manifests>")
|
||||
sys.exit(1)
|
||||
|
||||
pr_number = int(sys.argv[1])
|
||||
|
||||
token = os.getenv("GITHUB_TOKEN")
|
||||
if not token:
|
||||
raise EnvironmentError("GITHUB_TOKEN not found in environment.")
|
||||
|
||||
repo_name = os.getenv("GITHUB_REPOSITORY") # "owner/repo"
|
||||
if not repo_name:
|
||||
raise EnvironmentError("GITHUB_REPOSITORY not found in environment.")
|
||||
|
||||
oldFiles = sys.argv[2]
|
||||
old = set(os.path.join(oldFiles, f) for f in os.listdir(oldFiles) if os.path.isfile(f))
|
||||
newFiles = sys.argv[3]
|
||||
new = set(os.path.join(newFiles, f) for f in os.listdir(newFiles) if os.path.isfile(f))
|
||||
|
||||
startMarkdown = "# Target Size Changes\n\n"
|
||||
markdown = ""
|
||||
|
||||
newlyIntroduced = new - old
|
||||
if len(newlyIntroduced) > 0:
|
||||
markdown += "## Newly Introduced Targets\n\n"
|
||||
# create a table
|
||||
markdown += "| File | Size |\n"
|
||||
markdown += "| ---- | ---- |\n"
|
||||
for f in newlyIntroduced:
|
||||
name, size = parseFile(f)
|
||||
markdown += f"| `{name}` | {size}b |\n"
|
||||
|
||||
# do not log removed targets
|
||||
# PRs only run a small subset of builds, so removed targets are not meaningful
|
||||
# since they are very likely to just be not ran in PR CI
|
||||
|
||||
both = old & new
|
||||
degradations = []
|
||||
improvements = []
|
||||
for f in both:
|
||||
oldName, oldSize = parseFile(f)
|
||||
_, newSize = parseFile(f)
|
||||
if oldSize != newSize:
|
||||
if newSize < oldSize:
|
||||
improvements.append((oldName, oldSize, newSize))
|
||||
else:
|
||||
degradations.append((oldName, oldSize, newSize))
|
||||
|
||||
if len(degradations) > 0:
|
||||
markdown += "\n## Degradation\n\n"
|
||||
# create a table
|
||||
markdown += "| File | Difference | Old Size | New Size |\n"
|
||||
markdown += "| ---- | ---------- | -------- | -------- |\n"
|
||||
for oldName, oldSize, newSize in degradations:
|
||||
markdown += f"| `{oldName}` | **{oldSize - newSize}b** | {oldSize}b | {newSize}b |\n"
|
||||
|
||||
if len(improvements) > 0:
|
||||
markdown += "\n## Improvement\n\n"
|
||||
# create a table
|
||||
markdown += "| File | Difference | Old Size | New Size |\n"
|
||||
markdown += "| ---- | ---------- | -------- | -------- |\n"
|
||||
for oldName, oldSize, newSize in improvements:
|
||||
markdown += f"| `{oldName}` | **{oldSize - newSize}b** | {oldSize}b | {newSize}b |\n"
|
||||
|
||||
if len(markdown) == 0:
|
||||
markdown = "No changes in target sizes detected."
|
||||
|
||||
g = Github(token)
|
||||
repo = g.get_repo(repo_name)
|
||||
pr = repo.get_pull(pr_number)
|
||||
|
||||
existing_comment = None
|
||||
for comment in pr.get_issue_comments():
|
||||
if comment.body.startswith(startMarkdown):
|
||||
existing_comment = comment
|
||||
break
|
||||
|
||||
final_markdown = startMarkdown + markdown
|
||||
|
||||
if existing_comment:
|
||||
existing_comment.edit(body=final_markdown)
|
||||
else:
|
||||
pr.create_issue_comment(body=final_markdown)
|
||||
39
boards/t-beam-1w.json
Normal file
39
boards/t-beam-1w.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "esp32s3_out.ld",
|
||||
"memory_type": "qio_opi"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DBOARD_HAS_PSRAM",
|
||||
"-DLILYGO_TBEAM_1W",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MODE=0",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"psram_type": "opi",
|
||||
"hwids": [["0x303A", "0x1001"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "t-beam-1w"
|
||||
},
|
||||
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||
"debug": {
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "LilyGo TBeam-1W",
|
||||
"upload": {
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 16777216,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
"url": "http://www.lilygo.cn/",
|
||||
"vendor": "LilyGo"
|
||||
}
|
||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@@ -1,3 +1,9 @@
|
||||
meshtasticd (2.7.18.0) unstable; urgency=medium
|
||||
|
||||
* Version 2.7.18
|
||||
|
||||
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Fri, 02 Jan 2026 12:45:36 +0000
|
||||
|
||||
meshtasticd (2.7.17.0) unstable; urgency=medium
|
||||
|
||||
* Version 2.7.17
|
||||
|
||||
1
debian/meshtasticd.install
vendored
1
debian/meshtasticd.install
vendored
@@ -4,5 +4,6 @@ bin/config.yaml etc/meshtasticd
|
||||
bin/config.d/* etc/meshtasticd/available.d
|
||||
|
||||
bin/meshtasticd.service lib/systemd/system
|
||||
bin/meshtasticd-start.sh usr/bin
|
||||
|
||||
web/* usr/share/meshtasticd/web
|
||||
|
||||
@@ -10,6 +10,12 @@ Import("env")
|
||||
platform = env.PioPlatform()
|
||||
|
||||
sys.path.append(join(platform.get_package_dir("tool-esptoolpy")))
|
||||
# IntelHex workaround, remove after fixed upstream
|
||||
# https://github.com/platformio/platform-espressif32/issues/1632
|
||||
try:
|
||||
import intelhex
|
||||
except ImportError:
|
||||
env.Execute("$PYTHONEXE -m pip install intelhex")
|
||||
import esptool
|
||||
|
||||
|
||||
|
||||
@@ -95,6 +95,9 @@ cp -r bin/config.d/* %{buildroot}%{_sysconfdir}/meshtasticd/available.d
|
||||
# Install systemd service
|
||||
install -D -m 0644 bin/meshtasticd.service %{buildroot}%{_unitdir}/meshtasticd.service
|
||||
|
||||
# Install meshtasticd start wrapper
|
||||
install -D -m 0755 bin/meshtasticd-start.sh %{buildroot}%{_bindir}/meshtasticd-start.sh
|
||||
|
||||
# Install the web files under /usr/share/meshtasticd/web
|
||||
mkdir -p %{buildroot}%{_datadir}/meshtasticd/web
|
||||
cp -r web/* %{buildroot}%{_datadir}/meshtasticd/web
|
||||
|
||||
@@ -64,7 +64,7 @@ monitor_speed = 115200
|
||||
monitor_filters = direct
|
||||
lib_deps =
|
||||
# renovate: datasource=git-refs depName=meshtastic-esp8266-oled-ssd1306 packageName=https://github.com/meshtastic/esp8266-oled-ssd1306 gitBranch=master
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/2887bf4a19f64d92c984dcc8fd5ca7429e425e4a.zip
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/b34c6817c25d6faabb3a8a162b5d14fb75395433.zip
|
||||
# renovate: datasource=git-refs depName=meshtastic-OneButton packageName=https://github.com/meshtastic/OneButton gitBranch=master
|
||||
https://github.com/meshtastic/OneButton/archive/fa352d668c53f290cfa480a5f79ad422cd828c70.zip
|
||||
# renovate: datasource=git-refs depName=meshtastic-arduino-fsm packageName=https://github.com/meshtastic/arduino-fsm gitBranch=master
|
||||
@@ -103,17 +103,13 @@ lib_deps =
|
||||
thingsboard/TBPubSubClient@2.12.1
|
||||
# renovate: datasource=custom.pio depName=NTPClient packageName=arduino-libraries/library/NTPClient
|
||||
arduino-libraries/NTPClient@3.2.1
|
||||
|
||||
; Extra TCP/IP networking libs for supported devices
|
||||
[networking_extra]
|
||||
lib_deps =
|
||||
# renovate: datasource=custom.pio depName=Syslog packageName=arcao/library/Syslog
|
||||
arcao/Syslog@2.0.0
|
||||
|
||||
; Minimal networking libs for nrf52 (excludes Syslog to save flash)
|
||||
[nrf52_networking_base]
|
||||
lib_deps =
|
||||
# renovate: datasource=custom.pio depName=TBPubSubClient packageName=thingsboard/library/TBPubSubClient
|
||||
thingsboard/TBPubSubClient@2.12.1
|
||||
# renovate: datasource=custom.pio depName=NTPClient packageName=arduino-libraries/library/NTPClient
|
||||
arduino-libraries/NTPClient@3.2.1
|
||||
|
||||
[radiolib_base]
|
||||
lib_deps =
|
||||
# renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib
|
||||
@@ -123,7 +119,7 @@ lib_deps =
|
||||
[device-ui_base]
|
||||
lib_deps =
|
||||
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
||||
https://github.com/meshtastic/device-ui/archive/4fb5f24787caa841b58dbf623a52c4c5861d6722.zip
|
||||
https://github.com/meshtastic/device-ui/archive/272defcb35651461830ebfd1b39c9167c8f49317.zip
|
||||
|
||||
; Common libs for environmental measurements in telemetry module
|
||||
[environmental_base]
|
||||
@@ -162,8 +158,8 @@ lib_deps =
|
||||
emotibit/EmotiBit MLX90632@1.0.8
|
||||
# renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library
|
||||
adafruit/Adafruit MLX90614 Library@2.1.5
|
||||
# renovate: datasource=github-tags depName=INA3221 packageName=sgtwilko/INA3221
|
||||
https://github.com/sgtwilko/INA3221#bb03d7e9bfcc74fc798838a54f4f99738f29fc6a
|
||||
# renovate: datasource=git-refs depName=INA3221 packageName=https://github.com/sgtwilko/INA3221 gitBranch=FixOverflow
|
||||
https://github.com/sgtwilko/INA3221/archive/bb03d7e9bfcc74fc798838a54f4f99738f29fc6a.zip
|
||||
# renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass
|
||||
mprograms/QMC5883LCompass@1.2.3
|
||||
# renovate: datasource=custom.pio depName=DFRobot_RTU packageName=dfrobot/library/DFRobot_RTU
|
||||
@@ -171,7 +167,7 @@ lib_deps =
|
||||
# renovate: datasource=git-refs depName=DFRobot_RainfallSensor packageName=https://github.com/DFRobot/DFRobot_RainfallSensor gitBranch=master
|
||||
https://github.com/DFRobot/DFRobot_RainfallSensor/archive/38fea5e02b40a5430be6dab39a99a6f6347d667e.zip
|
||||
# renovate: datasource=custom.pio depName=INA226 packageName=robtillaart/library/INA226
|
||||
robtillaart/INA226@0.6.5
|
||||
robtillaart/INA226@0.6.6
|
||||
# renovate: datasource=custom.pio depName=SparkFun MAX3010x packageName=sparkfun/library/SparkFun MAX3010x Pulse and Proximity Sensor Library
|
||||
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
|
||||
# renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library
|
||||
@@ -207,7 +203,7 @@ lib_deps =
|
||||
# renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library
|
||||
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
|
||||
# renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001
|
||||
ClosedCube OPT3001@1.1.2
|
||||
closedcube/ClosedCube OPT3001@1.1.2
|
||||
# renovate: datasource=custom.pio depName=Bosch BSEC2 packageName=boschsensortec/library/bsec2
|
||||
boschsensortec/bsec2@1.10.2610
|
||||
# renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library
|
||||
|
||||
Submodule protobufs updated: 4095e59890...aa48faf5b5
@@ -31,6 +31,9 @@ const char *DisplayFormatters::getModemPresetDisplayName(meshtastic_Config_LoRaC
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST:
|
||||
return useShortName ? "LongF" : "LongFast";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO:
|
||||
return useShortName ? "LongT" : "LongTurbo";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE:
|
||||
return useShortName ? "LongM" : "LongMod";
|
||||
break;
|
||||
|
||||
@@ -296,22 +296,23 @@ void MessageStore::clearAllMessages()
|
||||
template <typename Predicate> static void eraseIf(std::deque<StoredMessage> &deque, Predicate pred, bool fromBack = false)
|
||||
{
|
||||
if (fromBack) {
|
||||
// Iterate from the back and erase the first match from the end
|
||||
for (auto it = deque.rbegin(); it != deque.rend(); ++it) {
|
||||
// Iterate from the back and erase all matches from the end
|
||||
for (auto it = deque.rbegin(); it != deque.rend();) {
|
||||
if (pred(*it)) {
|
||||
deque.erase(std::next(it).base());
|
||||
break;
|
||||
it = std::deque<StoredMessage>::reverse_iterator(deque.erase(std::next(it).base()));
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Manual forward search to avoid std::find_if
|
||||
auto it = deque.begin();
|
||||
for (; it != deque.end(); ++it) {
|
||||
if (pred(*it))
|
||||
break;
|
||||
// Manual forward search to erase all matches
|
||||
for (auto it = deque.begin(); it != deque.end();) {
|
||||
if (pred(*it)) {
|
||||
it = deque.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (it != deque.end())
|
||||
deque.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1149,11 +1149,11 @@ bool Power::axpChipInit()
|
||||
PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300);
|
||||
PMU->enablePowerOutput(XPOWERS_ALDO1);
|
||||
|
||||
// sdcard power channel
|
||||
// sdcard (T-Beam S3) / gnns (T-Watch S3 Plus) power channel
|
||||
PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300);
|
||||
#ifndef T_WATCH_S3
|
||||
PMU->enablePowerOutput(XPOWERS_BLDO1);
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#else
|
||||
// DRV2605 power channel
|
||||
PMU->setPowerChannelVoltage(XPOWERS_BLDO2, 3300);
|
||||
PMU->enablePowerOutput(XPOWERS_BLDO2);
|
||||
|
||||
@@ -22,12 +22,19 @@ int BuzzerFeedbackThread::handleInputEvent(const InputEvent *event)
|
||||
|
||||
// Handle different input events with appropriate buzzer feedback
|
||||
switch (event->inputEvent) {
|
||||
#ifdef INPUTDRIVER_ENCODER_TYPE
|
||||
case INPUT_BROKER_SELECT:
|
||||
case INPUT_BROKER_SELECT_LONG:
|
||||
playClick();
|
||||
break;
|
||||
#else
|
||||
case INPUT_BROKER_USER_PRESS:
|
||||
case INPUT_BROKER_ALT_PRESS:
|
||||
case INPUT_BROKER_SELECT:
|
||||
case INPUT_BROKER_SELECT_LONG:
|
||||
playBeep(); // Confirmation feedback
|
||||
playBeep();
|
||||
break;
|
||||
#endif
|
||||
|
||||
case INPUT_BROKER_UP:
|
||||
case INPUT_BROKER_UP_LONG:
|
||||
@@ -58,4 +65,4 @@ int BuzzerFeedbackThread::handleInputEvent(const InputEvent *event)
|
||||
}
|
||||
|
||||
return 0; // Allow other handlers to process the event
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,14 @@ struct ToneDuration {
|
||||
#define NOTE_G6 1568
|
||||
#define NOTE_E7 2637
|
||||
|
||||
#define NOTE_C4 262
|
||||
#define NOTE_E4 330
|
||||
#define NOTE_G4 392
|
||||
#define NOTE_A4 440
|
||||
#define NOTE_C5 523
|
||||
#define NOTE_E5 659
|
||||
#define NOTE_G5 784
|
||||
|
||||
const int DURATION_1_16 = 62; // 1/16 note
|
||||
const int DURATION_1_8 = 125; // 1/8 note
|
||||
const int DURATION_1_4 = 250; // 1/4 note
|
||||
@@ -65,7 +73,7 @@ void playTones(const ToneDuration *tone_durations, int size)
|
||||
|
||||
void playBeep()
|
||||
{
|
||||
ToneDuration melody[] = {{NOTE_B3, DURATION_1_8}};
|
||||
ToneDuration melody[] = {{NOTE_B3, DURATION_1_16}};
|
||||
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||
}
|
||||
|
||||
@@ -113,7 +121,14 @@ void playShutdownMelody()
|
||||
void playChirp()
|
||||
{
|
||||
// A short, friendly "chirp" sound for key presses
|
||||
ToneDuration melody[] = {{NOTE_AS3, 20}}; // Very short AS3 note
|
||||
ToneDuration melody[] = {{NOTE_AS3, 20}}; // Short AS3 note
|
||||
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||
}
|
||||
|
||||
void playClick()
|
||||
{
|
||||
// A very short "click" sound with minimum delay; ideal for rotary encoder events
|
||||
ToneDuration melody[] = {{NOTE_AS3, 1}}; // Very Short AS3
|
||||
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||
}
|
||||
|
||||
@@ -182,3 +197,17 @@ void playComboTune()
|
||||
};
|
||||
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||
}
|
||||
|
||||
void play4ClickDown()
|
||||
{
|
||||
ToneDuration melody[] = {{NOTE_G5, 55}, {NOTE_E5, 55}, {NOTE_C5, 60}, {NOTE_A4, 55}, {NOTE_G4, 55},
|
||||
{NOTE_E4, 65}, {NOTE_C4, 80}, {NOTE_G3, 120}, {NOTE_E3, 160}, {NOTE_SILENT, 120}};
|
||||
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||
}
|
||||
|
||||
void play4ClickUp()
|
||||
{
|
||||
// Quick high-pitched notes with trills
|
||||
ToneDuration melody[] = {{NOTE_F5, 50}, {NOTE_G6, 45}, {NOTE_E7, 60}};
|
||||
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||
}
|
||||
@@ -7,8 +7,11 @@ void playShutdownMelody();
|
||||
void playGPSEnableBeep();
|
||||
void playGPSDisableBeep();
|
||||
void playComboTune();
|
||||
void play4ClickDown();
|
||||
void play4ClickUp();
|
||||
void playBoop();
|
||||
void playChirp();
|
||||
void playClick();
|
||||
void playLongPressLeadUp();
|
||||
bool playNextLeadUpNote(); // Play the next note in the lead-up sequence
|
||||
void resetLeadUpSequence(); // Reset the lead-up sequence to start from beginning
|
||||
@@ -29,8 +29,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#if __has_include("Melopero_RV3028.h")
|
||||
#include "Melopero_RV3028.h"
|
||||
#endif
|
||||
#if __has_include("pcf8563.h")
|
||||
#include "pcf8563.h"
|
||||
#if __has_include("SensorRtcHelper.hpp")
|
||||
#include "SensorRtcHelper.hpp"
|
||||
#endif
|
||||
|
||||
/* Offer chance for variant-specific defines */
|
||||
@@ -444,6 +444,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// BME680 BSEC2 support detection
|
||||
#if !defined(MESHTASTIC_BME680_BSEC2_SUPPORTED)
|
||||
#if defined(RAK_4631) || defined(TBEAM_V10)
|
||||
|
||||
#define MESHTASTIC_BME680_BSEC2_SUPPORTED 1
|
||||
#define MESHTASTIC_BME680_HEADER <bsec2.h>
|
||||
#else
|
||||
#define MESHTASTIC_BME680_BSEC2_SUPPORTED 0
|
||||
#define MESHTASTIC_BME680_HEADER <Adafruit_BME680.h>
|
||||
#endif // defined(RAK_4631)
|
||||
#endif // !defined(MESHTASTIC_BME680_BSEC2_SUPPORTED)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Global switches to turn off features for a minimized build
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -25,8 +25,8 @@ ScanI2C::FoundDevice ScanI2C::firstScreen() const
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstRTC() const
|
||||
{
|
||||
ScanI2C::DeviceType types[] = {RTC_RV3028, RTC_PCF8563, RTC_RX8130CE};
|
||||
return firstOfOrNONE(3, types);
|
||||
ScanI2C::DeviceType types[] = {RTC_RV3028, RTC_PCF8563, RTC_PCF85063, RTC_RX8130CE};
|
||||
return firstOfOrNONE(4, types);
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
|
||||
|
||||
@@ -14,6 +14,7 @@ class ScanI2C
|
||||
SCREEN_ST7567,
|
||||
RTC_RV3028,
|
||||
RTC_PCF8563,
|
||||
RTC_PCF85063,
|
||||
RTC_RX8130CE,
|
||||
CARDKB,
|
||||
TDECKKB,
|
||||
|
||||
@@ -68,7 +68,7 @@ ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const
|
||||
if (r == 0x08 || r == 0x00) {
|
||||
logFoundDevice("SH1106", (uint8_t)addr.address);
|
||||
o_probe = SCREEN_SH1106; // SH1106
|
||||
} else if (r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) {
|
||||
} else if (r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07 || r == 0x05) {
|
||||
logFoundDevice("SSD1306", (uint8_t)addr.address);
|
||||
o_probe = SCREEN_SSD1306; // SSD1306
|
||||
}
|
||||
@@ -202,6 +202,10 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
SCAN_SIMPLE_CASE(RX8130CE_RTC, RTC_RX8130CE, "RX8130CE", (uint8_t)addr.address)
|
||||
#endif
|
||||
|
||||
#ifdef PCF85063_RTC
|
||||
SCAN_SIMPLE_CASE(PCF85063_RTC, RTC_PCF85063, "PCF85063", (uint8_t)addr.address)
|
||||
#endif
|
||||
|
||||
case CARDKB_ADDR:
|
||||
// Do we have the RAK14006 instead?
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x04), 1);
|
||||
@@ -483,7 +487,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
}
|
||||
break;
|
||||
case TSL25911_ADDR:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x12), 1);
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xA0 | 0x12), 1);
|
||||
if (registerValue == 0x50) {
|
||||
type = TSL2591;
|
||||
logFoundDevice("TSL25911", (uint8_t)addr.address);
|
||||
|
||||
@@ -934,8 +934,11 @@ void GPS::setPowerPMU(bool on)
|
||||
// t-beam v1.2 GNSS power channel
|
||||
on ? PMU->enablePowerOutput(XPOWERS_ALDO3) : PMU->disablePowerOutput(XPOWERS_ALDO3);
|
||||
} else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) {
|
||||
// t-beam-s3-core GNSS power channel
|
||||
// t-beam-s3-core GNSS power channel
|
||||
on ? PMU->enablePowerOutput(XPOWERS_ALDO4) : PMU->disablePowerOutput(XPOWERS_ALDO4);
|
||||
} else if (HW_VENDOR == meshtastic_HardwareModel_T_WATCH_S3) {
|
||||
// t-watch-s3-plus GNSS power channel
|
||||
on ? PMU->enablePowerOutput(XPOWERS_BLDO1) : PMU->disablePowerOutput(XPOWERS_BLDO1);
|
||||
}
|
||||
} else if (model == XPOWERS_AXP192) {
|
||||
// t-beam v1.1 GNSS power channel
|
||||
|
||||
@@ -66,26 +66,26 @@ RTCSetResult readFromRTC()
|
||||
currentQuality = RTCQualityDevice;
|
||||
}
|
||||
return RTCSetResultSuccess;
|
||||
} else {
|
||||
LOG_WARN("RTC not found (found address 0x%02X)", rtc_found.address);
|
||||
}
|
||||
#elif defined(PCF8563_RTC)
|
||||
#elif defined(PCF8563_RTC) || defined(PCF85063_RTC)
|
||||
#if defined(PCF8563_RTC)
|
||||
if (rtc_found.address == PCF8563_RTC) {
|
||||
#elif defined(PCF85063_RTC)
|
||||
if (rtc_found.address == PCF85063_RTC) {
|
||||
#endif
|
||||
uint32_t now = millis();
|
||||
PCF8563_Class rtc;
|
||||
SensorRtcHelper rtc;
|
||||
|
||||
#if WIRE_INTERFACES_COUNT == 2
|
||||
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
|
||||
#else
|
||||
rtc.begin();
|
||||
rtc.begin(Wire);
|
||||
#endif
|
||||
|
||||
auto tc = rtc.getDateTime();
|
||||
tm t;
|
||||
t.tm_year = tc.year - 1900;
|
||||
t.tm_mon = tc.month - 1;
|
||||
t.tm_mday = tc.day;
|
||||
t.tm_hour = tc.hour;
|
||||
t.tm_min = tc.minute;
|
||||
t.tm_sec = tc.second;
|
||||
RTC_DateTime datetime = rtc.getDateTime();
|
||||
tm t = datetime.toUnixTime();
|
||||
tv.tv_sec = gm_mktime(&t);
|
||||
tv.tv_usec = 0;
|
||||
uint32_t printableEpoch = tv.tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
|
||||
@@ -100,14 +100,16 @@ RTCSetResult readFromRTC()
|
||||
}
|
||||
#endif
|
||||
|
||||
LOG_DEBUG("Read RTC time from PCF8563 getDateTime as %02d-%02d-%02d %02d:%02d:%02d (%ld)", t.tm_year + 1900, t.tm_mon + 1,
|
||||
t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, printableEpoch);
|
||||
LOG_DEBUG("Read RTC time from %s getDateTime as %02d-%02d-%02d %02d:%02d:%02d (%ld)", rtc.getChipName(), t.tm_year + 1900,
|
||||
t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, printableEpoch);
|
||||
if (currentQuality == RTCQualityNone) {
|
||||
timeStartMsec = now;
|
||||
zeroOffsetSecs = tv.tv_sec;
|
||||
currentQuality = RTCQualityDevice;
|
||||
}
|
||||
return RTCSetResultSuccess;
|
||||
} else {
|
||||
LOG_WARN("RTC not found (found address 0x%02X)", rtc_found.address);
|
||||
}
|
||||
#elif defined(RX8130CE_RTC)
|
||||
if (rtc_found.address == RX8130CE_RTC) {
|
||||
@@ -232,20 +234,28 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd
|
||||
rtc.setTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
LOG_DEBUG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d (%ld)", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
|
||||
t->tm_hour, t->tm_min, t->tm_sec, printableEpoch);
|
||||
} else {
|
||||
LOG_WARN("RTC not found (found address 0x%02X)", rtc_found.address);
|
||||
}
|
||||
#elif defined(PCF8563_RTC)
|
||||
#elif defined(PCF8563_RTC) || defined(PCF85063_RTC)
|
||||
#if defined(PCF8563_RTC)
|
||||
if (rtc_found.address == PCF8563_RTC) {
|
||||
PCF8563_Class rtc;
|
||||
#elif defined(PCF85063_RTC)
|
||||
if (rtc_found.address == PCF85063_RTC) {
|
||||
#endif
|
||||
SensorRtcHelper rtc;
|
||||
|
||||
#if WIRE_INTERFACES_COUNT == 2
|
||||
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
|
||||
#else
|
||||
rtc.begin();
|
||||
rtc.begin(Wire);
|
||||
#endif
|
||||
tm *t = gmtime(&tv->tv_sec);
|
||||
rtc.setDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
LOG_DEBUG("PCF8563_RTC setDateTime %02d-%02d-%02d %02d:%02d:%02d (%ld)", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
|
||||
t->tm_hour, t->tm_min, t->tm_sec, printableEpoch);
|
||||
rtc.setDateTime(*t);
|
||||
LOG_DEBUG("%s setDateTime %02d-%02d-%02d %02d:%02d:%02d (%ld)", rtc.getChipName(), t->tm_year + 1900, t->tm_mon + 1,
|
||||
t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, printableEpoch);
|
||||
} else {
|
||||
LOG_WARN("RTC not found (found address 0x%02X)", rtc_found.address);
|
||||
}
|
||||
#elif defined(RX8130CE_RTC)
|
||||
if (rtc_found.address == RX8130CE_RTC) {
|
||||
|
||||
@@ -148,7 +148,7 @@ bool EInkDisplay::connect()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(TTGO_T_ECHO) || defined(ELECROW_ThinkNode_M1) || defined(T_ECHO_LITE)
|
||||
#if defined(TTGO_T_ECHO) || defined(ELECROW_ThinkNode_M1) || defined(T_ECHO_LITE) || defined(TTGO_T_ECHO_PLUS)
|
||||
{
|
||||
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, SPI1);
|
||||
|
||||
|
||||
@@ -312,6 +312,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
|
||||
|
||||
// Only validate the combined value once
|
||||
if (rawRGB > 0 && rawRGB <= 255255255) {
|
||||
LOG_INFO("Setting screen RGB color to user chosen: 0x%06X", rawRGB);
|
||||
// Extract each component as a normal int first
|
||||
int r = (rawRGB >> 16) & 0xFF;
|
||||
int g = (rawRGB >> 8) & 0xFF;
|
||||
@@ -319,6 +320,16 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
|
||||
if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) {
|
||||
TFT_MESH = COLOR565(static_cast<uint8_t>(r), static_cast<uint8_t>(g), static_cast<uint8_t>(b));
|
||||
}
|
||||
#ifdef TFT_MESH_OVERRIDE
|
||||
} else if (rawRGB == 0) {
|
||||
LOG_INFO("Setting screen RGB color to TFT_MESH_OVERRIDE: 0x%04X", TFT_MESH_OVERRIDE);
|
||||
// Default to TFT_MESH_OVERRIDE if available
|
||||
TFT_MESH = TFT_MESH_OVERRIDE;
|
||||
#endif
|
||||
} else {
|
||||
// Default best readable yellow color
|
||||
LOG_INFO("Setting screen RGB color to default: (255,255,128)");
|
||||
TFT_MESH = COLOR565(255, 255, 128);
|
||||
}
|
||||
|
||||
#if defined(USE_SH1106) || defined(USE_SH1107) || defined(USE_SH1107_128_64)
|
||||
@@ -654,7 +665,7 @@ void Screen::setup()
|
||||
|
||||
// Turn on display and trigger first draw
|
||||
handleSetOn(true);
|
||||
determineResolution(dispdev->height(), dispdev->width());
|
||||
graphics::currentResolution = graphics::determineScreenResolution(dispdev->height(), dispdev->width());
|
||||
ui->update();
|
||||
#ifndef USE_EINK
|
||||
ui->update(); // Some SSD1306 clones drop the first draw, so run twice
|
||||
@@ -1046,11 +1057,16 @@ void Screen::setFrames(FrameFocus focus)
|
||||
indicatorIcons.push_back(icon_mail);
|
||||
|
||||
#ifndef USE_EINK
|
||||
if (!hiddenFrames.nodelist) {
|
||||
fsi.positions.nodelist = numframes;
|
||||
normalFrames[numframes++] = graphics::NodeListRenderer::drawDynamicNodeListScreen;
|
||||
if (!hiddenFrames.nodelist_nodes) {
|
||||
fsi.positions.nodelist_nodes = numframes;
|
||||
normalFrames[numframes++] = graphics::NodeListRenderer::drawDynamicListScreen_Nodes;
|
||||
indicatorIcons.push_back(icon_nodes);
|
||||
}
|
||||
if (!hiddenFrames.nodelist_location) {
|
||||
fsi.positions.nodelist_location = numframes;
|
||||
normalFrames[numframes++] = graphics::NodeListRenderer::drawDynamicListScreen_Location;
|
||||
indicatorIcons.push_back(icon_list);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Show detailed node views only on E-Ink builds
|
||||
@@ -1072,11 +1088,13 @@ void Screen::setFrames(FrameFocus focus)
|
||||
}
|
||||
#endif
|
||||
#if HAS_GPS
|
||||
#ifdef USE_EINK
|
||||
if (!hiddenFrames.nodelist_bearings) {
|
||||
fsi.positions.nodelist_bearings = numframes;
|
||||
normalFrames[numframes++] = graphics::NodeListRenderer::drawNodeListWithCompasses;
|
||||
indicatorIcons.push_back(icon_list);
|
||||
}
|
||||
#endif
|
||||
if (!hiddenFrames.gps) {
|
||||
fsi.positions.gps = numframes;
|
||||
normalFrames[numframes++] = graphics::UIRenderer::drawCompassAndLocationScreen;
|
||||
@@ -1238,8 +1256,11 @@ void Screen::setFrameImmediateDraw(FrameCallback *drawFrames)
|
||||
void Screen::toggleFrameVisibility(const std::string &frameName)
|
||||
{
|
||||
#ifndef USE_EINK
|
||||
if (frameName == "nodelist") {
|
||||
hiddenFrames.nodelist = !hiddenFrames.nodelist;
|
||||
if (frameName == "nodelist_nodes") {
|
||||
hiddenFrames.nodelist_nodes = !hiddenFrames.nodelist_nodes;
|
||||
}
|
||||
if (frameName == "nodelist_location") {
|
||||
hiddenFrames.nodelist_location = !hiddenFrames.nodelist_location;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_EINK
|
||||
@@ -1254,9 +1275,11 @@ void Screen::toggleFrameVisibility(const std::string &frameName)
|
||||
}
|
||||
#endif
|
||||
#if HAS_GPS
|
||||
#ifdef USE_EINK
|
||||
if (frameName == "nodelist_bearings") {
|
||||
hiddenFrames.nodelist_bearings = !hiddenFrames.nodelist_bearings;
|
||||
}
|
||||
#endif
|
||||
if (frameName == "gps") {
|
||||
hiddenFrames.gps = !hiddenFrames.gps;
|
||||
}
|
||||
@@ -1278,8 +1301,10 @@ void Screen::toggleFrameVisibility(const std::string &frameName)
|
||||
bool Screen::isFrameHidden(const std::string &frameName) const
|
||||
{
|
||||
#ifndef USE_EINK
|
||||
if (frameName == "nodelist")
|
||||
return hiddenFrames.nodelist;
|
||||
if (frameName == "nodelist_nodes")
|
||||
return hiddenFrames.nodelist_nodes;
|
||||
if (frameName == "nodelist_location")
|
||||
return hiddenFrames.nodelist_location;
|
||||
#endif
|
||||
#ifdef USE_EINK
|
||||
if (frameName == "nodelist_lastheard")
|
||||
@@ -1290,8 +1315,10 @@ bool Screen::isFrameHidden(const std::string &frameName) const
|
||||
return hiddenFrames.nodelist_distance;
|
||||
#endif
|
||||
#if HAS_GPS
|
||||
#ifdef USE_EINK
|
||||
if (frameName == "nodelist_bearings")
|
||||
return hiddenFrames.nodelist_bearings;
|
||||
#endif
|
||||
if (frameName == "gps")
|
||||
return hiddenFrames.gps;
|
||||
#endif
|
||||
@@ -1413,10 +1440,15 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)
|
||||
}
|
||||
nodeDB->updateGUI = false;
|
||||
break;
|
||||
case STATUS_TYPE_POWER:
|
||||
forceDisplay(true);
|
||||
case STATUS_TYPE_POWER: {
|
||||
bool currentUSB = powerStatus->getHasUSB();
|
||||
if (currentUSB != lastPowerUSBState) {
|
||||
lastPowerUSBState = currentUSB;
|
||||
forceDisplay(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1523,11 +1555,11 @@ int Screen::handleTextMessage(const meshtastic_MeshPacket *packet)
|
||||
screen->showSimpleBanner(banner, 3000);
|
||||
} else if (!channel.settings.has_module_settings || !channel.settings.module_settings.is_muted) {
|
||||
if (longName && longName[0]) {
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
strcpy(banner, "New Message");
|
||||
#else
|
||||
snprintf(banner, sizeof(banner), "New Message from\n%s", longName);
|
||||
#endif
|
||||
if (currentResolution == ScreenResolution::UltraLow) {
|
||||
strcpy(banner, "New Message");
|
||||
} else {
|
||||
snprintf(banner, sizeof(banner), "New Message from\n%s", longName);
|
||||
}
|
||||
} else {
|
||||
strcpy(banner, "New Message");
|
||||
}
|
||||
@@ -1643,6 +1675,25 @@ int Screen::handleInputEvent(const InputEvent *event)
|
||||
}
|
||||
}
|
||||
}
|
||||
// UP/DOWN in node list screens scrolls through node pages
|
||||
if (ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_nodes ||
|
||||
ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_location ||
|
||||
ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_lastheard ||
|
||||
ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_hopsignal ||
|
||||
ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_distance ||
|
||||
ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_bearings) {
|
||||
if (event->inputEvent == INPUT_BROKER_UP) {
|
||||
graphics::NodeListRenderer::scrollUp();
|
||||
setFastFramerate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (event->inputEvent == INPUT_BROKER_DOWN) {
|
||||
graphics::NodeListRenderer::scrollDown();
|
||||
setFastFramerate();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// Use left or right input from a keyboard to move between frames,
|
||||
// so long as a mesh module isn't using these events for some other purpose
|
||||
if (showingNormalScreen) {
|
||||
@@ -1706,17 +1757,18 @@ int Screen::handleInputEvent(const InputEvent *event)
|
||||
if (!messageStore.getMessages().empty()) {
|
||||
menuHandler::messageResponseMenu();
|
||||
} else {
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
menuHandler::textMessageMenu();
|
||||
#else
|
||||
menuHandler::textMessageBaseMenu();
|
||||
#endif
|
||||
if (currentResolution == ScreenResolution::UltraLow) {
|
||||
menuHandler::textMessageMenu();
|
||||
} else {
|
||||
menuHandler::textMessageBaseMenu();
|
||||
}
|
||||
}
|
||||
} else if (framesetInfo.positions.firstFavorite != 255 &&
|
||||
this->ui->getUiState()->currentFrame >= framesetInfo.positions.firstFavorite &&
|
||||
this->ui->getUiState()->currentFrame <= framesetInfo.positions.lastFavorite) {
|
||||
menuHandler::favoriteBaseMenu();
|
||||
} else if (this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist ||
|
||||
} else if (this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_nodes ||
|
||||
this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_location ||
|
||||
this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_lastheard ||
|
||||
this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_hopsignal ||
|
||||
this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_distance ||
|
||||
|
||||
@@ -558,6 +558,42 @@ class Screen : public concurrency::OSThread
|
||||
if (ch == 0xC2 || ch == 0xC3 || ch == 0xC4 || ch == 0xC5)
|
||||
return (uint8_t)0;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(OLED_GR)
|
||||
|
||||
switch (last) {
|
||||
case 0xC3: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)(ch | 0xC0);
|
||||
}
|
||||
// Map UTF-8 Greek chars to Windows-1253 (CP-1253) ASCII codes
|
||||
case 0xCE: {
|
||||
SKIPREST = false;
|
||||
// Uppercase Greek: Α-Ρ (U+0391-U+03A1) -> CP-1253 193-209
|
||||
if (ch >= 145 && ch <= 161)
|
||||
return (uint8_t)(ch + 48);
|
||||
// Uppercase Greek: Σ-Ω (U+03A3-U+03A9) -> CP-1253 211-217
|
||||
else if (ch >= 163 && ch <= 169)
|
||||
return (uint8_t)(ch + 48);
|
||||
// Lowercase Greek: α-ρ (U+03B1-U+03C1) -> CP-1253 225-241
|
||||
else if (ch >= 177 && ch <= 193)
|
||||
return (uint8_t)(ch + 48);
|
||||
break;
|
||||
}
|
||||
case 0xCF: {
|
||||
SKIPREST = false;
|
||||
// Lowercase Greek: ς-ω (U+03C2-U+03C9) -> CP-1253 242-249
|
||||
if (ch >= 130 && ch <= 137)
|
||||
return (uint8_t)(ch + 112);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We want to strip out prefix chars for two-byte Greek char formats
|
||||
if (ch == 0xC2 || ch == 0xC3 || ch == 0xCE || ch == 0xCF)
|
||||
return (uint8_t)0;
|
||||
|
||||
#endif
|
||||
|
||||
// If we already returned an unconvertable-character symbol for this unconvertable-character sequence, return NULs for the
|
||||
@@ -654,7 +690,8 @@ class Screen : public concurrency::OSThread
|
||||
uint8_t gps = 255;
|
||||
uint8_t home = 255;
|
||||
uint8_t textMessage = 255;
|
||||
uint8_t nodelist = 255;
|
||||
uint8_t nodelist_nodes = 255;
|
||||
uint8_t nodelist_location = 255;
|
||||
uint8_t nodelist_lastheard = 255;
|
||||
uint8_t nodelist_hopsignal = 255;
|
||||
uint8_t nodelist_distance = 255;
|
||||
@@ -677,7 +714,8 @@ class Screen : public concurrency::OSThread
|
||||
bool home = false;
|
||||
bool clock = false;
|
||||
#ifndef USE_EINK
|
||||
bool nodelist = false;
|
||||
bool nodelist_nodes = false;
|
||||
bool nodelist_location = false;
|
||||
#endif
|
||||
#ifdef USE_EINK
|
||||
bool nodelist_lastheard = false;
|
||||
@@ -685,7 +723,9 @@ class Screen : public concurrency::OSThread
|
||||
bool nodelist_distance = false;
|
||||
#endif
|
||||
#if HAS_GPS
|
||||
#ifdef USE_EINK
|
||||
bool nodelist_bearings = false;
|
||||
#endif
|
||||
bool gps = false;
|
||||
#endif
|
||||
bool lora = false;
|
||||
@@ -711,6 +751,8 @@ class Screen : public concurrency::OSThread
|
||||
// Whether we are showing the regular screen (as opposed to booth screen or
|
||||
// Bluetooth PIN screen)
|
||||
bool showingNormalScreen = false;
|
||||
/// Track USB power state to only wake screen on actual power state changes
|
||||
bool lastPowerUSBState = false;
|
||||
|
||||
// Implementation to Adjust Brightness
|
||||
uint8_t brightness = BRIGHTNESS_DEFAULT; // H = 254, MH = 192, ML = 130 L = 103
|
||||
|
||||
@@ -16,10 +16,17 @@
|
||||
#include "graphics/fonts/OLEDDisplayFontsCS.h"
|
||||
#endif
|
||||
|
||||
#ifdef OLED_GR
|
||||
#include "graphics/fonts/OLEDDisplayFontsGR.h"
|
||||
#endif
|
||||
|
||||
#if defined(CROWPANEL_ESP32S3_5_EPAPER) && defined(USE_EINK)
|
||||
#include "graphics/fonts/EinkDisplayFonts.h"
|
||||
#endif
|
||||
|
||||
#ifdef OLED_GR
|
||||
#define FONT_SMALL_LOCAL ArialMT_Plain_10_GR // Height: 13
|
||||
#else
|
||||
#ifdef OLED_PL
|
||||
#define FONT_SMALL_LOCAL ArialMT_Plain_10_PL
|
||||
#else
|
||||
@@ -37,6 +44,10 @@
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifdef OLED_GR
|
||||
#define FONT_MEDIUM_LOCAL ArialMT_Plain_16_GR // Height: 19
|
||||
#else
|
||||
#ifdef OLED_PL
|
||||
#define FONT_MEDIUM_LOCAL ArialMT_Plain_16_PL // Height: 19
|
||||
#else
|
||||
@@ -54,6 +65,10 @@
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifdef OLED_GR
|
||||
#define FONT_LARGE_LOCAL ArialMT_Plain_24_GR // Height: 28
|
||||
#else
|
||||
#ifdef OLED_PL
|
||||
#define FONT_LARGE_LOCAL ArialMT_Plain_24_PL // Height: 28
|
||||
#else
|
||||
@@ -71,6 +86,7 @@
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || \
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "graphics/draw/UIRenderer.h"
|
||||
#include "main.h"
|
||||
#include "meshtastic/config.pb.h"
|
||||
#include "modules/ExternalNotificationModule.h"
|
||||
#include "power.h"
|
||||
#include <OLEDDisplay.h>
|
||||
#include <graphics/images.h>
|
||||
@@ -15,21 +16,30 @@
|
||||
namespace graphics
|
||||
{
|
||||
|
||||
void determineResolution(int16_t screenheight, int16_t screenwidth)
|
||||
ScreenResolution determineScreenResolution(int16_t screenheight, int16_t screenwidth)
|
||||
{
|
||||
|
||||
#ifdef FORCE_LOW_RES
|
||||
isHighResolution = false;
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (screenwidth > 128) {
|
||||
isHighResolution = true;
|
||||
return ScreenResolution::Low;
|
||||
#else
|
||||
// Unit C6L and other ultra low res screens
|
||||
if (screenwidth <= 64 || screenheight <= 48) {
|
||||
return ScreenResolution::UltraLow;
|
||||
}
|
||||
|
||||
// Standard OLED screens
|
||||
if (screenwidth > 128 && screenheight <= 64) {
|
||||
isHighResolution = false;
|
||||
return ScreenResolution::Low;
|
||||
}
|
||||
|
||||
// High Resolutions screens like T114, TDeck, TLora Pager, etc
|
||||
if (screenwidth > 128) {
|
||||
return ScreenResolution::High;
|
||||
}
|
||||
|
||||
// Default to low resolution
|
||||
return ScreenResolution::Low;
|
||||
#endif
|
||||
}
|
||||
|
||||
void decomposeTime(uint32_t rtc_sec, int &hour, int &minute, int &second)
|
||||
@@ -47,8 +57,7 @@ void decomposeTime(uint32_t rtc_sec, int &hour, int &minute, int &second)
|
||||
|
||||
// === Shared External State ===
|
||||
bool hasUnreadMessage = false;
|
||||
bool isMuted = false;
|
||||
bool isHighResolution = false;
|
||||
ScreenResolution currentResolution = ScreenResolution::Low;
|
||||
|
||||
// === Internal State ===
|
||||
bool isBoltVisibleShared = true;
|
||||
@@ -104,7 +113,7 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
||||
display->setColor(BLACK);
|
||||
display->fillRect(0, 0, screenW, highlightHeight + 2);
|
||||
display->setColor(WHITE);
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
display->drawLine(0, 20, screenW, 20);
|
||||
} else {
|
||||
display->drawLine(0, 14, screenW, 14);
|
||||
@@ -142,7 +151,7 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
||||
}
|
||||
#endif
|
||||
|
||||
bool useHorizontalBattery = (isHighResolution && screenW >= screenH);
|
||||
bool useHorizontalBattery = (currentResolution == ScreenResolution::High && screenW >= screenH);
|
||||
const int textY = y + (highlightHeight - FONT_HEIGHT_SMALL) / 2;
|
||||
|
||||
int batteryX = 1;
|
||||
@@ -152,7 +161,7 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
||||
if (usbPowered && !isCharging) { // This is a basic check to determine USB Powered is flagged but not charging
|
||||
batteryX += 1;
|
||||
batteryY += 2;
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
display->drawXbm(batteryX, batteryY, 19, 12, imgUSB_HighResolution);
|
||||
batteryX += 20; // Icon + 1 pixel
|
||||
} else {
|
||||
@@ -222,7 +231,7 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
||||
UIRenderer::formatDateTime(datetimeStr, sizeof(datetimeStr), rtc_sec, display, false);
|
||||
char dateLine[40];
|
||||
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
snprintf(dateLine, sizeof(dateLine), "%s", datetimeStr);
|
||||
} else {
|
||||
if (hasUnreadMessage) {
|
||||
@@ -297,8 +306,8 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
||||
}
|
||||
display->drawXbm(iconX, iconY, mail_width, mail_height, mail);
|
||||
}
|
||||
} else if (isMuted) {
|
||||
if (isHighResolution) {
|
||||
} else if (externalNotificationModule->getMute()) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
int iconX = iconRightEdge - mute_symbol_big_width;
|
||||
int iconY = textY + (FONT_HEIGHT_SMALL - mute_symbol_big_height) / 2;
|
||||
|
||||
@@ -316,7 +325,7 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
||||
int iconX = iconRightEdge - mute_symbol_width;
|
||||
int iconY = textY + (FONT_HEIGHT_SMALL - mail_height) / 2;
|
||||
|
||||
if (isInverted) {
|
||||
if (isInverted && !force_no_invert) {
|
||||
display->setColor(WHITE);
|
||||
display->fillRect(iconX - 1, iconY - 1, mute_symbol_width + 2, mute_symbol_height + 2);
|
||||
display->setColor(BLACK);
|
||||
@@ -374,8 +383,8 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
||||
int iconY = textY + (FONT_HEIGHT_SMALL - mail_height) / 2;
|
||||
display->drawXbm(iconX, iconY, mail_width, mail_height, mail);
|
||||
}
|
||||
} else if (isMuted) {
|
||||
if (isHighResolution) {
|
||||
} else if (externalNotificationModule->getMute()) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
int iconX = iconRightEdge - mute_symbol_big_width;
|
||||
int iconY = textY + (FONT_HEIGHT_SMALL - mute_symbol_big_height) / 2;
|
||||
display->drawXbm(iconX, iconY, mute_symbol_big_width, mute_symbol_big_height, mute_symbol_big);
|
||||
@@ -394,7 +403,7 @@ const int *getTextPositions(OLEDDisplay *display)
|
||||
{
|
||||
static int textPositions[7]; // Static array that persists beyond function scope
|
||||
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
textPositions[0] = textZeroLine;
|
||||
textPositions[1] = textFirstLine_medium;
|
||||
textPositions[2] = textSecondLine_medium;
|
||||
@@ -427,12 +436,12 @@ void drawCommonFooter(OLEDDisplay *display, int16_t x, int16_t y)
|
||||
}
|
||||
|
||||
if (drawConnectionState) {
|
||||
const int scale = isHighResolution ? 2 : 1;
|
||||
const int scale = (currentResolution == ScreenResolution::High) ? 2 : 1;
|
||||
display->setColor(BLACK);
|
||||
display->fillRect(0, SCREEN_HEIGHT - (1 * scale) - (connection_icon_height * scale), (connection_icon_width * scale),
|
||||
(connection_icon_height * scale) + (2 * scale));
|
||||
display->setColor(WHITE);
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
const int bytesPerRow = (connection_icon_width + 7) / 8;
|
||||
int iconX = 0;
|
||||
int iconY = SCREEN_HEIGHT - (connection_icon_height * 2);
|
||||
@@ -461,18 +470,49 @@ bool isAllowedPunctuation(char c)
|
||||
return allowed.find(c) != std::string::npos;
|
||||
}
|
||||
|
||||
static void replaceAll(std::string &s, const std::string &from, const std::string &to)
|
||||
{
|
||||
if (from.empty())
|
||||
return;
|
||||
size_t pos = 0;
|
||||
while ((pos = s.find(from, pos)) != std::string::npos) {
|
||||
s.replace(pos, from.size(), to);
|
||||
pos += to.size();
|
||||
}
|
||||
}
|
||||
|
||||
std::string sanitizeString(const std::string &input)
|
||||
{
|
||||
std::string output;
|
||||
bool inReplacement = false;
|
||||
|
||||
for (char c : input) {
|
||||
if (std::isalnum(static_cast<unsigned char>(c)) || isAllowedPunctuation(c)) {
|
||||
// Make a mutable copy so we can normalize UTF-8 “smart punctuation” into ASCII first.
|
||||
std::string s = input;
|
||||
|
||||
// Curly single quotes: ‘ ’
|
||||
replaceAll(s, "\xE2\x80\x98", "'"); // U+2018
|
||||
replaceAll(s, "\xE2\x80\x99", "'"); // U+2019
|
||||
|
||||
// Curly double quotes: “ ”
|
||||
replaceAll(s, "\xE2\x80\x9C", "\""); // U+201C
|
||||
replaceAll(s, "\xE2\x80\x9D", "\""); // U+201D
|
||||
|
||||
// En dash / Em dash: – —
|
||||
replaceAll(s, "\xE2\x80\x93", "-"); // U+2013
|
||||
replaceAll(s, "\xE2\x80\x94", "-"); // U+2014
|
||||
|
||||
// Non-breaking space
|
||||
replaceAll(s, "\xC2\xA0", " "); // U+00A0
|
||||
|
||||
// Now do your original sanitize pass over the normalized string.
|
||||
for (unsigned char uc : s) {
|
||||
char c = static_cast<char>(uc);
|
||||
if (std::isalnum(uc) || isAllowedPunctuation(c)) {
|
||||
output += c;
|
||||
inReplacement = false;
|
||||
} else {
|
||||
if (!inReplacement) {
|
||||
output += 0xbf; // ISO-8859-1 for inverted question mark
|
||||
output += static_cast<char>(0xBF); // ISO-8859-1 for inverted question mark
|
||||
inReplacement = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,9 +41,9 @@ namespace graphics
|
||||
|
||||
// Shared state (declare inside namespace)
|
||||
extern bool hasUnreadMessage;
|
||||
extern bool isMuted;
|
||||
extern bool isHighResolution;
|
||||
void determineResolution(int16_t screenheight, int16_t screenwidth);
|
||||
enum class ScreenResolution : uint8_t { UltraLow = 0, Low = 1, High = 2 };
|
||||
extern ScreenResolution currentResolution;
|
||||
ScreenResolution determineScreenResolution(int16_t screenheight, int16_t screenwidth);
|
||||
|
||||
void decomposeTime(uint32_t rtc_sec, int &hour, int &minute, int &second);
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
||||
float target_width = display->getWidth() * screenwidth_target_ratio;
|
||||
float target_height =
|
||||
display->getHeight() -
|
||||
(isHighResolution
|
||||
((currentResolution == ScreenResolution::High)
|
||||
? 46
|
||||
: 33); // Be careful adjusting this number, we have to account for header and the text under the time
|
||||
|
||||
@@ -262,9 +262,16 @@ void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
||||
|
||||
// draw seconds string + AM/PM
|
||||
display->setFont(FONT_SMALL);
|
||||
int xOffset = (isHighResolution) ? 0 : -1;
|
||||
int xOffset = -1;
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
xOffset = 0;
|
||||
}
|
||||
if (hour >= 10) {
|
||||
xOffset += (isHighResolution) ? 32 : 18;
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
xOffset += 32;
|
||||
} else {
|
||||
xOffset += 18;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.display.use_12h_clock) {
|
||||
@@ -272,7 +279,7 @@ void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
||||
}
|
||||
|
||||
#ifndef USE_EINK
|
||||
xOffset = (isHighResolution) ? 18 : 10;
|
||||
xOffset = (currentResolution == ScreenResolution::High) ? 18 : 10;
|
||||
if (scale >= 2.0f) {
|
||||
xOffset -= (int)(4.5f * scale);
|
||||
}
|
||||
@@ -312,8 +319,8 @@ void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
// tick mark outer y coordinate; (first nested circle)
|
||||
int16_t tickMarkOuterNoonY = secondHandNoonY;
|
||||
|
||||
double secondsTickMarkInnerNoonY = noonY + (isHighResolution ? 8 : 4);
|
||||
double hoursTickMarkInnerNoonY = noonY + (isHighResolution ? 16 : 6);
|
||||
double secondsTickMarkInnerNoonY = noonY + ((currentResolution == ScreenResolution::High) ? 8 : 4);
|
||||
double hoursTickMarkInnerNoonY = noonY + ((currentResolution == ScreenResolution::High) ? 16 : 6);
|
||||
|
||||
// minute hand y coordinate
|
||||
int16_t minuteHandNoonY = secondsTickMarkInnerNoonY + 4;
|
||||
@@ -323,7 +330,7 @@ void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
|
||||
// hour hand radius and y coordinate
|
||||
int16_t hourHandRadius = radius * 0.35;
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
hourHandRadius = radius * 0.55;
|
||||
}
|
||||
int16_t hourHandNoonY = centerY - hourHandRadius;
|
||||
@@ -339,7 +346,7 @@ void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
if (config.display.use_12h_clock) {
|
||||
bool isPM = hour >= 12;
|
||||
display->setFont(FONT_SMALL);
|
||||
int yOffset = isHighResolution ? 1 : 0;
|
||||
int yOffset = (currentResolution == ScreenResolution::High) ? 1 : 0;
|
||||
#ifdef USE_EINK
|
||||
yOffset += 3;
|
||||
#endif
|
||||
@@ -430,12 +437,13 @@ void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
display->drawStringf(hourStringX, hourStringY, buffer, "%d", hourInt);
|
||||
#else
|
||||
#ifdef USE_EINK
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
// draw hour number
|
||||
display->drawStringf(hourStringX, hourStringY, buffer, "%d", hourInt);
|
||||
}
|
||||
#else
|
||||
if (isHighResolution && (hourInt == 3 || hourInt == 6 || hourInt == 9 || hourInt == 12)) {
|
||||
if (currentResolution == ScreenResolution::High &&
|
||||
(hourInt == 3 || hourInt == 6 || hourInt == 9 || hourInt == 12)) {
|
||||
// draw hour number
|
||||
display->drawStringf(hourStringX, hourStringY, buffer, "%d", hourInt);
|
||||
}
|
||||
@@ -447,7 +455,7 @@ void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
double startX = sineAngleInRadians * (secondsTickMarkInnerNoonY - centerY) + noonX;
|
||||
double startY = cosineAngleInRadians * (secondsTickMarkInnerNoonY - centerY) + centerY;
|
||||
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
// draw minute tick mark
|
||||
display->drawLine(startX, startY, endX, endY);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY,
|
||||
// This could draw a "N" indicator or north arrow
|
||||
// For now, we'll draw a simple north indicator
|
||||
// const float radius = 17.0f;
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
radius += 4;
|
||||
}
|
||||
Point north(0, -radius);
|
||||
@@ -59,7 +59,7 @@ void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY,
|
||||
display->setFont(FONT_SMALL);
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setColor(BLACK);
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
display->fillRect(north.x - 8, north.y - 1, display->getStringWidth("N") + 3, FONT_HEIGHT_SMALL - 6);
|
||||
} else {
|
||||
display->fillRect(north.x - 4, north.y - 1, display->getStringWidth("N") + 2, FONT_HEIGHT_SMALL - 6);
|
||||
|
||||
@@ -282,13 +282,13 @@ void drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
||||
std::string uptime = UIRenderer::drawTimeDelta(days, hours, minutes, seconds);
|
||||
|
||||
// Line 1 (Still)
|
||||
#if !defined(M5STACK_UNITC6L)
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(uptime.c_str()), y, uptime.c_str());
|
||||
if (config.display.heading_bold)
|
||||
display->drawString(x - 1 + SCREEN_WIDTH - display->getStringWidth(uptime.c_str()), y, uptime.c_str());
|
||||
if (currentResolution != graphics::ScreenResolution::UltraLow) {
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(uptime.c_str()), y, uptime.c_str());
|
||||
if (config.display.heading_bold)
|
||||
display->drawString(x - 1 + SCREEN_WIDTH - display->getStringWidth(uptime.c_str()), y, uptime.c_str());
|
||||
|
||||
display->setColor(WHITE);
|
||||
#endif
|
||||
display->setColor(WHITE);
|
||||
}
|
||||
// Setup string to assemble analogClock string
|
||||
std::string analogClock = "";
|
||||
|
||||
@@ -378,7 +378,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
||||
int line = 1;
|
||||
|
||||
// === Set Title
|
||||
const char *titleStr = (isHighResolution) ? "LoRa Info" : "LoRa";
|
||||
const char *titleStr = (currentResolution == ScreenResolution::High) ? "LoRa Info" : "LoRa";
|
||||
|
||||
// === Header ===
|
||||
graphics::drawCommonHeader(display, x, y, titleStr);
|
||||
@@ -390,11 +390,11 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
||||
char shortnameble[35];
|
||||
getMacAddr(dmac);
|
||||
snprintf(screen->ourId, sizeof(screen->ourId), "%02x%02x", dmac[4], dmac[5]);
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
snprintf(shortnameble, sizeof(shortnameble), "%s", screen->ourId);
|
||||
#else
|
||||
snprintf(shortnameble, sizeof(shortnameble), "BLE: %s", screen->ourId);
|
||||
#endif
|
||||
if (currentResolution == ScreenResolution::UltraLow) {
|
||||
snprintf(shortnameble, sizeof(shortnameble), "%s", screen->ourId);
|
||||
} else {
|
||||
snprintf(shortnameble, sizeof(shortnameble), "BLE: %s", screen->ourId);
|
||||
}
|
||||
int textWidth = display->getStringWidth(shortnameble);
|
||||
int nameX = (SCREEN_WIDTH - textWidth);
|
||||
display->drawString(nameX, getTextPositions(display)[line++], shortnameble);
|
||||
@@ -413,11 +413,11 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
||||
char regionradiopreset[25];
|
||||
const char *region = myRegion ? myRegion->name : NULL;
|
||||
if (region != nullptr) {
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
snprintf(regionradiopreset, sizeof(regionradiopreset), "%s", region);
|
||||
#else
|
||||
snprintf(regionradiopreset, sizeof(regionradiopreset), "%s/%s", region, mode);
|
||||
#endif
|
||||
if (currentResolution == ScreenResolution::UltraLow) {
|
||||
snprintf(regionradiopreset, sizeof(regionradiopreset), "%s", region);
|
||||
} else {
|
||||
snprintf(regionradiopreset, sizeof(regionradiopreset), "%s/%s", region, mode);
|
||||
}
|
||||
}
|
||||
textWidth = display->getStringWidth(regionradiopreset);
|
||||
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
||||
@@ -429,17 +429,17 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
||||
float freq = RadioLibInterface::instance->getFreq();
|
||||
snprintf(freqStr, sizeof(freqStr), "%.3f", freq);
|
||||
if (config.lora.channel_num == 0) {
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
snprintf(frequencyslot, sizeof(frequencyslot), "%sMHz", freqStr);
|
||||
#else
|
||||
snprintf(frequencyslot, sizeof(frequencyslot), "Freq: %sMHz", freqStr);
|
||||
#endif
|
||||
if (currentResolution == ScreenResolution::UltraLow) {
|
||||
snprintf(frequencyslot, sizeof(frequencyslot), "%sMHz", freqStr);
|
||||
} else {
|
||||
snprintf(frequencyslot, sizeof(frequencyslot), "Freq: %sMHz", freqStr);
|
||||
}
|
||||
} else {
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
snprintf(frequencyslot, sizeof(frequencyslot), "%sMHz (%d)", freqStr, config.lora.channel_num);
|
||||
#else
|
||||
snprintf(frequencyslot, sizeof(frequencyslot), "Freq/Ch: %sMHz (%d)", freqStr, config.lora.channel_num);
|
||||
#endif
|
||||
if (currentResolution == ScreenResolution::UltraLow) {
|
||||
snprintf(frequencyslot, sizeof(frequencyslot), "%sMHz (%d)", freqStr, config.lora.channel_num);
|
||||
} else {
|
||||
snprintf(frequencyslot, sizeof(frequencyslot), "Freq/Ch: %sMHz (%d)", freqStr, config.lora.channel_num);
|
||||
}
|
||||
}
|
||||
size_t len = strlen(frequencyslot);
|
||||
if (len >= 4 && strcmp(frequencyslot + len - 4, " (0)") == 0) {
|
||||
@@ -455,12 +455,13 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
||||
char chUtilPercentage[10];
|
||||
snprintf(chUtilPercentage, sizeof(chUtilPercentage), "%2.0f%%", airTime->channelUtilizationPercent());
|
||||
|
||||
int chUtil_x = (isHighResolution) ? display->getStringWidth(chUtil) + 10 : display->getStringWidth(chUtil) + 5;
|
||||
int chUtil_x = (currentResolution == ScreenResolution::High) ? display->getStringWidth(chUtil) + 10
|
||||
: display->getStringWidth(chUtil) + 5;
|
||||
int chUtil_y = getTextPositions(display)[line] + 3;
|
||||
|
||||
int chutil_bar_width = (isHighResolution) ? 100 : 50;
|
||||
int chutil_bar_height = (isHighResolution) ? 12 : 7;
|
||||
int extraoffset = (isHighResolution) ? 6 : 3;
|
||||
int chutil_bar_width = (currentResolution == ScreenResolution::High) ? 100 : 50;
|
||||
int chutil_bar_height = (currentResolution == ScreenResolution::High) ? 12 : 7;
|
||||
int extraoffset = (currentResolution == ScreenResolution::High) ? 6 : 3;
|
||||
int chutil_percent = airTime->channelUtilizationPercent();
|
||||
|
||||
int centerofscreen = SCREEN_WIDTH / 2;
|
||||
@@ -529,15 +530,18 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
|
||||
int line = 1;
|
||||
const int barHeight = 6;
|
||||
const int labelX = x;
|
||||
int barsOffset = (isHighResolution) ? 24 : 0;
|
||||
int barsOffset = (currentResolution == ScreenResolution::High) ? 24 : 0;
|
||||
#ifdef USE_EINK
|
||||
#ifndef T_DECK_PRO
|
||||
barsOffset -= 12;
|
||||
#endif
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
const int barX = x + 45 + barsOffset;
|
||||
#else
|
||||
const int barX = x + 40 + barsOffset;
|
||||
#endif
|
||||
int barX = x + barsOffset;
|
||||
if (currentResolution == ScreenResolution::UltraLow) {
|
||||
barX += 45;
|
||||
} else {
|
||||
barX += 40;
|
||||
}
|
||||
auto drawUsageRow = [&](const char *label, uint32_t used, uint32_t total, bool isHeap = false) {
|
||||
if (total == 0)
|
||||
return;
|
||||
@@ -545,7 +549,7 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
|
||||
int percent = (used * 100) / total;
|
||||
|
||||
char combinedStr[24];
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
snprintf(combinedStr, sizeof(combinedStr), "%s%3d%% %u/%uKB", (percent > 80) ? "! " : "", percent, used / 1024,
|
||||
total / 1024);
|
||||
} else {
|
||||
@@ -573,7 +577,7 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
|
||||
#endif
|
||||
// Value string
|
||||
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||
display->drawString(SCREEN_WIDTH - 2, getTextPositions(display)[line], combinedStr);
|
||||
display->drawString(SCREEN_WIDTH, getTextPositions(display)[line], combinedStr);
|
||||
};
|
||||
|
||||
// === Memory values ===
|
||||
@@ -625,25 +629,33 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
|
||||
line += 1;
|
||||
|
||||
char appversionstr[35];
|
||||
snprintf(appversionstr, sizeof(appversionstr), "Ver: %s", optstr(APP_VERSION));
|
||||
char appversionstr_formatted[40];
|
||||
char *lastDot = strrchr(appversionstr, '.');
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
if (lastDot != nullptr) {
|
||||
*lastDot = '\0'; // truncate string
|
||||
|
||||
const char *ver = optstr(APP_VERSION);
|
||||
char verbuf[32];
|
||||
strncpy(verbuf, ver, sizeof(verbuf) - 1);
|
||||
verbuf[sizeof(verbuf) - 1] = '\0';
|
||||
|
||||
char *lastDot = strrchr(verbuf, '.');
|
||||
|
||||
if (currentResolution == ScreenResolution::UltraLow) {
|
||||
if (lastDot != nullptr) {
|
||||
*lastDot = '\0';
|
||||
}
|
||||
snprintf(appversionstr, sizeof(appversionstr), "Ver: %s", verbuf);
|
||||
} else {
|
||||
if (lastDot) {
|
||||
size_t prefixLen = (size_t)(lastDot - verbuf);
|
||||
snprintf(appversionstr_formatted, sizeof(appversionstr_formatted), "Ver: %.*s", (int)prefixLen, verbuf);
|
||||
strncat(appversionstr_formatted, " (", sizeof(appversionstr_formatted) - strlen(appversionstr_formatted) - 1);
|
||||
strncat(appversionstr_formatted, lastDot + 1, sizeof(appversionstr_formatted) - strlen(appversionstr_formatted) - 1);
|
||||
strncat(appversionstr_formatted, ")", sizeof(appversionstr_formatted) - strlen(appversionstr_formatted) - 1);
|
||||
strncpy(appversionstr, appversionstr_formatted, sizeof(appversionstr) - 1);
|
||||
appversionstr[sizeof(appversionstr) - 1] = '\0';
|
||||
} else {
|
||||
snprintf(appversionstr, sizeof(appversionstr), "Ver: %s", verbuf);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (lastDot) {
|
||||
size_t prefixLen = lastDot - appversionstr;
|
||||
strncpy(appversionstr_formatted, appversionstr, prefixLen);
|
||||
appversionstr_formatted[prefixLen] = '\0';
|
||||
strncat(appversionstr_formatted, " (", sizeof(appversionstr_formatted) - strlen(appversionstr_formatted) - 1);
|
||||
strncat(appversionstr_formatted, lastDot + 1, sizeof(appversionstr_formatted) - strlen(appversionstr_formatted) - 1);
|
||||
strncat(appversionstr_formatted, ")", sizeof(appversionstr_formatted) - strlen(appversionstr_formatted) - 1);
|
||||
strncpy(appversionstr, appversionstr_formatted, sizeof(appversionstr) - 1);
|
||||
appversionstr[sizeof(appversionstr) - 1] = '\0';
|
||||
}
|
||||
#endif
|
||||
int textWidth = display->getStringWidth(appversionstr);
|
||||
int nameX = (SCREEN_WIDTH - textWidth) / 2;
|
||||
|
||||
@@ -662,7 +674,7 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
|
||||
const char *clientWord = nullptr;
|
||||
|
||||
// Determine if narrow or wide screen
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
clientWord = "Client";
|
||||
} else {
|
||||
clientWord = "App";
|
||||
@@ -703,7 +715,7 @@ void drawChirpy(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int1
|
||||
int iconX = SCREEN_WIDTH - chirpy_width - (chirpy_width / 3);
|
||||
int iconY = (SCREEN_HEIGHT - chirpy_height) / 2;
|
||||
int textX_offset = 10;
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
textX_offset = textX_offset * 4;
|
||||
const int scale = 2;
|
||||
const int bytesPerRow = (chirpy_width + 7) / 8;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,8 +19,12 @@ class menuHandler
|
||||
clock_face_picker,
|
||||
clock_menu,
|
||||
position_base_menu,
|
||||
node_base_menu,
|
||||
gps_toggle_menu,
|
||||
gps_format_menu,
|
||||
gps_smart_position_menu,
|
||||
gps_update_interval_menu,
|
||||
gps_position_broadcast_menu,
|
||||
compass_point_north_menu,
|
||||
reset_node_db_menu,
|
||||
buzzermodemenupicker,
|
||||
@@ -35,7 +39,6 @@ class menuHandler
|
||||
number_test,
|
||||
wifi_toggle_menu,
|
||||
bluetooth_toggle_menu,
|
||||
notifications_menu,
|
||||
screen_options_menu,
|
||||
power_menu,
|
||||
system_base_menu,
|
||||
@@ -76,6 +79,9 @@ class menuHandler
|
||||
static void compassNorthMenu();
|
||||
static void GPSToggleMenu();
|
||||
static void GPSFormatMenu();
|
||||
static void GPSSmartPositionMenu();
|
||||
static void GPSUpdateIntervalMenu();
|
||||
static void GPSPositionBroadcastMenu();
|
||||
static void BuzzerModeMenu();
|
||||
static void switchToMUIMenu();
|
||||
static void TFTColorPickerMenu(OLEDDisplay *display);
|
||||
@@ -91,7 +97,6 @@ class menuHandler
|
||||
static void numberTest();
|
||||
static void wifiBaseMenu();
|
||||
static void wifiToggleMenu();
|
||||
static void notificationsMenu();
|
||||
static void screenOptionsMenu();
|
||||
static void powerMenu();
|
||||
static void nodeNameLengthMenu();
|
||||
@@ -106,5 +111,45 @@ class menuHandler
|
||||
static void BluetoothToggleMenu();
|
||||
};
|
||||
|
||||
/* Generic Menu Options designations */
|
||||
enum class OptionsAction { Back, Select };
|
||||
|
||||
template <typename T> struct MenuOption {
|
||||
const char *label;
|
||||
OptionsAction action;
|
||||
bool hasValue;
|
||||
T value;
|
||||
|
||||
MenuOption(const char *labelIn, OptionsAction actionIn, T valueIn)
|
||||
: label(labelIn), action(actionIn), hasValue(true), value(valueIn)
|
||||
{
|
||||
}
|
||||
|
||||
MenuOption(const char *labelIn, OptionsAction actionIn) : label(labelIn), action(actionIn), hasValue(false), value() {}
|
||||
};
|
||||
|
||||
struct ScreenColor {
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
bool useVariant;
|
||||
|
||||
ScreenColor(uint8_t rIn = 0, uint8_t gIn = 0, uint8_t bIn = 0, bool variantIn = false)
|
||||
: r(rIn), g(gIn), b(bIn), useVariant(variantIn)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
using RadioPresetOption = MenuOption<meshtastic_Config_LoRaConfig_ModemPreset>;
|
||||
using LoraRegionOption = MenuOption<meshtastic_Config_LoRaConfig_RegionCode>;
|
||||
using TimezoneOption = MenuOption<const char *>;
|
||||
using CompassOption = MenuOption<meshtastic_CompassMode>;
|
||||
using ScreenColorOption = MenuOption<ScreenColor>;
|
||||
using GPSToggleOption = MenuOption<meshtastic_Config_PositionConfig_GpsMode>;
|
||||
using GPSFormatOption = MenuOption<meshtastic_DeviceUIConfig_GpsCoordinateFormat>;
|
||||
using NodeNameOption = MenuOption<bool>;
|
||||
using PositionMenuOption = MenuOption<int>;
|
||||
using ClockFaceOption = MenuOption<bool>;
|
||||
|
||||
} // namespace graphics
|
||||
#endif
|
||||
|
||||
@@ -479,7 +479,13 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
const int navHeight = FONT_HEIGHT_SMALL;
|
||||
const int scrollBottom = SCREEN_HEIGHT - navHeight;
|
||||
const int usableHeight = scrollBottom;
|
||||
const int textWidth = SCREEN_WIDTH;
|
||||
constexpr int LEFT_MARGIN = 2;
|
||||
constexpr int RIGHT_MARGIN = 2;
|
||||
constexpr int SCROLLBAR_WIDTH = 3;
|
||||
|
||||
const int leftTextWidth = SCREEN_WIDTH - LEFT_MARGIN - RIGHT_MARGIN;
|
||||
|
||||
const int rightTextWidth = SCREEN_WIDTH - LEFT_MARGIN - RIGHT_MARGIN - SCROLLBAR_WIDTH;
|
||||
|
||||
// Title string depending on mode
|
||||
static char titleBuf[32];
|
||||
@@ -647,7 +653,8 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
|
||||
const char *msgText = MessageStore::getText(m);
|
||||
|
||||
std::vector<std::string> wrapped = generateLines(display, "", msgText, textWidth);
|
||||
int wrapWidth = mine ? rightTextWidth : leftTextWidth;
|
||||
std::vector<std::string> wrapped = generateLines(display, "", msgText, wrapWidth);
|
||||
for (auto &ln : wrapped) {
|
||||
allLines.push_back(ln);
|
||||
isMine.push_back(mine);
|
||||
@@ -718,14 +725,12 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
if (isHeader[i]) {
|
||||
|
||||
int w = display->getStringWidth(cachedLines[i].c_str());
|
||||
|
||||
// Render header
|
||||
constexpr int SCROLLBAR_WIDTH = 3;
|
||||
|
||||
int headerX;
|
||||
if (isMine[i]) {
|
||||
// push header left to avoid overlap with scrollbar
|
||||
headerX = (SCREEN_WIDTH - SCROLLBAR_WIDTH) - w - 2;
|
||||
headerX = SCREEN_WIDTH - w - SCROLLBAR_WIDTH - RIGHT_MARGIN;
|
||||
if (headerX < LEFT_MARGIN)
|
||||
headerX = LEFT_MARGIN;
|
||||
} else {
|
||||
headerX = x;
|
||||
}
|
||||
@@ -758,8 +763,10 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
if (isMine[i]) {
|
||||
// Calculate actual rendered width including emotes
|
||||
int renderedWidth = getRenderedLineWidth(display, cachedLines[i], emotes, numEmotes);
|
||||
constexpr int SCROLLBAR_WIDTH = 3;
|
||||
int rightX = SCREEN_WIDTH - renderedWidth - SCROLLBAR_WIDTH - 2;
|
||||
int rightX = SCREEN_WIDTH - renderedWidth - SCROLLBAR_WIDTH - RIGHT_MARGIN;
|
||||
if (rightX < LEFT_MARGIN)
|
||||
rightX = LEFT_MARGIN;
|
||||
|
||||
drawStringWithEmotes(display, rightX, lineY, cachedLines[i], emotes, numEmotes);
|
||||
} else {
|
||||
drawStringWithEmotes(display, x, lineY, cachedLines[i], emotes, numEmotes);
|
||||
@@ -920,7 +927,7 @@ void handleNewMessage(OLEDDisplay *display, const StoredMessage &sm, const mesht
|
||||
strncpy(longName, node->user.long_name, sizeof(longName) - 1);
|
||||
longName[sizeof(longName) - 1] = '\0';
|
||||
}
|
||||
int availWidth = display->getWidth() - (isHighResolution ? 40 : 20);
|
||||
int availWidth = display->getWidth() - ((currentResolution == ScreenResolution::High) ? 40 : 20);
|
||||
if (availWidth < 0)
|
||||
availWidth = 0;
|
||||
|
||||
@@ -958,11 +965,11 @@ void handleNewMessage(OLEDDisplay *display, const StoredMessage &sm, const mesht
|
||||
return;
|
||||
|
||||
if (longName && longName[0]) {
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
strcpy(banner, "New Message");
|
||||
#else
|
||||
snprintf(banner, sizeof(banner), "New Message from\n%s", longName);
|
||||
#endif
|
||||
if (currentResolution == ScreenResolution::UltraLow) {
|
||||
strcpy(banner, "New Message");
|
||||
} else {
|
||||
snprintf(banner, sizeof(banner), "New Message from\n%s", longName);
|
||||
}
|
||||
} else
|
||||
strcpy(banner, "New Message");
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ extern graphics::Screen *screen;
|
||||
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
static uint32_t lastSwitchTime = 0;
|
||||
#else
|
||||
#endif
|
||||
namespace graphics
|
||||
{
|
||||
@@ -46,16 +45,43 @@ void drawScaledXBitmap16x16(int x, int y, int width, int height, const uint8_t *
|
||||
}
|
||||
|
||||
// Static variables for dynamic cycling
|
||||
static NodeListMode currentMode = MODE_LAST_HEARD;
|
||||
static ListMode_Node currentMode_Nodes = MODE_LAST_HEARD;
|
||||
static ListMode_Location currentMode_Location = MODE_DISTANCE;
|
||||
static int scrollIndex = 0;
|
||||
// Popup overlay state
|
||||
static uint32_t popupTime = 0;
|
||||
static int popupTotal = 0;
|
||||
static int popupStart = 0;
|
||||
static int popupEnd = 0;
|
||||
static int popupPage = 1;
|
||||
static int popupMaxPage = 1;
|
||||
|
||||
static const uint32_t POPUP_DURATION_MS = 1000; // 1 second visible
|
||||
|
||||
// =============================
|
||||
// Scrolling Logic
|
||||
// =============================
|
||||
void scrollUp()
|
||||
{
|
||||
if (scrollIndex > 0)
|
||||
scrollIndex--;
|
||||
|
||||
popupTime = millis(); // show popup
|
||||
}
|
||||
|
||||
void scrollDown()
|
||||
{
|
||||
scrollIndex++;
|
||||
popupTime = millis();
|
||||
}
|
||||
|
||||
// =============================
|
||||
// Utility Functions
|
||||
// =============================
|
||||
|
||||
const char *getSafeNodeName(OLEDDisplay *display, meshtastic_NodeInfoLite *node)
|
||||
const char *getSafeNodeName(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int columnWidth)
|
||||
{
|
||||
static char nodeName[16]; // single static buffer we return
|
||||
static char nodeName[25]; // single static buffer we return
|
||||
nodeName[0] = '\0';
|
||||
|
||||
auto writeFallbackId = [&] {
|
||||
@@ -81,7 +107,7 @@ const char *getSafeNodeName(OLEDDisplay *display, meshtastic_NodeInfoLite *node)
|
||||
|
||||
// 4) Width-based truncation + ellipsis (long-name mode only)
|
||||
if (config.display.use_long_node_name && display) {
|
||||
int availWidth = (SCREEN_WIDTH / 2) - 65;
|
||||
int availWidth = columnWidth - ((currentResolution == ScreenResolution::High) ? 65 : 38);
|
||||
if (availWidth < 0)
|
||||
availWidth = 0;
|
||||
|
||||
@@ -109,19 +135,29 @@ const char *getSafeNodeName(OLEDDisplay *display, meshtastic_NodeInfoLite *node)
|
||||
return nodeName;
|
||||
}
|
||||
|
||||
const char *getCurrentModeTitle(int screenWidth)
|
||||
const char *getCurrentModeTitle_Nodes(int screenWidth)
|
||||
{
|
||||
switch (currentMode) {
|
||||
switch (currentMode_Nodes) {
|
||||
case MODE_LAST_HEARD:
|
||||
return "Last Heard";
|
||||
case MODE_HOP_SIGNAL:
|
||||
#ifdef USE_EINK
|
||||
return "Hops/Sig";
|
||||
#else
|
||||
return (isHighResolution) ? "Hops/Signal" : "Hops/Sig";
|
||||
return (currentResolution == ScreenResolution::High) ? "Hops/Signal" : "Hops/Sig";
|
||||
#endif
|
||||
default:
|
||||
return "Nodes";
|
||||
}
|
||||
}
|
||||
|
||||
const char *getCurrentModeTitle_Location(int screenWidth)
|
||||
{
|
||||
switch (currentMode_Location) {
|
||||
case MODE_DISTANCE:
|
||||
return "Distance";
|
||||
case MODE_BEARING:
|
||||
return "Bearings";
|
||||
default:
|
||||
return "Nodes";
|
||||
}
|
||||
@@ -140,10 +176,8 @@ int calculateMaxScroll(int totalEntries, int visibleRows)
|
||||
|
||||
void drawColumnSeparator(OLEDDisplay *display, int16_t x, int16_t yStart, int16_t yEnd)
|
||||
{
|
||||
int columnWidth = display->getWidth() / 2;
|
||||
int separatorX = x + columnWidth - 2;
|
||||
for (int y = yStart; y <= yEnd; y += 2) {
|
||||
display->setPixel(separatorX, y);
|
||||
display->setPixel(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +189,8 @@ void drawScrollbar(OLEDDisplay *display, int visibleNodeRows, int totalEntries,
|
||||
int scrollbarX = display->getWidth() - 2;
|
||||
int scrollbarHeight = display->getHeight() - scrollStartY - 10;
|
||||
int thumbHeight = std::max(4, (scrollbarHeight * visibleNodeRows * columns) / totalEntries);
|
||||
int maxScroll = calculateMaxScroll(totalEntries, visibleNodeRows);
|
||||
int perPage = visibleNodeRows * columns;
|
||||
int maxScroll = std::max(0, (totalEntries - 1) / perPage);
|
||||
int thumbY = scrollStartY + (scrollIndex * (scrollbarHeight - thumbHeight)) / std::max(1, maxScroll);
|
||||
|
||||
for (int i = 0; i < thumbHeight; i++) {
|
||||
@@ -170,9 +205,9 @@ void drawScrollbar(OLEDDisplay *display, int visibleNodeRows, int totalEntries,
|
||||
void drawEntryLastHeard(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth)
|
||||
{
|
||||
bool isLeftCol = (x < SCREEN_WIDTH / 2);
|
||||
int timeOffset = (isHighResolution) ? (isLeftCol ? 7 : 10) : (isLeftCol ? 3 : 7);
|
||||
int timeOffset = (currentResolution == ScreenResolution::High) ? (isLeftCol ? 7 : 10) : (isLeftCol ? 3 : 7);
|
||||
|
||||
const char *nodeName = getSafeNodeName(display, node);
|
||||
const char *nodeName = getSafeNodeName(display, node, columnWidth);
|
||||
|
||||
char timeStr[10];
|
||||
uint32_t seconds = sinceLastSeen(node);
|
||||
@@ -191,9 +226,9 @@ void drawEntryLastHeard(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_SMALL);
|
||||
display->drawString(x + ((isHighResolution) ? 6 : 3), y, nodeName);
|
||||
display->drawString(x + ((currentResolution == ScreenResolution::High) ? 6 : 3), y, nodeName);
|
||||
if (node->is_favorite) {
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
drawScaledXBitmap16x16(x, y + 6, smallbulletpoint_width, smallbulletpoint_height, smallbulletpoint, display);
|
||||
} else {
|
||||
display->drawXbm(x, y + 5, smallbulletpoint_width, smallbulletpoint_height, smallbulletpoint);
|
||||
@@ -212,19 +247,19 @@ void drawEntryHopSignal(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int
|
||||
bool isLeftCol = (x < SCREEN_WIDTH / 2);
|
||||
|
||||
int nameMaxWidth = columnWidth - 25;
|
||||
int barsOffset = (isHighResolution) ? (isLeftCol ? 20 : 24) : (isLeftCol ? 15 : 19);
|
||||
int hopOffset = (isHighResolution) ? (isLeftCol ? 21 : 29) : (isLeftCol ? 13 : 17);
|
||||
int barsOffset = (currentResolution == ScreenResolution::High) ? (isLeftCol ? 20 : 24) : (isLeftCol ? 15 : 19);
|
||||
int hopOffset = (currentResolution == ScreenResolution::High) ? (isLeftCol ? 21 : 29) : (isLeftCol ? 13 : 17);
|
||||
|
||||
int barsXOffset = columnWidth - barsOffset;
|
||||
|
||||
const char *nodeName = getSafeNodeName(display, node);
|
||||
const char *nodeName = getSafeNodeName(display, node, columnWidth);
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
display->drawStringMaxWidth(x + ((isHighResolution) ? 6 : 3), y, nameMaxWidth, nodeName);
|
||||
display->drawStringMaxWidth(x + ((currentResolution == ScreenResolution::High) ? 6 : 3), y, nameMaxWidth, nodeName);
|
||||
if (node->is_favorite) {
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
drawScaledXBitmap16x16(x, y + 6, smallbulletpoint_width, smallbulletpoint_height, smallbulletpoint, display);
|
||||
} else {
|
||||
display->drawXbm(x, y + 5, smallbulletpoint_width, smallbulletpoint_height, smallbulletpoint);
|
||||
@@ -259,9 +294,10 @@ void drawEntryHopSignal(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int
|
||||
void drawNodeDistance(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth)
|
||||
{
|
||||
bool isLeftCol = (x < SCREEN_WIDTH / 2);
|
||||
int nameMaxWidth = columnWidth - (isHighResolution ? (isLeftCol ? 25 : 28) : (isLeftCol ? 20 : 22));
|
||||
int nameMaxWidth =
|
||||
columnWidth - ((currentResolution == ScreenResolution::High) ? (isLeftCol ? 25 : 28) : (isLeftCol ? 20 : 22));
|
||||
|
||||
const char *nodeName = getSafeNodeName(display, node);
|
||||
const char *nodeName = getSafeNodeName(display, node, columnWidth);
|
||||
char distStr[10] = "";
|
||||
|
||||
meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
@@ -314,9 +350,9 @@ void drawNodeDistance(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_SMALL);
|
||||
display->drawStringMaxWidth(x + ((isHighResolution) ? 6 : 3), y, nameMaxWidth, nodeName);
|
||||
display->drawStringMaxWidth(x + ((currentResolution == ScreenResolution::High) ? 6 : 3), y, nameMaxWidth, nodeName);
|
||||
if (node->is_favorite) {
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
drawScaledXBitmap16x16(x, y + 6, smallbulletpoint_width, smallbulletpoint_height, smallbulletpoint, display);
|
||||
} else {
|
||||
display->drawXbm(x, y + 5, smallbulletpoint_width, smallbulletpoint_height, smallbulletpoint);
|
||||
@@ -324,26 +360,24 @@ void drawNodeDistance(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16
|
||||
}
|
||||
|
||||
if (strlen(distStr) > 0) {
|
||||
int offset = (isHighResolution) ? (isLeftCol ? 7 : 10) // Offset for Wide Screens (Left Column:Right Column)
|
||||
: (isLeftCol ? 4 : 7); // Offset for Narrow Screens (Left Column:Right Column)
|
||||
int offset = (currentResolution == ScreenResolution::High)
|
||||
? (isLeftCol ? 7 : 10) // Offset for Wide Screens (Left Column:Right Column)
|
||||
: (isLeftCol ? 4 : 7); // Offset for Narrow Screens (Left Column:Right Column)
|
||||
int rightEdge = x + columnWidth - offset;
|
||||
int textWidth = display->getStringWidth(distStr);
|
||||
display->drawString(rightEdge - textWidth, y, distStr);
|
||||
}
|
||||
}
|
||||
|
||||
void drawEntryDynamic(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth)
|
||||
void drawEntryDynamic_Nodes(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth)
|
||||
{
|
||||
switch (currentMode) {
|
||||
switch (currentMode_Nodes) {
|
||||
case MODE_LAST_HEARD:
|
||||
drawEntryLastHeard(display, node, x, y, columnWidth);
|
||||
break;
|
||||
case MODE_HOP_SIGNAL:
|
||||
drawEntryHopSignal(display, node, x, y, columnWidth);
|
||||
break;
|
||||
case MODE_DISTANCE:
|
||||
drawNodeDistance(display, node, x, y, columnWidth);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -354,15 +388,16 @@ void drawEntryCompass(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16
|
||||
bool isLeftCol = (x < SCREEN_WIDTH / 2);
|
||||
|
||||
// Adjust max text width depending on column and screen width
|
||||
int nameMaxWidth = columnWidth - (isHighResolution ? (isLeftCol ? 25 : 28) : (isLeftCol ? 20 : 22));
|
||||
int nameMaxWidth =
|
||||
columnWidth - ((currentResolution == ScreenResolution::High) ? (isLeftCol ? 25 : 28) : (isLeftCol ? 20 : 22));
|
||||
|
||||
const char *nodeName = getSafeNodeName(display, node);
|
||||
const char *nodeName = getSafeNodeName(display, node, columnWidth);
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_SMALL);
|
||||
display->drawStringMaxWidth(x + ((isHighResolution) ? 6 : 3), y, nameMaxWidth, nodeName);
|
||||
display->drawStringMaxWidth(x + ((currentResolution == ScreenResolution::High) ? 6 : 3), y, nameMaxWidth, nodeName);
|
||||
if (node->is_favorite) {
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
drawScaledXBitmap16x16(x, y + 6, smallbulletpoint_width, smallbulletpoint_height, smallbulletpoint, display);
|
||||
} else {
|
||||
display->drawXbm(x, y + 5, smallbulletpoint_width, smallbulletpoint_height, smallbulletpoint);
|
||||
@@ -377,7 +412,7 @@ void drawCompassArrow(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16
|
||||
return;
|
||||
|
||||
bool isLeftCol = (x < SCREEN_WIDTH / 2);
|
||||
int arrowXOffset = (isHighResolution) ? (isLeftCol ? 22 : 24) : (isLeftCol ? 12 : 18);
|
||||
int arrowXOffset = (currentResolution == ScreenResolution::High) ? (isLeftCol ? 22 : 24) : (isLeftCol ? 12 : 18);
|
||||
|
||||
int centerX = x + columnWidth - arrowXOffset;
|
||||
int centerY = y + FONT_HEIGHT_SMALL / 2;
|
||||
@@ -434,11 +469,6 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
||||
locationScreen = true;
|
||||
else if (strcmp(title, "Distance") == 0)
|
||||
locationScreen = true;
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
int columnWidth = display->getWidth();
|
||||
#else
|
||||
int columnWidth = display->getWidth() / 2;
|
||||
#endif
|
||||
display->clear();
|
||||
|
||||
// Draw the battery/time header
|
||||
@@ -447,39 +477,74 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
||||
// Space below header
|
||||
y += COMMON_HEADER_HEIGHT;
|
||||
|
||||
int totalColumns = 1; // Default to 1 column
|
||||
|
||||
if (config.display.use_long_node_name) {
|
||||
if (SCREEN_WIDTH <= 240) {
|
||||
totalColumns = 1;
|
||||
} else if (SCREEN_WIDTH > 240) {
|
||||
totalColumns = 2;
|
||||
}
|
||||
} else {
|
||||
if (SCREEN_WIDTH <= 64) {
|
||||
totalColumns = 1;
|
||||
} else if (SCREEN_WIDTH > 64 && SCREEN_WIDTH <= 240) {
|
||||
totalColumns = 2;
|
||||
} else {
|
||||
totalColumns = 3;
|
||||
}
|
||||
}
|
||||
|
||||
int columnWidth = display->getWidth() / totalColumns;
|
||||
|
||||
int totalEntries = nodeDB->getNumMeshNodes();
|
||||
int totalRowsAvailable = (display->getHeight() - y) / rowYOffset;
|
||||
int numskipped = 0;
|
||||
int visibleNodeRows = totalRowsAvailable;
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
int totalColumns = 1;
|
||||
#else
|
||||
int totalColumns = 2;
|
||||
#endif
|
||||
int startIndex = scrollIndex * visibleNodeRows * totalColumns;
|
||||
if (nodeDB->getMeshNodeByIndex(startIndex)->num == nodeDB->getNodeNum()) {
|
||||
startIndex++; // skip own node
|
||||
}
|
||||
int endIndex = std::min(startIndex + visibleNodeRows * totalColumns, totalEntries);
|
||||
|
||||
// Build filtered + ordered list
|
||||
std::vector<int> drawList;
|
||||
drawList.reserve(totalEntries);
|
||||
for (int i = 0; i < totalEntries; i++) {
|
||||
auto *n = nodeDB->getMeshNodeByIndex(i);
|
||||
|
||||
if (!n)
|
||||
continue;
|
||||
if (n->num == nodeDB->getNodeNum())
|
||||
continue;
|
||||
if (locationScreen && !n->has_position)
|
||||
continue;
|
||||
|
||||
drawList.push_back(n->num);
|
||||
}
|
||||
totalEntries = drawList.size();
|
||||
int perPage = visibleNodeRows * totalColumns;
|
||||
|
||||
int maxScroll = 0;
|
||||
if (perPage > 0) {
|
||||
maxScroll = std::max(0, (totalEntries - 1) / perPage);
|
||||
}
|
||||
|
||||
if (scrollIndex > maxScroll)
|
||||
scrollIndex = maxScroll;
|
||||
int startIndex = scrollIndex * visibleNodeRows * totalColumns;
|
||||
int endIndex = std::min(startIndex + visibleNodeRows * totalColumns, totalEntries);
|
||||
int yOffset = 0;
|
||||
int col = 0;
|
||||
int lastNodeY = y;
|
||||
int shownCount = 0;
|
||||
int rowCount = 0;
|
||||
|
||||
for (int i = startIndex; i < endIndex; ++i) {
|
||||
if (locationScreen && !nodeDB->getMeshNodeByIndex(i)->has_position) {
|
||||
numskipped++;
|
||||
continue;
|
||||
}
|
||||
for (int idx = startIndex; idx < endIndex; idx++) {
|
||||
uint32_t nodeNum = drawList[idx];
|
||||
auto *node = nodeDB->getMeshNode(nodeNum);
|
||||
int xPos = x + (col * columnWidth);
|
||||
int yPos = y + yOffset;
|
||||
renderer(display, nodeDB->getMeshNodeByIndex(i), xPos, yPos, columnWidth);
|
||||
|
||||
if (extras) {
|
||||
extras(display, nodeDB->getMeshNodeByIndex(i), xPos, yPos, columnWidth, heading, lat, lon);
|
||||
}
|
||||
renderer(display, node, xPos, yPos, columnWidth);
|
||||
|
||||
if (extras)
|
||||
extras(display, node, xPos, yPos, columnWidth, heading, lat, lon);
|
||||
|
||||
lastNodeY = std::max(lastNodeY, yPos + FONT_HEIGHT_SMALL);
|
||||
yOffset += rowYOffset;
|
||||
@@ -498,17 +563,73 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
||||
// This should correct the scrollbar
|
||||
totalEntries -= numskipped;
|
||||
|
||||
#if !defined(M5STACK_UNITC6L)
|
||||
// Draw column separator
|
||||
if (shownCount > 0) {
|
||||
if (currentResolution != ScreenResolution::UltraLow && shownCount > 0) {
|
||||
const int firstNodeY = y + 3;
|
||||
drawColumnSeparator(display, x, firstNodeY, lastNodeY);
|
||||
for (int horizontal_offset = 1; horizontal_offset < totalColumns; horizontal_offset++) {
|
||||
drawColumnSeparator(display, columnWidth * horizontal_offset, firstNodeY, lastNodeY);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
const int scrollStartY = y + 3;
|
||||
drawScrollbar(display, visibleNodeRows, totalEntries, scrollIndex, 2, scrollStartY);
|
||||
drawScrollbar(display, visibleNodeRows, totalEntries, scrollIndex, totalColumns, scrollStartY);
|
||||
graphics::drawCommonFooter(display, x, y);
|
||||
|
||||
// Scroll Popup Overlay
|
||||
if (millis() - popupTime < POPUP_DURATION_MS) {
|
||||
popupTotal = totalEntries;
|
||||
|
||||
int perPage = visibleNodeRows * totalColumns;
|
||||
|
||||
popupStart = startIndex + 1;
|
||||
popupEnd = std::min(startIndex + perPage, totalEntries);
|
||||
|
||||
popupPage = (scrollIndex + 1);
|
||||
popupMaxPage = std::max(1, (totalEntries + perPage - 1) / perPage);
|
||||
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "%d-%d/%d Pg %d/%d", popupStart, popupEnd, popupTotal, popupPage, popupMaxPage);
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
// Box padding
|
||||
int padding = 2;
|
||||
int textW = display->getStringWidth(buf);
|
||||
int textH = FONT_HEIGHT_SMALL;
|
||||
int boxWidth = textW + padding * 3;
|
||||
int boxHeight = textH + padding * 2;
|
||||
|
||||
// Center of usable screen area:
|
||||
int headerHeight = FONT_HEIGHT_SMALL - 1;
|
||||
int footerHeight = FONT_HEIGHT_SMALL + 2;
|
||||
|
||||
int usableTop = headerHeight;
|
||||
int usableBottom = display->getHeight() - footerHeight;
|
||||
int usableHeight = usableBottom - usableTop;
|
||||
|
||||
// Center point inside usable area
|
||||
int boxLeft = (display->getWidth() - boxWidth) / 2;
|
||||
int boxTop = usableTop + (usableHeight - boxHeight) / 2;
|
||||
|
||||
// Draw Box
|
||||
display->setColor(BLACK);
|
||||
display->fillRect(boxLeft - 1, boxTop - 1, boxWidth + 2, boxHeight + 2);
|
||||
display->fillRect(boxLeft, boxTop - 2, boxWidth, 1);
|
||||
display->fillRect(boxLeft, boxTop + boxHeight + 1, boxWidth, 1);
|
||||
display->fillRect(boxLeft - 2, boxTop, 1, boxHeight);
|
||||
display->fillRect(boxLeft + boxWidth + 1, boxTop, 1, boxHeight);
|
||||
display->setColor(WHITE);
|
||||
display->drawRect(boxLeft, boxTop, boxWidth, boxHeight);
|
||||
display->setColor(BLACK);
|
||||
display->fillRect(boxLeft, boxTop, 1, 1);
|
||||
display->fillRect(boxLeft + boxWidth - 1, boxTop, 1, 1);
|
||||
display->fillRect(boxLeft, boxTop + boxHeight - 1, 1, 1);
|
||||
display->fillRect(boxLeft + boxWidth - 1, boxTop + boxHeight - 1, 1, 1);
|
||||
display->setColor(WHITE);
|
||||
|
||||
// Text
|
||||
display->drawString(boxLeft + padding, boxTop + padding, buf);
|
||||
}
|
||||
}
|
||||
|
||||
// =============================
|
||||
@@ -516,10 +637,11 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
||||
// =============================
|
||||
|
||||
#ifndef USE_EINK
|
||||
void drawDynamicNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
// Node list for Last Heard and Hop Signal views
|
||||
void drawDynamicListScreen_Nodes(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
// Static variables to track mode and duration
|
||||
static NodeListMode lastRenderedMode = MODE_COUNT;
|
||||
static ListMode_Node lastRenderedMode = MODE_COUNT_NODE;
|
||||
static unsigned long modeStartTime = 0;
|
||||
|
||||
unsigned long now = millis();
|
||||
@@ -532,23 +654,65 @@ void drawDynamicNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state,
|
||||
}
|
||||
#endif
|
||||
// On very first call (on boot or state enter)
|
||||
if (lastRenderedMode == MODE_COUNT) {
|
||||
currentMode = MODE_LAST_HEARD;
|
||||
if (lastRenderedMode == MODE_COUNT_NODE) {
|
||||
currentMode_Nodes = MODE_LAST_HEARD;
|
||||
modeStartTime = now;
|
||||
}
|
||||
|
||||
// Time to switch to next mode?
|
||||
if (now - modeStartTime >= getModeCycleIntervalMs()) {
|
||||
currentMode = static_cast<NodeListMode>((currentMode + 1) % MODE_COUNT);
|
||||
currentMode_Nodes = static_cast<ListMode_Node>((currentMode_Nodes + 1) % MODE_COUNT_NODE);
|
||||
modeStartTime = now;
|
||||
}
|
||||
|
||||
// Render screen based on currentMode
|
||||
const char *title = getCurrentModeTitle(display->getWidth());
|
||||
drawNodeListScreen(display, state, x, y, title, drawEntryDynamic);
|
||||
const char *title = getCurrentModeTitle_Nodes(display->getWidth());
|
||||
drawNodeListScreen(display, state, x, y, title, drawEntryDynamic_Nodes);
|
||||
|
||||
// Track the last mode to avoid reinitializing modeStartTime
|
||||
lastRenderedMode = currentMode;
|
||||
lastRenderedMode = currentMode_Nodes;
|
||||
}
|
||||
|
||||
// Node list for Distance and Bearings views
|
||||
void drawDynamicListScreen_Location(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
// Static variables to track mode and duration
|
||||
static ListMode_Location lastRenderedMode = MODE_COUNT_LOCATION;
|
||||
static unsigned long modeStartTime = 0;
|
||||
|
||||
unsigned long now = millis();
|
||||
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
display->clear();
|
||||
if (now - lastSwitchTime >= 3000) {
|
||||
display->display();
|
||||
lastSwitchTime = now;
|
||||
}
|
||||
#endif
|
||||
// On very first call (on boot or state enter)
|
||||
if (lastRenderedMode == MODE_COUNT_LOCATION) {
|
||||
currentMode_Location = MODE_DISTANCE;
|
||||
modeStartTime = now;
|
||||
}
|
||||
|
||||
// Time to switch to next mode?
|
||||
if (now - modeStartTime >= getModeCycleIntervalMs()) {
|
||||
currentMode_Location = static_cast<ListMode_Location>((currentMode_Location + 1) % MODE_COUNT_LOCATION);
|
||||
modeStartTime = now;
|
||||
}
|
||||
|
||||
// Render screen based on currentMode
|
||||
const char *title = getCurrentModeTitle_Location(display->getWidth());
|
||||
|
||||
// Render screen based on currentMode_Location
|
||||
if (currentMode_Location == MODE_DISTANCE) {
|
||||
drawNodeListScreen(display, state, x, y, title, drawNodeDistance);
|
||||
} else if (currentMode_Location == MODE_BEARING) {
|
||||
drawNodeListWithCompasses(display, state, x, y);
|
||||
}
|
||||
|
||||
// Track the last mode to avoid reinitializing modeStartTime
|
||||
lastRenderedMode = currentMode_Location;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -569,14 +733,12 @@ void drawHopSignalScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
#endif
|
||||
drawNodeListScreen(display, state, x, y, title, drawEntryHopSignal);
|
||||
}
|
||||
|
||||
void drawDistanceScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
const char *title = "Distance";
|
||||
drawNodeListScreen(display, state, x, y, title, drawNodeDistance);
|
||||
}
|
||||
#endif
|
||||
|
||||
void drawNodeListWithCompasses(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
float heading = 0;
|
||||
|
||||
@@ -23,8 +23,11 @@ namespace NodeListRenderer
|
||||
typedef void (*EntryRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int);
|
||||
typedef void (*NodeExtrasRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int, float, double, double);
|
||||
|
||||
// Node list mode enumeration
|
||||
enum NodeListMode { MODE_LAST_HEARD = 0, MODE_HOP_SIGNAL = 1, MODE_DISTANCE = 2, MODE_COUNT = 3 };
|
||||
// Node list mode enumeration for Last Heard and Hop Signal views
|
||||
enum ListMode_Node { MODE_LAST_HEARD = 0, MODE_HOP_SIGNAL = 1, MODE_COUNT_NODE = 2 };
|
||||
|
||||
// Node list mode enumeration for Distance and Bearings views
|
||||
enum ListMode_Location { MODE_DISTANCE = 0, MODE_BEARING = 1, MODE_COUNT_LOCATION = 2 };
|
||||
|
||||
// Main node list screen function
|
||||
void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *title,
|
||||
@@ -35,7 +38,7 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
||||
void drawEntryLastHeard(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth);
|
||||
void drawEntryHopSignal(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth);
|
||||
void drawNodeDistance(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth);
|
||||
void drawEntryDynamic(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth);
|
||||
void drawEntryDynamic_Nodes(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth);
|
||||
void drawEntryCompass(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth);
|
||||
|
||||
// Extras renderers
|
||||
@@ -46,14 +49,20 @@ void drawCompassArrow(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16
|
||||
void drawLastHeardScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
void drawHopSignalScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
void drawDistanceScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
void drawDynamicNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
void drawDynamicListScreen_Nodes(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
void drawDynamicListScreen_Location(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
void drawNodeListWithCompasses(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
// Utility functions
|
||||
const char *getCurrentModeTitle(int screenWidth);
|
||||
const char *getSafeNodeName(meshtastic_NodeInfoLite *node);
|
||||
const char *getCurrentModeTitle_Nodes(int screenWidth);
|
||||
const char *getCurrentModeTitle_Location(int screenWidth);
|
||||
const char *getSafeNodeName(meshtastic_NodeInfoLite *node, int columnWidth);
|
||||
void drawColumns(OLEDDisplay *display, int16_t x, int16_t y, const char **fields);
|
||||
|
||||
// Scrolling controls
|
||||
void scrollUp();
|
||||
void scrollDown();
|
||||
|
||||
// Bitmap drawing function
|
||||
void drawScaledXBitmap16x16(int x, int y, int width, int height, const uint8_t *bitmapXBM, OLEDDisplay *display);
|
||||
|
||||
|
||||
@@ -321,7 +321,7 @@ void NotificationRenderer::drawNodePicker(OLEDDisplay *display, OLEDDisplayUiSta
|
||||
}
|
||||
if (i == curSelected) {
|
||||
selectedNodenum = nodeDB->getMeshNodeByIndex(i + 1)->num;
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
strncpy(scratchLineBuffer[scratchLineNum], "> ", 3);
|
||||
strncpy(scratchLineBuffer[scratchLineNum] + 2, temp_name, 36);
|
||||
strncpy(scratchLineBuffer[scratchLineNum] + strlen(temp_name) + 2, " <", 3);
|
||||
@@ -449,7 +449,7 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp
|
||||
|
||||
for (int i = firstOptionToShow; i < alertBannerOptions && linesShown < visibleTotalLines; i++, linesShown++) {
|
||||
if (i == curSelected) {
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
strncpy(lineBuffer, "> ", 3);
|
||||
strncpy(lineBuffer + 2, optionsArrayPtr[i], 36);
|
||||
strncpy(lineBuffer + strlen(optionsArrayPtr[i]) + 2, " <", 3);
|
||||
@@ -533,9 +533,9 @@ void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplay
|
||||
uint16_t boxWidth = hPadding * 2 + maxWidth;
|
||||
|
||||
if (needs_bell) {
|
||||
if (isHighResolution && boxWidth <= 150)
|
||||
if ((currentResolution == ScreenResolution::High) && boxWidth <= 150)
|
||||
boxWidth += 26;
|
||||
if (!isHighResolution && boxWidth <= 100)
|
||||
if ((currentResolution == ScreenResolution::Low || currentResolution == ScreenResolution::UltraLow) && boxWidth <= 100)
|
||||
boxWidth += 20;
|
||||
}
|
||||
|
||||
@@ -545,15 +545,15 @@ void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplay
|
||||
uint16_t contentHeight = visibleTotalLines * effectiveLineHeight;
|
||||
uint16_t boxHeight = contentHeight + vPadding * 2;
|
||||
if (visibleTotalLines == 1) {
|
||||
boxHeight += (isHighResolution) ? 4 : 3;
|
||||
boxHeight += (currentResolution == ScreenResolution::High) ? 4 : 3;
|
||||
}
|
||||
|
||||
int16_t boxLeft = (display->width() / 2) - (boxWidth / 2);
|
||||
if (totalLines > visibleTotalLines) {
|
||||
boxWidth += (isHighResolution) ? 4 : 2;
|
||||
boxWidth += (currentResolution == ScreenResolution::High) ? 4 : 2;
|
||||
}
|
||||
int16_t boxTop = (display->height() / 2) - (boxHeight / 2);
|
||||
boxHeight += (isHighResolution) ? 2 : 1;
|
||||
boxHeight += (currentResolution == ScreenResolution::High) ? 2 : 1;
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
if (visibleTotalLines == 1) {
|
||||
boxTop += 25;
|
||||
|
||||
@@ -28,8 +28,8 @@ std::vector<meshtastic_NodeInfoLite *> graphics::UIRenderer::favoritedNodes;
|
||||
|
||||
static inline void drawSatelliteIcon(OLEDDisplay *display, int16_t x, int16_t y)
|
||||
{
|
||||
int yOffset = (isHighResolution) ? -5 : 1;
|
||||
if (isHighResolution) {
|
||||
int yOffset = (currentResolution == ScreenResolution::High) ? -5 : 1;
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
NodeListRenderer::drawScaledXBitmap16x16(x, y + yOffset, imgSatellite_width, imgSatellite_height, imgSatellite, display);
|
||||
} else {
|
||||
display->drawXbm(x + 1, y + yOffset, imgSatellite_width, imgSatellite_height, imgSatellite);
|
||||
@@ -63,7 +63,7 @@ extern uint32_t dopThresholds[5];
|
||||
void UIRenderer::drawGps(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gps)
|
||||
{
|
||||
// Draw satellite image
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
NodeListRenderer::drawScaledXBitmap16x16(x, y - 2, imgSatellite_width, imgSatellite_height, imgSatellite, display);
|
||||
} else {
|
||||
display->drawXbm(x + 1, y + 1, imgSatellite_width, imgSatellite_height, imgSatellite);
|
||||
@@ -83,7 +83,7 @@ void UIRenderer::drawGps(OLEDDisplay *display, int16_t x, int16_t y, const mesht
|
||||
} else {
|
||||
snprintf(textString, sizeof(textString), "%u sats", gps->getNumSatellites());
|
||||
}
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
display->drawString(x + 18, y, textString);
|
||||
} else {
|
||||
display->drawString(x + 11, y, textString);
|
||||
@@ -268,19 +268,19 @@ void UIRenderer::drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const mes
|
||||
defined(HACKADAY_COMMUNICATOR) || defined(USE_ST7796)) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
NodeListRenderer::drawScaledXBitmap16x16(x, y - 1, 8, 8, imgUser, display);
|
||||
} else {
|
||||
display->drawFastImage(x, y + 3, 8, 8, imgUser);
|
||||
}
|
||||
#else
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
NodeListRenderer::drawScaledXBitmap16x16(x, y - 1, 8, 8, imgUser, display);
|
||||
} else {
|
||||
display->drawFastImage(x, y + 1, 8, 8, imgUser);
|
||||
}
|
||||
#endif
|
||||
int string_offset = (isHighResolution) ? 9 : 0;
|
||||
int string_offset = (currentResolution == ScreenResolution::High) ? 9 : 0;
|
||||
display->drawString(x + 10 + string_offset, y - 2, usersString);
|
||||
}
|
||||
|
||||
@@ -328,11 +328,12 @@ void UIRenderer::drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *st
|
||||
int line = 1; // which slot to use next
|
||||
std::string usernameStr;
|
||||
// === 1. Long Name (always try to show first) ===
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
const char *username = (node->has_user && node->user.long_name[0]) ? node->user.short_name : nullptr;
|
||||
#else
|
||||
const char *username = (node->has_user && node->user.long_name[0]) ? node->user.long_name : nullptr;
|
||||
#endif
|
||||
const char *username;
|
||||
if (currentResolution == ScreenResolution::UltraLow) {
|
||||
username = (node->has_user && node->user.long_name[0]) ? node->user.short_name : nullptr;
|
||||
} else {
|
||||
username = (node->has_user && node->user.long_name[0]) ? node->user.long_name : nullptr;
|
||||
}
|
||||
|
||||
if (username) {
|
||||
usernameStr = sanitizeString(username); // Sanitize the incoming long_name just in case
|
||||
@@ -508,7 +509,7 @@ void UIRenderer::drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *st
|
||||
const int margin = 4;
|
||||
// --------- PATCH FOR EINK NAV BAR (ONLY CHANGE BELOW) -----------
|
||||
#if defined(USE_EINK)
|
||||
const int iconSize = (isHighResolution) ? 16 : 8;
|
||||
const int iconSize = (currentResolution == ScreenResolution::High) ? 16 : 8;
|
||||
const int navBarHeight = iconSize + 6;
|
||||
#else
|
||||
const int navBarHeight = 0;
|
||||
@@ -566,11 +567,11 @@ void UIRenderer::drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *sta
|
||||
meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
|
||||
// === Header ===
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
graphics::drawCommonHeader(display, x, y, "Home");
|
||||
#else
|
||||
graphics::drawCommonHeader(display, x, y, "");
|
||||
#endif
|
||||
if (currentResolution == ScreenResolution::UltraLow) {
|
||||
graphics::drawCommonHeader(display, x, y, "Home");
|
||||
} else {
|
||||
graphics::drawCommonHeader(display, x, y, "");
|
||||
}
|
||||
|
||||
// === Content below header ===
|
||||
|
||||
@@ -585,15 +586,15 @@ void UIRenderer::drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *sta
|
||||
config.display.heading_bold = false;
|
||||
|
||||
// Display Region and Channel Utilization
|
||||
#if defined(M5STACK_UNITC6L)
|
||||
drawNodes(display, x, getTextPositions(display)[line] + 2, nodeStatus, -1, false, "online");
|
||||
#else
|
||||
drawNodes(display, x + 1, getTextPositions(display)[line] + 2, nodeStatus, -1, false, "online");
|
||||
#endif
|
||||
if (currentResolution == ScreenResolution::UltraLow) {
|
||||
drawNodes(display, x, getTextPositions(display)[line] + 2, nodeStatus, -1, false, "online");
|
||||
} else {
|
||||
drawNodes(display, x + 1, getTextPositions(display)[line] + 2, nodeStatus, -1, false, "online");
|
||||
}
|
||||
char uptimeStr[32] = "";
|
||||
#if !defined(M5STACK_UNITC6L)
|
||||
getUptimeStr(millis(), "Up", uptimeStr, sizeof(uptimeStr));
|
||||
#endif
|
||||
if (currentResolution != ScreenResolution::UltraLow) {
|
||||
getUptimeStr(millis(), "Up", uptimeStr, sizeof(uptimeStr));
|
||||
}
|
||||
display->drawString(SCREEN_WIDTH - display->getStringWidth(uptimeStr), getTextPositions(display)[line++], uptimeStr);
|
||||
|
||||
// === Second Row: Satellites and Voltage ===
|
||||
@@ -608,7 +609,7 @@ void UIRenderer::drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *sta
|
||||
displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off";
|
||||
}
|
||||
drawSatelliteIcon(display, x, getTextPositions(display)[line]);
|
||||
int xOffset = (isHighResolution) ? 6 : 0;
|
||||
int xOffset = (currentResolution == ScreenResolution::High) ? 6 : 0;
|
||||
display->drawString(x + 11 + xOffset, getTextPositions(display)[line], displayLine);
|
||||
} else {
|
||||
UIRenderer::drawGps(display, 0, getTextPositions(display)[line], gpsStatus);
|
||||
@@ -647,21 +648,22 @@ void UIRenderer::drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *sta
|
||||
char chUtilPercentage[10];
|
||||
snprintf(chUtilPercentage, sizeof(chUtilPercentage), "%2.0f%%", airTime->channelUtilizationPercent());
|
||||
|
||||
int chUtil_x = (isHighResolution) ? display->getStringWidth(chUtil) + 10 : display->getStringWidth(chUtil) + 5;
|
||||
int chUtil_x = (currentResolution == ScreenResolution::High) ? display->getStringWidth(chUtil) + 10
|
||||
: display->getStringWidth(chUtil) + 5;
|
||||
int chUtil_y = getTextPositions(display)[line] + 3;
|
||||
|
||||
int chutil_bar_width = (isHighResolution) ? 100 : 50;
|
||||
int chutil_bar_width = (currentResolution == ScreenResolution::High) ? 100 : 50;
|
||||
if (!config.bluetooth.enabled) {
|
||||
#if defined(USE_EINK)
|
||||
chutil_bar_width = (isHighResolution) ? 50 : 30;
|
||||
chutil_bar_width = (currentResolution == ScreenResolution::High) ? 50 : 30;
|
||||
#else
|
||||
chutil_bar_width = (isHighResolution) ? 80 : 40;
|
||||
chutil_bar_width = (currentResolution == ScreenResolution::High) ? 80 : 40;
|
||||
#endif
|
||||
}
|
||||
int chutil_bar_height = (isHighResolution) ? 12 : 7;
|
||||
int extraoffset = (isHighResolution) ? 6 : 3;
|
||||
int chutil_bar_height = (currentResolution == ScreenResolution::High) ? 12 : 7;
|
||||
int extraoffset = (currentResolution == ScreenResolution::High) ? 6 : 3;
|
||||
if (!config.bluetooth.enabled) {
|
||||
extraoffset = (isHighResolution) ? 6 : 1;
|
||||
extraoffset = (currentResolution == ScreenResolution::High) ? 6 : 1;
|
||||
}
|
||||
int chutil_percent = airTime->channelUtilizationPercent();
|
||||
|
||||
@@ -721,7 +723,7 @@ void UIRenderer::drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *sta
|
||||
// === Fourth & Fifth Rows: Node Identity ===
|
||||
int textWidth = 0;
|
||||
int nameX = 0;
|
||||
int yOffset = (isHighResolution) ? 0 : 5;
|
||||
int yOffset = (currentResolution == ScreenResolution::High) ? 0 : 5;
|
||||
std::string longNameStr;
|
||||
|
||||
if (ourNode && ourNode->has_user && strlen(ourNode->user.long_name) > 0) {
|
||||
@@ -991,7 +993,7 @@ void UIRenderer::drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayU
|
||||
displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off";
|
||||
}
|
||||
drawSatelliteIcon(display, x, getTextPositions(display)[line]);
|
||||
int xOffset = (isHighResolution) ? 6 : 0;
|
||||
int xOffset = (currentResolution == ScreenResolution::High) ? 6 : 0;
|
||||
display->drawString(x + 11 + xOffset, getTextPositions(display)[line++], displayLine);
|
||||
} else {
|
||||
// Onboard GPS
|
||||
@@ -1149,7 +1151,7 @@ void UIRenderer::drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayU
|
||||
void UIRenderer::drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
static const uint8_t xbm[] = USERPREFS_OEM_IMAGE_DATA;
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - USERPREFS_OEM_IMAGE_WIDTH) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - USERPREFS_OEM_IMAGE_HEIGHT) / 2 + 2, USERPREFS_OEM_IMAGE_WIDTH,
|
||||
USERPREFS_OEM_IMAGE_HEIGHT, xbm);
|
||||
@@ -1174,7 +1176,7 @@ void UIRenderer::drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, O
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
const char *title = USERPREFS_OEM_TEXT;
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
|
||||
}
|
||||
display->setFont(FONT_SMALL);
|
||||
@@ -1218,15 +1220,15 @@ void UIRenderer::drawNavigationBar(OLEDDisplay *display, OLEDDisplayUiState *sta
|
||||
lastFrameChangeTime = millis();
|
||||
}
|
||||
|
||||
const int iconSize = isHighResolution ? 16 : 8;
|
||||
const int spacing = isHighResolution ? 8 : 4;
|
||||
const int bigOffset = isHighResolution ? 1 : 0;
|
||||
const int iconSize = (currentResolution == ScreenResolution::High) ? 16 : 8;
|
||||
const int spacing = (currentResolution == ScreenResolution::High) ? 8 : 4;
|
||||
const int bigOffset = (currentResolution == ScreenResolution::High) ? 1 : 0;
|
||||
|
||||
const size_t totalIcons = screen->indicatorIcons.size();
|
||||
if (totalIcons == 0)
|
||||
return;
|
||||
|
||||
const int navPadding = isHighResolution ? 24 : 12; // padding per side
|
||||
const int navPadding = (currentResolution == ScreenResolution::High) ? 24 : 12; // padding per side
|
||||
|
||||
int usableWidth = SCREEN_WIDTH - (navPadding * 2);
|
||||
if (usableWidth < iconSize)
|
||||
@@ -1293,7 +1295,7 @@ void UIRenderer::drawNavigationBar(OLEDDisplay *display, OLEDDisplayUiState *sta
|
||||
display->setColor(BLACK);
|
||||
}
|
||||
|
||||
if (isHighResolution) {
|
||||
if (currentResolution == ScreenResolution::High) {
|
||||
NodeListRenderer::drawScaledXBitmap16x16(x, y, 8, 8, icon, display);
|
||||
} else {
|
||||
display->drawXbm(x, y, iconSize, iconSize, icon);
|
||||
@@ -1308,7 +1310,7 @@ void UIRenderer::drawNavigationBar(OLEDDisplay *display, OLEDDisplayUiState *sta
|
||||
auto drawArrow = [&](bool rightSide) {
|
||||
display->setColor(WHITE);
|
||||
|
||||
const int offset = isHighResolution ? 3 : 1;
|
||||
const int offset = (currentResolution == ScreenResolution::High) ? 3 : 1;
|
||||
const int halfH = rectHeight / 2;
|
||||
|
||||
const int top = (y - 2) + (rectHeight - halfH) / 2;
|
||||
|
||||
@@ -13,41 +13,81 @@ const Emote emotes[] = {
|
||||
{"\U0001F44E", thumbdown, thumbs_width, thumbs_height}, // 👎 Thumbs Down
|
||||
|
||||
// --- Smileys (Multiple Unicode Aliases) ---
|
||||
{"\U0001F60A", Smiling_Eyes, Smiling_Eyes_width, Smiling_Eyes_height}, // 😊 Smiling Eyes
|
||||
{"\U0001F600", Grinning, Grinning_width, Grinning_height}, // 😀 Grinning Face
|
||||
{"\U0001F642", Slightly_Smiling, Slightly_Smiling_width, Slightly_Smiling_height}, // 🙂 Slightly Smiling Face
|
||||
{"\U0001F609", Winking_Face, Winking_Face_width, Winking_Face_height}, // 😉 Winking Face
|
||||
{"\U0001F601", Grinning_Smiling_Eyes, Grinning_Smiling_Eyes_width, Grinning_Smiling_Eyes_height}, // 😁 Grinning Smiling Eyes
|
||||
{"\U0001F60D", Heart_eyes, Heart_eyes_width, Heart_eyes_height}, // 😍 Heart Eyes
|
||||
{"\U0001F60A", smiling_eyes, smiling_eyes_width, smiling_eyes_height}, // 😊 Smiling Eyes
|
||||
{"\U0001F600", grinning, grinning_width, grinning_height}, // 😀 Grinning Face
|
||||
{"\U0001F642", slightly_smiling, slightly_smiling_width, slightly_smiling_height}, // 🙂 Slightly Smiling Face
|
||||
{"\U0001F609", winking_face, winking_face_width, winking_face_height}, // 😉 Winking Face
|
||||
{"\U0001F601", grinning_smiling_eyes, grinning_smiling_eyes_width, grinning_smiling_eyes_height}, // 😁 Grinning Smiling Eyes
|
||||
{"\U0001F60D", heart_eyes, heart_eyes_width, heart_eyes_height}, // 😍 Heart Eyes
|
||||
{"\U0001F970", heart_smile, heart_smile_width, heart_smile_height}, // 🥰 Smiling Face with Hearts
|
||||
|
||||
// --- Question/Alert ---
|
||||
{"\u2753", question, question_width, question_height}, // ❓ Question Mark
|
||||
{"\u203C\uFE0F", bang, bang_width, bang_height}, // ‼️ Double Exclamation Mark
|
||||
{"\u2753", question, question_width, question_height}, // ❓ Question Mark
|
||||
{"\u203C\uFE0F", bang, bang_width, bang_height}, // ‼️ Double Exclamation Mark
|
||||
{"\u26A0\uFE0F", caution, caution_width, caution_height}, // ⚠️ Warning Sign
|
||||
|
||||
// --- Laughing Faces ---
|
||||
{"\U0001F602", haha, haha_width, haha_height}, // 😂 Face with Tears of Joy
|
||||
{"\U0001F923", ROFL, ROFL_width, ROFL_height}, // 🤣 Rolling on the Floor Laughing
|
||||
{"\U0001F606", Smiling_Closed_Eyes, Smiling_Closed_Eyes_width, Smiling_Closed_Eyes_height}, // 😆 Smiling Closed Eyes
|
||||
{"\U0001F923", rofl, rofl_width, rofl_height}, // 🤣 Rolling on the Floor Laughing
|
||||
{"\U0001F606", smiling_closed_eyes, smiling_closed_eyes_width, smiling_closed_eyes_height}, // 😆 Smiling Closed Eyes
|
||||
{"\U0001F605", haha, haha_width, haha_height}, // 😅 Smiling with Sweat
|
||||
{"\U0001F604", Grinning_SmilingEyes2, Grinning_SmilingEyes2_width,
|
||||
Grinning_SmilingEyes2_height}, // 😄 Grinning Face with Smiling Eyes
|
||||
{"\U0001F62D", Loudly_Crying_Face, Loudly_Crying_Face_width, Loudly_Crying_Face_height}, // 😭 Loudly Crying Face
|
||||
{"\U0001F604", grinning_smiling_eyes_2, grinning_smiling_eyes_2_width,
|
||||
grinning_smiling_eyes_2_height}, // 😄 Grinning Face with Smiling Eyes
|
||||
{"\U0001F62D", loudly_crying_face, loudly_crying_face_width, loudly_crying_face_height}, // 😭 Loudly Crying Face
|
||||
{"\U0001F92E", vomiting, vomiting_width, vomiting_height}, // 🤮 Face Vomiting
|
||||
{"\U0001F60E", cool, cool_width, cool_height}, // 😎 Smiling Face with Sunglasses
|
||||
{"\U0001F440", eyes, eyes_width, eyes_height}, // 👀 Eyes
|
||||
{"\U0001F441\uFE0F", eye, eye_width, eye_height}, // 👁️ Eye
|
||||
|
||||
// --- Gestures and People ---
|
||||
{"\U0001F44B", wave_icon, wave_icon_width, wave_icon_height}, // 👋 Waving Hand
|
||||
{"\u270C\uFE0F", peace_sign, peace_sign_width, peace_sign_height}, // ✌️ Victory Hand
|
||||
{"\U0001F596", vulcan_salute, vulcan_salute_width, vulcan_salute_height}, // 🖖 Vulcan Salute
|
||||
{"\U0001F64F", Praying, Praying_width, Praying_height}, // 🙏 Praying Hands
|
||||
{"\U0001F64F", praying, praying_width, praying_height}, // 🙏 Praying Hands
|
||||
{"\U0001F4AA", strong, strong_width, strong_height}, // 💪 Flexed Biceps
|
||||
{"\U0001F937", shrug, shrug_width, shrug_height}, // 🤷 Person Shrugging
|
||||
{"\U0001F920", cowboy, cowboy_width, cowboy_height}, // 🤠 Cowboy Hat Face
|
||||
{"\U0001F3A7", deadmau5, deadmau5_width, deadmau5_height}, // 🎧 Headphones
|
||||
|
||||
// --- Symbols ---
|
||||
{"\u2714\uFE0F", check_mark, check_mark_width, check_mark_height}, // ✔️ Check Mark
|
||||
{"\u2705", check_mark, check_mark_width, check_mark_height}, // ✅ Check Mark Button
|
||||
{"\u2611\uFE0F", check_mark, check_mark_width, check_mark_height}, // ☑️ Check Box with Check
|
||||
{"\U0001F3E0", house, house_width, house_height}, // 🏠 House
|
||||
|
||||
// --- Weather ---
|
||||
{"\u2600", sun, sun_width, sun_height}, // ☀ Sun (without variation selector)
|
||||
{"\u2600\uFE0F", sun, sun_width, sun_height}, // ☀️ Sun (with variation selector)
|
||||
{"\U0001F327\uFE0F", rain, rain_width, rain_height}, // 🌧️ Cloud with Rain
|
||||
{"\u2601\uFE0F", cloud, cloud_width, cloud_height}, // ☁️ Cloud
|
||||
{"\U0001F32B\uFE0F", fog, fog_width, fog_height}, // 🌫️ Fog
|
||||
{"\u2600", sun, sun_width, sun_height}, // ☀ Sun (without variation selector)
|
||||
{"\u2600\uFE0F", sun, sun_width, sun_height}, // ☀️ Sun (with variation selector)
|
||||
{"\U0001F327\uFE0F", rain, rain_width, rain_height}, // 🌧️ Cloud with Rain
|
||||
{"\u2601\uFE0F", cloud, cloud_width, cloud_height}, // ☁️ Cloud
|
||||
{"\U0001F32B\uFE0F", fog, fog_width, fog_height}, // 🌫️ Fog
|
||||
{"\u2744\uFE0F", snowflake, snowflake_width, snowflake_height}, // ❄️ Snowflake
|
||||
{"\U0001F4A7", drop, drop_width, drop_height}, // 💧 Droplet
|
||||
{"\U0001F321\uFE0F", thermometer, thermometer_width, thermometer_height}, // 🌡️ Thermometer
|
||||
{"\U0001F326\uFE0F", sun_behind_raincloud, sun_behind_raincloud_width,
|
||||
sun_behind_raincloud_height}, // 🌦️ Sun Behind Rain Cloud
|
||||
{"\u26C5", sun_behind_cloud, sun_behind_cloud_width, sun_behind_cloud_height}, // ⛅ Sun Behind Cloud
|
||||
{"\u26C5\uFE0F", sun_behind_cloud, sun_behind_cloud_width, sun_behind_cloud_height}, // ⛅️ Sun Behind Cloud
|
||||
{"\U0001F328\uFE0F", cloud_with_snow, cloud_with_snow_width, cloud_with_snow_height}, // 🌨️ Cloud with Snow
|
||||
{"\U0001F329\uFE0F", cloud_with_lightning, cloud_with_lightning_width,
|
||||
cloud_with_lightning_height}, // 🌩️ Cloud with Lightning
|
||||
{"\u26C8", cloud_with_lightning_rain, cloud_with_lightning_rain_width,
|
||||
cloud_with_lightning_rain_height}, // ⛈ Cloud with Lightning and Rain
|
||||
{"\u26C8\uFE0F", cloud_with_lightning_rain, cloud_with_lightning_rain_width,
|
||||
cloud_with_lightning_rain_height}, // ⛈️ Cloud with Lightning and Rain
|
||||
{"\U0001F32C\uFE0F", wind_face, wind_face_width, wind_face_height}, // 🌬️ Wind Face
|
||||
|
||||
// --- Moon Phases ---
|
||||
{"\U0001F311", new_moon, new_moon_width, new_moon_height}, // 🌑 New Moon
|
||||
{"\U0001F312", waxing_crescent_moon, waxing_crescent_moon_width, waxing_crescent_moon_height}, // 🌒 Waxing Crescent Moon
|
||||
{"\U0001F313", first_quarter_moon, first_quarter_moon_width, first_quarter_moon_height}, // 🌓 First Quarter Moon
|
||||
{"\U0001F314", waxing_gibbous_moon, waxing_gibbous_moon_width, waxing_gibbous_moon_height}, // 🌔 Waxing Gibbous Moon
|
||||
{"\U0001F315", full_moon, full_moon_width, full_moon_height}, // 🌕 Full Moon
|
||||
{"\U0001F316", waning_gibbous_moon, waning_gibbous_moon_width, waning_gibbous_moon_height}, // 🌖 Waning Gibbous Moon
|
||||
{"\U0001F317", last_quarter_moon, last_quarter_moon_width, last_quarter_moon_height}, // 🌗 Last Quarter Moon
|
||||
{"\U0001F318", waning_crescent_moon, waning_crescent_moon_width, waning_crescent_moon_height}, // 🌘 Waning Crescent Moon
|
||||
{"\U0001F31B", first_quarter_moon_face, first_quarter_moon_face_width,
|
||||
first_quarter_moon_face_height}, // 🌛 First Quarter Moon Face
|
||||
|
||||
// --- Misc Faces ---
|
||||
{"\U0001F608", devil, devil_width, devil_height}, // 😈 Smiling Face with Horns
|
||||
@@ -67,13 +107,49 @@ const Emote emotes[] = {
|
||||
{"\U0001F498", heart, heart_width, heart_height}, // 💘 Heart with Arrow
|
||||
|
||||
// --- Objects ---
|
||||
{"\U0001F4A9", poo, poo_width, poo_height}, // 💩 Pile of Poo
|
||||
{"\U0001F514", bell_icon, bell_icon_width, bell_icon_height}, // 🔔 Bell
|
||||
{"\U0001F36A", cookie, cookie_width, cookie_height}, // 🍪 Cookie
|
||||
{"\U0001F525", Fire, Fire_width, Fire_height}, // 🔥 Fire
|
||||
{"\u2728", Sparkles, Sparkles_width, Sparkles_height}, // ✨ Sparkles
|
||||
{"\U0001F573\uFE0F", hole, hole_width, hole_height}, // 🕳️ Hole
|
||||
{"\U0001F3B3", bowling, bowling_width, bowling_height} // 🎳 Bowling
|
||||
{"\U0001F4A9", poo, poo_width, poo_height}, // 💩 Pile of Poo
|
||||
{"\U0001F514", bell_icon, bell_icon_width, bell_icon_height}, // 🔔 Bell
|
||||
{"\U0001F4CB", clipboard, clipboard_width, clipboard_height}, // 📋 Clipboard
|
||||
{"\U0001F36A", cookie, cookie_width, cookie_height}, // 🍪 Cookie
|
||||
{"\U0001F370", shortcake, shortcake_width, shortcake_height}, // 🍰 Shortcake
|
||||
{"\U0001F351", peach, peach_width, peach_height}, // 🍑 Peach
|
||||
{"\U0001F983", turkey, turkey_width, turkey_height}, // 🦃 Turkey
|
||||
{"\U0001F357", turkey_leg, turkey_leg_width, turkey_leg_height}, // 🍗 Poultry Leg
|
||||
{"\U0001F525", fire, fire_width, fire_height}, // 🔥 Fire
|
||||
{"\u2728", sparkles, sparkles_width, sparkles_height}, // ✨ Sparkles
|
||||
{"\U0001F573\uFE0F", hole, hole_width, hole_height}, // 🕳️ Hole
|
||||
{"\U0001F3B3", bowling, bowling_width, bowling_height}, // 🎳 Bowling
|
||||
|
||||
// --- Arrows ---
|
||||
{"\u2193", downwards_arrow, downwards_arrow_width, downwards_arrow_height}, // ↓ Downwards Arrow
|
||||
{"\u2193\uFE0E", downwards_arrow, downwards_arrow_width, downwards_arrow_height}, // ↓︎ Downwards Arrow (text)
|
||||
{"\u2193\uFE0F", downwards_arrow, downwards_arrow_width, downwards_arrow_height}, // ↓️ Downwards Arrow (emoji)
|
||||
{"\u2199", south_west_arrow, south_west_arrow_width, south_west_arrow_height}, // ↙ South West Arrow
|
||||
{"\u2199\uFE0E", south_west_arrow, south_west_arrow_width, south_west_arrow_height}, // ↙︎ South West Arrow (text)
|
||||
{"\u2199\uFE0F", south_west_arrow, south_west_arrow_width, south_west_arrow_height}, // ↙️ South West Arrow (emoji)
|
||||
{"\u2190", leftwards_arrow, leftwards_arrow_width, leftwards_arrow_height}, // ← Leftwards Arrow
|
||||
{"\u2190\uFE0E", leftwards_arrow, leftwards_arrow_width, leftwards_arrow_height}, // ←︎ Leftwards Arrow (text)
|
||||
{"\u2190\uFE0F", leftwards_arrow, leftwards_arrow_width, leftwards_arrow_height}, // ←️ Leftwards Arrow (emoji)
|
||||
{"\u2196", north_west_arrow, north_west_arrow_width, north_west_arrow_height}, // ↖ North West Arrow
|
||||
{"\u2196\uFE0E", north_west_arrow, north_west_arrow_width, north_west_arrow_height}, // ↖︎ North West Arrow (text)
|
||||
{"\u2196\uFE0F", north_west_arrow, north_west_arrow_width, north_west_arrow_height}, // ↖️ North West Arrow (emoji)
|
||||
{"\u2191", upwards_arrow, upwards_arrow_width, upwards_arrow_height}, // ↑ Upwards Arrow
|
||||
{"\u2191\uFE0E", upwards_arrow, upwards_arrow_width, upwards_arrow_height}, // ↑︎ Upwards Arrow (text)
|
||||
{"\u2191\uFE0F", upwards_arrow, upwards_arrow_width, upwards_arrow_height}, // ↑️ Upwards Arrow (emoji)
|
||||
{"\u2197", north_east_arrow, north_east_arrow_width, north_east_arrow_height}, // ↗ North East Arrow
|
||||
{"\u2197\uFE0E", north_east_arrow, north_east_arrow_width, north_east_arrow_height}, // ↗︎ North East Arrow (text)
|
||||
{"\u2197\uFE0F", north_east_arrow, north_east_arrow_width, north_east_arrow_height}, // ↗️ North East Arrow (emoji)
|
||||
{"\u2192", rightwards_arrow, rightwards_arrow_width, rightwards_arrow_height}, // → Rightwards Arrow
|
||||
{"\u2192\uFE0E", rightwards_arrow, rightwards_arrow_width, rightwards_arrow_height}, // →︎ Rightwards Arrow (text)
|
||||
{"\u2192\uFE0F", rightwards_arrow, rightwards_arrow_width, rightwards_arrow_height}, // →️ Rightwards Arrow (emoji)
|
||||
{"\u2198", south_east_arrow, south_east_arrow_width, south_east_arrow_height}, // ↘ South East Arrow
|
||||
{"\u2198\uFE0E", south_east_arrow, south_east_arrow_width, south_east_arrow_height}, // ↘︎ South East Arrow (text)
|
||||
{"\u2198\uFE0F", south_east_arrow, south_east_arrow_width, south_east_arrow_height}, // ↘️ South East Arrow (emoji)
|
||||
|
||||
// --- Halloween ---
|
||||
{"\U0001F383", jack_o_lantern, jack_o_lantern_width, jack_o_lantern_height}, // 🎃 Jack-O-Lantern
|
||||
{"\U0001F47B", ghost, ghost_width, ghost_height}, // 👻 Ghost
|
||||
{"\U0001F480", skull, skull_width, skull_height} // 💀 Skull
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -88,23 +164,23 @@ const unsigned char thumbdown[] PROGMEM = {0xF0, 0x1F, 0x08, 0x20, 0x06, 0x30, 0
|
||||
0x40, 0x06, 0x70, 0x06, 0x40, 0x06, 0x3F, 0x18, 0x02, 0x20, 0x02,
|
||||
0x40, 0x04, 0x80, 0x04, 0x80, 0x04, 0x00, 0x03, 0x00, 0x00};
|
||||
|
||||
const unsigned char Smiling_Eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52,
|
||||
const unsigned char smiling_eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52,
|
||||
0x4A, 0x02, 0x40, 0x02, 0x40, 0x22, 0x44, 0x22, 0x44, 0xC2, 0x43,
|
||||
0x04, 0x20, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char Grinning[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x22, 0x42,
|
||||
const unsigned char grinning[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x22, 0x42,
|
||||
0x42, 0x02, 0x40, 0x02, 0x40, 0xF2, 0x4F, 0x12, 0x48, 0x22, 0x44,
|
||||
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char Slightly_Smiling[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x22, 0x42,
|
||||
const unsigned char slightly_smiling[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x22, 0x42,
|
||||
0x42, 0x02, 0x40, 0x02, 0x40, 0x12, 0x48, 0x12, 0x48, 0x22, 0x44,
|
||||
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char Winking_Face[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x20, 0x42,
|
||||
const unsigned char winking_face[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x20, 0x42,
|
||||
0x46, 0x02, 0x40, 0x02, 0x40, 0x12, 0x48, 0x12, 0x48, 0x22, 0x44,
|
||||
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char Grinning_Smiling_Eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52,
|
||||
const unsigned char grinning_smiling_eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52,
|
||||
0x4A, 0x02, 0x40, 0xFA, 0x5F, 0x0A, 0x50, 0x0A, 0x50, 0x12, 0x48,
|
||||
0x24, 0x24, 0xC4, 0x23, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
@@ -112,7 +188,7 @@ const unsigned char heart_smile[] PROGMEM = {0x00, 0x00, 0x6C, 0x07, 0x7C, 0x18,
|
||||
0x0A, 0x02, 0xD8, 0x02, 0xF8, 0x22, 0xFC, 0x20, 0x74, 0xDB, 0x23,
|
||||
0x1F, 0x00, 0x1F, 0x20, 0x0E, 0x18, 0xE4, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char Heart_eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x54, 0x2A, 0xFA,
|
||||
const unsigned char heart_eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x54, 0x2A, 0xFA,
|
||||
0x5F, 0x72, 0x4E, 0x22, 0x44, 0x02, 0x40, 0x12, 0x48, 0x12, 0x48,
|
||||
0x24, 0x24, 0xC4, 0x23, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
@@ -128,19 +204,19 @@ const unsigned char haha[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04,
|
||||
0x4A, 0x0A, 0x50, 0x0E, 0x70, 0xF2, 0x4F, 0x12, 0x48, 0x32, 0x44,
|
||||
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char ROFL[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x84, 0x21, 0x84, 0x20, 0x02,
|
||||
const unsigned char rofl[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x84, 0x21, 0x84, 0x20, 0x02,
|
||||
0x4C, 0x02, 0x4A, 0x1A, 0x49, 0x8A, 0x48, 0x42, 0x48, 0x22, 0x44,
|
||||
0xE4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char Smiling_Closed_Eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x42,
|
||||
const unsigned char smiling_closed_eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x42,
|
||||
0x42, 0x22, 0x44, 0x02, 0x40, 0xF2, 0x4F, 0x12, 0x48, 0x22, 0x44,
|
||||
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char Grinning_SmilingEyes2[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52,
|
||||
0x4A, 0x02, 0x40, 0x02, 0x40, 0xF2, 0x4F, 0x12, 0x48, 0x22, 0x44,
|
||||
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
const unsigned char grinning_smiling_eyes_2[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52,
|
||||
0x4A, 0x02, 0x40, 0x02, 0x40, 0xF2, 0x4F, 0x12, 0x48, 0x22, 0x44,
|
||||
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char Loudly_Crying_Face[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x34, 0x2C, 0x4A,
|
||||
const unsigned char loudly_crying_face[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x34, 0x2C, 0x4A,
|
||||
0x52, 0x12, 0x48, 0x12, 0x48, 0x92, 0x49, 0x52, 0x4A, 0x52, 0x4A,
|
||||
0x54, 0x2A, 0x94, 0x29, 0x18, 0x18, 0xF0, 0x0F, 0x00, 0x00};
|
||||
|
||||
@@ -192,7 +268,7 @@ const unsigned char cookie[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04
|
||||
0x40, 0x02, 0x58, 0x82, 0x5B, 0x92, 0x43, 0x82, 0x43, 0x02, 0x40,
|
||||
0x64, 0x28, 0x64, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char Fire[] PROGMEM = {0x30, 0x00, 0xF0, 0x00, 0xF8, 0x03, 0xF8, 0x07, 0xFC, 0x1F, 0xFC,
|
||||
const unsigned char fire[] PROGMEM = {0x30, 0x00, 0xF0, 0x00, 0xF8, 0x03, 0xF8, 0x07, 0xFC, 0x1F, 0xFC,
|
||||
0x1F, 0xFE, 0x3E, 0x7E, 0x3E, 0x3E, 0x7C, 0x1E, 0x78, 0x1E, 0x70,
|
||||
0x1C, 0x70, 0x1C, 0x70, 0x38, 0x38, 0x30, 0x38, 0x60, 0x0C};
|
||||
|
||||
@@ -200,11 +276,11 @@ const unsigned char peace_sign[] PROGMEM = {0xC0, 0x30, 0x40, 0x29, 0x40, 0x25,
|
||||
0x0A, 0x54, 0x68, 0x54, 0x58, 0x54, 0x44, 0x3C, 0x22, 0x04, 0x22,
|
||||
0x04, 0x12, 0x08, 0x10, 0x10, 0x08, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char Praying[] PROGMEM = {0x00, 0x00, 0x40, 0x02, 0xA0, 0x05, 0x90, 0x09, 0x90, 0x09, 0x90,
|
||||
const unsigned char praying[] PROGMEM = {0x00, 0x00, 0x40, 0x02, 0xA0, 0x05, 0x90, 0x09, 0x90, 0x09, 0x90,
|
||||
0x09, 0x98, 0x19, 0x94, 0x29, 0xA4, 0x25, 0xA4, 0x25, 0x84, 0x21,
|
||||
0x84, 0x21, 0x86, 0x61, 0x4E, 0x72, 0x7F, 0x7E, 0x3F, 0xFC};
|
||||
|
||||
const unsigned char Sparkles[] PROGMEM = {0x00, 0x00, 0x10, 0x00, 0x38, 0x04, 0x10, 0x04, 0x00, 0x0E, 0x00,
|
||||
const unsigned char sparkles[] PROGMEM = {0x00, 0x00, 0x10, 0x00, 0x38, 0x04, 0x10, 0x04, 0x00, 0x0E, 0x00,
|
||||
0x1F, 0x80, 0x3F, 0xE0, 0xFF, 0x80, 0x3F, 0x10, 0x1F, 0x10, 0x0E,
|
||||
0x38, 0x04, 0xFE, 0x04, 0x38, 0x00, 0x10, 0x00, 0x10, 0x00};
|
||||
|
||||
@@ -227,7 +303,179 @@ const unsigned char bowling[] PROGMEM = {0x00, 0x38, 0x00, 0x44, 0x00, 0x44, 0x0
|
||||
const unsigned char vulcan_salute[] PROGMEM = {0x08, 0x02, 0x16, 0x0D, 0x15, 0x15, 0x15, 0x15, 0xA9, 0x12, 0x4A,
|
||||
0x0A, 0x02, 0x38, 0x04, 0x48, 0x04, 0x44, 0x04, 0x22, 0x04, 0x22,
|
||||
0x04, 0x12, 0x08, 0x10, 0x10, 0x08, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char jack_o_lantern[] PROGMEM = {0xC0, 0x00, 0x80, 0x01, 0xB8, 0x1D, 0xC4, 0x23, 0x22, 0x44, 0x05,
|
||||
0xA0, 0x31, 0x8C, 0x51, 0x8A, 0x61, 0x86, 0x09, 0x90, 0xB9, 0x9D,
|
||||
0x49, 0x92, 0xB2, 0x4D, 0x42, 0x42, 0x04, 0x20, 0xF8, 0x1F};
|
||||
|
||||
const unsigned char ghost[] PROGMEM = {0xC0, 0x03, 0xF0, 0x0F, 0xF8, 0x1F, 0xDC, 0x3B, 0xBC, 0x3D, 0xDF,
|
||||
0xFB, 0xFF, 0xFF, 0x1F, 0xF8, 0x1E, 0x78, 0x1C, 0x38, 0x3C, 0x3C,
|
||||
0xFC, 0x3F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0x8C, 0x31};
|
||||
|
||||
const unsigned char skull[] PROGMEM = {0xE0, 0x07, 0xF8, 0x1F, 0xFC, 0x3F, 0xFE, 0x7F, 0xFE, 0x7F, 0xC7,
|
||||
0xE3, 0x87, 0xE1, 0x87, 0xE1, 0x8F, 0xF1, 0xFE, 0x7F, 0x7C, 0x3E,
|
||||
0xFC, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xF8, 0x1F, 0xB0, 0x0D};
|
||||
|
||||
const unsigned char vomiting[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x04, 0x20, 0x22,
|
||||
0x44, 0x42, 0x42, 0x22, 0x44, 0x02, 0x40, 0x02, 0x40, 0xC2, 0x43,
|
||||
0x64, 0x26, 0x64, 0x26, 0x68, 0x16, 0x50, 0x0A, 0xF8, 0x1F};
|
||||
|
||||
const unsigned char cool[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0xFC, 0x3F, 0xFA,
|
||||
0x5F, 0x72, 0x4E, 0x02, 0x40, 0x12, 0x48, 0x12, 0x48, 0x22, 0x44,
|
||||
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char shortcake[] PROGMEM = {0x00, 0x00, 0x00, 0x0F, 0x80, 0x3F, 0xE0, 0xFC, 0xE0, 0xE1, 0xF0,
|
||||
0xB8, 0x10, 0x87, 0xC8, 0x80, 0x3C, 0xE0, 0x06, 0x98, 0x02, 0xC7,
|
||||
0xE2, 0x30, 0x1A, 0x0E, 0xC6, 0x01, 0x32, 0x00, 0x0E, 0x00};
|
||||
|
||||
const unsigned char caution[] PROGMEM = {0x00, 0x00, 0x80, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x60, 0x06, 0x60,
|
||||
0x06, 0x70, 0x0E, 0x70, 0x0E, 0x78, 0x1E, 0x78, 0x1E, 0x7C, 0x3E,
|
||||
0xFC, 0x3F, 0x7E, 0x7E, 0x7E, 0x7E, 0xFC, 0x3F, 0x00, 0x00};
|
||||
|
||||
const unsigned char clipboard[] PROGMEM = {0xC0, 0x03, 0x7E, 0x7E, 0xC2, 0x43, 0xFA, 0x5F, 0x0A, 0x5B, 0xFA,
|
||||
0x5F, 0x8A, 0x54, 0xFA, 0x5F, 0x4A, 0x58, 0xFA, 0x5F, 0x2A, 0x51,
|
||||
0xFA, 0x5F, 0x0A, 0x59, 0xFA, 0x5F, 0x02, 0x40, 0xFE, 0x7F};
|
||||
|
||||
const unsigned char snowflake[] PROGMEM = {0x00, 0x00, 0x40, 0x01, 0x88, 0x08, 0x8C, 0x18, 0xD0, 0x05, 0x60,
|
||||
0x03, 0x32, 0x26, 0x1C, 0x1C, 0x32, 0x26, 0x60, 0x03, 0xD0, 0x05,
|
||||
0x8C, 0x18, 0x88, 0x08, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
const unsigned char drop[] PROGMEM = {0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xE0,
|
||||
0x0F, 0xF0, 0x1F, 0xF0, 0x1F, 0xF8, 0x3F, 0xF8, 0x3F, 0xF8, 0x3F,
|
||||
0xF8, 0x3F, 0xF0, 0x1F, 0xE0, 0x0F, 0x80, 0x03, 0x00, 0x00};
|
||||
|
||||
const unsigned char thermometer[] PROGMEM = {0x00, 0x00, 0x0C, 0x00, 0x16, 0x00, 0x2E, 0x00, 0x5C, 0x00, 0xB8,
|
||||
0x00, 0x70, 0x01, 0xE0, 0x02, 0xC0, 0x05, 0x80, 0x3B, 0x00, 0x47,
|
||||
0x00, 0xBE, 0x00, 0x9E, 0x00, 0xBE, 0x00, 0x7C, 0x00, 0x38};
|
||||
|
||||
const unsigned char sun_behind_raincloud[] PROGMEM = {0xC0, 0x03, 0x20, 0x04, 0x10, 0x0E, 0x38, 0x1F, 0xFC, 0x37, 0xEE,
|
||||
0x77, 0xDE, 0x7B, 0x3E, 0x7C, 0xFC, 0x3F, 0x00, 0x00, 0x48, 0x12,
|
||||
0x48, 0x12, 0x24, 0x09, 0x24, 0x09, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
const unsigned char sun_behind_cloud[] PROGMEM = {0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x04, 0x0E, 0x3C, 0x1B, 0xFC,
|
||||
0x3B, 0xFE, 0x7B, 0xFA, 0x7B, 0xF6, 0x7D, 0x0C, 0x3E, 0xF8, 0x1F,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
const unsigned char cloud_with_snow[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, 0x1F, 0xFC, 0x3F, 0xFE,
|
||||
0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFC, 0x3F, 0x00, 0x00, 0x08, 0x02,
|
||||
0x40, 0x10, 0x00, 0x00, 0x24, 0x09, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
const unsigned char cloud_with_lightning[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, 0x1F, 0xFC, 0x3F, 0xFE,
|
||||
0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFC, 0x3F, 0x00, 0x01, 0x80, 0x01,
|
||||
0x80, 0x01, 0xC0, 0x07, 0x00, 0x03, 0x00, 0x03, 0x00, 0x01};
|
||||
|
||||
const unsigned char cloud_with_lightning_rain[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, 0x1F, 0xFC, 0x3F, 0xFE,
|
||||
0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFC, 0x3F, 0x00, 0x01, 0x90, 0x21,
|
||||
0x90, 0x21, 0xC8, 0x17, 0x08, 0x13, 0x00, 0x03, 0x00, 0x01};
|
||||
|
||||
const unsigned char wind_face[] PROGMEM = {0xFF, 0x00, 0x01, 0x01, 0x01, 0x01, 0xF9, 0x00, 0xF9, 0x01, 0xD9,
|
||||
0x01, 0x99, 0x01, 0xF9, 0x01, 0xF9, 0x33, 0xFD, 0x4B, 0xFD, 0x85,
|
||||
0xFD, 0x9A, 0xFD, 0x75, 0xFD, 0x09, 0xFD, 0x01, 0xFF, 0x00};
|
||||
|
||||
const unsigned char new_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x04, 0x20, 0x02,
|
||||
0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40,
|
||||
0x04, 0x20, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char waxing_crescent_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x1F, 0x04, 0x3E, 0x04, 0x3C, 0x02,
|
||||
0x78, 0x02, 0x78, 0x02, 0x78, 0x02, 0x78, 0x02, 0x78, 0x02, 0x78,
|
||||
0x04, 0x3C, 0x04, 0x3E, 0x18, 0x1F, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char first_quarter_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x1F, 0x04, 0x3F, 0x04, 0x3F, 0x02,
|
||||
0x7F, 0x02, 0x7F, 0x02, 0x7F, 0x02, 0x7F, 0x02, 0x7F, 0x02, 0x7F,
|
||||
0x04, 0x3F, 0x04, 0x3F, 0x18, 0x1F, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char waxing_gibbous_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x1F, 0x84, 0x3F, 0xC4, 0x3F, 0xC2,
|
||||
0x7F, 0xC2, 0x7F, 0xC2, 0x7F, 0xC2, 0x7F, 0xC2, 0x7F, 0xC2, 0x7F,
|
||||
0xC4, 0x3F, 0x84, 0x3F, 0x18, 0x1F, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char full_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0xF8, 0x1F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFE,
|
||||
0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F,
|
||||
0xFC, 0x3F, 0xFC, 0x3F, 0xF8, 0x1F, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char waning_gibbous_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0xF8, 0x18, 0xFC, 0x21, 0xFC, 0x23, 0xFE,
|
||||
0x43, 0xFE, 0x43, 0xFE, 0x43, 0xFE, 0x43, 0xFE, 0x43, 0xFE, 0x43,
|
||||
0xFC, 0x23, 0xFC, 0x21, 0xF8, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char last_quarter_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0xF8, 0x18, 0xFC, 0x20, 0xFC, 0x20, 0xFE,
|
||||
0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0x40,
|
||||
0xFC, 0x20, 0xFC, 0x20, 0xF8, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char waning_crescent_moon[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0xF8, 0x18, 0x7C, 0x20, 0x3C, 0x20, 0x1E,
|
||||
0x40, 0x1E, 0x40, 0x1E, 0x40, 0x1E, 0x40, 0x1E, 0x40, 0x1E, 0x40,
|
||||
0x3C, 0x20, 0x7C, 0x20, 0xF8, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||
|
||||
const unsigned char first_quarter_moon_face[] PROGMEM = {0x00, 0x0F, 0x00, 0x12, 0x00, 0x24, 0x00, 0x44, 0x00, 0x48, 0x00,
|
||||
0x88, 0x00, 0x84, 0x80, 0x93, 0x80, 0x80, 0x03, 0x81, 0x8D, 0x80,
|
||||
0x71, 0x40, 0x82, 0x41, 0x02, 0x20, 0x0C, 0x18, 0xF0, 0x07};
|
||||
|
||||
const unsigned char peach[] PROGMEM = {0x70, 0x0F, 0x88, 0x10, 0x78, 0x1F, 0x88, 0x11, 0x04, 0x22, 0x02,
|
||||
0x44, 0x02, 0x44, 0x02, 0x44, 0x02, 0x44, 0x02, 0x42, 0x02, 0x40,
|
||||
0x04, 0x20, 0x04, 0x20, 0x08, 0x10, 0x30, 0x0C, 0xC0, 0x03};
|
||||
|
||||
const unsigned char turkey[] PROGMEM = {0x00, 0x00, 0x38, 0x00, 0x44, 0x38, 0x56, 0x54, 0x45, 0x52, 0xE2,
|
||||
0x21, 0x2C, 0x56, 0x14, 0x58, 0x0A, 0x37, 0x86, 0x68, 0x82, 0x50,
|
||||
0x82, 0x20, 0x04, 0x41, 0xF8, 0x7F, 0x40, 0x02, 0xF0, 0x07};
|
||||
|
||||
const unsigned char turkey_leg[] PROGMEM = {0x0C, 0x00, 0x1E, 0x00, 0x1F, 0x00, 0x2F, 0x00, 0x46, 0x00, 0x88,
|
||||
0x01, 0x10, 0x0E, 0x20, 0x30, 0x20, 0x40, 0x40, 0x40, 0x40, 0x80,
|
||||
0x40, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x43, 0x00, 0x3C};
|
||||
|
||||
const unsigned char south_west_arrow[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1C, 0x00, 0x3E, 0x00,
|
||||
0x1F, 0x80, 0x0F, 0xC2, 0x07, 0xE6, 0x03, 0xFE, 0x01, 0xFE, 0x00,
|
||||
0x7E, 0x00, 0x7E, 0x00, 0xFE, 0x00, 0xFE, 0x01, 0x00, 0x00};
|
||||
|
||||
const unsigned char south_east_arrow[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x00, 0x7C, 0x00, 0xF8,
|
||||
0x00, 0xF0, 0x01, 0xE0, 0x43, 0xC0, 0x67, 0x80, 0x7F, 0x00, 0x7F,
|
||||
0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7F, 0x80, 0x7F, 0x00, 0x00};
|
||||
|
||||
const unsigned char north_west_arrow[] PROGMEM = {0x00, 0x00, 0xFE, 0x01, 0xFE, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0xFE,
|
||||
0x00, 0xFE, 0x01, 0xE6, 0x03, 0xC2, 0x07, 0x80, 0x0F, 0x00, 0x1F,
|
||||
0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
const unsigned char north_east_arrow[] PROGMEM = {0x00, 0x00, 0x80, 0x7F, 0x00, 0x7F, 0x00, 0x7E, 0x00, 0x7E, 0x00,
|
||||
0x7F, 0x80, 0x7F, 0xC0, 0x67, 0xE0, 0x43, 0xF0, 0x01, 0xF8, 0x00,
|
||||
0x7C, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
const unsigned char downwards_arrow[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0,
|
||||
0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xFC, 0x3F,
|
||||
0xF8, 0x1F, 0xF0, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01};
|
||||
|
||||
const unsigned char leftwards_arrow[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x38, 0x00, 0x3C,
|
||||
0x00, 0xFE, 0x3F, 0xFF, 0x3F, 0xFF, 0x3F, 0xFE, 0x3F, 0x3C, 0x00,
|
||||
0x38, 0x00, 0x30, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
const unsigned char upwards_arrow[] PROGMEM = {0x80, 0x01, 0xC0, 0x03, 0xE0, 0x07, 0xF0, 0x0F, 0xF8, 0x1F, 0xFC,
|
||||
0x3F, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03,
|
||||
0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
const unsigned char rightwards_arrow[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x1C, 0x00,
|
||||
0x3C, 0xFC, 0x7F, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0x7F, 0x00, 0x3C,
|
||||
0x00, 0x1C, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
const unsigned char strong[] PROGMEM = {0x38, 0x00, 0x44, 0x00, 0x62, 0x00, 0x42, 0x00, 0x42, 0x00, 0x3A,
|
||||
0x00, 0x11, 0x3C, 0x11, 0x42, 0xD1, 0x81, 0x31, 0x82, 0x11, 0x82,
|
||||
0x21, 0x80, 0x01, 0x80, 0x01, 0x80, 0x02, 0x40, 0xFC, 0x3F};
|
||||
|
||||
const unsigned char check_mark[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x70, 0x00, 0x3C, 0x00,
|
||||
0x1E, 0x00, 0x0F, 0x80, 0x07, 0xC3, 0x03, 0xEE, 0x03, 0xFC, 0x01,
|
||||
0xF8, 0x00, 0xF0, 0x00, 0x70, 0x00, 0x60, 0x00, 0x20, 0x00};
|
||||
|
||||
const unsigned char house[] PROGMEM = {0x80, 0x01, 0x5C, 0x02, 0x34, 0x04, 0x14, 0x08, 0x0C, 0x10, 0x04,
|
||||
0x20, 0x02, 0x40, 0xFF, 0xFF, 0x02, 0x40, 0x7A, 0x5F, 0x4A, 0x55,
|
||||
0x4A, 0x5F, 0x6A, 0x55, 0x4A, 0x5F, 0x4A, 0x40, 0xFE, 0x7F};
|
||||
|
||||
const unsigned char shrug[] PROGMEM = {0xC0, 0x03, 0x20, 0x04, 0x10, 0x08, 0x50, 0x0A, 0x10, 0x08, 0x90,
|
||||
0x09, 0x27, 0xE4, 0x49, 0x92, 0xAA, 0x55, 0x16, 0x68, 0x12, 0x48,
|
||||
0x02, 0x40, 0x02, 0x40, 0x0C, 0x30, 0x08, 0x10, 0xF8, 0x1F};
|
||||
|
||||
const unsigned char eyes[] PROGMEM = {0x00, 0x00, 0x3C, 0x3C, 0x42, 0x42, 0x81, 0x81, 0x85, 0x85, 0x8F,
|
||||
0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F,
|
||||
0x85, 0x85, 0x81, 0x81, 0x42, 0x42, 0x3C, 0x3C, 0x00, 0x00};
|
||||
|
||||
const unsigned char eye[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x07, 0xF8, 0x1F, 0xF4,
|
||||
0x2F, 0x7A, 0x5E, 0x39, 0x9C, 0x39, 0x9C, 0x7A, 0x5E, 0xF4, 0x2F,
|
||||
0xF8, 0x1F, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
#endif
|
||||
|
||||
} // namespace graphics
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -22,33 +22,33 @@ extern const int numEmotes;
|
||||
extern const unsigned char thumbup[] PROGMEM;
|
||||
extern const unsigned char thumbdown[] PROGMEM;
|
||||
|
||||
#define Smiling_Eyes_height 16
|
||||
#define Smiling_Eyes_width 16
|
||||
extern const unsigned char Smiling_Eyes[] PROGMEM;
|
||||
#define smiling_eyes_height 16
|
||||
#define smiling_eyes_width 16
|
||||
extern const unsigned char smiling_eyes[] PROGMEM;
|
||||
|
||||
#define Grinning_height 16
|
||||
#define Grinning_width 16
|
||||
extern const unsigned char Grinning[] PROGMEM;
|
||||
#define grinning_height 16
|
||||
#define grinning_width 16
|
||||
extern const unsigned char grinning[] PROGMEM;
|
||||
|
||||
#define Slightly_Smiling_height 16
|
||||
#define Slightly_Smiling_width 16
|
||||
extern const unsigned char Slightly_Smiling[] PROGMEM;
|
||||
#define slightly_smiling_height 16
|
||||
#define slightly_smiling_width 16
|
||||
extern const unsigned char slightly_smiling[] PROGMEM;
|
||||
|
||||
#define Winking_Face_height 16
|
||||
#define Winking_Face_width 16
|
||||
extern const unsigned char Winking_Face[] PROGMEM;
|
||||
#define winking_face_height 16
|
||||
#define winking_face_width 16
|
||||
extern const unsigned char winking_face[] PROGMEM;
|
||||
|
||||
#define Grinning_Smiling_Eyes_height 16
|
||||
#define Grinning_Smiling_Eyes_width 16
|
||||
extern const unsigned char Grinning_Smiling_Eyes[] PROGMEM;
|
||||
#define grinning_smiling_eyes_height 16
|
||||
#define grinning_smiling_eyes_width 16
|
||||
extern const unsigned char grinning_smiling_eyes[] PROGMEM;
|
||||
|
||||
#define heart_smile_height 16
|
||||
#define heart_smile_width 16
|
||||
extern const unsigned char heart_smile[] PROGMEM;
|
||||
|
||||
#define Heart_eyes_height 16
|
||||
#define Heart_eyes_width 16
|
||||
extern const unsigned char Heart_eyes[] PROGMEM;
|
||||
#define heart_eyes_height 16
|
||||
#define heart_eyes_width 16
|
||||
extern const unsigned char heart_eyes[] PROGMEM;
|
||||
|
||||
#define question_height 16
|
||||
#define question_width 16
|
||||
@@ -62,21 +62,21 @@ extern const unsigned char bang[] PROGMEM;
|
||||
#define haha_width 16
|
||||
extern const unsigned char haha[] PROGMEM;
|
||||
|
||||
#define ROFL_height 16
|
||||
#define ROFL_width 16
|
||||
extern const unsigned char ROFL[] PROGMEM;
|
||||
#define rofl_height 16
|
||||
#define rofl_width 16
|
||||
extern const unsigned char rofl[] PROGMEM;
|
||||
|
||||
#define Smiling_Closed_Eyes_height 16
|
||||
#define Smiling_Closed_Eyes_width 16
|
||||
extern const unsigned char Smiling_Closed_Eyes[] PROGMEM;
|
||||
#define smiling_closed_eyes_height 16
|
||||
#define smiling_closed_eyes_width 16
|
||||
extern const unsigned char smiling_closed_eyes[] PROGMEM;
|
||||
|
||||
#define Grinning_SmilingEyes2_height 16
|
||||
#define Grinning_SmilingEyes2_width 16
|
||||
extern const unsigned char Grinning_SmilingEyes2[] PROGMEM;
|
||||
#define grinning_smiling_eyes_2_height 16
|
||||
#define grinning_smiling_eyes_2_width 16
|
||||
extern const unsigned char grinning_smiling_eyes_2[] PROGMEM;
|
||||
|
||||
#define Loudly_Crying_Face_height 16
|
||||
#define Loudly_Crying_Face_width 16
|
||||
extern const unsigned char Loudly_Crying_Face[] PROGMEM;
|
||||
#define loudly_crying_face_height 16
|
||||
#define loudly_crying_face_width 16
|
||||
extern const unsigned char loudly_crying_face[] PROGMEM;
|
||||
|
||||
#define wave_icon_height 16
|
||||
#define wave_icon_width 16
|
||||
@@ -126,21 +126,21 @@ extern const unsigned char bell_icon[] PROGMEM;
|
||||
#define cookie_height 16
|
||||
extern const unsigned char cookie[] PROGMEM;
|
||||
|
||||
#define Fire_width 16
|
||||
#define Fire_height 16
|
||||
extern const unsigned char Fire[] PROGMEM;
|
||||
#define fire_width 16
|
||||
#define fire_height 16
|
||||
extern const unsigned char fire[] PROGMEM;
|
||||
|
||||
#define peace_sign_width 16
|
||||
#define peace_sign_height 16
|
||||
extern const unsigned char peace_sign[] PROGMEM;
|
||||
|
||||
#define Praying_width 16
|
||||
#define Praying_height 16
|
||||
extern const unsigned char Praying[] PROGMEM;
|
||||
#define praying_width 16
|
||||
#define praying_height 16
|
||||
extern const unsigned char praying[] PROGMEM;
|
||||
|
||||
#define Sparkles_width 16
|
||||
#define Sparkles_height 16
|
||||
extern const unsigned char Sparkles[] PROGMEM;
|
||||
#define sparkles_width 16
|
||||
#define sparkles_height 16
|
||||
extern const unsigned char sparkles[] PROGMEM;
|
||||
|
||||
#define clown_width 16
|
||||
#define clown_height 16
|
||||
@@ -161,6 +161,178 @@ extern const unsigned char bowling[] PROGMEM;
|
||||
#define vulcan_salute_width 16
|
||||
#define vulcan_salute_height 16
|
||||
extern const unsigned char vulcan_salute[] PROGMEM;
|
||||
|
||||
#define jack_o_lantern_width 16
|
||||
#define jack_o_lantern_height 16
|
||||
extern const unsigned char jack_o_lantern[] PROGMEM;
|
||||
|
||||
#define ghost_width 16
|
||||
#define ghost_height 16
|
||||
extern const unsigned char ghost[] PROGMEM;
|
||||
|
||||
#define skull_width 16
|
||||
#define skull_height 16
|
||||
extern const unsigned char skull[] PROGMEM;
|
||||
|
||||
#define vomiting_width 16
|
||||
#define vomiting_height 16
|
||||
extern const unsigned char vomiting[] PROGMEM;
|
||||
|
||||
#define cool_width 16
|
||||
#define cool_height 16
|
||||
extern const unsigned char cool[] PROGMEM;
|
||||
|
||||
#define shortcake_width 16
|
||||
#define shortcake_height 16
|
||||
extern const unsigned char shortcake[] PROGMEM;
|
||||
|
||||
#define caution_width 16
|
||||
#define caution_height 16
|
||||
extern const unsigned char caution[] PROGMEM;
|
||||
|
||||
#define clipboard_width 16
|
||||
#define clipboard_height 16
|
||||
extern const unsigned char clipboard[] PROGMEM;
|
||||
|
||||
#define snowflake_width 16
|
||||
#define snowflake_height 16
|
||||
extern const unsigned char snowflake[] PROGMEM;
|
||||
|
||||
#define drop_width 16
|
||||
#define drop_height 16
|
||||
extern const unsigned char drop[] PROGMEM;
|
||||
|
||||
#define thermometer_width 16
|
||||
#define thermometer_height 16
|
||||
extern const unsigned char thermometer[] PROGMEM;
|
||||
|
||||
#define sun_behind_raincloud_width 16
|
||||
#define sun_behind_raincloud_height 16
|
||||
extern const unsigned char sun_behind_raincloud[] PROGMEM;
|
||||
|
||||
#define sun_behind_cloud_width 16
|
||||
#define sun_behind_cloud_height 16
|
||||
extern const unsigned char sun_behind_cloud[] PROGMEM;
|
||||
|
||||
#define cloud_with_snow_width 16
|
||||
#define cloud_with_snow_height 16
|
||||
extern const unsigned char cloud_with_snow[] PROGMEM;
|
||||
|
||||
#define cloud_with_lightning_width 16
|
||||
#define cloud_with_lightning_height 16
|
||||
extern const unsigned char cloud_with_lightning[] PROGMEM;
|
||||
|
||||
#define cloud_with_lightning_rain_width 16
|
||||
#define cloud_with_lightning_rain_height 16
|
||||
extern const unsigned char cloud_with_lightning_rain[] PROGMEM;
|
||||
|
||||
#define wind_face_width 16
|
||||
#define wind_face_height 16
|
||||
extern const unsigned char wind_face[] PROGMEM;
|
||||
|
||||
#define new_moon_width 16
|
||||
#define new_moon_height 16
|
||||
extern const unsigned char new_moon[] PROGMEM;
|
||||
|
||||
#define waxing_crescent_moon_width 16
|
||||
#define waxing_crescent_moon_height 16
|
||||
extern const unsigned char waxing_crescent_moon[] PROGMEM;
|
||||
|
||||
#define first_quarter_moon_width 16
|
||||
#define first_quarter_moon_height 16
|
||||
extern const unsigned char first_quarter_moon[] PROGMEM;
|
||||
|
||||
#define waxing_gibbous_moon_width 16
|
||||
#define waxing_gibbous_moon_height 16
|
||||
extern const unsigned char waxing_gibbous_moon[] PROGMEM;
|
||||
|
||||
#define full_moon_width 16
|
||||
#define full_moon_height 16
|
||||
extern const unsigned char full_moon[] PROGMEM;
|
||||
|
||||
#define waning_gibbous_moon_width 16
|
||||
#define waning_gibbous_moon_height 16
|
||||
extern const unsigned char waning_gibbous_moon[] PROGMEM;
|
||||
|
||||
#define last_quarter_moon_width 16
|
||||
#define last_quarter_moon_height 16
|
||||
extern const unsigned char last_quarter_moon[] PROGMEM;
|
||||
|
||||
#define waning_crescent_moon_width 16
|
||||
#define waning_crescent_moon_height 16
|
||||
extern const unsigned char waning_crescent_moon[] PROGMEM;
|
||||
|
||||
#define first_quarter_moon_face_width 16
|
||||
#define first_quarter_moon_face_height 16
|
||||
extern const unsigned char first_quarter_moon_face[] PROGMEM;
|
||||
|
||||
#define peach_width 16
|
||||
#define peach_height 16
|
||||
extern const unsigned char peach[] PROGMEM;
|
||||
|
||||
#define turkey_width 16
|
||||
#define turkey_height 16
|
||||
extern const unsigned char turkey[] PROGMEM;
|
||||
|
||||
#define turkey_leg_width 16
|
||||
#define turkey_leg_height 16
|
||||
extern const unsigned char turkey_leg[] PROGMEM;
|
||||
|
||||
#define south_west_arrow_width 16
|
||||
#define south_west_arrow_height 16
|
||||
extern const unsigned char south_west_arrow[] PROGMEM;
|
||||
|
||||
#define south_east_arrow_width 16
|
||||
#define south_east_arrow_height 16
|
||||
extern const unsigned char south_east_arrow[] PROGMEM;
|
||||
|
||||
#define north_west_arrow_width 16
|
||||
#define north_west_arrow_height 16
|
||||
extern const unsigned char north_west_arrow[] PROGMEM;
|
||||
|
||||
#define north_east_arrow_width 16
|
||||
#define north_east_arrow_height 16
|
||||
extern const unsigned char north_east_arrow[] PROGMEM;
|
||||
|
||||
#define downwards_arrow_width 16
|
||||
#define downwards_arrow_height 16
|
||||
extern const unsigned char downwards_arrow[] PROGMEM;
|
||||
|
||||
#define leftwards_arrow_width 16
|
||||
#define leftwards_arrow_height 16
|
||||
extern const unsigned char leftwards_arrow[] PROGMEM;
|
||||
|
||||
#define upwards_arrow_width 16
|
||||
#define upwards_arrow_height 16
|
||||
extern const unsigned char upwards_arrow[] PROGMEM;
|
||||
|
||||
#define rightwards_arrow_width 16
|
||||
#define rightwards_arrow_height 16
|
||||
extern const unsigned char rightwards_arrow[] PROGMEM;
|
||||
|
||||
#define strong_width 16
|
||||
#define strong_height 16
|
||||
extern const unsigned char strong[] PROGMEM;
|
||||
|
||||
#define check_mark_width 16
|
||||
#define check_mark_height 16
|
||||
extern const unsigned char check_mark[] PROGMEM;
|
||||
|
||||
#define house_width 16
|
||||
#define house_height 16
|
||||
extern const unsigned char house[] PROGMEM;
|
||||
|
||||
#define shrug_width 16
|
||||
#define shrug_height 16
|
||||
extern const unsigned char shrug[] PROGMEM;
|
||||
|
||||
#define eyes_width 16
|
||||
#define eyes_height 16
|
||||
extern const unsigned char eyes[] PROGMEM;
|
||||
|
||||
#define eye_width 16
|
||||
#define eye_height 16
|
||||
extern const unsigned char eye[] PROGMEM;
|
||||
#endif // EXCLUDE_EMOJI
|
||||
|
||||
} // namespace graphics
|
||||
} // namespace graphics
|
||||
|
||||
429
src/graphics/fonts/OLEDDisplayFontsGR.cpp
Normal file
429
src/graphics/fonts/OLEDDisplayFontsGR.cpp
Normal file
@@ -0,0 +1,429 @@
|
||||
#ifdef OLED_GR
|
||||
|
||||
#include "OLEDDisplayFontsGR.h"
|
||||
|
||||
/**
|
||||
* Greek font for OLED displays - ArialMT Plain 10pt
|
||||
* Contains ASCII 32-127 + Greek characters mapped to CP-1253 positions (192-254)
|
||||
*
|
||||
* Generated using ThingPulse OLED font converter
|
||||
* Font: Arial, Size: 10px
|
||||
* Character set: Basic Latin + Greek (Α-Ω, α-ω, accented)
|
||||
*
|
||||
* CP-1253 Greek character mapping:
|
||||
* 193-209: Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ
|
||||
* 211-217: Σ Τ Υ Φ Χ Ψ Ω
|
||||
* 225-241: α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ
|
||||
* 242-249: ς σ τ υ φ χ ψ ω
|
||||
*/
|
||||
const uint8_t ArialMT_Plain_10_GR[] PROGMEM = {
|
||||
0x0A, // Width: 10
|
||||
0x0D, // Height: 13
|
||||
0x20, // First char: 32
|
||||
0xE0, // Number of chars: 224
|
||||
|
||||
// Jump Table (4 bytes per character: offset high, offset low, size, width)
|
||||
// Characters 32-127: Standard ASCII
|
||||
0xFF, 0xFF, 0x00, 0x03, // 32 space
|
||||
0x00, 0x00, 0x04, 0x03, // 33 !
|
||||
0x00, 0x04, 0x05, 0x04, // 34 "
|
||||
0x00, 0x09, 0x09, 0x06, // 35 #
|
||||
0x00, 0x12, 0x0A, 0x06, // 36 $
|
||||
0x00, 0x1C, 0x10, 0x09, // 37 %
|
||||
0x00, 0x2C, 0x0E, 0x08, // 38 &
|
||||
0x00, 0x3A, 0x01, 0x02, // 39 '
|
||||
0x00, 0x3B, 0x06, 0x04, // 40 (
|
||||
0x00, 0x41, 0x06, 0x04, // 41 )
|
||||
0x00, 0x47, 0x05, 0x04, // 42 *
|
||||
0x00, 0x4C, 0x09, 0x06, // 43 +
|
||||
0x00, 0x55, 0x04, 0x03, // 44 ,
|
||||
0x00, 0x59, 0x03, 0x03, // 45 -
|
||||
0x00, 0x5C, 0x04, 0x03, // 46 .
|
||||
0x00, 0x60, 0x05, 0x04, // 47 /
|
||||
0x00, 0x65, 0x0A, 0x06, // 48 0
|
||||
0x00, 0x6F, 0x08, 0x05, // 49 1
|
||||
0x00, 0x77, 0x0A, 0x06, // 50 2
|
||||
0x00, 0x81, 0x0A, 0x06, // 51 3
|
||||
0x00, 0x8B, 0x0B, 0x07, // 52 4
|
||||
0x00, 0x96, 0x0A, 0x06, // 53 5
|
||||
0x00, 0xA0, 0x0A, 0x06, // 54 6
|
||||
0x00, 0xAA, 0x09, 0x06, // 55 7
|
||||
0x00, 0xB3, 0x0A, 0x06, // 56 8
|
||||
0x00, 0xBD, 0x0A, 0x06, // 57 9
|
||||
0x00, 0xC7, 0x04, 0x03, // 58 :
|
||||
0x00, 0xCB, 0x04, 0x03, // 59 ;
|
||||
0x00, 0xCF, 0x0A, 0x06, // 60 <
|
||||
0x00, 0xD9, 0x09, 0x06, // 61 =
|
||||
0x00, 0xE2, 0x09, 0x06, // 62 >
|
||||
0x00, 0xEB, 0x0B, 0x07, // 63 ?
|
||||
0x00, 0xF6, 0x14, 0x0B, // 64 @
|
||||
0x01, 0x0A, 0x0E, 0x08, // 65 A
|
||||
0x01, 0x18, 0x0C, 0x07, // 66 B
|
||||
0x01, 0x24, 0x0C, 0x07, // 67 C
|
||||
0x01, 0x30, 0x0B, 0x07, // 68 D
|
||||
0x01, 0x3B, 0x0C, 0x07, // 69 E
|
||||
0x01, 0x47, 0x09, 0x06, // 70 F
|
||||
0x01, 0x50, 0x0D, 0x08, // 71 G
|
||||
0x01, 0x5D, 0x0C, 0x07, // 72 H
|
||||
0x01, 0x69, 0x04, 0x03, // 73 I
|
||||
0x01, 0x6D, 0x08, 0x05, // 74 J
|
||||
0x01, 0x75, 0x0E, 0x08, // 75 K
|
||||
0x01, 0x83, 0x0C, 0x07, // 76 L
|
||||
0x01, 0x8F, 0x10, 0x09, // 77 M
|
||||
0x01, 0x9F, 0x0C, 0x07, // 78 N
|
||||
0x01, 0xAB, 0x0E, 0x08, // 79 O
|
||||
0x01, 0xB9, 0x0B, 0x07, // 80 P
|
||||
0x01, 0xC4, 0x0E, 0x08, // 81 Q
|
||||
0x01, 0xD2, 0x0C, 0x07, // 82 R
|
||||
0x01, 0xDE, 0x0C, 0x07, // 83 S
|
||||
0x01, 0xEA, 0x0B, 0x07, // 84 T
|
||||
0x01, 0xF5, 0x0C, 0x07, // 85 U
|
||||
0x02, 0x01, 0x0D, 0x08, // 86 V
|
||||
0x02, 0x0E, 0x11, 0x0A, // 87 W
|
||||
0x02, 0x1F, 0x0E, 0x08, // 88 X
|
||||
0x02, 0x2D, 0x0D, 0x08, // 89 Y
|
||||
0x02, 0x3A, 0x0C, 0x07, // 90 Z
|
||||
0x02, 0x46, 0x06, 0x04, // 91 [
|
||||
0x02, 0x4C, 0x06, 0x04, // 92 backslash
|
||||
0x02, 0x52, 0x04, 0x03, // 93 ]
|
||||
0x02, 0x56, 0x09, 0x06, // 94 ^
|
||||
0x02, 0x5F, 0x0C, 0x07, // 95 _
|
||||
0x02, 0x6B, 0x03, 0x03, // 96 `
|
||||
0x02, 0x6E, 0x0A, 0x06, // 97 a
|
||||
0x02, 0x78, 0x0A, 0x06, // 98 b
|
||||
0x02, 0x82, 0x0A, 0x06, // 99 c
|
||||
0x02, 0x8C, 0x0A, 0x06, // 100 d
|
||||
0x02, 0x96, 0x0A, 0x06, // 101 e
|
||||
0x02, 0xA0, 0x05, 0x04, // 102 f
|
||||
0x02, 0xA5, 0x0A, 0x06, // 103 g
|
||||
0x02, 0xAF, 0x0A, 0x06, // 104 h
|
||||
0x02, 0xB9, 0x04, 0x03, // 105 i
|
||||
0x02, 0xBD, 0x04, 0x03, // 106 j
|
||||
0x02, 0xC1, 0x08, 0x05, // 107 k
|
||||
0x02, 0xC9, 0x04, 0x03, // 108 l
|
||||
0x02, 0xCD, 0x10, 0x09, // 109 m
|
||||
0x02, 0xDD, 0x0A, 0x06, // 110 n
|
||||
0x02, 0xE7, 0x0A, 0x06, // 111 o
|
||||
0x02, 0xF1, 0x0A, 0x06, // 112 p
|
||||
0x02, 0xFB, 0x0A, 0x06, // 113 q
|
||||
0x03, 0x05, 0x05, 0x04, // 114 r
|
||||
0x03, 0x0A, 0x08, 0x05, // 115 s
|
||||
0x03, 0x12, 0x06, 0x04, // 116 t
|
||||
0x03, 0x18, 0x0A, 0x06, // 117 u
|
||||
0x03, 0x22, 0x09, 0x06, // 118 v
|
||||
0x03, 0x2B, 0x0E, 0x08, // 119 w
|
||||
0x03, 0x39, 0x0A, 0x06, // 120 x
|
||||
0x03, 0x43, 0x09, 0x06, // 121 y
|
||||
0x03, 0x4C, 0x0A, 0x06, // 122 z
|
||||
0x03, 0x56, 0x06, 0x04, // 123 {
|
||||
0x03, 0x5C, 0x04, 0x03, // 124 |
|
||||
0x03, 0x60, 0x05, 0x04, // 125 }
|
||||
0x03, 0x65, 0x09, 0x06, // 126 ~
|
||||
0xFF, 0xFF, 0x00, 0x03, // 127
|
||||
// Characters 128-191: Placeholders (extended ASCII)
|
||||
0xFF, 0xFF, 0x00, 0x03, // 128
|
||||
0xFF, 0xFF, 0x00, 0x03, // 129
|
||||
0xFF, 0xFF, 0x00, 0x03, // 130
|
||||
0xFF, 0xFF, 0x00, 0x03, // 131
|
||||
0xFF, 0xFF, 0x00, 0x03, // 132
|
||||
0xFF, 0xFF, 0x00, 0x03, // 133
|
||||
0xFF, 0xFF, 0x00, 0x03, // 134
|
||||
0xFF, 0xFF, 0x00, 0x03, // 135
|
||||
0xFF, 0xFF, 0x00, 0x03, // 136
|
||||
0xFF, 0xFF, 0x00, 0x03, // 137
|
||||
0xFF, 0xFF, 0x00, 0x03, // 138
|
||||
0xFF, 0xFF, 0x00, 0x03, // 139
|
||||
0xFF, 0xFF, 0x00, 0x03, // 140
|
||||
0xFF, 0xFF, 0x00, 0x03, // 141
|
||||
0xFF, 0xFF, 0x00, 0x03, // 142
|
||||
0xFF, 0xFF, 0x00, 0x03, // 143
|
||||
0xFF, 0xFF, 0x00, 0x03, // 144
|
||||
0xFF, 0xFF, 0x00, 0x03, // 145
|
||||
0xFF, 0xFF, 0x00, 0x03, // 146
|
||||
0xFF, 0xFF, 0x00, 0x03, // 147
|
||||
0xFF, 0xFF, 0x00, 0x03, // 148
|
||||
0xFF, 0xFF, 0x00, 0x03, // 149
|
||||
0xFF, 0xFF, 0x00, 0x03, // 150
|
||||
0xFF, 0xFF, 0x00, 0x03, // 151
|
||||
0xFF, 0xFF, 0x00, 0x03, // 152
|
||||
0xFF, 0xFF, 0x00, 0x03, // 153
|
||||
0xFF, 0xFF, 0x00, 0x03, // 154
|
||||
0xFF, 0xFF, 0x00, 0x03, // 155
|
||||
0xFF, 0xFF, 0x00, 0x03, // 156
|
||||
0xFF, 0xFF, 0x00, 0x03, // 157
|
||||
0xFF, 0xFF, 0x00, 0x03, // 158
|
||||
0xFF, 0xFF, 0x00, 0x03, // 159
|
||||
0xFF, 0xFF, 0x00, 0x03, // 160
|
||||
0xFF, 0xFF, 0x00, 0x03, // 161
|
||||
0xFF, 0xFF, 0x00, 0x03, // 162
|
||||
0xFF, 0xFF, 0x00, 0x03, // 163
|
||||
0xFF, 0xFF, 0x00, 0x03, // 164
|
||||
0xFF, 0xFF, 0x00, 0x03, // 165
|
||||
0xFF, 0xFF, 0x00, 0x03, // 166
|
||||
0xFF, 0xFF, 0x00, 0x03, // 167
|
||||
0xFF, 0xFF, 0x00, 0x03, // 168
|
||||
0xFF, 0xFF, 0x00, 0x03, // 169
|
||||
0xFF, 0xFF, 0x00, 0x03, // 170
|
||||
0xFF, 0xFF, 0x00, 0x03, // 171
|
||||
0xFF, 0xFF, 0x00, 0x03, // 172
|
||||
0xFF, 0xFF, 0x00, 0x03, // 173
|
||||
0xFF, 0xFF, 0x00, 0x03, // 174
|
||||
0xFF, 0xFF, 0x00, 0x03, // 175
|
||||
0xFF, 0xFF, 0x00, 0x03, // 176
|
||||
0xFF, 0xFF, 0x00, 0x03, // 177
|
||||
0xFF, 0xFF, 0x00, 0x03, // 178
|
||||
0xFF, 0xFF, 0x00, 0x03, // 179
|
||||
0xFF, 0xFF, 0x00, 0x03, // 180
|
||||
0xFF, 0xFF, 0x00, 0x03, // 181
|
||||
0xFF, 0xFF, 0x00, 0x03, // 182
|
||||
0xFF, 0xFF, 0x00, 0x03, // 183
|
||||
0xFF, 0xFF, 0x00, 0x03, // 184
|
||||
0xFF, 0xFF, 0x00, 0x03, // 185
|
||||
0xFF, 0xFF, 0x00, 0x03, // 186
|
||||
0xFF, 0xFF, 0x00, 0x03, // 187
|
||||
0xFF, 0xFF, 0x00, 0x03, // 188
|
||||
0xFF, 0xFF, 0x00, 0x03, // 189
|
||||
0xFF, 0xFF, 0x00, 0x03, // 190
|
||||
0xFF, 0xFF, 0x00, 0x03, // 191
|
||||
// Characters 192-255: Greek letters (CP-1253 positions)
|
||||
0xFF, 0xFF, 0x00, 0x03, // 192 (unused)
|
||||
0x03, 0x6E, 0x0E, 0x08, // 193 Α Alpha
|
||||
0x03, 0x7C, 0x0C, 0x07, // 194 Β Beta
|
||||
0x03, 0x88, 0x09, 0x06, // 195 Γ Gamma
|
||||
0x03, 0x91, 0x0C, 0x07, // 196 Δ Delta
|
||||
0x03, 0x9D, 0x0C, 0x07, // 197 Ε Epsilon
|
||||
0x03, 0xA9, 0x0A, 0x06, // 198 Ζ Zeta
|
||||
0x03, 0xB3, 0x0C, 0x07, // 199 Η Eta
|
||||
0x03, 0xBF, 0x0E, 0x08, // 200 Θ Theta
|
||||
0x03, 0xCD, 0x04, 0x03, // 201 Ι Iota
|
||||
0x03, 0xD1, 0x0E, 0x08, // 202 Κ Kappa
|
||||
0x03, 0xDF, 0x0E, 0x08, // 203 Λ Lambda
|
||||
0x03, 0xED, 0x10, 0x09, // 204 Μ Mu
|
||||
0x03, 0xFD, 0x0C, 0x07, // 205 Ν Nu
|
||||
0x04, 0x09, 0x0C, 0x07, // 206 Ξ Xi
|
||||
0x04, 0x15, 0x0E, 0x08, // 207 Ο Omicron
|
||||
0x04, 0x23, 0x0C, 0x07, // 208 Π Pi
|
||||
0x04, 0x2F, 0x0B, 0x07, // 209 Ρ Rho
|
||||
0xFF, 0xFF, 0x00, 0x03, // 210 (unused)
|
||||
0x04, 0x3A, 0x0C, 0x07, // 211 Σ Sigma
|
||||
0x04, 0x46, 0x0B, 0x07, // 212 Τ Tau
|
||||
0x04, 0x51, 0x0D, 0x08, // 213 Υ Upsilon
|
||||
0x04, 0x5E, 0x0E, 0x08, // 214 Φ Phi
|
||||
0x04, 0x6C, 0x0E, 0x08, // 215 Χ Chi
|
||||
0x04, 0x7A, 0x0E, 0x08, // 216 Ψ Psi
|
||||
0x04, 0x88, 0x0E, 0x08, // 217 Ω Omega
|
||||
0xFF, 0xFF, 0x00, 0x03, // 218
|
||||
0xFF, 0xFF, 0x00, 0x03, // 219
|
||||
0xFF, 0xFF, 0x00, 0x03, // 220
|
||||
0xFF, 0xFF, 0x00, 0x03, // 221
|
||||
0xFF, 0xFF, 0x00, 0x03, // 222
|
||||
0xFF, 0xFF, 0x00, 0x03, // 223
|
||||
0xFF, 0xFF, 0x00, 0x03, // 224
|
||||
0x04, 0x96, 0x0A, 0x06, // 225 α alpha
|
||||
0x04, 0xA0, 0x0A, 0x06, // 226 β beta
|
||||
0x04, 0xAA, 0x09, 0x06, // 227 γ gamma
|
||||
0x04, 0xB3, 0x0A, 0x06, // 228 δ delta
|
||||
0x04, 0xBD, 0x08, 0x05, // 229 ε epsilon
|
||||
0x04, 0xC5, 0x08, 0x05, // 230 ζ zeta
|
||||
0x04, 0xCD, 0x0A, 0x06, // 231 η eta
|
||||
0x04, 0xD7, 0x0A, 0x06, // 232 θ theta
|
||||
0x04, 0xE1, 0x04, 0x03, // 233 ι iota
|
||||
0x04, 0xE5, 0x08, 0x05, // 234 κ kappa
|
||||
0x04, 0xED, 0x0A, 0x06, // 235 λ lambda
|
||||
0x04, 0xF7, 0x0A, 0x06, // 236 μ mu
|
||||
0x05, 0x01, 0x08, 0x05, // 237 ν nu
|
||||
0x05, 0x09, 0x0A, 0x06, // 238 ξ xi
|
||||
0x05, 0x13, 0x0A, 0x06, // 239 ο omicron
|
||||
0x05, 0x1D, 0x0A, 0x06, // 240 π pi
|
||||
0x05, 0x27, 0x0A, 0x06, // 241 ρ rho
|
||||
0x05, 0x31, 0x08, 0x05, // 242 ς final sigma
|
||||
0x05, 0x39, 0x0A, 0x06, // 243 σ sigma
|
||||
0x05, 0x43, 0x06, 0x04, // 244 τ tau
|
||||
0x05, 0x49, 0x0A, 0x06, // 245 υ upsilon
|
||||
0x05, 0x53, 0x0C, 0x07, // 246 φ phi
|
||||
0x05, 0x5F, 0x0A, 0x06, // 247 χ chi
|
||||
0x05, 0x69, 0x0C, 0x07, // 248 ψ psi
|
||||
0x05, 0x75, 0x0C, 0x07, // 249 ω omega
|
||||
0xFF, 0xFF, 0x00, 0x03, // 250
|
||||
0xFF, 0xFF, 0x00, 0x03, // 251
|
||||
0xFF, 0xFF, 0x00, 0x03, // 252
|
||||
0xFF, 0xFF, 0x00, 0x03, // 253
|
||||
0xFF, 0xFF, 0x00, 0x03, // 254
|
||||
0xFF, 0xFF, 0x00, 0x03, // 255
|
||||
|
||||
// Font Data - Basic ASCII (32-127)
|
||||
0x00, 0x00, 0xF8, 0x02, // 33 !
|
||||
0x38, 0x00, 0x00, 0x00, 0x38, // 34 "
|
||||
0xA0, 0x03, 0xE0, 0x00, 0xB8, 0x03, 0xE0, 0x00, 0xB8, // 35 #
|
||||
0x30, 0x01, 0x28, 0x02, 0xF8, 0x07, 0x48, 0x02, 0x90, 0x01, // 36 $
|
||||
0x00, 0x00, 0x30, 0x00, 0x48, 0x00, 0x30, 0x03, 0xC0, 0x00, 0xB0, 0x01, 0x48, 0x02, 0x80, 0x01, // 37 %
|
||||
0x80, 0x01, 0x50, 0x02, 0x68, 0x02, 0xA8, 0x02, 0x18, 0x01, 0x80, 0x03, 0x80, 0x02, // 38 &
|
||||
0x38, // 39 '
|
||||
0xE0, 0x03, 0x10, 0x04, 0x08, 0x08, // 40 (
|
||||
0x08, 0x08, 0x10, 0x04, 0xE0, 0x03, // 41 )
|
||||
0x28, 0x00, 0x18, 0x00, 0x28, // 42 *
|
||||
0x40, 0x00, 0x40, 0x00, 0xF0, 0x01, 0x40, 0x00, 0x40, // 43 +
|
||||
0x00, 0x00, 0x00, 0x06, // 44 ,
|
||||
0x80, 0x00, 0x80, // 45 -
|
||||
0x00, 0x00, 0x00, 0x02, // 46 .
|
||||
0x00, 0x03, 0xE0, 0x00, 0x18, // 47 /
|
||||
0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 48 0
|
||||
0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0xF8, 0x03, // 49 1
|
||||
0x10, 0x02, 0x08, 0x03, 0x88, 0x02, 0x48, 0x02, 0x30, 0x02, // 50 2
|
||||
0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 51 3
|
||||
0xC0, 0x00, 0xA0, 0x00, 0x90, 0x00, 0x88, 0x00, 0xF8, 0x03, 0x80, // 52 4
|
||||
0x60, 0x01, 0x38, 0x02, 0x28, 0x02, 0x28, 0x02, 0xC8, 0x01, // 53 5
|
||||
0xF0, 0x01, 0x28, 0x02, 0x28, 0x02, 0x28, 0x02, 0xD0, 0x01, // 54 6
|
||||
0x08, 0x00, 0x08, 0x03, 0xC8, 0x00, 0x38, 0x00, 0x08, // 55 7
|
||||
0xB0, 0x01, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 56 8
|
||||
0x70, 0x01, 0x88, 0x02, 0x88, 0x02, 0x88, 0x02, 0xF0, 0x01, // 57 9
|
||||
0x00, 0x00, 0x20, 0x02, // 58 :
|
||||
0x00, 0x00, 0x20, 0x06, // 59 ;
|
||||
0x00, 0x00, 0x40, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x10, 0x01, // 60 <
|
||||
0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0xA0, // 61 =
|
||||
0x00, 0x00, 0x10, 0x01, 0xA0, 0x00, 0xA0, 0x00, 0x40, // 62 >
|
||||
0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0xC8, 0x02, 0x48, 0x00, 0x30, // 63 ?
|
||||
0x00, 0x00, 0xC0, 0x03, 0x30, 0x04, 0xD0, 0x09, 0x28, 0x0A, 0x28, 0x0A, 0xC8, 0x0B, 0x68, 0x0A, 0x10, 0x05, 0xE0,
|
||||
0x04, // 64 @
|
||||
0x00, 0x02, 0xC0, 0x01, 0xB0, 0x00, 0x88, 0x00, 0xB0, 0x00, 0xC0, 0x01, 0x00, 0x02, // 65 A
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xF0, 0x01, // 66 B
|
||||
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, // 67 C
|
||||
0x00, 0x00, 0xF8, 0x03, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, 0xE0, // 68 D
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, // 69 E
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x08, // 70 F
|
||||
0x00, 0x00, 0xE0, 0x00, 0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x50, 0x01, 0xC0, // 71 G
|
||||
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 72 H
|
||||
0x00, 0x00, 0xF8, 0x03, // 73 I
|
||||
0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x01, // 74 J
|
||||
0x00, 0x00, 0xF8, 0x03, 0x80, 0x00, 0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x02, // 75 K
|
||||
0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, // 76 L
|
||||
0x00, 0x00, 0xF8, 0x03, 0x30, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x30, 0x00, 0xF8, 0x03, // 77 M
|
||||
0x00, 0x00, 0xF8, 0x03, 0x30, 0x00, 0x40, 0x00, 0x80, 0x01, 0xF8, 0x03, // 78 N
|
||||
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 79 O
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 80 P
|
||||
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x03, 0x08, 0x03, 0xF0, 0x02, // 81 Q
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0xC8, 0x00, 0x30, 0x03, // 82 R
|
||||
0x00, 0x00, 0x30, 0x01, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x90, 0x01, // 83 S
|
||||
0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, // 84 T
|
||||
0x00, 0x00, 0xF8, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x01, // 85 U
|
||||
0x08, 0x00, 0x70, 0x00, 0x80, 0x01, 0x00, 0x02, 0x80, 0x01, 0x70, 0x00, 0x08, // 86 V
|
||||
0x18, 0x00, 0xE0, 0x01, 0x00, 0x02, 0xF0, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x02, 0xE0, 0x01, 0x18, // 87 W
|
||||
0x00, 0x02, 0x08, 0x01, 0x90, 0x00, 0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x02, // 88 X
|
||||
0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0xC0, 0x03, 0x20, 0x00, 0x10, 0x00, 0x08, // 89 Y
|
||||
0x08, 0x03, 0x88, 0x02, 0xC8, 0x02, 0x68, 0x02, 0x38, 0x02, 0x18, 0x02, // 90 Z
|
||||
0x00, 0x00, 0xF8, 0x0F, 0x08, 0x08, // 91 [
|
||||
0x18, 0x00, 0xE0, 0x00, 0x00, 0x03, // 92 backslash
|
||||
0x08, 0x08, 0xF8, 0x0F, // 93 ]
|
||||
0x40, 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, 0x40, // 94 ^
|
||||
0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, // 95 _
|
||||
0x08, 0x00, 0x10, // 96 `
|
||||
0x00, 0x00, 0x00, 0x03, 0xA0, 0x02, 0xA0, 0x02, 0xE0, 0x03, // 97 a
|
||||
0x00, 0x00, 0xF8, 0x03, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 98 b
|
||||
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x40, 0x01, // 99 c
|
||||
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xF8, 0x03, // 100 d
|
||||
0x00, 0x00, 0xC0, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x02, // 101 e
|
||||
0x20, 0x00, 0xF0, 0x03, 0x28, // 102 f
|
||||
0x00, 0x00, 0xC0, 0x05, 0x20, 0x0A, 0x20, 0x0A, 0xE0, 0x07, // 103 g
|
||||
0x00, 0x00, 0xF8, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 104 h
|
||||
0x00, 0x00, 0xE8, 0x03, // 105 i
|
||||
0x00, 0x08, 0xE8, 0x07, // 106 j
|
||||
0xF8, 0x03, 0x80, 0x00, 0xC0, 0x01, 0x20, 0x02, // 107 k
|
||||
0x00, 0x00, 0xF8, 0x03, // 108 l
|
||||
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 109 m
|
||||
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 110 n
|
||||
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 111 o
|
||||
0x00, 0x00, 0xE0, 0x0F, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 112 p
|
||||
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xE0, 0x0F, // 113 q
|
||||
0x00, 0x00, 0xE0, 0x03, 0x20, // 114 r
|
||||
0x40, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0x20, 0x01, // 115 s
|
||||
0x20, 0x00, 0xF8, 0x03, 0x20, 0x02, // 116 t
|
||||
0x00, 0x00, 0xE0, 0x01, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, // 117 u
|
||||
0x20, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x20, // 118 v
|
||||
0xE0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x20, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xE0, 0x01, // 119 w
|
||||
0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 120 x
|
||||
0x20, 0x00, 0xC0, 0x09, 0x00, 0x06, 0xC0, 0x01, 0x20, // 121 y
|
||||
0x20, 0x02, 0x20, 0x03, 0xA0, 0x02, 0x60, 0x02, 0x20, 0x02, // 122 z
|
||||
0x80, 0x00, 0x78, 0x0F, 0x08, 0x08, // 123 {
|
||||
0x00, 0x00, 0xF8, 0x0F, // 124 |
|
||||
0x08, 0x08, 0x78, 0x0F, 0x80, // 125 }
|
||||
0xC0, 0x00, 0x40, 0x00, 0xC0, 0x00, 0x80, 0x00, 0xC0, // 126 ~
|
||||
|
||||
// Greek uppercase letters (193-217 in CP-1253)
|
||||
0x00, 0x02, 0xC0, 0x01, 0xB0, 0x00, 0x88, 0x00, 0xB0, 0x00, 0xC0, 0x01, 0x00, 0x02, // Α Alpha (same as A)
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xF0, 0x01, // Β Beta (same as B)
|
||||
0x00, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x18, // Γ Gamma
|
||||
0x00, 0x02, 0x80, 0x01, 0x60, 0x00, 0x10, 0x00, 0x60, 0x00, 0x80, 0x01, 0x00, 0x02, // Δ Delta
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, // Ε Epsilon (same as E)
|
||||
0x08, 0x03, 0x88, 0x02, 0xC8, 0x02, 0x68, 0x02, 0x38, 0x02, // Ζ Zeta (same as Z)
|
||||
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // Η Eta (same as H)
|
||||
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0x08, 0x02, 0xF0, 0x01, // Θ Theta
|
||||
0x00, 0x00, 0xF8, 0x03, // Ι Iota (same as I)
|
||||
0x00, 0x00, 0xF8, 0x03, 0x80, 0x00, 0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x02, // Κ Kappa (same as K)
|
||||
0x00, 0x02, 0x80, 0x01, 0x70, 0x00, 0x08, 0x00, 0x70, 0x00, 0x80, 0x01, 0x00, 0x02, // Λ Lambda
|
||||
0x00, 0x00, 0xF8, 0x03, 0x30, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x30, 0x00, 0xF8, 0x03, // Μ Mu (same as M)
|
||||
0x00, 0x00, 0xF8, 0x03, 0x30, 0x00, 0x40, 0x00, 0x80, 0x01, 0xF8, 0x03, // Ν Nu (same as N)
|
||||
0x00, 0x00, 0x48, 0x02, 0x48, 0x02, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, // Ξ Xi
|
||||
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // Ο Omicron (same as O)
|
||||
0x00, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, // Π Pi
|
||||
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // Ρ Rho (same as P)
|
||||
0x00, 0x00, 0x30, 0x01, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x90, 0x01, // Σ Sigma
|
||||
0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, // Τ Tau (same as T)
|
||||
0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0xC0, 0x03, 0x20, 0x00, 0x10, 0x00, 0x08, // Υ Upsilon (same as Y)
|
||||
0x00, 0x00, 0x70, 0x00, 0x88, 0x00, 0xF8, 0x03, 0x88, 0x00, 0x70, 0x00, 0x00, // Φ Phi
|
||||
0x00, 0x02, 0x08, 0x01, 0x90, 0x00, 0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x02, // Χ Chi (same as X)
|
||||
0x00, 0x00, 0x08, 0x00, 0xF0, 0x01, 0x08, 0x02, 0xF8, 0x03, 0x08, 0x02, 0xF0, 0x01, // Ψ Psi
|
||||
0x00, 0x00, 0x08, 0x02, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, 0x08, 0x02, // Ω Omega
|
||||
|
||||
// Greek lowercase letters (225-249 in CP-1253)
|
||||
0x00, 0x00, 0x00, 0x03, 0xA0, 0x02, 0xA0, 0x02, 0xE0, 0x03, // α alpha
|
||||
0x00, 0x00, 0xF8, 0x07, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // β beta
|
||||
0x00, 0x04, 0x20, 0x02, 0xC0, 0x01, 0x20, 0x00, 0x20, // γ gamma
|
||||
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x50, 0x01, // δ delta
|
||||
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x40, // ε epsilon
|
||||
0x00, 0x04, 0x00, 0x03, 0xE0, 0x00, 0x18, // ζ zeta
|
||||
0x00, 0x00, 0xE0, 0x05, 0x20, 0x0A, 0x20, 0x02, 0xC0, 0x01, // η eta
|
||||
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0xA0, 0x02, 0xC0, 0x01, // θ theta
|
||||
0x00, 0x00, 0xE0, 0x03, // ι iota
|
||||
0xE0, 0x03, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // κ kappa
|
||||
0x00, 0x02, 0x80, 0x01, 0x40, 0x00, 0x20, 0x00, 0xE0, 0x03, // λ lambda
|
||||
0x00, 0x00, 0xE0, 0x0F, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, // μ mu
|
||||
0x20, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xE0, 0x03, // ν nu
|
||||
0x00, 0x04, 0xC0, 0x03, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x01, // ξ xi
|
||||
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // ο omicron
|
||||
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, // π pi
|
||||
0x00, 0x00, 0xE0, 0x0F, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // ρ rho
|
||||
0x00, 0x04, 0x00, 0x03, 0xA0, 0x02, 0x40, 0x01, // ς final sigma
|
||||
0x00, 0x00, 0x40, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xE0, 0x03, // σ sigma
|
||||
0x20, 0x00, 0xE0, 0x03, 0x20, // τ tau
|
||||
0x00, 0x00, 0xE0, 0x01, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, // υ upsilon
|
||||
0x00, 0x00, 0xC0, 0x00, 0x20, 0x01, 0xE0, 0x03, 0x20, 0x01, 0xC0, // φ phi
|
||||
0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // χ chi
|
||||
0x00, 0x00, 0x20, 0x00, 0xC0, 0x05, 0x20, 0x02, 0xE0, 0x03, 0x20, // ψ psi
|
||||
0x00, 0x00, 0x20, 0x02, 0xC0, 0x01, 0x20, 0x02, 0xC0, 0x01, 0x20, 0x02, // ω omega
|
||||
};
|
||||
|
||||
// Placeholder for 16pt font - needs to be generated with font converter tool
|
||||
const uint8_t ArialMT_Plain_16_GR[] PROGMEM = {
|
||||
0x10, // Width: 16
|
||||
0x13, // Height: 19
|
||||
0x20, // First Char: 32
|
||||
0x01, // Number of chars: 1 (placeholder)
|
||||
// Minimal placeholder - replace with full font data
|
||||
0xFF, 0xFF, 0x00, 0x04, // 32 space
|
||||
// Font Data:
|
||||
// (empty placeholder)
|
||||
};
|
||||
|
||||
// Placeholder for 24pt font - needs to be generated with font converter tool
|
||||
const uint8_t ArialMT_Plain_24_GR[] PROGMEM = {
|
||||
0x18, // Width: 24
|
||||
0x1C, // Height: 28
|
||||
0x20, // First Char: 32
|
||||
0x01, // Number of chars: 1 (placeholder)
|
||||
// Minimal placeholder - replace with full font data
|
||||
0xFF, 0xFF, 0x00, 0x06, // 32 space
|
||||
// Font Data:
|
||||
// (empty placeholder)
|
||||
};
|
||||
|
||||
#endif // OLED_GR
|
||||
22
src/graphics/fonts/OLEDDisplayFontsGR.h
Normal file
22
src/graphics/fonts/OLEDDisplayFontsGR.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef OLEDDISPLAYFONTSGR_h
|
||||
#define OLEDDISPLAYFONTSGR_h
|
||||
|
||||
#ifdef ARDUINO
|
||||
#include <Arduino.h>
|
||||
#elif __MBED__
|
||||
#define PROGMEM
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Localization for Greek language containing glyphs for the Greek alphabet.
|
||||
* Uses Windows-1253 (CP-1253) encoding for Greek characters.
|
||||
*
|
||||
* Supported characters:
|
||||
* - Uppercase Greek: Α-Ω (U+0391 to U+03A9)
|
||||
* - Lowercase Greek: α-ω (U+03B1 to U+03C9)
|
||||
* - Accented Greek: ά, έ, ή, ί, ό, ύ, ώ, etc.
|
||||
*/
|
||||
extern const uint8_t ArialMT_Plain_10_GR[] PROGMEM;
|
||||
extern const uint8_t ArialMT_Plain_16_GR[] PROGMEM;
|
||||
extern const uint8_t ArialMT_Plain_24_GR[] PROGMEM;
|
||||
#endif
|
||||
527
src/graphics/niche/Fonts/FreeSans12pt_Win1253.h
Normal file
527
src/graphics/niche/Fonts/FreeSans12pt_Win1253.h
Normal file
@@ -0,0 +1,527 @@
|
||||
// trunk-ignore-all(clang-format)
|
||||
#pragma once
|
||||
/* PROPERTIES
|
||||
|
||||
FONT_NAME FreeSans12pt_Win1253
|
||||
*/
|
||||
const uint8_t FreeSans12pt_Win1253Bitmaps[] PROGMEM = {
|
||||
/* 0x01 */ 0x00, 0x30, 0x00, 0x09, 0x00, 0x01, 0x20, 0x00, 0x24, 0x00, 0x04, 0x80, 0x01, 0x90, 0x00, 0x62, 0x00, 0x30, 0xFE, 0x04, 0x10, 0x5F, 0x02, 0x0B, 0x00, 0x7F, 0xE0, 0x0C, 0x1C, 0x02, 0x83, 0x81, 0x9F, 0xF0, 0x02, 0x1E, 0x00, 0x41, 0xC0, 0x0E, 0x7F, 0x81, 0x78, 0x18, 0x62, 0x00, 0xFF, 0xC0,
|
||||
/* 0x02 */ 0x00, 0xFF, 0x80, 0x61, 0x13, 0xF0, 0x62, 0x60, 0x07, 0xFC, 0x00, 0x83, 0x80, 0x10, 0xF0, 0x33, 0xF6, 0x01, 0x41, 0xC0, 0x18, 0x38, 0x03, 0xFF, 0xE0, 0x47, 0x02, 0x08, 0x20, 0x61, 0xC4, 0x06, 0x17, 0x00, 0x22, 0x00, 0x02, 0x40, 0x00, 0x48, 0x00, 0x09, 0x00, 0x01, 0x20, 0x00, 0x3C, 0x00,
|
||||
/* 0x03 */ 0x01, 0xFC, 0x00, 0x38, 0x18, 0x02, 0x00, 0x30, 0x20, 0x00, 0xC2, 0x00, 0x02, 0x30, 0x00, 0x09, 0x04, 0x08, 0x48, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x08, 0x10, 0x70, 0x00, 0x03, 0x80, 0x00, 0x14, 0x00, 0x00, 0xA1, 0x81, 0x8D, 0x87, 0xF0, 0x44, 0x00, 0x06, 0x30, 0x00, 0x60, 0xC0, 0x06, 0x03, 0x80, 0x60, 0x07, 0xFC, 0x00,
|
||||
/* 0x04 */ 0x01, 0xFC, 0x00, 0x38, 0x18, 0x02, 0x00, 0x30, 0x20, 0x00, 0xC2, 0x00, 0x02, 0x30, 0x00, 0x09, 0x10, 0x02, 0x48, 0xE0, 0x61, 0xC1, 0xCC, 0x0E, 0x78, 0x1C, 0x70, 0x00, 0x03, 0x80, 0x00, 0x14, 0xFF, 0xFC, 0xA6, 0x00, 0xCD, 0x9F, 0xFE, 0x44, 0x71, 0xE6, 0x30, 0xFC, 0x60, 0xC0, 0x06, 0x03, 0x80, 0x60, 0x07, 0xFC, 0x00,
|
||||
/* 0x05 */ 0x00, 0x18, 0x00, 0x00, 0x40, 0x01, 0x90, 0x01, 0xF4, 0x08, 0x12, 0x23, 0xC1, 0x91, 0x2C, 0x1C, 0x8A, 0xC3, 0x64, 0x64, 0x13, 0x22, 0x41, 0x98, 0x26, 0x2C, 0xC4, 0x22, 0x60, 0x42, 0x13, 0x04, 0x30, 0x80, 0x61, 0xA4, 0x02, 0x18, 0x20, 0x03, 0x41, 0x00, 0x20, 0x08, 0x02, 0x00, 0x60, 0x40, 0x03, 0xF8,
|
||||
/* 0x06 */ 0x00, 0x10, 0x00, 0x03, 0x00, 0x1C, 0x48, 0x00, 0xB4, 0x80, 0x09, 0xF9, 0xC0, 0xE0, 0xE4, 0x0C, 0x02, 0x8F, 0x80, 0x38, 0x88, 0x01, 0x0D, 0x00, 0x18, 0x30, 0x01, 0x60, 0x80, 0x13, 0x18, 0x03, 0xF2, 0xC0, 0x20, 0x26, 0x06, 0x07, 0xFF, 0xA0, 0x02, 0x39, 0x00, 0x14, 0x70, 0x01, 0xC3, 0x00, 0x18, 0x00,
|
||||
/* 0x07 */
|
||||
/* 0x08 */ 0x00, 0x1F, 0x80, 0x00, 0x60, 0x80, 0x01, 0x00, 0x80, 0x06, 0x00, 0x80, 0x3C, 0x01, 0x01, 0x8C, 0x02, 0x02, 0x08, 0x04, 0x04, 0x08, 0x0C, 0x38, 0x00, 0x04, 0x80, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x2E, 0xC0, 0x01, 0x83, 0x7E, 0x0C, 0x10, 0x37, 0xE2, 0x61, 0x00, 0x0C, 0xC6, 0x10, 0x98, 0x0C, 0x63, 0x00, 0x00, 0xC6, 0x00,
|
||||
/* 0x09 */ 0x00, 0x1F, 0x80, 0x00, 0x60, 0x80, 0x01, 0x00, 0x80, 0x06, 0x00, 0x80, 0x3C, 0x01, 0x01, 0x8C, 0x02, 0x02, 0x08, 0x04, 0x04, 0x08, 0x0C, 0x38, 0x00, 0x04, 0x80, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x2E, 0xC0, 0x01, 0x83, 0x7E, 0x0C, 0x00, 0x37, 0xE0,
|
||||
/* 0x0A */
|
||||
/* 0x0B */ 0x1F, 0x07, 0xC1, 0x86, 0x41, 0x10, 0x0C, 0x04, 0x80, 0x40, 0x18, 0x00, 0x00, 0xC0, 0x00, 0x06, 0x00, 0x00, 0x30, 0x00, 0x01, 0x40, 0x00, 0x0A, 0x00, 0x00, 0x88, 0x00, 0x04, 0x40, 0x00, 0x41, 0x00, 0x02, 0x04, 0x00, 0x20, 0x20, 0x02, 0x00, 0x80, 0x20, 0x02, 0x02, 0x00, 0x08, 0x20, 0x00, 0x22, 0x00, 0x00, 0xE0, 0x00,
|
||||
/* 0x0C */ 0x01, 0x00, 0x00, 0x38, 0x00, 0x04, 0xC0, 0x01, 0x08, 0x00, 0x18, 0x80, 0x1C, 0x10, 0x02, 0x07, 0x80, 0x81, 0x10, 0x1F, 0xC2, 0x02, 0x00, 0x60, 0x80, 0x1A, 0x20, 0x1C, 0x42, 0x1C, 0x08, 0xFE, 0x03, 0xA0, 0x01, 0x8C, 0x01, 0xC1, 0x43, 0xD0, 0x27, 0x81, 0xF8,
|
||||
/* 0x0D */
|
||||
/* 0x0E */ 0x00, 0xE0, 0x00, 0x11, 0x00, 0x01, 0x10, 0x00, 0x0B, 0x00, 0x03, 0xF8, 0x00, 0x60, 0x60, 0x09, 0x02, 0x00, 0xA0, 0x10, 0x16, 0x01, 0x01, 0x40, 0x10, 0x10, 0x01, 0x01, 0x00, 0x08, 0x10, 0x00, 0x82, 0x1F, 0x08, 0x3F, 0x90, 0x44, 0x00, 0x06, 0xBF, 0xFF, 0xAF, 0xF0, 0xFF, 0xFF, 0x0F, 0xE3, 0xFB, 0xFC,
|
||||
/* 0x0F */ 0x01, 0xFC, 0x00, 0x38, 0x18, 0x02, 0x00, 0x30, 0x20, 0x00, 0xC2, 0x40, 0x12, 0x34, 0x00, 0x69, 0x40, 0x01, 0x49, 0xE0, 0xF1, 0xCD, 0x06, 0x8E, 0x28, 0x14, 0x71, 0x40, 0xA3, 0x8B, 0xFD, 0x14, 0x50, 0x68, 0xA2, 0x81, 0x4D, 0x97, 0xFA, 0x44, 0xBF, 0xD6, 0x31, 0x02, 0xE0, 0xC8, 0x16, 0x08, 0x61, 0x08, 0x21, 0xF0, 0x80, 0xF8, 0x78, 0x00,
|
||||
/* 0x10 */ 0x00, 0xF0, 0x00, 0x3A, 0x00, 0x07, 0xC0, 0x00, 0xA8, 0x00, 0x1F, 0x00, 0x02, 0xB0, 0x00, 0x52, 0x00, 0x0A, 0x40, 0x02, 0x48, 0x00, 0x49, 0x00, 0x09, 0x30, 0x01, 0x22, 0x01, 0xC4, 0x70, 0xF0, 0x85, 0xE1, 0x10, 0x88, 0x37, 0x20, 0x03, 0x9C, 0x00, 0x37, 0x00, 0x06, 0x40, 0x01, 0x86, 0x00,
|
||||
/* 0x11 */ 0x01, 0xFC, 0x00, 0x38, 0x18, 0x02, 0x00, 0x30, 0x20, 0x00, 0xC2, 0x60, 0x02, 0x36, 0x00, 0x09, 0x04, 0x0C, 0x48, 0x60, 0xC1, 0xC3, 0x0F, 0x0E, 0x00, 0x08, 0x70, 0x00, 0x23, 0x80, 0x63, 0x84, 0x01, 0x9F, 0x20, 0x0C, 0xFD, 0x80, 0x27, 0xE4, 0x03, 0x3F, 0x30, 0x33, 0xE0, 0xC0, 0x00, 0x03, 0x80, 0x60, 0x07, 0xFC, 0x00,
|
||||
/* 0x12 */ 0x00, 0xC2, 0x00, 0x1C, 0x24, 0x02, 0x18, 0x60, 0x64, 0x02, 0x02, 0x40, 0x20, 0x00, 0xF2, 0x03, 0x89, 0xE0, 0x7C, 0x80, 0x0E, 0x25, 0x80, 0xE1, 0x00, 0x1A, 0x08, 0x71, 0xB0, 0xC4, 0x39, 0x84, 0xC2, 0xCC, 0x40, 0x76, 0x7C, 0x05, 0xBB, 0x80, 0x4C, 0xE0, 0x0A, 0x78, 0x00, 0x9C, 0x00, 0x0F, 0x00, 0x00,
|
||||
/* 0x13 */ 0x01, 0xFC, 0x00, 0x38, 0x18, 0x02, 0x00, 0x30, 0x20, 0x00, 0xC2, 0x00, 0x02, 0x30, 0x00, 0x09, 0x00, 0x00, 0x48, 0x60, 0xC1, 0xC6, 0xC9, 0x0E, 0x00, 0x00, 0x70, 0x00, 0x03, 0x80, 0x00, 0x14, 0xFF, 0xF8, 0xA6, 0x00, 0xCD, 0x9F, 0xFE, 0x44, 0x71, 0xE6, 0x30, 0xFC, 0x60, 0xC0, 0x06, 0x03, 0x80, 0x60, 0x07, 0xFC, 0x00,
|
||||
/* 0x14 */ 0x01, 0xFC, 0x00, 0x38, 0x18, 0x02, 0x00, 0x30, 0x20, 0x00, 0xC2, 0x20, 0x22, 0x33, 0x01, 0x89, 0x20, 0x02, 0x48, 0x60, 0xE1, 0xC8, 0x80, 0x8E, 0x46, 0x46, 0x72, 0x32, 0x33, 0x9F, 0x9F, 0x94, 0x78, 0x78, 0xA0, 0x00, 0x0D, 0x80, 0x00, 0x44, 0x0E, 0x06, 0x30, 0x00, 0x60, 0xC0, 0x06, 0x03, 0x80, 0x60, 0x07, 0xFC, 0x00,
|
||||
/* 0x15 */ 0x03, 0xFC, 0x20, 0x38, 0x1C, 0x81, 0x80, 0x1D, 0x08, 0x00, 0x32, 0x60, 0x00, 0x89, 0x00, 0x02, 0x18, 0x00, 0x08, 0x61, 0xC3, 0x22, 0x8D, 0x93, 0x72, 0x00, 0x00, 0x48, 0x00, 0x01, 0x20, 0x00, 0x04, 0x9F, 0xFF, 0x92, 0x60, 0x0E, 0x44, 0xFF, 0xF2, 0x11, 0xC3, 0x88, 0x21, 0xF8, 0x40, 0x40, 0x02, 0x00, 0xC0, 0x30, 0x00, 0xFF, 0x00,
|
||||
/* 0x16 */ 0x03, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x01, 0xE0, 0x03, 0xF0, 0x03, 0xF0, 0x27, 0xF0, 0x6F, 0x70, 0x6E, 0x60, 0xFC, 0x60, 0xFC, 0x7E, 0xFC, 0x7E, 0xFC, 0x3F, 0xF4, 0x1F, 0xF4, 0x1F, 0xF0, 0x0E, 0x70, 0x0E, 0x30, 0x1C, 0x38, 0x38, 0x0F, 0xF0,
|
||||
/* 0x17 */ 0x01, 0xFC, 0x00, 0x38, 0x18, 0x02, 0x00, 0x30, 0x20, 0x00, 0xC2, 0x00, 0x02, 0x30, 0x00, 0x09, 0x00, 0x00, 0x48, 0x00, 0x21, 0xC0, 0x02, 0x8E, 0x20, 0xF4, 0x70, 0x84, 0x11, 0x82, 0x40, 0x84, 0x01, 0x03, 0x20, 0x0F, 0x85, 0x80, 0x03, 0x04, 0x00, 0x04, 0x30, 0x78, 0x10, 0xC0, 0x06, 0x03, 0x80, 0x60, 0x07, 0xFC, 0x00,
|
||||
/* 0x18 */ 0x00, 0xFC, 0x00, 0x02, 0x06, 0x00, 0x08, 0x24, 0x00, 0x21, 0xA4, 0x00, 0x4C, 0x48, 0x00, 0xA0, 0x50, 0x01, 0x92, 0x60, 0x03, 0x24, 0xC0, 0x06, 0x01, 0x81, 0x28, 0x03, 0x49, 0x6C, 0xC4, 0xAD, 0xD8, 0x16, 0xA4, 0xCC, 0xC4, 0x44, 0x86, 0x13, 0x05, 0x00, 0x28, 0x0A, 0x00, 0x50, 0x14, 0x00, 0x90, 0x48, 0x01, 0x20, 0x90, 0x02, 0x41, 0x20, 0x00, 0x00,
|
||||
/* 0x19 */ 0x01, 0xFC, 0x00, 0x38, 0x18, 0x02, 0x00, 0x30, 0x20, 0x00, 0xC2, 0x00, 0x02, 0x30, 0x00, 0x09, 0x00, 0x00, 0x49, 0xC3, 0x81, 0xC0, 0x00, 0x0E, 0x78, 0xF0, 0x77, 0xEF, 0xC3, 0xA7, 0x4E, 0x15, 0x0A, 0x10, 0xA7, 0x8F, 0x0D, 0x80, 0x00, 0x44, 0x00, 0x06, 0x33, 0xF0, 0x60, 0xC0, 0x06, 0x03, 0x80, 0x60, 0x07, 0xFC, 0x00,
|
||||
/* 0x1A */ 0xFF, 0xFF, 0x00, 0x06, 0x00, 0x0C, 0x3E, 0x18, 0x82, 0x32, 0x02, 0x64, 0x04, 0xC8, 0x09, 0x80, 0x23, 0x00, 0x86, 0x02, 0x0C, 0x08, 0x18, 0x10, 0x30, 0x00, 0x60, 0x00, 0xC0, 0x81, 0x80, 0x03, 0x00, 0x07, 0xFF, 0xF8,
|
||||
/* 0x1B */ 0x00, 0xFE, 0x00, 0x03, 0x81, 0x80, 0x04, 0x00, 0x60, 0x08, 0x00, 0x30, 0x10, 0x00, 0x10, 0x30, 0x07, 0x88, 0x23, 0xC8, 0x08, 0x22, 0x00, 0x04, 0x60, 0x00, 0x44, 0x60, 0x00, 0x84, 0x63, 0x03, 0x04, 0x61, 0xFC, 0x04, 0x6B, 0x00, 0x9E, 0xA5, 0x01, 0x6A, 0xD5, 0x01, 0x43, 0xA8, 0x81, 0x05, 0xD0, 0x82, 0x0A, 0xA0, 0x82, 0x05, 0xC0, 0x82, 0x02, 0x61, 0xFF, 0x0C, 0x1E, 0x00, 0xF0,
|
||||
/* 0x1C */ 0x01, 0xFC, 0x00, 0x38, 0x18, 0x02, 0x00, 0x30, 0x20, 0x00, 0xC2, 0x30, 0x02, 0x32, 0x00, 0x09, 0x00, 0x00, 0x48, 0x20, 0x61, 0xC3, 0x84, 0x0E, 0x1C, 0x78, 0x70, 0x40, 0x03, 0x80, 0x00, 0x14, 0x00, 0x00, 0xA0, 0x03, 0x0D, 0x83, 0xF0, 0x44, 0x00, 0x06, 0x30, 0x00, 0x60, 0xC0, 0x06, 0x03, 0x80, 0x60, 0x07, 0xFC, 0x00,
|
||||
/* 0x1D */ 0x01, 0xFE, 0x00, 0x3A, 0x1C, 0x03, 0x00, 0x30, 0x23, 0x1E, 0xC3, 0x38, 0x03, 0x10, 0xC3, 0x09, 0x00, 0x18, 0x68, 0x00, 0xC1, 0x40, 0x00, 0x0A, 0x07, 0x80, 0x50, 0x46, 0x02, 0x80, 0x00, 0x1A, 0x1E, 0x00, 0xCB, 0x10, 0x0D, 0x03, 0x00, 0x48, 0x60, 0x06, 0x40, 0x00, 0x22, 0x0C, 0x02, 0x10, 0x60, 0x60, 0x43, 0xFC, 0x01, 0xE0, 0x00, 0x00,
|
||||
/* 0x1E */ 0x01, 0xF0, 0x00, 0xEA, 0xC0, 0x31, 0x5F, 0x04, 0x5F, 0x88, 0x80, 0xA0, 0x48, 0x0E, 0x02, 0x8F, 0x40, 0x3C, 0x10, 0x21, 0x66, 0x87, 0x15, 0x98, 0x71, 0x41, 0x02, 0x14, 0x00, 0x01, 0x40, 0x00, 0x14, 0x00, 0x01, 0x21, 0xFE, 0x12, 0x00, 0x02, 0x10, 0x00, 0x60, 0x80, 0x0C, 0x06, 0x01, 0x80, 0x3F, 0xE0,
|
||||
/* 0x1F */ 0x0E, 0x00, 0x13, 0x00, 0x23, 0x00, 0xF3, 0x01, 0x31, 0x01, 0x11, 0x03, 0xD3, 0x06, 0xF2, 0x30, 0x34, 0xC7, 0x25, 0x33, 0x2B, 0xC2, 0x57, 0x04, 0x3A, 0x08, 0x72, 0x30, 0xA3, 0xC3, 0x40, 0x04, 0x40, 0x18, 0x40, 0x60, 0x7F, 0x80,
|
||||
/* ' ' 0x20 */
|
||||
/* '!' 0x21 */ 0xFF, 0xFF, 0xFF, 0xF0, 0xF0,
|
||||
/* '"' 0x22 */ 0xCF, 0x3C, 0xF3, 0x8A, 0x20,
|
||||
/* '#' 0x23 */ 0x06, 0x30, 0x31, 0x03, 0x18, 0x18, 0xC7, 0xFF, 0xBF, 0xFC, 0x31, 0x01, 0x18, 0x18, 0xC7, 0xFF, 0xBF, 0xFC, 0x31, 0x01, 0x18, 0x18, 0xC0, 0xC6, 0x06, 0x30,
|
||||
/* '$' 0x24 */ 0x04, 0x03, 0xE1, 0xFF, 0x72, 0x7C, 0x47, 0x88, 0xF1, 0x07, 0xA0, 0x7E, 0x03, 0xF0, 0x17, 0x02, 0x7C, 0x47, 0x88, 0xF1, 0x1B, 0x26, 0x7F, 0xC3, 0xE0, 0x10, 0x02, 0x00,
|
||||
/* '%' 0x25 */ 0x00, 0x06, 0x03, 0xC0, 0x40, 0x7E, 0x0C, 0x0E, 0x70, 0x80, 0xC3, 0x18, 0x0C, 0x31, 0x00, 0xE7, 0x30, 0x07, 0xE6, 0x00, 0x3C, 0x40, 0x00, 0x0C, 0x7C, 0x00, 0x8F, 0xE0, 0x19, 0xC7, 0x01, 0x18, 0x30, 0x31, 0x83, 0x02, 0x1C, 0x70, 0x40, 0xFE, 0x04, 0x07, 0xC0,
|
||||
/* '&' 0x26 */ 0x0F, 0x00, 0x7E, 0x03, 0x9C, 0x0C, 0x30, 0x30, 0xC0, 0xE7, 0x01, 0xF8, 0x03, 0x80, 0x3E, 0x01, 0xCC, 0x6E, 0x39, 0xB0, 0x7C, 0xC0, 0xF3, 0x03, 0xCE, 0x1F, 0x9F, 0xE6, 0x3E, 0x1C,
|
||||
/* ''' 0x27 */ 0xFF, 0xA0,
|
||||
/* '(' 0x28 */ 0x08, 0x8C, 0x46, 0x31, 0x98, 0xC6, 0x31, 0x8C, 0x63, 0x08, 0x63, 0x08, 0x61, 0x0C, 0x20,
|
||||
/* ')' 0x29 */ 0x82, 0x18, 0xC3, 0x18, 0xC3, 0x18, 0xC6, 0x31, 0x8C, 0x62, 0x31, 0x88, 0xC4, 0x62, 0x00,
|
||||
/* '*' 0x2A */ 0x10, 0x23, 0x5B, 0xE3, 0x8D, 0x91, 0x00,
|
||||
/* '+' 0x2B */ 0x0C, 0x03, 0x00, 0xC0, 0x30, 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0,
|
||||
/* ',' 0x2C */ 0xF5, 0x60,
|
||||
/* '-' 0x2D */ 0xFF, 0xF0,
|
||||
/* '.' 0x2E */ 0xF0,
|
||||
/* '/' 0x2F */ 0x02, 0x0C, 0x10, 0x20, 0xC1, 0x02, 0x0C, 0x10, 0x20, 0xC1, 0x02, 0x0C, 0x10, 0x20, 0xC1, 0x00,
|
||||
/* '0' 0x30 */ 0x1F, 0x07, 0xF1, 0xC7, 0x30, 0x6C, 0x0F, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3E, 0x0E, 0xC1, 0x9C, 0x71, 0xFC, 0x1F, 0x00,
|
||||
/* '1' 0x31 */ 0x08, 0xCF, 0xFF, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18,
|
||||
/* '2' 0x32 */ 0x1F, 0x0F, 0xF9, 0x87, 0x60, 0x7C, 0x06, 0x00, 0xC0, 0x18, 0x07, 0x01, 0xC0, 0xF0, 0x78, 0x1C, 0x06, 0x00, 0xC0, 0x30, 0x07, 0xFF, 0xFF, 0xE0,
|
||||
/* '3' 0x33 */ 0x3F, 0x0F, 0xF3, 0x87, 0x60, 0x6C, 0x0C, 0x01, 0x80, 0x60, 0x78, 0x0F, 0x80, 0x18, 0x01, 0x80, 0x3C, 0x07, 0x80, 0xD8, 0x73, 0xFC, 0x3F, 0x00,
|
||||
/* '4' 0x34 */ 0x01, 0x80, 0x70, 0x0E, 0x03, 0xC0, 0xD8, 0x1B, 0x06, 0x61, 0x8C, 0x21, 0x8C, 0x33, 0x06, 0x7F, 0xFF, 0xFE, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80,
|
||||
/* '5' 0x35 */ 0x3F, 0xCF, 0xF9, 0x80, 0x30, 0x06, 0x00, 0xDE, 0x1F, 0xE7, 0x0E, 0x00, 0xE0, 0x0C, 0x01, 0x80, 0x30, 0x07, 0x81, 0xB8, 0x73, 0xFC, 0x1F, 0x00,
|
||||
/* '6' 0x36 */ 0x0F, 0x07, 0xF9, 0xC3, 0x30, 0x74, 0x01, 0x80, 0x33, 0xC7, 0xFE, 0xF1, 0xDC, 0x1F, 0x01, 0xE0, 0x3C, 0x06, 0xC1, 0xDC, 0x71, 0xFC, 0x1F, 0x00,
|
||||
/* '7' 0x37 */ 0xFF, 0xFF, 0xFC, 0x01, 0x00, 0x60, 0x18, 0x02, 0x00, 0xC0, 0x30, 0x06, 0x01, 0x80, 0x30, 0x04, 0x01, 0x80, 0x30, 0x06, 0x01, 0x80, 0x30, 0x00,
|
||||
/* '8' 0x38 */ 0x1F, 0x07, 0xF1, 0xC7, 0x30, 0x66, 0x0C, 0xC1, 0x8C, 0x61, 0xF8, 0x3F, 0x8E, 0x3B, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xD8, 0x31, 0xFC, 0x1F, 0x00,
|
||||
/* '9' 0x39 */ 0x1F, 0x07, 0xF1, 0xC7, 0x70, 0x6C, 0x07, 0x80, 0xF0, 0x1E, 0x07, 0x61, 0xEF, 0xFC, 0x79, 0x80, 0x30, 0x05, 0xC1, 0x98, 0x73, 0xFC, 0x1E, 0x00,
|
||||
/* ':' 0x3A */ 0xF0, 0x00, 0x03, 0xC0,
|
||||
/* ';' 0x3B */ 0xF0, 0x00, 0x0F, 0x56,
|
||||
/* '<' 0x3C */ 0x00, 0x70, 0x1E, 0x0F, 0x83, 0xC0, 0xF0, 0x0E, 0x00, 0x7C, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x10,
|
||||
/* '=' 0x3D */ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
|
||||
/* '>' 0x3E */ 0xE0, 0x07, 0x80, 0x1F, 0x00, 0x7C, 0x00, 0xF0, 0x07, 0x01, 0xE0, 0xF0, 0x3C, 0x0F, 0x00, 0x80, 0x00,
|
||||
/* '?' 0x3F */ 0x3F, 0x1F, 0xEE, 0x1F, 0x03, 0xC0, 0xC0, 0x30, 0x0C, 0x06, 0x03, 0x81, 0xC0, 0xE0, 0x30, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x00,
|
||||
/* '@' 0x40 */ 0x00, 0xFE, 0x00, 0x0F, 0xFE, 0x00, 0xF0, 0x3E, 0x07, 0x00, 0x3C, 0x38, 0x00, 0x38, 0xC1, 0xE0, 0x66, 0x0F, 0xD9, 0xD8, 0x61, 0xC3, 0xC3, 0x07, 0x0F, 0x1C, 0x1C, 0x3C, 0x60, 0x60, 0xF1, 0x81, 0x83, 0xC6, 0x06, 0x1B, 0x18, 0x38, 0xEE, 0x71, 0xE7, 0x18, 0xFD, 0xF8, 0x71, 0xE7, 0xC0, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFC, 0x00,
|
||||
/* 'A' 0x41 */ 0x07, 0x80, 0x1E, 0x00, 0x78, 0x03, 0xF0, 0x0C, 0xC0, 0x33, 0x01, 0xCE, 0x06, 0x18, 0x18, 0x60, 0xE1, 0xC3, 0x03, 0x0F, 0xFC, 0x7F, 0xF9, 0x80, 0x66, 0x01, 0xB8, 0x07, 0xC0, 0x0F, 0x00, 0x30,
|
||||
/* 'B' 0x42 */ 0xFF, 0xC7, 0xFF, 0x30, 0x1D, 0x80, 0x6C, 0x03, 0x60, 0x1B, 0x00, 0xD8, 0x0C, 0xFF, 0xC7, 0xFF, 0x30, 0x0D, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x06, 0xFF, 0xF7, 0xFE, 0x00,
|
||||
/* 'C' 0x43 */ 0x07, 0xE0, 0x3F, 0xF0, 0xE0, 0x73, 0x80, 0x76, 0x00, 0x6C, 0x00, 0x30, 0x00, 0x60, 0x00, 0xC0, 0x01, 0x80, 0x03, 0x00, 0x06, 0x00, 0x0E, 0x00, 0x6C, 0x00, 0xDC, 0x03, 0x1E, 0x0E, 0x1F, 0xF8, 0x0F, 0xC0,
|
||||
/* 'D' 0x44 */ 0xFF, 0xC3, 0xFF, 0x8C, 0x07, 0x30, 0x0E, 0xC0, 0x1B, 0x00, 0x7C, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0, 0x1F, 0x00, 0x6C, 0x03, 0xB0, 0x1C, 0xFF, 0xE3, 0xFE, 0x00,
|
||||
/* 'E' 0x45 */ 0xFF, 0xFF, 0xFF, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xFF, 0xEF, 0xFE, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xFF, 0xFF, 0xFF,
|
||||
/* 'F' 0x46 */ 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xFF, 0xDF, 0xFB, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x00,
|
||||
/* 'G' 0x47 */ 0x07, 0xF0, 0x1F, 0xFC, 0x3C, 0x1E, 0x70, 0x07, 0x60, 0x03, 0xE0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x7F, 0xC0, 0x7F, 0xC0, 0x03, 0xC0, 0x03, 0x60, 0x03, 0x60, 0x07, 0x30, 0x0F, 0x3C, 0x1F, 0x1F, 0xFB, 0x07, 0xE1,
|
||||
/* 'H' 0x48 */ 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xC0,
|
||||
/* 'I' 0x49 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xF0,
|
||||
/* 'J' 0x4A */ 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x3C, 0x1E, 0x0F, 0x07, 0xC7, 0x7F, 0x1F, 0x00,
|
||||
/* 'K' 0x4B */ 0xC0, 0x3E, 0x03, 0xB0, 0x39, 0x83, 0x8C, 0x38, 0x63, 0x83, 0x38, 0x19, 0xC0, 0xDE, 0x07, 0xB8, 0x38, 0xE1, 0x83, 0x0C, 0x1C, 0x60, 0x73, 0x01, 0x98, 0x0E, 0xC0, 0x3E, 0x00, 0xC0,
|
||||
/* 'L' 0x4C */ 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xFF, 0xFF, 0xF0,
|
||||
/* 'M' 0x4D */ 0xE0, 0x07, 0xE0, 0x07, 0xF0, 0x0F, 0xF0, 0x0F, 0xD0, 0x0F, 0xD8, 0x1B, 0xD8, 0x1B, 0xD8, 0x1B, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xC6, 0x63, 0xC6, 0x63, 0xC6, 0x63, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC1, 0x83,
|
||||
/* 'N' 0x4E */ 0xE0, 0x1F, 0x00, 0xFC, 0x07, 0xE0, 0x3D, 0x81, 0xEE, 0x0F, 0x30, 0x79, 0xC3, 0xC6, 0x1E, 0x18, 0xF0, 0xE7, 0x83, 0x3C, 0x1D, 0xE0, 0x6F, 0x01, 0xF8, 0x0F, 0xC0, 0x3E, 0x01, 0xC0,
|
||||
/* 'O' 0x4F */ 0x07, 0xF0, 0x0F, 0xFE, 0x0F, 0x07, 0x86, 0x00, 0xC6, 0x00, 0x33, 0x00, 0x1B, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0x78, 0x00, 0x36, 0x00, 0x33, 0x00, 0x18, 0xC0, 0x18, 0x78, 0x3C, 0x1F, 0xFC, 0x03, 0xF8, 0x00,
|
||||
/* 'P' 0x50 */ 0xFF, 0x8F, 0xFE, 0xC0, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x06, 0xFF, 0xEF, 0xFC, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00,
|
||||
/* 'Q' 0x51 */ 0x07, 0xF0, 0x0F, 0xFE, 0x0F, 0x07, 0x86, 0x00, 0xC6, 0x00, 0x33, 0x00, 0x1B, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0x78, 0x00, 0x36, 0x00, 0x33, 0x01, 0x98, 0xC0, 0xFC, 0x78, 0x3C, 0x1F, 0xFF, 0x03, 0xF9, 0x80, 0x00, 0x40,
|
||||
/* 'R' 0x52 */ 0xFF, 0xE3, 0xFF, 0xCC, 0x03, 0xB0, 0x06, 0xC0, 0x1B, 0x00, 0x6C, 0x01, 0xB0, 0x0C, 0xFF, 0xE3, 0xFF, 0xCC, 0x03, 0xB0, 0x06, 0xC0, 0x1B, 0x00, 0x6C, 0x01, 0xB0, 0x06, 0xC0, 0x1B, 0x00, 0x70,
|
||||
/* 'S' 0x53 */ 0x0F, 0xE0, 0x7F, 0xC3, 0x83, 0x98, 0x07, 0x60, 0x0D, 0x80, 0x07, 0x00, 0x1E, 0x00, 0x3F, 0x80, 0x3F, 0xC0, 0x0F, 0x80, 0x07, 0xC0, 0x0F, 0x00, 0x3E, 0x00, 0xDE, 0x0E, 0x3F, 0xF0, 0x3F, 0x80,
|
||||
/* 'T' 0x54 */ 0xFF, 0xFF, 0xFF, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60,
|
||||
/* 'U' 0x55 */ 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x80, 0xEE, 0x0E, 0x3F, 0xE0, 0xFC, 0x00,
|
||||
/* 'V' 0x56 */ 0xC0, 0x0F, 0x00, 0x7E, 0x01, 0x98, 0x06, 0x60, 0x39, 0xC0, 0xC3, 0x03, 0x0C, 0x1C, 0x38, 0x60, 0x61, 0x81, 0x8E, 0x07, 0x30, 0x0C, 0xC0, 0x37, 0x00, 0xF8, 0x01, 0xE0, 0x07, 0x80, 0x1C, 0x00,
|
||||
/* 'W' 0x57 */ 0xE0, 0x30, 0x1D, 0x80, 0xE0, 0x76, 0x07, 0x81, 0xDC, 0x1E, 0x06, 0x70, 0x7C, 0x18, 0xC1, 0xB0, 0xE3, 0x0C, 0xC3, 0x8C, 0x33, 0x0C, 0x38, 0xC6, 0x30, 0x67, 0x18, 0xC1, 0x98, 0x67, 0x06, 0x61, 0xD8, 0x1D, 0x83, 0x60, 0x3C, 0x0D, 0x80, 0xF0, 0x3E, 0x03, 0xC0, 0x70, 0x0F, 0x01, 0xC0, 0x18, 0x07, 0x00,
|
||||
/* 'X' 0x58 */ 0xE0, 0x1D, 0x80, 0xE7, 0x03, 0x0E, 0x1C, 0x18, 0x60, 0x73, 0x00, 0xFC, 0x01, 0xE0, 0x07, 0x00, 0x1E, 0x00, 0xF8, 0x03, 0x30, 0x1C, 0xE0, 0xE1, 0x83, 0x07, 0x1C, 0x0E, 0xE0, 0x1B, 0x00, 0x70,
|
||||
/* 'Y' 0x59 */ 0xC0, 0x0F, 0x80, 0x76, 0x01, 0x9C, 0x0C, 0x38, 0x70, 0x61, 0x81, 0xCE, 0x03, 0x30, 0x0F, 0x80, 0x1E, 0x00, 0x30, 0x00, 0xC0, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x03, 0x00, 0x0C, 0x00,
|
||||
/* 'Z' 0x5A */ 0xFF, 0xFF, 0xFF, 0xC0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0x60, 0x07, 0x00, 0x70, 0x07, 0x00, 0x30, 0x03, 0x80, 0x38, 0x03, 0x80, 0x18, 0x01, 0xC0, 0x1C, 0x00, 0xFF, 0xFF, 0xFF, 0xC0,
|
||||
/* '[' 0x5B */ 0xFF, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCF, 0xF0,
|
||||
/* '\' 0x5C */ 0x81, 0x81, 0x02, 0x06, 0x04, 0x08, 0x18, 0x10, 0x20, 0x60, 0x40, 0x81, 0x81, 0x02, 0x06, 0x04,
|
||||
/* ']' 0x5D */ 0xFF, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0xF0,
|
||||
/* '^' 0x5E */ 0x0C, 0x0E, 0x05, 0x86, 0xC3, 0x21, 0x19, 0x8C, 0x83, 0xC1, 0x80,
|
||||
/* '_' 0x5F */ 0xFF, 0xFE,
|
||||
/* '`' 0x60 */ 0xE3, 0x8C, 0x30,
|
||||
/* 'a' 0x61 */ 0x3F, 0x07, 0xF8, 0xE1, 0xCC, 0x0C, 0x00, 0xC0, 0x1C, 0x3F, 0xCF, 0x8C, 0xC0, 0xCC, 0x0C, 0xE3, 0xC7, 0xEF, 0x3C, 0x70,
|
||||
/* 'b' 0x62 */ 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0xF8, 0xDF, 0xCF, 0x0E, 0xE0, 0x7C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xE0, 0x6F, 0x0E, 0xDF, 0xCC, 0xF8,
|
||||
/* 'c' 0x63 */ 0x1F, 0x0F, 0xE6, 0x1F, 0x83, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x38, 0x37, 0x1C, 0xFE, 0x1F, 0x00,
|
||||
/* 'd' 0x64 */ 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x3C, 0xCF, 0xFB, 0x8F, 0xE0, 0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF8, 0x3B, 0x8F, 0x3F, 0x63, 0xCC,
|
||||
/* 'e' 0x65 */ 0x1F, 0x07, 0xF1, 0xC7, 0x70, 0x3C, 0x07, 0xFF, 0xFF, 0xFE, 0x00, 0xC0, 0x1C, 0x0D, 0xC3, 0x1F, 0xC1, 0xF0,
|
||||
/* 'f' 0x66 */ 0x3B, 0xD8, 0xC6, 0x7F, 0xEC, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x00,
|
||||
/* 'g' 0x67 */ 0x1E, 0x67, 0xFD, 0xC7, 0xF0, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x7C, 0x1D, 0xC7, 0x9F, 0xB1, 0xE6, 0x00, 0xC0, 0x3E, 0x0E, 0x7F, 0xC7, 0xE0,
|
||||
/* 'h' 0x68 */ 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x33, 0xCD, 0xFB, 0xC7, 0xE0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x30,
|
||||
/* 'i' 0x69 */ 0xF0, 0x3F, 0xFF, 0xFF, 0xF0,
|
||||
/* 'j' 0x6A */ 0x33, 0x00, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0xE0,
|
||||
/* 'k' 0x6B */ 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x6C, 0x33, 0x18, 0xCC, 0x37, 0x0F, 0xC3, 0xB8, 0xC6, 0x31, 0xCC, 0x3B, 0x06, 0xC1, 0xF0, 0x30,
|
||||
/* 'l' 0x6C */ 0xFF, 0xFF, 0xFF, 0xFF, 0xF0,
|
||||
/* 'm' 0x6D */ 0xCF, 0x1F, 0x6F, 0xDF, 0xFC, 0x78, 0xFC, 0x18, 0x3C, 0x0C, 0x1E, 0x06, 0x0F, 0x03, 0x07, 0x81, 0x83, 0xC0, 0xC1, 0xE0, 0x60, 0xF0, 0x30, 0x78, 0x18, 0x3C, 0x0C, 0x18,
|
||||
/* 'n' 0x6E */ 0xCF, 0x37, 0xEF, 0x1F, 0x83, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xC0,
|
||||
/* 'o' 0x6F */ 0x1F, 0x07, 0xF1, 0xC7, 0x70, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x7C, 0x1D, 0xC7, 0x1F, 0xC1, 0xF0,
|
||||
/* 'p' 0x70 */ 0xCF, 0x8D, 0xFC, 0xF0, 0xEE, 0x06, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3E, 0x06, 0xF0, 0xEF, 0xFC, 0xCF, 0x8C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x00,
|
||||
/* 'q' 0x71 */ 0x1E, 0x67, 0xFD, 0xC7, 0xF0, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x7C, 0x1D, 0xC7, 0x9F, 0xF1, 0xE6, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60,
|
||||
/* 'r' 0x72 */ 0xCF, 0x7F, 0x38, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC0,
|
||||
/* 's' 0x73 */ 0x3E, 0x1F, 0xEE, 0x1B, 0x00, 0xC0, 0x3C, 0x07, 0xF0, 0x3F, 0x01, 0xF0, 0x3E, 0x1D, 0xFE, 0x3F, 0x00,
|
||||
/* 't' 0x74 */ 0x63, 0x19, 0xFF, 0xB1, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0xE7,
|
||||
/* 'u' 0x75 */ 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x7E, 0x3D, 0xFB, 0x3C, 0xC0,
|
||||
/* 'v' 0x76 */ 0xE0, 0x6C, 0x0D, 0x81, 0xB8, 0x63, 0x0C, 0x61, 0x8E, 0x60, 0xCC, 0x19, 0x83, 0xE0, 0x3C, 0x07, 0x00, 0xE0,
|
||||
/* 'w' 0x77 */ 0xC1, 0xC1, 0xB0, 0xE1, 0xD8, 0x70, 0xCC, 0x2C, 0x66, 0x36, 0x31, 0x9B, 0x18, 0xCD, 0x98, 0x64, 0x6C, 0x16, 0x36, 0x0F, 0x1A, 0x07, 0x8F, 0x03, 0x83, 0x80, 0xC1, 0xC0,
|
||||
/* 'x' 0x78 */ 0xC1, 0xF8, 0x66, 0x30, 0xCC, 0x3E, 0x07, 0x00, 0xC0, 0x78, 0x36, 0x0C, 0xC6, 0x3B, 0x06, 0xC0, 0xC0,
|
||||
/* 'y' 0x79 */ 0xE0, 0x6C, 0x0D, 0x83, 0x38, 0x63, 0x0C, 0x63, 0x0C, 0x60, 0xCC, 0x1B, 0x03, 0x60, 0x3C, 0x07, 0x00, 0xE0, 0x18, 0x03, 0x00, 0xE0, 0x78, 0x0E, 0x00,
|
||||
/* 'z' 0x7A */ 0xFF, 0xFF, 0xF0, 0x18, 0x0C, 0x07, 0x03, 0x81, 0xC0, 0x60, 0x30, 0x18, 0x0E, 0x03, 0xFF, 0xFF, 0xC0,
|
||||
/* '{' 0x7B */ 0x19, 0xCC, 0x63, 0x18, 0xC6, 0x31, 0x99, 0x86, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x1C, 0x60,
|
||||
/* '|' 0x7C */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
|
||||
/* '}' 0x7D */ 0xC7, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x0C, 0x33, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x73, 0x00,
|
||||
/* '~' 0x7E */ 0x70, 0x3E, 0x09, 0xE4, 0x1F, 0x03, 0x80,
|
||||
/* 0x7F */
|
||||
/* 0x80 */ 0x01, 0xF0, 0x1F, 0xF0, 0xE0, 0xC7, 0x00, 0x18, 0x00, 0xC0, 0x07, 0xFF, 0x3F, 0xFC, 0x30, 0x01, 0xFF, 0x8F, 0xFC, 0x0C, 0x00, 0x18, 0x00, 0x70, 0x00, 0xE0, 0x81, 0xFE, 0x03, 0xF0,
|
||||
/* 0x81 */
|
||||
/* 0x82 */ 0xF5, 0x80,
|
||||
/* 0x83 */ 0x1C, 0xF3, 0x0C, 0x31, 0xF7, 0xCC, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x33, 0xCE, 0x00,
|
||||
/* 0x84 */ 0xCF, 0x34, 0x51, 0x88,
|
||||
/* 0x85 */ 0xC6, 0x3C, 0x63,
|
||||
/* 0x86 */ 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x3F, 0xFF, 0xFC, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x00,
|
||||
/* 0x87 */ 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x3F, 0xFF, 0xFC, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x0F, 0xFF, 0xFF, 0x0C, 0x03, 0x00, 0xC0, 0x30,
|
||||
/* 0x88 */ 0x38, 0xD9, 0xB6, 0x30,
|
||||
/* 0x89 */ 0x38, 0x18, 0x00, 0xF8, 0x30, 0x03, 0x18, 0xC0, 0x04, 0x11, 0x80, 0x0C, 0x66, 0x00, 0x0F, 0x8C, 0x00, 0x0E, 0x30, 0x00, 0x00, 0x40, 0x00, 0x01, 0x80, 0x00, 0x06, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x31, 0xC0, 0xE0, 0x67, 0xC3, 0xC1, 0x98, 0xCC, 0xC3, 0x20, 0x90, 0x8C, 0x63, 0x33, 0x10, 0x7C, 0x3C, 0x60, 0x70, 0x38,
|
||||
/* 0x8A */ 0x0C, 0x40, 0x1F, 0x00, 0x38, 0x03, 0xF8, 0x1F, 0xF0, 0xE0, 0xE6, 0x01, 0xD8, 0x03, 0x60, 0x01, 0xC0, 0x07, 0x80, 0x0F, 0xE0, 0x0F, 0xF0, 0x03, 0xE0, 0x01, 0xF0, 0x03, 0xC0, 0x0F, 0x80, 0x37, 0x83, 0x8F, 0xFC, 0x0F, 0xE0,
|
||||
/* 0x8B */ 0x2F, 0x49, 0x99,
|
||||
/* 0x8C */ 0x07, 0xCF, 0xFC, 0x7F, 0xFF, 0xF3, 0x83, 0xC0, 0x18, 0x07, 0x00, 0x60, 0x0C, 0x03, 0x00, 0x30, 0x0C, 0x00, 0xC0, 0x30, 0x03, 0x00, 0xC0, 0x0F, 0xFF, 0x00, 0x3F, 0xFC, 0x00, 0xC0, 0x30, 0x03, 0x00, 0xC0, 0x0C, 0x01, 0x80, 0x30, 0x07, 0x01, 0xC0, 0x0E, 0x0F, 0x00, 0x1F, 0xEF, 0xFC, 0x1F, 0x3F, 0xF0,
|
||||
/* 0x8D */
|
||||
/* 0x8E */ 0x0C, 0xC0, 0x3C, 0x00, 0xE1, 0xFF, 0xFF, 0xFF, 0x80, 0x1C, 0x01, 0xC0, 0x1C, 0x00, 0xC0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0x60, 0x07, 0x00, 0x70, 0x07, 0x00, 0x30, 0x03, 0x80, 0x38, 0x01, 0xFF, 0xFF, 0xFF, 0x80,
|
||||
/* 0x8F */
|
||||
/* 0x90 */
|
||||
/* 0x91 */ 0x6A, 0xF0,
|
||||
/* 0x92 */ 0xF5, 0x60,
|
||||
/* 0x93 */ 0x4E, 0x28, 0xA2, 0xCF, 0x30,
|
||||
/* 0x94 */ 0xCF, 0x34, 0x51, 0x4E, 0x20,
|
||||
/* 0x95 */ 0x7B, 0xFF, 0xFF, 0xFD, 0xE0,
|
||||
/* 0x96 */ 0xFF, 0xFF, 0xF0,
|
||||
/* 0x97 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0,
|
||||
/* 0x98 */ 0x63, 0xFE, 0x70,
|
||||
/* 0x99 */ 0xFF, 0x70, 0x1F, 0xFD, 0xC0, 0x71, 0x87, 0x83, 0xC6, 0x1E, 0x0F, 0x18, 0x68, 0x3C, 0x61, 0xB1, 0xB1, 0x86, 0xC6, 0xC6, 0x19, 0x1B, 0x18, 0x66, 0xCC, 0x61, 0x9B, 0x31, 0x86, 0x3C, 0xC6, 0x18, 0xE3, 0x18, 0x63, 0x8C,
|
||||
/* 0x9A */ 0x63, 0x0D, 0x83, 0x60, 0x70, 0x00, 0x0F, 0x87, 0xFB, 0x86, 0xC0, 0x30, 0x0F, 0x01, 0xFC, 0x0F, 0xC0, 0x7C, 0x0F, 0x87, 0x7F, 0x8F, 0xC0,
|
||||
/* 0x9B */ 0x99, 0x92, 0xF4,
|
||||
/* 0x9C */ 0x1F, 0x0F, 0x83, 0xF9, 0xFC, 0x71, 0xF8, 0x6E, 0x0F, 0x03, 0xC0, 0x60, 0x3C, 0x07, 0xFF, 0xC0, 0x7F, 0xFC, 0x06, 0x00, 0xC0, 0x60, 0x0E, 0x0F, 0x03, 0x71, 0xF8, 0x63, 0xF9, 0xFC, 0x1F, 0x0F, 0x80,
|
||||
/* 0x9D */
|
||||
/* 0x9E */ 0x63, 0x0C, 0x83, 0x60, 0x70, 0x00, 0x3F, 0xFF, 0xFC, 0x06, 0x03, 0x01, 0xC0, 0xE0, 0x70, 0x18, 0x0C, 0x06, 0x03, 0x80, 0xFF, 0xFF, 0xF0,
|
||||
/* 0x9F */ 0x0C, 0xC0, 0x33, 0x00, 0x00, 0x30, 0x03, 0xE0, 0x1D, 0x80, 0x67, 0x03, 0x0E, 0x1C, 0x18, 0x60, 0x73, 0x80, 0xCC, 0x03, 0xE0, 0x07, 0x80, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x03, 0x00,
|
||||
/* 0xA0 */
|
||||
/* 0xA1 */ 0xF0, 0xBF, 0xFF, 0xFF, 0xF0,
|
||||
/* 0xA2 */ 0x04, 0x00, 0x80, 0x7C, 0x1F, 0xE7, 0x4C, 0xC8, 0xF1, 0x1E, 0x20, 0xC4, 0x18, 0x83, 0x10, 0x72, 0x37, 0x4E, 0x7F, 0x87, 0xC0, 0x20, 0x04, 0x00,
|
||||
/* 0xA3 */ 0x0F, 0xC1, 0xFE, 0x38, 0x76, 0x03, 0x60, 0x36, 0x00, 0x70, 0x03, 0x80, 0xFF, 0x0F, 0xF0, 0x1C, 0x00, 0xC0, 0x0C, 0x01, 0x80, 0x10, 0x02, 0xF1, 0x7F, 0xF6, 0x1F,
|
||||
/* 0xA4 */ 0xDD, 0xFF, 0xD8, 0xD8, 0x3C, 0x1E, 0x0F, 0x8D, 0xFF, 0xDD, 0x80,
|
||||
/* 0xA5 */ 0xC0, 0x3E, 0x06, 0x60, 0x63, 0x0C, 0x30, 0xC1, 0x98, 0x19, 0x80, 0xF0, 0x0F, 0x07, 0xFE, 0x06, 0x00, 0x60, 0x7F, 0xE0, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00,
|
||||
/* 0xA6 */ 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFC,
|
||||
/* 0xA7 */ 0x0F, 0x03, 0xF0, 0xE7, 0x18, 0x63, 0x0C, 0x70, 0x07, 0x03, 0xF8, 0xC3, 0x98, 0x3B, 0x03, 0xF0, 0x37, 0x06, 0x78, 0xC7, 0xB0, 0x7C, 0x03, 0x80, 0x39, 0x83, 0x30, 0x67, 0x1C, 0x7F, 0x07, 0xC0,
|
||||
/* 0xA8 */ 0xCF, 0x30,
|
||||
/* 0xA9 */ 0x03, 0xF0, 0x03, 0xFF, 0x01, 0xE0, 0xE0, 0xE3, 0x1C, 0x73, 0xF3, 0x99, 0x86, 0x6C, 0xC1, 0x8F, 0x30, 0x03, 0xCC, 0x00, 0xF3, 0x00, 0x3C, 0xC1, 0x8D, 0x98, 0x66, 0x77, 0xF3, 0x8E, 0x79, 0xC1, 0xC0, 0xE0, 0x3F, 0xF0, 0x03, 0xF0, 0x00,
|
||||
/* 0xAA */ 0x79, 0x08, 0x11, 0xEE, 0x50, 0xA3, 0x3B, 0x00, 0x03, 0xF8,
|
||||
/* 0xAB */ 0x21, 0x63, 0xE7, 0x84, 0x84, 0xE7, 0x63, 0x21,
|
||||
/* 0xAC */ 0xFF, 0xFF, 0xFF, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03,
|
||||
/* 0xAD */ 0xFF, 0xF0,
|
||||
/* 0xAE */ 0x03, 0xF0, 0x03, 0xFF, 0x01, 0xE0, 0xE0, 0xFF, 0x1C, 0x7F, 0xF3, 0x9B, 0x04, 0x6C, 0xC1, 0x8F, 0x30, 0x43, 0xCF, 0xF0, 0xF3, 0xFC, 0x3C, 0xC1, 0x0D, 0xB0, 0x66, 0x7C, 0x1B, 0x8F, 0x07, 0xC1, 0xC0, 0xE0, 0x3F, 0xF0, 0x03, 0xF0, 0x00,
|
||||
/* 0xAF */ 0xFF, 0xF0,
|
||||
/* 0xB0 */ 0x38, 0xFB, 0x1C, 0x18, 0x38, 0xDF, 0x1C,
|
||||
/* 0xB1 */ 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x7F, 0xE7, 0xFE, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xF0,
|
||||
/* 0xB2 */ 0x7D, 0x8F, 0x18, 0x30, 0xC6, 0x18, 0x60, 0xFF, 0xFC,
|
||||
/* 0xB3 */ 0x7D, 0x8F, 0x18, 0x31, 0x80, 0xC1, 0xE3, 0xC6, 0xF8,
|
||||
/* 0xB4 */ 0x3B, 0x99, 0x80,
|
||||
/* 0xB5 */ 0xC0, 0xCC, 0x0C, 0xC0, 0xCC, 0x0C, 0xC0, 0xCC, 0x0C, 0xC0, 0xCC, 0x0C, 0xC0, 0xCC, 0x1C, 0xE3, 0xCF, 0xEF, 0xFC, 0x7C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x00,
|
||||
/* 0xB6 */ 0x1F, 0xE7, 0xFD, 0xF3, 0x7E, 0x6F, 0xCD, 0xF9, 0xBF, 0x37, 0xE6, 0x7C, 0xCF, 0x98, 0xF3, 0x06, 0x60, 0xCC, 0x19, 0x83, 0x30, 0x66, 0x0C, 0xC1, 0x98, 0x33, 0x06, 0x60, 0xCC,
|
||||
/* 0xB7 */ 0xF0,
|
||||
/* 0xB8 */ 0x10, 0xF0, 0xE3, 0x78,
|
||||
/* 0xB9 */ 0x2F, 0xB6, 0xDB, 0x6C,
|
||||
/* 0xBA */ 0x79, 0x38, 0x61, 0x86, 0x1C, 0xDE, 0x00, 0x0F, 0xC0,
|
||||
/* 0xBB */ 0x88, 0xC6, 0xE7, 0x21, 0x21, 0xE7, 0xC6, 0x88,
|
||||
/* 0xBC */ 0x20, 0x08, 0x30, 0x0C, 0x38, 0x04, 0x0C, 0x06, 0x06, 0x02, 0x03, 0x02, 0x01, 0x81, 0x00, 0xC1, 0x06, 0x61, 0x87, 0x30, 0x83, 0x80, 0xC2, 0xC0, 0x42, 0x60, 0x43, 0x30, 0x21, 0xFC, 0x20, 0x0C, 0x30, 0x06, 0x10, 0x03, 0x00,
|
||||
/* 0xBD */ 0x20, 0x00, 0x08, 0x02, 0x06, 0x01, 0x83, 0x80, 0x40, 0x60, 0x20, 0x18, 0x18, 0x06, 0x04, 0x01, 0x83, 0x00, 0x61, 0x9F, 0x98, 0x4E, 0x76, 0x33, 0x0C, 0x08, 0x03, 0x04, 0x03, 0x83, 0x01, 0x80, 0x81, 0x80, 0x60, 0xC0, 0x30, 0x3F, 0xC8, 0x0F, 0xF0,
|
||||
/* 0xBE */ 0x7C, 0x00, 0x18, 0xC0, 0x43, 0x18, 0x18, 0x03, 0x02, 0x00, 0x60, 0xC0, 0x30, 0x10, 0x01, 0x84, 0x00, 0x31, 0x80, 0xC6, 0x20, 0xD8, 0xC8, 0x39, 0xF1, 0x07, 0x00, 0x41, 0x60, 0x18, 0x4C, 0x02, 0x11, 0x80, 0x83, 0xF8, 0x10, 0x06, 0x04, 0x00, 0xC1, 0x00, 0x18,
|
||||
/* 0xBF */ 0x0C, 0x06, 0x00, 0x00, 0x00, 0xC0, 0x60, 0x60, 0x30, 0x30, 0x38, 0x38, 0x18, 0x0C, 0x06, 0x0F, 0x07, 0xC7, 0x7F, 0x1F, 0x00,
|
||||
/* 0xC0 */ 0x0C, 0xDB, 0xD3, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
/* 0xC1 */ 0x03, 0x80, 0x07, 0x00, 0x1B, 0x00, 0x36, 0x00, 0xEE, 0x01, 0x8C, 0x03, 0x18, 0x0C, 0x18, 0x18, 0x30, 0x30, 0x60, 0xFF, 0xE1, 0xFF, 0xC7, 0x01, 0xCC, 0x01, 0x98, 0x03, 0x60, 0x03, 0xC0, 0x06,
|
||||
/* 0xC2 */ 0xFF, 0x87, 0xFF, 0x30, 0x1D, 0x80, 0x6C, 0x03, 0x60, 0x1B, 0x01, 0x9F, 0xFC, 0xFF, 0xE6, 0x03, 0xB0, 0x0F, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0xDF, 0xFE, 0xFF, 0xC0,
|
||||
/* 0xC3 */ 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x00,
|
||||
/* 0xC4 */ 0x01, 0xC0, 0x01, 0xC0, 0x03, 0x60, 0x03, 0x60, 0x07, 0x60, 0x06, 0x30, 0x06, 0x30, 0x0C, 0x18, 0x0C, 0x18, 0x1C, 0x18, 0x18, 0x0C, 0x18, 0x0C, 0x30, 0x06, 0x30, 0x06, 0x70, 0x06, 0x7F, 0xFF, 0x7F, 0xFF,
|
||||
/* 0xC5 */ 0xFF, 0xFF, 0xFF, 0xF0, 0x01, 0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x1F, 0xFE, 0xFF, 0xF6, 0x00, 0x30, 0x01, 0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x1F, 0xFF, 0xFF, 0xF8,
|
||||
/* 0xC6 */ 0x7F, 0xFD, 0xFF, 0xF0, 0x01, 0x80, 0x0C, 0x00, 0x60, 0x03, 0x80, 0x1C, 0x00, 0x60, 0x03, 0x00, 0x18, 0x00, 0xE0, 0x07, 0x00, 0x18, 0x00, 0xC0, 0x06, 0x00, 0x3F, 0xFF, 0xFF, 0xFC,
|
||||
/* 0xC7 */ 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,
|
||||
/* 0xC8 */ 0x07, 0xF0, 0x0F, 0xFE, 0x0F, 0x07, 0x8E, 0x00, 0xE6, 0x00, 0x37, 0x00, 0x1F, 0x00, 0x07, 0x9F, 0xF3, 0xCF, 0xF9, 0xE0, 0x00, 0xF0, 0x00, 0x7C, 0x00, 0x76, 0x00, 0x33, 0x80, 0x38, 0xF0, 0x78, 0x3F, 0xF8, 0x07, 0xF0, 0x00,
|
||||
/* 0xC9 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xC0,
|
||||
/* 0xCA */ 0xC0, 0x3B, 0x01, 0xCC, 0x0E, 0x30, 0x70, 0xC3, 0x83, 0x1C, 0x0C, 0xE0, 0x37, 0x80, 0xFF, 0x03, 0xDC, 0x0E, 0x38, 0x30, 0x70, 0xC0, 0xE3, 0x03, 0x8C, 0x07, 0x30, 0x0E, 0xC0, 0x1C,
|
||||
/* 0xCB */ 0x01, 0xC0, 0x00, 0xE0, 0x00, 0xD8, 0x00, 0x6C, 0x00, 0x37, 0x00, 0x31, 0x80, 0x18, 0xC0, 0x18, 0x30, 0x0C, 0x18, 0x0E, 0x0E, 0x06, 0x03, 0x03, 0x01, 0x83, 0x00, 0x61, 0x80, 0x31, 0xC0, 0x1C, 0xC0, 0x06, 0x60, 0x03, 0x00,
|
||||
/* 0xCC */ 0xE0, 0x0F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80, 0xFD, 0x83, 0x7B, 0x06, 0xF6, 0x0D, 0xE4, 0x13, 0xCC, 0x67, 0x98, 0xCF, 0x31, 0x9E, 0x36, 0x3C, 0x6C, 0x78, 0xD8, 0xF0, 0xA1, 0xE1, 0xC3, 0xC3, 0x86,
|
||||
/* 0xCD */ 0xC0, 0x1F, 0x00, 0xFC, 0x07, 0xE0, 0x3D, 0x81, 0xEE, 0x0F, 0x30, 0x78, 0xC3, 0xC7, 0x1E, 0x18, 0xF0, 0x67, 0x83, 0xBC, 0x0D, 0xE0, 0x3F, 0x01, 0xF8, 0x07, 0xC0, 0x18,
|
||||
/* 0xCE */ 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFE, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFC,
|
||||
/* 0xCF */ 0x07, 0xF0, 0x0F, 0xFE, 0x0F, 0x07, 0x8E, 0x00, 0xE6, 0x00, 0x37, 0x00, 0x1F, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0x7C, 0x00, 0x76, 0x00, 0x33, 0x80, 0x38, 0xF0, 0x78, 0x3F, 0xF8, 0x07, 0xF0, 0x00,
|
||||
/* 0xD0 */ 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x18,
|
||||
/* 0xD1 */ 0xFF, 0xC7, 0xFF, 0xB0, 0x0D, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x06, 0xFF, 0xF7, 0xFE, 0x30, 0x01, 0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x18, 0x00, 0xC0, 0x00,
|
||||
/* 0xD2 */
|
||||
/* 0xD3 */ 0xFF, 0xEF, 0xFE, 0xC0, 0x06, 0x00, 0x30, 0x01, 0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x0F, 0xFF, 0xFF, 0xF0,
|
||||
/* 0xD4 */ 0xFF, 0xFF, 0xFF, 0xF0, 0x30, 0x00, 0xC0, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x03, 0x00,
|
||||
/* 0xD5 */ 0xE0, 0x07, 0x60, 0x0E, 0x30, 0x1C, 0x38, 0x1C, 0x1C, 0x38, 0x0E, 0x70, 0x06, 0x60, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
|
||||
/* 0xD6 */ 0x01, 0x80, 0x01, 0x80, 0x0F, 0xF0, 0x3F, 0xFC, 0x71, 0x8E, 0x61, 0x86, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0x61, 0x86, 0x71, 0x8E, 0x3F, 0xFC, 0x0F, 0xF0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
|
||||
/* 0xD7 */ 0x70, 0x1C, 0x70, 0x70, 0x61, 0xC0, 0xE3, 0x80, 0xEE, 0x00, 0xD8, 0x01, 0xF0, 0x01, 0xC0, 0x03, 0x80, 0x0D, 0x80, 0x3B, 0x80, 0x77, 0x01, 0xC7, 0x07, 0x07, 0x0E, 0x06, 0x38, 0x0E, 0xE0, 0x0E,
|
||||
/* 0xD8 */ 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0x61, 0x86, 0x79, 0x9E, 0x3F, 0xFC, 0x0F, 0xF0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
|
||||
/* 0xD9 */ 0x07, 0xE0, 0x1F, 0xF8, 0x38, 0x3C, 0x70, 0x0E, 0x60, 0x06, 0xE0, 0x07, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0x60, 0x06, 0x60, 0x06, 0x30, 0x0C, 0x1C, 0x38, 0xFE, 0x7F, 0xFE, 0x7F,
|
||||
/* 0xDA */ 0xCF, 0x30, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C,
|
||||
/* 0xDB */ 0x06, 0x60, 0x06, 0x60, 0x00, 0x00, 0xE0, 0x07, 0x60, 0x0E, 0x30, 0x1C, 0x38, 0x1C, 0x1C, 0x38, 0x0E, 0x70, 0x06, 0x60, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
|
||||
/* 0xDC */ 0x03, 0x80, 0x30, 0x06, 0x00, 0x00, 0x1E, 0x33, 0xFB, 0x71, 0xFE, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6E, 0x0E, 0x71, 0xF3, 0xFF, 0x1F, 0x30,
|
||||
/* 0xDD */ 0x0C, 0x0C, 0x04, 0x00, 0x03, 0xE3, 0xFF, 0x8D, 0x80, 0xE0, 0x3E, 0x1F, 0x1C, 0x0C, 0x06, 0x0B, 0x8E, 0xFE, 0x3E, 0x00,
|
||||
/* 0xDE */ 0x07, 0x01, 0x80, 0xC0, 0x00, 0xCF, 0x3F, 0xEE, 0x1F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30,
|
||||
/* 0xDF */ 0x76, 0xC0, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60,
|
||||
/* 0xE0 */ 0x0C, 0x1B, 0x66, 0x98, 0x00, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x36, 0x19, 0xFE, 0x1E, 0x00,
|
||||
/* 0xE1 */ 0x1E, 0x33, 0xFB, 0x71, 0xFE, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x6E, 0x0E, 0x71, 0xF3, 0xFF, 0x1F, 0x30,
|
||||
/* 0xE2 */ 0x1F, 0x0F, 0xF1, 0x87, 0x60, 0x6C, 0x0D, 0x83, 0x33, 0x86, 0x7C, 0xC1, 0xD8, 0x1F, 0x01, 0xE0, 0x3C, 0x07, 0xC0, 0xFC, 0x36, 0xFE, 0xCF, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x00,
|
||||
/* 0xE3 */ 0x60, 0x66, 0x06, 0x60, 0x63, 0x0C, 0x30, 0xC3, 0x8C, 0x19, 0x81, 0x98, 0x1F, 0x80, 0xF0, 0x0F, 0x00, 0xF0, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60,
|
||||
/* 0xE4 */ 0x7F, 0xCF, 0xF8, 0xE0, 0x07, 0x01, 0xF0, 0x7F, 0x1C, 0x77, 0x07, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0xC1, 0x9C, 0x71, 0xFC, 0x1F, 0x00,
|
||||
/* 0xE5 */ 0x3E, 0x3F, 0xF8, 0xD8, 0x0E, 0x03, 0xE1, 0xF1, 0xC0, 0xC0, 0x60, 0xB8, 0xEF, 0xE3, 0xE0,
|
||||
/* 0xE6 */ 0x3F, 0x9F, 0xC0, 0xC1, 0xC1, 0xC0, 0xC0, 0xC0, 0xC0, 0x60, 0x70, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x80, 0xFC, 0x3F, 0x80, 0xC0, 0x60, 0x70, 0xF0, 0x70,
|
||||
/* 0xE7 */ 0xCF, 0x3F, 0xEE, 0x1F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30,
|
||||
/* 0xE8 */ 0x1F, 0x07, 0xF1, 0xC7, 0x30, 0x6C, 0x07, 0x80, 0xF0, 0x1F, 0xFF, 0xFF, 0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x0E, 0xC1, 0x9C, 0x71, 0xFC, 0x1F, 0x00,
|
||||
/* 0xE9 */ 0xFF, 0xFF, 0xFF, 0xC0,
|
||||
/* 0xEA */ 0xC1, 0xB0, 0xCC, 0x63, 0x30, 0xD8, 0x3C, 0x0F, 0x83, 0x60, 0xCC, 0x31, 0x8C, 0x73, 0x0C, 0xC1, 0x80,
|
||||
/* 0xEB */ 0x0C, 0x00, 0x60, 0x01, 0x80, 0x0C, 0x00, 0x60, 0x01, 0x80, 0x1C, 0x00, 0xF0, 0x0D, 0x80, 0x6C, 0x06, 0x30, 0x31, 0x83, 0x8E, 0x18, 0x30, 0xC1, 0x8C, 0x06, 0x60, 0x30,
|
||||
/* 0xEC */ 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF8, 0x7E, 0x1F, 0xFF, 0xDE, 0xF0, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x00,
|
||||
/* 0xED */ 0xC0, 0x78, 0x0D, 0x83, 0x30, 0x66, 0x0C, 0x63, 0x0C, 0x60, 0xD8, 0x1B, 0x03, 0x60, 0x38, 0x07, 0x00, 0x40,
|
||||
/* 0xEE */ 0x1F, 0x1F, 0x9C, 0x0C, 0x07, 0x01, 0xF8, 0x3C, 0x70, 0x70, 0x30, 0x30, 0x18, 0x0C, 0x06, 0x01, 0xC0, 0xFC, 0x1F, 0x00, 0xC0, 0x60, 0x70, 0xF0, 0x70,
|
||||
/* 0xEF */ 0x1F, 0x07, 0xF1, 0xC7, 0x70, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x7C, 0x1D, 0xC7, 0x1F, 0xC1, 0xF0,
|
||||
/* 0xF0 */ 0xFF, 0xFF, 0xFF, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
/* 0xF1 */ 0x1F, 0x07, 0xF1, 0xC7, 0x70, 0x6C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x7C, 0x1F, 0xC7, 0x7F, 0xCD, 0xF1, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x00,
|
||||
/* 0xF2 */ 0x07, 0xE3, 0xFC, 0xE0, 0x30, 0x06, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x1C, 0x01, 0xC0, 0x1F, 0x80, 0xF8, 0x03, 0x80, 0x30, 0x0E, 0x0F, 0x81, 0xE0,
|
||||
/* 0xF3 */ 0x1F, 0xF9, 0xFF, 0xDC, 0x39, 0xC0, 0xCC, 0x03, 0x60, 0x1B, 0x00, 0xD8, 0x06, 0xC0, 0x37, 0x03, 0x9C, 0x38, 0x7F, 0x81, 0xF8, 0x00,
|
||||
/* 0xF4 */ 0xFF, 0xF3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30,
|
||||
/* 0xF5 */ 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x36, 0x19, 0xFE, 0x1E, 0x00,
|
||||
/* 0xF6 */ 0x19, 0xE0, 0xEF, 0xC6, 0x31, 0xB8, 0xC3, 0xC3, 0x0F, 0x0C, 0x3C, 0x30, 0xF0, 0xC3, 0xE3, 0x1D, 0x8C, 0x67, 0xB7, 0x0F, 0xF8, 0x0F, 0xC0, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x03, 0x00, 0x0C, 0x00,
|
||||
/* 0xF7 */ 0x60, 0x33, 0x03, 0x8C, 0x18, 0x71, 0xC1, 0x8C, 0x0E, 0xC0, 0x36, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x1B, 0x00, 0xDC, 0x0C, 0x60, 0xE3, 0x86, 0x0C, 0x70, 0x33, 0x01, 0x80,
|
||||
/* 0xF8 */ 0xC3, 0x0F, 0x0C, 0x3C, 0x30, 0xF0, 0xC3, 0xC3, 0x0F, 0x0C, 0x3C, 0x30, 0xF0, 0xC3, 0xC3, 0x0F, 0x8C, 0x77, 0x33, 0x8F, 0xFC, 0x1F, 0xE0, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x03, 0x00, 0x0C, 0x00,
|
||||
/* 0xF9 */ 0x30, 0x0C, 0x60, 0x06, 0x60, 0x06, 0xE1, 0x87, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xE1, 0x87, 0x63, 0xC6, 0x7E, 0x7E, 0x3C, 0x38,
|
||||
/* 0xFA */ 0xCF, 0x30, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C,
|
||||
/* 0xFB */ 0x33, 0x0C, 0xC0, 0x03, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xD8, 0x67, 0xF8, 0x78,
|
||||
/* 0xFC */ 0x07, 0x00, 0xC0, 0x30, 0x00, 0x01, 0xF0, 0x7F, 0x1C, 0x77, 0x07, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0xC1, 0xDC, 0x71, 0xFC, 0x1F, 0x00,
|
||||
/* 0xFD */ 0x06, 0x03, 0x00, 0x80, 0x00, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x36, 0x19, 0xFE, 0x1E, 0x00,
|
||||
/* 0xFE */ 0x00, 0xC0, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x30, 0x0C, 0x60, 0x06, 0x60, 0x06, 0xE1, 0x87, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xC1, 0x83, 0xE1, 0x87, 0x63, 0xC6, 0x7E, 0x7E, 0x3C, 0x38,
|
||||
/* 0xFF */
|
||||
};
|
||||
|
||||
const GFXglyph FreeSans12pt_Win1253Glyphs[] PROGMEM = {
|
||||
/* 0x01 */ { 0, 19, 20, 21, 1, -17 },
|
||||
/* 0x02 */ { 48, 19, 20, 21, 1, -17 },
|
||||
/* 0x03 */ { 96, 21, 20, 23, 1, -17 },
|
||||
/* 0x04 */ { 149, 21, 20, 23, 1, -17 },
|
||||
/* 0x05 */ { 202, 20, 20, 22, 1, -17 },
|
||||
/* 0x06 */ { 252, 20, 20, 22, 1, -17 },
|
||||
/* 0x07 */ { 302, 0, 0, 8, 0, 0 },
|
||||
/* 0x08 */ { 302, 23, 20, 25, 1, -17 },
|
||||
/* 0x09 */ { 360, 23, 16, 25, 1, -16 },
|
||||
/* 0x0A */ { 406, 0, 0, 8, 0, 0 },
|
||||
/* 0x0B */ { 406, 21, 20, 23, 1, -17 },
|
||||
/* 0x0C */ { 459, 19, 18, 21, 1, -15 },
|
||||
/* 0x0D */ { 502, 0, 0, 8, 0, 0 },
|
||||
/* 0x0E */ { 502, 20, 20, 22, 1, -17 },
|
||||
/* 0x0F */ { 552, 21, 21, 23, 1, -18 },
|
||||
/* 0x10 */ { 608, 19, 20, 21, 1, -17 },
|
||||
/* 0x11 */ { 656, 21, 20, 23, 1, -17 },
|
||||
/* 0x12 */ { 709, 20, 20, 22, 1, -17 },
|
||||
/* 0x13 */ { 759, 21, 20, 23, 1, -17 },
|
||||
/* 0x14 */ { 812, 21, 20, 23, 1, -17 },
|
||||
/* 0x15 */ { 865, 22, 20, 24, 1, -17 },
|
||||
/* 0x16 */ { 920, 16, 20, 18, 1, -17 },
|
||||
/* 0x17 */ { 960, 21, 20, 23, 1, -17 },
|
||||
/* 0x18 */ { 1013, 23, 20, 25, 1, -17 },
|
||||
/* 0x19 */ { 1071, 21, 20, 23, 1, -17 },
|
||||
/* 0x1A */ { 1124, 15, 19, 17, 1, -16 },
|
||||
/* 0x1B */ { 1160, 24, 21, 26, 1, -18 },
|
||||
/* 0x1C */ { 1223, 21, 20, 23, 1, -17 },
|
||||
/* 0x1D */ { 1276, 21, 21, 23, 1, -18 },
|
||||
/* 0x1E */ { 1332, 20, 20, 22, 1, -17 },
|
||||
/* 0x1F */ { 1382, 15, 20, 17, 1, -17 },
|
||||
/* ' ' 0x20 */ { 1420, 0, 0, 6, 0, 0 },
|
||||
/* '!' 0x21 */ { 1420, 2, 18, 8, 3, -16 },
|
||||
/* '"' 0x22 */ { 1425, 6, 6, 8, 1, -15 },
|
||||
/* '#' 0x23 */ { 1430, 13, 16, 13, 0, -14 },
|
||||
/* '$' 0x24 */ { 1456, 11, 20, 13, 1, -16 },
|
||||
/* '%' 0x25 */ { 1484, 20, 17, 21, 1, -15 },
|
||||
/* '&' 0x26 */ { 1527, 14, 17, 16, 1, -15 },
|
||||
/* ''' 0x27 */ { 1557, 2, 6, 5, 1, -15 },
|
||||
/* '(' 0x28 */ { 1559, 5, 23, 8, 2, -16 },
|
||||
/* ')' 0x29 */ { 1574, 5, 23, 8, 1, -16 },
|
||||
/* '*' 0x2A */ { 1589, 7, 7, 9, 1, -16 },
|
||||
/* '+' 0x2B */ { 1596, 10, 11, 14, 2, -9 },
|
||||
/* ',' 0x2C */ { 1610, 2, 6, 7, 2, 0 },
|
||||
/* '-' 0x2D */ { 1612, 6, 2, 8, 1, -6 },
|
||||
/* '.' 0x2E */ { 1614, 2, 2, 6, 2, 0 },
|
||||
/* '/' 0x2F */ { 1615, 7, 18, 7, 0, -16 },
|
||||
/* '0' 0x30 */ { 1631, 11, 17, 13, 1, -15 },
|
||||
/* '1' 0x31 */ { 1655, 5, 17, 13, 3, -15 },
|
||||
/* '2' 0x32 */ { 1666, 11, 17, 13, 1, -15 },
|
||||
/* '3' 0x33 */ { 1690, 11, 17, 13, 1, -15 },
|
||||
/* '4' 0x34 */ { 1714, 11, 17, 13, 1, -15 },
|
||||
/* '5' 0x35 */ { 1738, 11, 17, 13, 1, -15 },
|
||||
/* '6' 0x36 */ { 1762, 11, 17, 13, 1, -15 },
|
||||
/* '7' 0x37 */ { 1786, 11, 17, 13, 1, -15 },
|
||||
/* '8' 0x38 */ { 1810, 11, 17, 13, 1, -15 },
|
||||
/* '9' 0x39 */ { 1834, 11, 17, 13, 1, -15 },
|
||||
/* ':' 0x3A */ { 1858, 2, 13, 6, 2, -11 },
|
||||
/* ';' 0x3B */ { 1862, 2, 16, 6, 2, -10 },
|
||||
/* '<' 0x3C */ { 1866, 12, 11, 14, 1, -9 },
|
||||
/* '=' 0x3D */ { 1883, 12, 6, 14, 1, -7 },
|
||||
/* '>' 0x3E */ { 1892, 12, 11, 14, 1, -9 },
|
||||
/* '?' 0x3F */ { 1909, 10, 18, 13, 2, -16 },
|
||||
/* '@' 0x40 */ { 1932, 22, 21, 24, 1, -16 },
|
||||
/* 'A' 0x41 */ { 1990, 14, 18, 16, 1, -16 },
|
||||
/* 'B' 0x42 */ { 2022, 13, 18, 16, 2, -16 },
|
||||
/* 'C' 0x43 */ { 2052, 15, 18, 17, 1, -16 },
|
||||
/* 'D' 0x44 */ { 2086, 14, 18, 17, 2, -16 },
|
||||
/* 'E' 0x45 */ { 2118, 12, 18, 15, 2, -16 },
|
||||
/* 'F' 0x46 */ { 2145, 11, 18, 14, 2, -16 },
|
||||
/* 'G' 0x47 */ { 2170, 16, 18, 18, 1, -16 },
|
||||
/* 'H' 0x48 */ { 2206, 13, 18, 17, 2, -16 },
|
||||
/* 'I' 0x49 */ { 2236, 2, 18, 7, 2, -16 },
|
||||
/* 'J' 0x4A */ { 2241, 9, 18, 13, 1, -16 },
|
||||
/* 'K' 0x4B */ { 2262, 13, 18, 16, 2, -16 },
|
||||
/* 'L' 0x4C */ { 2292, 10, 18, 14, 2, -16 },
|
||||
/* 'M' 0x4D */ { 2315, 16, 18, 20, 2, -16 },
|
||||
/* 'N' 0x4E */ { 2351, 13, 18, 18, 2, -16 },
|
||||
/* 'O' 0x4F */ { 2381, 17, 18, 19, 1, -16 },
|
||||
/* 'P' 0x50 */ { 2420, 12, 18, 16, 2, -16 },
|
||||
/* 'Q' 0x51 */ { 2447, 17, 19, 19, 1, -16 },
|
||||
/* 'R' 0x52 */ { 2488, 14, 18, 17, 2, -16 },
|
||||
/* 'S' 0x53 */ { 2520, 14, 18, 16, 1, -16 },
|
||||
/* 'T' 0x54 */ { 2552, 12, 18, 15, 1, -16 },
|
||||
/* 'U' 0x55 */ { 2579, 13, 18, 17, 2, -16 },
|
||||
/* 'V' 0x56 */ { 2609, 14, 18, 15, 1, -16 },
|
||||
/* 'W' 0x57 */ { 2641, 22, 18, 22, 0, -16 },
|
||||
/* 'X' 0x58 */ { 2691, 14, 18, 16, 1, -16 },
|
||||
/* 'Y' 0x59 */ { 2723, 14, 18, 16, 1, -16 },
|
||||
/* 'Z' 0x5A */ { 2755, 13, 18, 15, 1, -16 },
|
||||
/* '[' 0x5B */ { 2785, 4, 23, 7, 2, -16 },
|
||||
/* '\' 0x5C */ { 2797, 7, 18, 7, 0, -16 },
|
||||
/* ']' 0x5D */ { 2813, 4, 23, 7, 1, -16 },
|
||||
/* '^' 0x5E */ { 2825, 9, 9, 11, 1, -15 },
|
||||
/* '_' 0x5F */ { 2836, 15, 1, 13, -1, 5 },
|
||||
/* '`' 0x60 */ { 2838, 5, 4, 6, 1, -16 },
|
||||
/* 'a' 0x61 */ { 2841, 12, 13, 13, 1, -11 },
|
||||
/* 'b' 0x62 */ { 2861, 12, 18, 13, 1, -16 },
|
||||
/* 'c' 0x63 */ { 2888, 10, 13, 12, 1, -11 },
|
||||
/* 'd' 0x64 */ { 2905, 11, 18, 13, 1, -16 },
|
||||
/* 'e' 0x65 */ { 2930, 11, 13, 13, 1, -11 },
|
||||
/* 'f' 0x66 */ { 2948, 5, 18, 7, 1, -16 },
|
||||
/* 'g' 0x67 */ { 2960, 11, 18, 13, 1, -11 },
|
||||
/* 'h' 0x68 */ { 2985, 10, 18, 13, 1, -16 },
|
||||
/* 'i' 0x69 */ { 3008, 2, 18, 5, 2, -16 },
|
||||
/* 'j' 0x6A */ { 3013, 4, 23, 6, 0, -16 },
|
||||
/* 'k' 0x6B */ { 3025, 10, 18, 12, 1, -16 },
|
||||
/* 'l' 0x6C */ { 3048, 2, 18, 5, 1, -16 },
|
||||
/* 'm' 0x6D */ { 3053, 17, 13, 19, 1, -11 },
|
||||
/* 'n' 0x6E */ { 3081, 10, 13, 13, 1, -11 },
|
||||
/* 'o' 0x6F */ { 3098, 11, 13, 13, 1, -11 },
|
||||
/* 'p' 0x70 */ { 3116, 12, 17, 13, 1, -11 },
|
||||
/* 'q' 0x71 */ { 3142, 11, 17, 13, 1, -11 },
|
||||
/* 'r' 0x72 */ { 3166, 6, 13, 8, 1, -11 },
|
||||
/* 's' 0x73 */ { 3176, 10, 13, 12, 1, -11 },
|
||||
/* 't' 0x74 */ { 3193, 5, 16, 7, 1, -14 },
|
||||
/* 'u' 0x75 */ { 3203, 10, 13, 13, 1, -11 },
|
||||
/* 'v' 0x76 */ { 3220, 11, 13, 12, 0, -11 },
|
||||
/* 'w' 0x77 */ { 3238, 17, 13, 17, 0, -11 },
|
||||
/* 'x' 0x78 */ { 3266, 10, 13, 11, 1, -11 },
|
||||
/* 'y' 0x79 */ { 3283, 11, 18, 11, 0, -11 },
|
||||
/* 'z' 0x7A */ { 3308, 10, 13, 12, 1, -11 },
|
||||
/* '{' 0x7B */ { 3325, 5, 23, 8, 1, -16 },
|
||||
/* '|' 0x7C */ { 3340, 2, 23, 6, 2, -16 },
|
||||
/* '}' 0x7D */ { 3346, 5, 23, 8, 2, -16 },
|
||||
/* '~' 0x7E */ { 3361, 10, 5, 12, 1, -9 },
|
||||
/* 0x7F */ { 3368, 0, 0, 0, 0, 0 },
|
||||
/* 0x80 */ { 3368, 14, 17, 16, 1, -15 },
|
||||
/* 0x81 */ { 3398, 0, 0, 8, 0, 0 },
|
||||
/* 0x82 */ { 3398, 2, 5, 6, 2, 0 },
|
||||
/* 0x83 */ { 3400, 6, 23, 7, 0, -16 },
|
||||
/* 0x84 */ { 3418, 6, 5, 10, 2, 0 },
|
||||
/* 0x85 */ { 3422, 12, 2, 16, 2, 0 },
|
||||
/* 0x86 */ { 3425, 10, 21, 13, 2, -15 },
|
||||
/* 0x87 */ { 3452, 10, 20, 13, 2, -15 },
|
||||
/* 0x88 */ { 3477, 7, 4, 8, 0, -16 },
|
||||
/* 0x89 */ { 3481, 23, 18, 24, 0, -16 },
|
||||
/* 0x8A */ { 3533, 14, 21, 16, 1, -19 },
|
||||
/* 0x8B */ { 3570, 3, 8, 6, 1, -9 },
|
||||
/* 0x8C */ { 3573, 22, 18, 24, 1, -16 },
|
||||
/* 0x8D */ { 3623, 0, 0, 8, 0, 0 },
|
||||
/* 0x8E */ { 3623, 13, 21, 15, 1, -19 },
|
||||
/* 0x8F */ { 3658, 0, 0, 8, 0, 0 },
|
||||
/* 0x90 */ { 3658, 0, 0, 8, 0, 0 },
|
||||
/* 0x91 */ { 3658, 2, 6, 6, 2, -16 },
|
||||
/* 0x92 */ { 3660, 2, 6, 6, 2, -16 },
|
||||
/* 0x93 */ { 3662, 6, 6, 10, 2, -16 },
|
||||
/* 0x94 */ { 3667, 6, 6, 10, 2, -16 },
|
||||
/* 0x95 */ { 3672, 6, 6, 10, 2, -9 },
|
||||
/* 0x96 */ { 3677, 10, 2, 12, 1, -6 },
|
||||
/* 0x97 */ { 3680, 22, 2, 24, 1, -6 },
|
||||
/* 0x98 */ { 3686, 7, 3, 8, 0, -16 },
|
||||
/* 0x99 */ { 3689, 22, 13, 24, 2, -16 },
|
||||
/* 0x9A */ { 3725, 10, 18, 12, 1, -16 },
|
||||
/* 0x9B */ { 3748, 3, 8, 6, 2, -8 },
|
||||
/* 0x9C */ { 3751, 20, 13, 22, 1, -11 },
|
||||
/* 0x9D */ { 3784, 0, 0, 8, 0, 0 },
|
||||
/* 0x9E */ { 3784, 10, 18, 12, 1, -16 },
|
||||
/* 0x9F */ { 3807, 14, 21, 16, 1, -19 },
|
||||
/* 0xA0 */ { 3844, 0, 0, 7, 0, 0 },
|
||||
/* 0xA1 */ { 3844, 2, 18, 8, 3, -11 },
|
||||
/* 0xA2 */ { 3849, 11, 17, 13, 1, -13 },
|
||||
/* 0xA3 */ { 3873, 12, 18, 13, 0, -16 },
|
||||
/* 0xA4 */ { 3900, 9, 9, 13, 2, -11 },
|
||||
/* 0xA5 */ { 3911, 12, 17, 13, 1, -15 },
|
||||
/* 0xA6 */ { 3937, 2, 23, 6, 2, -16 },
|
||||
/* 0xA7 */ { 3943, 11, 23, 13, 1, -16 },
|
||||
/* 0xA8 */ { 3975, 6, 2, 8, 1, -15 },
|
||||
/* 0xA9 */ { 3977, 18, 17, 19, 1, -15 },
|
||||
/* 0xAA */ { 4016, 7, 11, 9, 1, -16 },
|
||||
/* 0xAB */ { 4026, 8, 8, 12, 2, -9 },
|
||||
/* 0xAC */ { 4034, 12, 6, 14, 1, -7 },
|
||||
/* 0xAD */ { 4043, 6, 2, 8, 1, -6 },
|
||||
/* 0xAE */ { 4045, 18, 17, 19, 1, -15 },
|
||||
/* 0xAF */ { 4084, 6, 2, 8, 1, -15 },
|
||||
/* 0xB0 */ { 4086, 7, 8, 15, 4, -15 },
|
||||
/* 0xB1 */ { 4093, 12, 15, 14, 1, -13 },
|
||||
/* 0xB2 */ { 4116, 7, 10, 8, 1, -17 },
|
||||
/* 0xB3 */ { 4125, 7, 10, 8, 1, -17 },
|
||||
/* 0xB4 */ { 4134, 5, 4, 8, 2, -16 },
|
||||
/* 0xB5 */ { 4137, 12, 17, 13, 2, -11 },
|
||||
/* 0xB6 */ { 4163, 11, 21, 13, 2, -16 },
|
||||
/* 0xB7 */ { 4192, 2, 2, 6, 2, -6 },
|
||||
/* 0xB8 */ { 4193, 6, 5, 8, 1, 2 },
|
||||
/* 0xB9 */ { 4197, 3, 10, 8, 3, -18 },
|
||||
/* 0xBA */ { 4201, 6, 11, 9, 1, -16 },
|
||||
/* 0xBB */ { 4210, 8, 8, 12, 2, -8 },
|
||||
/* 0xBC */ { 4218, 17, 17, 21, 3, -15 },
|
||||
/* 0xBD */ { 4255, 18, 18, 21, 3, -16 },
|
||||
/* 0xBE */ { 4296, 19, 18, 21, 1, -16 },
|
||||
/* 0xBF */ { 4339, 9, 18, 13, 3, -11 },
|
||||
/* 0xC0 */ { 4360, 8, 18, 6, -1, -18 },
|
||||
/* 0xC1 */ { 4378, 15, 17, 15, 0, -17 },
|
||||
/* 0xC2 */ { 4410, 13, 17, 16, 2, -17 },
|
||||
/* 0xC3 */ { 4438, 11, 17, 13, 2, -17 },
|
||||
/* 0xC4 */ { 4462, 16, 17, 16, -1, -17 },
|
||||
/* 0xC5 */ { 4496, 13, 17, 16, 2, -17 },
|
||||
/* 0xC6 */ { 4524, 14, 17, 15, 0, -17 },
|
||||
/* 0xC7 */ { 4554, 13, 17, 17, 2, -17 },
|
||||
/* 0xC8 */ { 4582, 17, 17, 19, 1, -17 },
|
||||
/* 0xC9 */ { 4619, 2, 17, 6, 2, -17 },
|
||||
/* 0xCA */ { 4624, 14, 17, 16, 2, -17 },
|
||||
/* 0xCB */ { 4654, 17, 17, 16, -1, -17 },
|
||||
/* 0xCC */ { 4691, 15, 17, 19, 2, -17 },
|
||||
/* 0xCD */ { 4723, 13, 17, 17, 2, -17 },
|
||||
/* 0xCE */ { 4751, 14, 17, 16, 1, -17 },
|
||||
/* 0xCF */ { 4781, 17, 17, 19, 1, -17 },
|
||||
/* 0xD0 */ { 4818, 13, 17, 17, 2, -17 },
|
||||
/* 0xD1 */ { 4846, 13, 17, 16, 2, -17 },
|
||||
/* 0xD2 */ { 4874, 0, 0, 5, 0, 0 },
|
||||
/* 0xD3 */ { 4874, 12, 17, 15, 2, -17 },
|
||||
/* 0xD4 */ { 4900, 14, 17, 14, 0, -17 },
|
||||
/* 0xD5 */ { 4930, 16, 17, 16, 0, -17 },
|
||||
/* 0xD6 */ { 4964, 16, 17, 18, 1, -17 },
|
||||
/* 0xD7 */ { 4998, 15, 17, 15, 0, -17 },
|
||||
/* 0xD8 */ { 5030, 16, 17, 19, 2, -17 },
|
||||
/* 0xD9 */ { 5064, 16, 17, 18, 1, -17 },
|
||||
/* 0xDA */ { 5098, 6, 20, 6, 0, -20 },
|
||||
/* 0xDB */ { 5113, 16, 20, 16, 0, -20 },
|
||||
/* 0xDC */ { 5153, 12, 17, 14, 1, -17 },
|
||||
/* 0xDD */ { 5179, 9, 17, 11, 1, -17 },
|
||||
/* 0xDE */ { 5199, 10, 22, 14, 2, -17 },
|
||||
/* 0xDF */ { 5227, 4, 17, 6, 1, -17 },
|
||||
/* 0xE0 */ { 5236, 10, 17, 14, 2, -17 },
|
||||
/* 0xE1 */ { 5258, 12, 13, 14, 1, -13 },
|
||||
/* 0xE2 */ { 5278, 11, 22, 14, 2, -17 },
|
||||
/* 0xE3 */ { 5309, 12, 18, 11, -1, -13 },
|
||||
/* 0xE4 */ { 5336, 11, 17, 13, 1, -17 },
|
||||
/* 0xE5 */ { 5360, 9, 13, 11, 1, -13 },
|
||||
/* 0xE6 */ { 5375, 9, 22, 11, 1, -17 },
|
||||
/* 0xE7 */ { 5400, 10, 18, 14, 2, -13 },
|
||||
/* 0xE8 */ { 5423, 11, 17, 13, 1, -17 },
|
||||
/* 0xE9 */ { 5447, 2, 13, 6, 2, -13 },
|
||||
/* 0xEA */ { 5451, 10, 13, 12, 2, -13 },
|
||||
/* 0xEB */ { 5468, 13, 17, 12, -1, -17 },
|
||||
/* 0xEC */ { 5496, 10, 18, 14, 2, -13 },
|
||||
/* 0xED */ { 5519, 11, 13, 11, 0, -13 },
|
||||
/* 0xEE */ { 5537, 9, 22, 11, 1, -17 },
|
||||
/* 0xEF */ { 5562, 11, 13, 13, 1, -13 },
|
||||
/* 0xF0 */ { 5580, 16, 13, 17, 0, -13 },
|
||||
/* 0xF1 */ { 5606, 11, 18, 14, 2, -13 },
|
||||
/* 0xF2 */ { 5631, 11, 18, 12, 1, -13 },
|
||||
/* 0xF3 */ { 5656, 13, 13, 15, 1, -13 },
|
||||
/* 0xF4 */ { 5678, 6, 13, 9, 1, -13 },
|
||||
/* 0xF5 */ { 5688, 10, 13, 14, 2, -13 },
|
||||
/* 0xF6 */ { 5705, 14, 18, 16, 1, -13 },
|
||||
/* 0xF7 */ { 5737, 13, 18, 13, 0, -13 },
|
||||
/* 0xF8 */ { 5767, 14, 18, 18, 2, -13 },
|
||||
/* 0xF9 */ { 5799, 16, 13, 18, 1, -13 },
|
||||
/* 0xFA */ { 5825, 6, 16, 6, 0, -16 },
|
||||
/* 0xFB */ { 5837, 10, 16, 14, 2, -16 },
|
||||
/* 0xFC */ { 5857, 11, 17, 13, 1, -17 },
|
||||
/* 0xFD */ { 5881, 10, 17, 14, 2, -17 },
|
||||
/* 0xFE */ { 5903, 16, 17, 18, 1, -17 },
|
||||
/* 0xFF */ { 5937, 0, 0, 5, 0, 0 },
|
||||
};
|
||||
|
||||
const GFXfont FreeSans12pt_Win1253 PROGMEM = {
|
||||
(uint8_t*)FreeSans12pt_Win1253Bitmaps,
|
||||
(GFXglyph*)FreeSans12pt_Win1253Glyphs,
|
||||
0x01, 0xFF, 19
|
||||
};
|
||||
527
src/graphics/niche/Fonts/FreeSans6pt_Win1253.h
Normal file
527
src/graphics/niche/Fonts/FreeSans6pt_Win1253.h
Normal file
@@ -0,0 +1,527 @@
|
||||
// trunk-ignore-all(clang-format)
|
||||
#pragma once
|
||||
/* PROPERTIES
|
||||
|
||||
FONT_NAME FreeSans6pt_Win1253
|
||||
*/
|
||||
const uint8_t FreeSans6pt_Win1253Bitmaps[] PROGMEM = {
|
||||
/* 0x01 */ 0x1C, 0x0A, 0x05, 0x04, 0xFE, 0x08, 0x1C, 0x02, 0x07, 0xE0, 0x9F, 0xC0,
|
||||
/* 0x02 */ 0x3F, 0xF0, 0x40, 0xE0, 0x10, 0x3F, 0x04, 0x9E, 0x28, 0x14, 0x0E, 0x00,
|
||||
/* 0x03 */ 0x3F, 0x10, 0x28, 0x06, 0x49, 0x80, 0x60, 0x19, 0x26, 0x31, 0x40, 0x8F, 0xC0,
|
||||
/* 0x04 */ 0x3F, 0x10, 0x2A, 0x16, 0x49, 0xA1, 0x60, 0x19, 0xE6, 0x31, 0x40, 0x8F, 0xC0,
|
||||
/* 0x05 */ 0x28, 0x15, 0x2A, 0xB5, 0x55, 0xA8, 0x54, 0x12, 0x04, 0x41, 0x08, 0x81, 0xC0,
|
||||
/* 0x06 */ 0x04, 0x08, 0x88, 0x82, 0x07, 0x01, 0x11, 0xA2, 0xC4, 0x40, 0x70, 0x20, 0x88, 0x88, 0x10, 0x00,
|
||||
/* 0x07 */
|
||||
/* 0x08 */ 0x03, 0x83, 0x44, 0x48, 0x28, 0x01, 0x80, 0x17, 0xFE, 0x08, 0x45, 0x28, 0x84, 0x00,
|
||||
/* 0x09 */ 0x01, 0xC0, 0x68, 0x82, 0x41, 0x10, 0x02, 0x80, 0x06, 0x00, 0x14, 0x00, 0x8F, 0xFC,
|
||||
/* 0x0A */
|
||||
/* 0x0B */ 0x22, 0x2A, 0xA2, 0x30, 0x18, 0x0A, 0x09, 0x04, 0x44, 0x14, 0x04, 0x00,
|
||||
/* 0x0C */ 0x46, 0x00, 0x19, 0x03, 0x21, 0x20, 0x93, 0x04, 0x20, 0x11, 0x80, 0x50, 0x02, 0x7F, 0xE0,
|
||||
/* 0x0D */
|
||||
/* 0x0E */ 0x08, 0x0E, 0x08, 0x88, 0x24, 0x12, 0x09, 0x05, 0x01, 0xFF, 0x8A, 0x02, 0x00,
|
||||
/* 0x0F */ 0x3F, 0x14, 0xAA, 0x16, 0x01, 0x92, 0x60, 0x18, 0xC6, 0x49, 0x40, 0x8F, 0xC0,
|
||||
/* 0x10 */ 0x1B, 0x02, 0xA0, 0x54, 0x12, 0x42, 0x48, 0x49, 0x31, 0x1E, 0x23, 0xEA, 0xFE, 0x3C,
|
||||
/* 0x11 */ 0x3F, 0x02, 0x00, 0x20, 0x6D, 0x27, 0xF8, 0x3F, 0xC1, 0xFE, 0x37, 0xD0, 0xBE, 0x40, 0xE1, 0xE2, 0x00,
|
||||
/* 0x12 */ 0x12, 0x42, 0x20, 0x24, 0xC0, 0x29, 0x99, 0x05, 0x23, 0x30, 0xB0, 0x30, 0x00,
|
||||
/* 0x13 */ 0x3F, 0x88, 0x0A, 0x44, 0xD5, 0x58, 0x03, 0x00, 0x67, 0xCC, 0x71, 0x40, 0x47, 0xF0,
|
||||
/* 0x14 */ 0x3F, 0x18, 0x69, 0x26, 0x85, 0xA1, 0x6C, 0xD8, 0x06, 0x31, 0x40, 0x8F, 0xC0,
|
||||
/* 0x15 */ 0x3F, 0x11, 0x00, 0xE8, 0x03, 0xA0, 0x1F, 0xB3, 0x7E, 0x00, 0xE9, 0xE0, 0x23, 0x00, 0x40, 0x40, 0xFE, 0x00,
|
||||
/* 0x16 */ 0x30, 0x38, 0x3A, 0x3E, 0x6E, 0xEB, 0xC3, 0xC3, 0x66, 0x3C,
|
||||
/* 0x17 */ 0x3F, 0x04, 0x00, 0x82, 0x88, 0x5C, 0xA4, 0x49, 0x22, 0x81, 0x98, 0xC4, 0x40, 0xA3, 0xF0,
|
||||
/* 0x18 */ 0x07, 0x80, 0x42, 0x04, 0x08, 0x21, 0x41, 0x42, 0x60, 0x0E, 0x8C, 0xB2, 0x89, 0x50, 0x52, 0x82, 0x80,
|
||||
/* 0x19 */ 0x3F, 0xC4, 0x02, 0x80, 0x18, 0x01, 0xB3, 0x1B, 0xB9, 0x80, 0x19, 0xE1, 0x40, 0x23, 0xFC,
|
||||
/* 0x1A */ 0xFF, 0xC0, 0x67, 0x34, 0x58, 0x4C, 0x46, 0x03, 0x11, 0x80, 0xFF, 0xC0,
|
||||
/* 0x1B */ 0x0F, 0xC0, 0x40, 0x82, 0x49, 0x08, 0x04, 0x00, 0x00, 0x12, 0x02, 0x31, 0x34, 0x0B, 0x88, 0x45, 0x00, 0x20,
|
||||
/* 0x1C */ 0x3F, 0x88, 0x0A, 0x44, 0xC9, 0x19, 0x3B, 0x00, 0x60, 0x4C, 0x71, 0x40, 0x47, 0xF0,
|
||||
/* 0x1D */ 0x3F, 0x8B, 0x0A, 0x00, 0xC8, 0x18, 0x13, 0x00, 0x48, 0xCA, 0xC1, 0x44, 0x53, 0x30,
|
||||
/* 0x1E */ 0x19, 0xC2, 0x02, 0x50, 0x1E, 0x49, 0x80, 0x12, 0x01, 0x27, 0x92, 0x01, 0x10, 0x20, 0xFC,
|
||||
/* 0x1F */ 0x30, 0x1C, 0x0C, 0x3E, 0x7E, 0xCF, 0x07, 0xC7, 0x7F, 0x3F,
|
||||
/* ' ' 0x20 */
|
||||
/* '!' 0x21 */ 0xFC, 0x80,
|
||||
/* '"' 0x22 */ 0xB6, 0x80,
|
||||
/* '#' 0x23 */ 0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28,
|
||||
/* '$' 0x24 */ 0x10, 0xE5, 0x55, 0x50, 0xE1, 0x65, 0x55, 0xE1, 0x00,
|
||||
/* '%' 0x25 */ 0x71, 0x24, 0x89, 0x22, 0x50, 0x74, 0x02, 0x70, 0xA4, 0x49, 0x11, 0xC0,
|
||||
/* '&' 0x26 */ 0x71, 0x24, 0x9C, 0x62, 0x58, 0xA7, 0xF4,
|
||||
/* ''' 0x27 */ 0xE0,
|
||||
/* '(' 0x28 */ 0x5A, 0xAA, 0x94,
|
||||
/* ')' 0x29 */ 0x89, 0x12, 0x49, 0x29, 0x00,
|
||||
/* '*' 0x2A */ 0x5E, 0x80,
|
||||
/* '+' 0x2B */ 0x21, 0x3E, 0x42, 0x00,
|
||||
/* ',' 0x2C */ 0xE0,
|
||||
/* '-' 0x2D */ 0xC0,
|
||||
/* '.' 0x2E */ 0x80,
|
||||
/* '/' 0x2F */ 0x24, 0xA4, 0xA4, 0x80,
|
||||
/* '0' 0x30 */ 0x76, 0xE3, 0x18, 0xC6, 0x3B, 0x70,
|
||||
/* '1' 0x31 */ 0x27, 0x92, 0x49, 0x20,
|
||||
/* '2' 0x32 */ 0x79, 0x10, 0x41, 0x08, 0xC6, 0x10, 0xFC,
|
||||
/* '3' 0x33 */ 0x79, 0x30, 0x43, 0x18, 0x10, 0x71, 0x78,
|
||||
/* '4' 0x34 */ 0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08,
|
||||
/* '5' 0x35 */ 0xFC, 0x21, 0xE8, 0x84, 0x31, 0xF0,
|
||||
/* '6' 0x36 */ 0x74, 0x61, 0xE8, 0xC6, 0x31, 0x70,
|
||||
/* '7' 0x37 */ 0xF8, 0x44, 0x22, 0x11, 0x08, 0x40,
|
||||
/* '8' 0x38 */ 0x39, 0x34, 0x53, 0x39, 0x1C, 0x51, 0x38,
|
||||
/* '9' 0x39 */ 0x39, 0x3C, 0x71, 0x4C, 0xF0, 0x53, 0x78,
|
||||
/* ':' 0x3A */ 0x82,
|
||||
/* ';' 0x3B */ 0x87,
|
||||
/* '<' 0x3C */ 0x3E, 0x30, 0x60, 0x80,
|
||||
/* '=' 0x3D */ 0xF8, 0x3E,
|
||||
/* '>' 0x3E */ 0xE0, 0xC6, 0xC8, 0x00,
|
||||
/* '?' 0x3F */ 0x74, 0x42, 0x11, 0x10, 0x80, 0x20,
|
||||
/* '@' 0x40 */ 0x0F, 0x86, 0x19, 0x9A, 0xA4, 0xD9, 0x13, 0x22, 0x56, 0xDA, 0x6E, 0x60, 0x06, 0x00, 0x3C, 0x00,
|
||||
/* 'A' 0x41 */ 0x18, 0x18, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3,
|
||||
/* 'B' 0x42 */ 0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC,
|
||||
/* 'C' 0x43 */ 0x3E, 0x63, 0x40, 0x40, 0xC0, 0x40, 0x41, 0x63, 0x3E,
|
||||
/* 'D' 0x44 */ 0xF9, 0x0A, 0x1C, 0x18, 0x30, 0x61, 0xC2, 0xF8,
|
||||
/* 'E' 0x45 */ 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC,
|
||||
/* 'F' 0x46 */ 0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80,
|
||||
/* 'G' 0x47 */ 0x1E, 0x61, 0x40, 0x40, 0xC7, 0x41, 0x41, 0x63, 0x1D,
|
||||
/* 'H' 0x48 */ 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82,
|
||||
/* 'I' 0x49 */ 0xFF, 0x80,
|
||||
/* 'J' 0x4A */ 0x08, 0x42, 0x10, 0x87, 0x29, 0x70,
|
||||
/* 'K' 0x4B */ 0x85, 0x12, 0x45, 0x0D, 0x13, 0x22, 0x42, 0x86,
|
||||
/* 'L' 0x4C */ 0x84, 0x21, 0x08, 0x42, 0x10, 0xF8,
|
||||
/* 'M' 0x4D */ 0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99,
|
||||
/* 'N' 0x4E */ 0x83, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86,
|
||||
/* 'O' 0x4F */ 0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x1E, 0x00,
|
||||
/* 'P' 0x50 */ 0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80,
|
||||
/* 'Q' 0x51 */ 0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x16, 0xC6, 0x1F, 0x00, 0x40,
|
||||
/* 'R' 0x52 */ 0xFD, 0x0E, 0x1C, 0x2F, 0x90, 0xA1, 0x42, 0x86,
|
||||
/* 'S' 0x53 */ 0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78,
|
||||
/* 'T' 0x54 */ 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10,
|
||||
/* 'U' 0x55 */ 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE2, 0x78,
|
||||
/* 'V' 0x56 */ 0xC2, 0x85, 0x0B, 0x22, 0x44, 0x8E, 0x0C, 0x18,
|
||||
/* 'W' 0x57 */ 0xC4, 0x28, 0xCD, 0x29, 0x25, 0x24, 0xA4, 0x52, 0x8C, 0x61, 0x8C, 0x31, 0x80,
|
||||
/* 'X' 0x58 */ 0x87, 0x34, 0x8C, 0x30, 0xC4, 0xA3, 0x84,
|
||||
/* 'Y' 0x59 */ 0xC3, 0x42, 0x24, 0x34, 0x18, 0x08, 0x08, 0x08, 0x08,
|
||||
/* 'Z' 0x5A */ 0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE,
|
||||
/* '[' 0x5B */ 0xEA, 0xAA, 0xAB,
|
||||
/* '\' 0x5C */ 0x92, 0x24, 0x89, 0x20,
|
||||
/* ']' 0x5D */ 0xD5, 0x55, 0x57,
|
||||
/* '^' 0x5E */ 0x46, 0xA9,
|
||||
/* '_' 0x5F */ 0xFE,
|
||||
/* '`' 0x60 */ 0x80,
|
||||
/* 'a' 0x61 */ 0x79, 0x20, 0x4F, 0xC6, 0x37, 0x40,
|
||||
/* 'b' 0x62 */ 0x84, 0x3D, 0x18, 0xC6, 0x31, 0xF0,
|
||||
/* 'c' 0x63 */ 0x39, 0x3C, 0x20, 0xC1, 0x33, 0x80,
|
||||
/* 'd' 0x64 */ 0x04, 0x13, 0xD3, 0xC6, 0x1C, 0x53, 0x3C,
|
||||
/* 'e' 0x65 */ 0x39, 0x38, 0x7F, 0x81, 0x13, 0x80,
|
||||
/* 'f' 0x66 */ 0x6B, 0xA4, 0x92, 0x40,
|
||||
/* 'g' 0x67 */ 0x35, 0x3C, 0x61, 0xC5, 0x33, 0x41, 0x4D, 0xE0,
|
||||
/* 'h' 0x68 */ 0x84, 0x3D, 0x38, 0xC6, 0x31, 0x88,
|
||||
/* 'i' 0x69 */ 0xBF, 0x80,
|
||||
/* 'j' 0x6A */ 0x45, 0x55, 0x57,
|
||||
/* 'k' 0x6B */ 0x84, 0x25, 0x4E, 0x52, 0xD2, 0x88,
|
||||
/* 'l' 0x6C */ 0xFF, 0x80,
|
||||
/* 'm' 0x6D */ 0xF7, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91,
|
||||
/* 'n' 0x6E */ 0xF4, 0x63, 0x18, 0xC6, 0x20,
|
||||
/* 'o' 0x6F */ 0x39, 0x3C, 0x61, 0xC5, 0x33, 0x80,
|
||||
/* 'p' 0x70 */ 0xF4, 0x63, 0x18, 0xC7, 0xD0, 0x80,
|
||||
/* 'q' 0x71 */ 0x3D, 0x3C, 0x61, 0xC5, 0x37, 0x41, 0x04,
|
||||
/* 'r' 0x72 */ 0xF2, 0x49, 0x20,
|
||||
/* 's' 0x73 */ 0x7A, 0x50, 0xE0, 0xE5, 0xE0,
|
||||
/* 't' 0x74 */ 0x5D, 0x24, 0x93,
|
||||
/* 'u' 0x75 */ 0x8C, 0x63, 0x18, 0xCF, 0xA0,
|
||||
/* 'v' 0x76 */ 0x85, 0x24, 0x92, 0x30, 0xC3, 0x00,
|
||||
/* 'w' 0x77 */ 0x89, 0x59, 0x59, 0x55, 0x56, 0x26, 0x26,
|
||||
/* 'x' 0x78 */ 0x4A, 0x4C, 0x43, 0x27, 0x20,
|
||||
/* 'y' 0x79 */ 0x8A, 0x52, 0xA5, 0x18, 0x84, 0x22, 0x00,
|
||||
/* 'z' 0x7A */ 0x78, 0x44, 0x46, 0x23, 0xE0,
|
||||
/* '{' 0x7B */ 0x6A, 0xAA, 0xA9,
|
||||
/* '|' 0x7C */ 0xFF, 0xE0,
|
||||
/* '}' 0x7D */ 0x95, 0x55, 0x56,
|
||||
/* '~' 0x7E */ 0x66, 0x60,
|
||||
/* 0x7F */
|
||||
/* 0x80 */ 0x1C, 0x45, 0x07, 0xE4, 0x1F, 0x10, 0x10, 0x1E,
|
||||
/* 0x81 */
|
||||
/* 0x82 */ 0xE0,
|
||||
/* 0x83 */ 0x6B, 0xA4, 0x92, 0x49, 0x60,
|
||||
/* 0x84 */ 0xB6, 0x80,
|
||||
/* 0x85 */ 0xA8,
|
||||
/* 0x86 */ 0x21, 0x09, 0xF2, 0x10, 0x84, 0x21, 0x08,
|
||||
/* 0x87 */ 0x21, 0x09, 0xF2, 0x10, 0x84, 0xF9, 0x08,
|
||||
/* 0x88 */ 0x54,
|
||||
/* 0x89 */ 0x62, 0x09, 0x40, 0x98, 0x06, 0x80, 0x10, 0x01, 0x66, 0x29, 0x92, 0x99, 0x06, 0x60,
|
||||
/* 0x8A */ 0x28, 0x47, 0xA1, 0x83, 0x07, 0x83, 0x87, 0x17, 0x80,
|
||||
/* 0x8B */ 0x64,
|
||||
/* 0x8C */ 0x3B, 0xE8, 0xC2, 0x08, 0x41, 0x08, 0x3F, 0x04, 0x20, 0x82, 0x30, 0x3B, 0xE0,
|
||||
/* 0x8D */
|
||||
/* 0x8E */ 0x14, 0x11, 0xF8, 0x30, 0xC1, 0x04, 0x18, 0x61, 0xFC,
|
||||
/* 0x8F */
|
||||
/* 0x90 */
|
||||
/* 0x91 */ 0xE0,
|
||||
/* 0x92 */ 0xE0,
|
||||
/* 0x93 */ 0xB6, 0x80,
|
||||
/* 0x94 */ 0xB6, 0x80,
|
||||
/* 0x95 */ 0xFF, 0x80,
|
||||
/* 0x96 */ 0xFC,
|
||||
/* 0x97 */ 0xFF, 0xF0,
|
||||
/* 0x98 */ 0xDB,
|
||||
/* 0x99 */ 0xE6, 0x28, 0xCD, 0x19, 0xA3, 0x34, 0x6A, 0x8B, 0x51, 0x68,
|
||||
/* 0x9A */ 0x52, 0x69, 0x8E, 0x19, 0x60,
|
||||
/* 0x9B */ 0x98,
|
||||
/* 0x9C */ 0x7B, 0xD9, 0xCE, 0x10, 0xC3, 0xF8, 0x41, 0x9C, 0x5E, 0xF0,
|
||||
/* 0x9D */
|
||||
/* 0x9E */ 0x51, 0x1E, 0x11, 0x11, 0x88, 0xF8,
|
||||
/* 0x9F */ 0x29, 0x05, 0x12, 0x22, 0x87, 0x04, 0x08, 0x10, 0x20,
|
||||
/* 0xA0 */
|
||||
/* 0xA1 */ 0xBF, 0x80,
|
||||
/* 0xA2 */ 0x23, 0xAB, 0x4A, 0x52, 0xAE, 0x20,
|
||||
/* 0xA3 */ 0x39, 0x14, 0x10, 0xF0, 0x82, 0x1C, 0x4C,
|
||||
/* 0xA4 */ 0xFC, 0x63, 0xF0,
|
||||
/* 0xA5 */ 0x8C, 0x54, 0xAF, 0x93, 0xE4, 0x20,
|
||||
/* 0xA6 */ 0xF9, 0xF0,
|
||||
/* 0xA7 */ 0x32, 0x91, 0xC9, 0x47, 0x26, 0x14, 0xA4, 0xC0,
|
||||
/* 0xA8 */ 0xA0,
|
||||
/* 0xA9 */ 0x3E, 0x3F, 0xB8, 0xF4, 0x1A, 0x0D, 0x17, 0x76, 0xC6, 0x3E, 0x00,
|
||||
/* 0xAA */ 0x61, 0x79, 0x60,
|
||||
/* 0xAB */ 0x5A, 0xA5,
|
||||
/* 0xAC */ 0xFC, 0x10, 0x40,
|
||||
/* 0xAD */
|
||||
/* 0xAE */ 0x3E, 0x31, 0xB7, 0x72, 0x99, 0xCC, 0xC7, 0x56, 0xC6, 0x3E, 0x00,
|
||||
/* 0xAF */ 0xE0,
|
||||
/* 0xB0 */ 0x69, 0x96,
|
||||
/* 0xB1 */ 0x21, 0x3E, 0x42, 0x03, 0xE0,
|
||||
/* 0xB2 */ 0x69, 0x3C, 0xF0,
|
||||
/* 0xB3 */ 0x79, 0x29, 0x70,
|
||||
/* 0xB4 */ 0x80,
|
||||
/* 0xB5 */ 0x8A, 0x28, 0xA2, 0x8A, 0x6E, 0xE0, 0x80,
|
||||
/* 0xB6 */ 0x7F, 0xAE, 0xBA, 0x68, 0xA2, 0x8A, 0x28, 0xA0,
|
||||
/* 0xB7 */ 0x80,
|
||||
/* 0xB8 */ 0x67, 0x80,
|
||||
/* 0xB9 */ 0x75, 0x50,
|
||||
/* 0xBA */ 0x69, 0x96, 0xF0,
|
||||
/* 0xBB */ 0xA5, 0x5A,
|
||||
/* 0xBC */ 0x42, 0x30, 0x84, 0x41, 0x10, 0x48, 0x82, 0x61, 0x28, 0x8F, 0x20, 0x80,
|
||||
/* 0xBD */ 0x40, 0x63, 0x11, 0x09, 0x74, 0xA8, 0x84, 0x44, 0x44, 0x43, 0x80,
|
||||
/* 0xBE */ 0x71, 0x24, 0x82, 0x20, 0x50, 0x98, 0x9A, 0x61, 0x28, 0x4F, 0x20, 0x80,
|
||||
/* 0xBF */ 0x20, 0x08, 0x44, 0x42, 0x11, 0x70,
|
||||
/* 0xC0 */ 0x2D, 0x02, 0x22, 0x22, 0x22,
|
||||
/* 0xC1 */ 0x10, 0x50, 0xA1, 0x44, 0x4F, 0x91, 0x41, 0x82,
|
||||
/* 0xC2 */ 0xFA, 0x18, 0x61, 0xFE, 0x18, 0x61, 0xF8,
|
||||
/* 0xC3 */ 0xFE, 0x08, 0x20, 0x82, 0x08, 0x20, 0x80,
|
||||
/* 0xC4 */ 0x08, 0x0A, 0x05, 0x02, 0x82, 0x21, 0x11, 0x04, 0x82, 0x7F, 0x00,
|
||||
/* 0xC5 */ 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC,
|
||||
/* 0xC6 */ 0x7E, 0x08, 0x20, 0x41, 0x04, 0x08, 0x20, 0xFE,
|
||||
/* 0xC7 */ 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82,
|
||||
/* 0xC8 */ 0x38, 0x8A, 0x0C, 0x1B, 0xB0, 0x60, 0xA2, 0x38,
|
||||
/* 0xC9 */ 0xFF, 0x80,
|
||||
/* 0xCA */ 0x83, 0x0A, 0x24, 0x8A, 0x1A, 0x22, 0x42, 0x82,
|
||||
/* 0xCB */ 0x08, 0x0A, 0x05, 0x02, 0x82, 0x21, 0x11, 0x04, 0x82, 0x41, 0x00,
|
||||
/* 0xCC */ 0x83, 0x8F, 0x1D, 0x5A, 0xB5, 0x6A, 0xC9, 0x92,
|
||||
/* 0xCD */ 0x83, 0x86, 0x8D, 0x19, 0x31, 0x62, 0xC3, 0x82,
|
||||
/* 0xCE */ 0xFC, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFC,
|
||||
/* 0xCF */ 0x38, 0x8A, 0x0C, 0x18, 0x30, 0x60, 0xA2, 0x38,
|
||||
/* 0xD0 */ 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x82,
|
||||
/* 0xD1 */ 0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80,
|
||||
/* 0xD2 */
|
||||
/* 0xD3 */ 0xFE, 0x04, 0x08, 0x10, 0x84, 0x20, 0xFC,
|
||||
/* 0xD4 */ 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10,
|
||||
/* 0xD5 */ 0x82, 0x89, 0x11, 0x41, 0x02, 0x04, 0x08, 0x10,
|
||||
/* 0xD6 */ 0x10, 0xFA, 0x4C, 0x99, 0x32, 0x64, 0xBE, 0x10,
|
||||
/* 0xD7 */ 0x82, 0x89, 0x11, 0x41, 0x05, 0x11, 0x22, 0x82,
|
||||
/* 0xD8 */ 0x93, 0x26, 0x4C, 0x99, 0x2F, 0x84, 0x08, 0x10,
|
||||
/* 0xD9 */ 0x38, 0x8A, 0x0C, 0x18, 0x30, 0x60, 0xA2, 0xEE,
|
||||
/* 0xDA */ 0xA1, 0x24, 0x92, 0x49, 0x00,
|
||||
/* 0xDB */ 0x28, 0x02, 0x0A, 0x24, 0x45, 0x04, 0x08, 0x10, 0x20, 0x40,
|
||||
/* 0xDC */ 0x11, 0x00, 0xD9, 0x4A, 0x52, 0x93, 0x40,
|
||||
/* 0xDD */ 0x11, 0x00, 0xF8, 0x41, 0x90, 0x83, 0xC0,
|
||||
/* 0xDE */ 0x11, 0x01, 0x6C, 0xC6, 0x31, 0x8C, 0x42, 0x10,
|
||||
/* 0xDF */ 0x62, 0xAA, 0xA0,
|
||||
/* 0xE0 */ 0x25, 0x81, 0x18, 0xC6, 0x31, 0x8B, 0x80,
|
||||
/* 0xE1 */ 0x6C, 0xA5, 0x29, 0x49, 0xA0,
|
||||
/* 0xE2 */ 0x74, 0x63, 0x1B, 0x46, 0x39, 0xB4, 0x20,
|
||||
/* 0xE3 */ 0x44, 0x89, 0x11, 0x42, 0x85, 0x04, 0x08, 0x10,
|
||||
/* 0xE4 */ 0x71, 0x1D, 0x18, 0xC6, 0x31, 0x70,
|
||||
/* 0xE5 */ 0x7C, 0x20, 0xC8, 0x41, 0xE0,
|
||||
/* 0xE6 */ 0x72, 0x44, 0x88, 0x88, 0x71, 0x20,
|
||||
/* 0xE7 */ 0xB6, 0x63, 0x18, 0xC6, 0x21, 0x08,
|
||||
/* 0xE8 */ 0x74, 0x63, 0x1F, 0xC6, 0x31, 0x70,
|
||||
/* 0xE9 */ 0xFE,
|
||||
/* 0xEA */ 0x8A, 0x4A, 0x38, 0x92, 0x48, 0x80,
|
||||
/* 0xEB */ 0x20, 0x41, 0x04, 0x28, 0xA2, 0x91, 0x44,
|
||||
/* 0xEC */ 0x8C, 0x63, 0x18, 0xC7, 0xF0, 0x80,
|
||||
/* 0xED */ 0x8C, 0x54, 0xA5, 0x10, 0x80,
|
||||
/* 0xEE */ 0x68, 0x86, 0x48, 0x88, 0x71, 0x20,
|
||||
/* 0xEF */ 0x74, 0x63, 0x18, 0xC5, 0xC0,
|
||||
/* 0xF0 */ 0xFF, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
||||
/* 0xF1 */ 0x74, 0x63, 0x18, 0xC7, 0xD0, 0x80,
|
||||
/* 0xF2 */ 0x34, 0x88, 0x88, 0x71, 0x60,
|
||||
/* 0xF3 */ 0x7F, 0x12, 0x24, 0x48, 0x91, 0x1C, 0x00,
|
||||
/* 0xF4 */ 0xE9, 0x24, 0x90,
|
||||
/* 0xF5 */ 0x8C, 0x63, 0x18, 0xC5, 0xC0,
|
||||
/* 0xF6 */ 0x5A, 0x59, 0x65, 0x95, 0x53, 0x84, 0x10,
|
||||
/* 0xF7 */ 0x49, 0x24, 0x8C, 0x30, 0xC4, 0x92, 0x48,
|
||||
/* 0xF8 */ 0x93, 0x26, 0x4C, 0x99, 0x32, 0x5F, 0x08, 0x10,
|
||||
/* 0xF9 */ 0x45, 0x06, 0x4C, 0x99, 0x32, 0x5B, 0x00,
|
||||
/* 0xFA */ 0xA1, 0x24, 0x92, 0x40,
|
||||
/* 0xFB */ 0x50, 0x23, 0x18, 0xC6, 0x31, 0x70,
|
||||
/* 0xFC */ 0x11, 0x00, 0xE8, 0xC6, 0x31, 0x8B, 0x80,
|
||||
/* 0xFD */ 0x21, 0x01, 0x18, 0xC6, 0x31, 0x8B, 0x80,
|
||||
/* 0xFE */ 0x08, 0x20, 0x02, 0x28, 0x32, 0x64, 0xC9, 0x92, 0xD8,
|
||||
/* 0xFF */
|
||||
};
|
||||
|
||||
const GFXglyph FreeSans6pt_Win1253Glyphs[] PROGMEM = {
|
||||
/* 0x01 */ { 0, 9, 10, 11, 1, -9 },
|
||||
/* 0x02 */ { 12, 9, 10, 11, 1, -8 },
|
||||
/* 0x03 */ { 24, 10, 10, 12, 1, -8 },
|
||||
/* 0x04 */ { 37, 10, 10, 12, 1, -8 },
|
||||
/* 0x05 */ { 50, 10, 10, 12, 1, -9 },
|
||||
/* 0x06 */ { 63, 11, 11, 13, 1, -9 },
|
||||
/* 0x07 */ { 79, 0, 0, 8, 0, 0 },
|
||||
/* 0x08 */ { 79, 12, 9, 14, 1, -8 },
|
||||
/* 0x09 */ { 93, 14, 8, 16, 1, -7 },
|
||||
/* 0x0A */ { 107, 0, 0, 8, 0, 0 },
|
||||
/* 0x0B */ { 107, 9, 10, 11, 1, -9 },
|
||||
/* 0x0C */ { 119, 13, 9, 15, 1, -8 },
|
||||
/* 0x0D */ { 134, 0, 0, 8, 0, 0 },
|
||||
/* 0x0E */ { 134, 9, 11, 11, 1, -9 },
|
||||
/* 0x0F */ { 147, 10, 10, 12, 1, -9 },
|
||||
/* 0x10 */ { 160, 11, 10, 13, 1, -9 },
|
||||
/* 0x11 */ { 174, 13, 10, 15, 1, -9 },
|
||||
/* 0x12 */ { 191, 10, 10, 12, 1, -9 },
|
||||
/* 0x13 */ { 204, 11, 10, 13, 1, -9 },
|
||||
/* 0x14 */ { 218, 10, 10, 12, 1, -9 },
|
||||
/* 0x15 */ { 231, 14, 10, 16, 1, -9 },
|
||||
/* 0x16 */ { 249, 8, 10, 10, 1, -9 },
|
||||
/* 0x17 */ { 259, 12, 10, 14, 1, -9 },
|
||||
/* 0x18 */ { 274, 13, 10, 15, 1, -9 },
|
||||
/* 0x19 */ { 291, 12, 10, 14, 1, -9 },
|
||||
/* 0x1A */ { 306, 9, 10, 11, 1, -8 },
|
||||
/* 0x1B */ { 318, 14, 10, 16, 1, -9 },
|
||||
/* 0x1C */ { 336, 11, 10, 13, 1, -9 },
|
||||
/* 0x1D */ { 350, 11, 10, 13, 1, -9 },
|
||||
/* 0x1E */ { 364, 12, 10, 14, 1, -9 },
|
||||
/* 0x1F */ { 379, 8, 10, 11, 2, -9 },
|
||||
/* ' ' 0x20 */ { 389, 0, 0, 3, 0, 0 },
|
||||
/* '!' 0x21 */ { 389, 1, 9, 4, 2, -8 },
|
||||
/* '"' 0x22 */ { 391, 3, 3, 4, 0, -8 },
|
||||
/* '#' 0x23 */ { 393, 7, 8, 7, 0, -7 },
|
||||
/* '$' 0x24 */ { 400, 6, 11, 7, 0, -9 },
|
||||
/* '%' 0x25 */ { 409, 10, 9, 11, 0, -8 },
|
||||
/* '&' 0x26 */ { 421, 6, 9, 8, 1, -8 },
|
||||
/* ''' 0x27 */ { 428, 1, 3, 2, 1, -8 },
|
||||
/* '(' 0x28 */ { 429, 2, 11, 4, 1, -8 },
|
||||
/* ')' 0x29 */ { 432, 3, 11, 4, 0, -8 },
|
||||
/* '*' 0x2A */ { 437, 3, 3, 5, 1, -8 },
|
||||
/* '+' 0x2B */ { 439, 5, 5, 7, 1, -4 },
|
||||
/* ',' 0x2C */ { 443, 1, 3, 3, 1, 0 },
|
||||
/* '-' 0x2D */ { 444, 2, 1, 4, 1, -3 },
|
||||
/* '.' 0x2E */ { 445, 1, 1, 3, 1, 0 },
|
||||
/* '/' 0x2F */ { 446, 3, 9, 3, 0, -8 },
|
||||
/* '0' 0x30 */ { 450, 5, 9, 7, 1, -8 },
|
||||
/* '1' 0x31 */ { 456, 3, 9, 7, 1, -8 },
|
||||
/* '2' 0x32 */ { 460, 6, 9, 7, 0, -8 },
|
||||
/* '3' 0x33 */ { 467, 6, 9, 7, 0, -8 },
|
||||
/* '4' 0x34 */ { 474, 6, 9, 7, 0, -8 },
|
||||
/* '5' 0x35 */ { 481, 5, 9, 7, 1, -8 },
|
||||
/* '6' 0x36 */ { 487, 5, 9, 7, 1, -8 },
|
||||
/* '7' 0x37 */ { 493, 5, 9, 7, 1, -8 },
|
||||
/* '8' 0x38 */ { 499, 6, 9, 7, 0, -8 },
|
||||
/* '9' 0x39 */ { 506, 6, 9, 7, 0, -8 },
|
||||
/* ':' 0x3A */ { 513, 1, 7, 3, 1, -6 },
|
||||
/* ';' 0x3B */ { 514, 1, 8, 3, 1, -5 },
|
||||
/* '<' 0x3C */ { 515, 5, 5, 7, 1, -4 },
|
||||
/* '=' 0x3D */ { 519, 5, 3, 7, 1, -3 },
|
||||
/* '>' 0x3E */ { 521, 5, 5, 7, 1, -4 },
|
||||
/* '?' 0x3F */ { 525, 5, 9, 7, 1, -8 },
|
||||
/* '@' 0x40 */ { 531, 11, 11, 12, 0, -8 },
|
||||
/* 'A' 0x41 */ { 547, 8, 9, 8, 0, -8 },
|
||||
/* 'B' 0x42 */ { 556, 6, 9, 8, 1, -8 },
|
||||
/* 'C' 0x43 */ { 563, 8, 9, 9, 0, -8 },
|
||||
/* 'D' 0x44 */ { 572, 7, 9, 8, 1, -8 },
|
||||
/* 'E' 0x45 */ { 580, 6, 9, 8, 1, -8 },
|
||||
/* 'F' 0x46 */ { 587, 6, 9, 7, 1, -8 },
|
||||
/* 'G' 0x47 */ { 594, 8, 9, 9, 0, -8 },
|
||||
/* 'H' 0x48 */ { 603, 7, 9, 9, 1, -8 },
|
||||
/* 'I' 0x49 */ { 611, 1, 9, 3, 1, -8 },
|
||||
/* 'J' 0x4A */ { 613, 5, 9, 6, 0, -8 },
|
||||
/* 'K' 0x4B */ { 619, 7, 9, 8, 1, -8 },
|
||||
/* 'L' 0x4C */ { 627, 5, 9, 7, 1, -8 },
|
||||
/* 'M' 0x4D */ { 633, 8, 9, 10, 1, -8 },
|
||||
/* 'N' 0x4E */ { 642, 7, 9, 9, 1, -8 },
|
||||
/* 'O' 0x4F */ { 650, 9, 9, 9, 0, -8 },
|
||||
/* 'P' 0x50 */ { 661, 6, 9, 8, 1, -8 },
|
||||
/* 'Q' 0x51 */ { 668, 9, 10, 9, 0, -8 },
|
||||
/* 'R' 0x52 */ { 680, 7, 9, 9, 1, -8 },
|
||||
/* 'S' 0x53 */ { 688, 6, 9, 8, 1, -8 },
|
||||
/* 'T' 0x54 */ { 695, 7, 9, 8, 0, -8 },
|
||||
/* 'U' 0x55 */ { 703, 7, 9, 9, 1, -8 },
|
||||
/* 'V' 0x56 */ { 711, 7, 9, 8, 0, -8 },
|
||||
/* 'W' 0x57 */ { 719, 11, 9, 11, 0, -8 },
|
||||
/* 'X' 0x58 */ { 732, 6, 9, 8, 1, -8 },
|
||||
/* 'Y' 0x59 */ { 739, 8, 9, 8, 0, -8 },
|
||||
/* 'Z' 0x5A */ { 748, 7, 9, 7, 0, -8 },
|
||||
/* '[' 0x5B */ { 756, 2, 12, 3, 1, -8 },
|
||||
/* '\' 0x5C */ { 759, 3, 9, 3, 0, -8 },
|
||||
/* ']' 0x5D */ { 763, 2, 12, 3, 0, -8 },
|
||||
/* '^' 0x5E */ { 766, 4, 4, 6, 1, -8 },
|
||||
/* '_' 0x5F */ { 768, 7, 1, 7, 0, 2 },
|
||||
/* '`' 0x60 */ { 769, 1, 1, 3, 1, -8 },
|
||||
/* 'a' 0x61 */ { 770, 6, 7, 7, 0, -6 },
|
||||
/* 'b' 0x62 */ { 776, 5, 9, 7, 1, -8 },
|
||||
/* 'c' 0x63 */ { 782, 6, 7, 6, 0, -6 },
|
||||
/* 'd' 0x64 */ { 788, 6, 9, 7, 0, -8 },
|
||||
/* 'e' 0x65 */ { 795, 6, 7, 6, 0, -6 },
|
||||
/* 'f' 0x66 */ { 801, 3, 9, 3, 0, -8 },
|
||||
/* 'g' 0x67 */ { 805, 6, 10, 7, 0, -6 },
|
||||
/* 'h' 0x68 */ { 813, 5, 9, 6, 1, -8 },
|
||||
/* 'i' 0x69 */ { 819, 1, 9, 3, 1, -8 },
|
||||
/* 'j' 0x6A */ { 821, 2, 12, 3, 0, -8 },
|
||||
/* 'k' 0x6B */ { 824, 5, 9, 6, 1, -8 },
|
||||
/* 'l' 0x6C */ { 830, 1, 9, 3, 1, -8 },
|
||||
/* 'm' 0x6D */ { 832, 8, 7, 10, 1, -6 },
|
||||
/* 'n' 0x6E */ { 839, 5, 7, 6, 1, -6 },
|
||||
/* 'o' 0x6F */ { 844, 6, 7, 6, 0, -6 },
|
||||
/* 'p' 0x70 */ { 850, 5, 9, 7, 1, -6 },
|
||||
/* 'q' 0x71 */ { 856, 6, 9, 7, 0, -6 },
|
||||
/* 'r' 0x72 */ { 863, 3, 7, 4, 1, -6 },
|
||||
/* 's' 0x73 */ { 866, 5, 7, 6, 0, -6 },
|
||||
/* 't' 0x74 */ { 871, 3, 8, 3, 0, -7 },
|
||||
/* 'u' 0x75 */ { 874, 5, 7, 6, 1, -6 },
|
||||
/* 'v' 0x76 */ { 879, 6, 7, 6, 0, -6 },
|
||||
/* 'w' 0x77 */ { 885, 8, 7, 9, 0, -6 },
|
||||
/* 'x' 0x78 */ { 892, 5, 7, 6, 0, -6 },
|
||||
/* 'y' 0x79 */ { 897, 5, 10, 6, 0, -6 },
|
||||
/* 'z' 0x7A */ { 904, 5, 7, 6, 0, -6 },
|
||||
/* '{' 0x7B */ { 909, 2, 12, 4, 1, -8 },
|
||||
/* '|' 0x7C */ { 912, 1, 11, 3, 1, -8 },
|
||||
/* '}' 0x7D */ { 914, 2, 12, 4, 1, -8 },
|
||||
/* '~' 0x7E */ { 917, 6, 2, 6, 0, -4 },
|
||||
/* 0x7F */ { 919, 0, 0, 0, 0, 0 },
|
||||
/* 0x80 */ { 919, 7, 9, 8, 0, -8 },
|
||||
/* 0x81 */ { 927, 0, 0, 8, 0, 0 },
|
||||
/* 0x82 */ { 927, 1, 3, 3, 1, 0 },
|
||||
/* 0x83 */ { 928, 3, 12, 3, 0, -8 },
|
||||
/* 0x84 */ { 933, 3, 3, 5, 1, 0 },
|
||||
/* 0x85 */ { 935, 5, 1, 7, 1, 0 },
|
||||
/* 0x86 */ { 936, 5, 11, 7, 1, -8 },
|
||||
/* 0x87 */ { 943, 5, 11, 7, 1, -8 },
|
||||
/* 0x88 */ { 950, 3, 2, 4, 0, -9 },
|
||||
/* 0x89 */ { 951, 12, 9, 12, 0, -8 },
|
||||
/* 0x8A */ { 965, 6, 11, 8, 1, -9 },
|
||||
/* 0x8B */ { 974, 2, 3, 4, 1, -4 },
|
||||
/* 0x8C */ { 975, 11, 9, 12, 0, -8 },
|
||||
/* 0x8D */ { 988, 0, 0, 8, 0, 0 },
|
||||
/* 0x8E */ { 988, 7, 10, 7, 0, -9 },
|
||||
/* 0x8F */ { 997, 0, 0, 8, 0, 0 },
|
||||
/* 0x90 */ { 997, 0, 0, 8, 0, 0 },
|
||||
/* 0x91 */ { 997, 1, 3, 3, 1, -8 },
|
||||
/* 0x92 */ { 998, 1, 3, 2, 1, -8 },
|
||||
/* 0x93 */ { 999, 3, 3, 5, 1, -8 },
|
||||
/* 0x94 */ { 1001, 3, 3, 5, 1, -8 },
|
||||
/* 0x95 */ { 1003, 3, 3, 5, 1, -5 },
|
||||
/* 0x96 */ { 1005, 6, 1, 6, 0, -3 },
|
||||
/* 0x97 */ { 1006, 12, 1, 12, 0, -3 },
|
||||
/* 0x98 */ { 1008, 4, 2, 4, 0, -8 },
|
||||
/* 0x99 */ { 1009, 11, 7, 12, 1, -8 },
|
||||
/* 0x9A */ { 1019, 4, 9, 6, 1, -8 },
|
||||
/* 0x9B */ { 1024, 2, 3, 3, 1, -4 },
|
||||
/* 0x9C */ { 1025, 11, 7, 11, 0, -6 },
|
||||
/* 0x9D */ { 1035, 0, 0, 8, 0, 0 },
|
||||
/* 0x9E */ { 1035, 5, 9, 6, 0, -8 },
|
||||
/* 0x9F */ { 1041, 7, 10, 8, 1, -9 },
|
||||
/* 0xA0 */ { 1050, 0, 0, 3, 0, 0 },
|
||||
/* 0xA1 */ { 1050, 1, 9, 4, 1, -5 },
|
||||
/* 0xA2 */ { 1052, 5, 9, 7, 1, -7 },
|
||||
/* 0xA3 */ { 1058, 6, 9, 7, 0, -8 },
|
||||
/* 0xA4 */ { 1065, 5, 4, 7, 1, -5 },
|
||||
/* 0xA5 */ { 1068, 5, 9, 7, 1, -8 },
|
||||
/* 0xA6 */ { 1074, 1, 12, 3, 1, -8 },
|
||||
/* 0xA7 */ { 1076, 5, 12, 7, 1, -8 },
|
||||
/* 0xA8 */ { 1084, 3, 1, 4, 0, -7 },
|
||||
/* 0xA9 */ { 1085, 9, 9, 10, 0, -8 },
|
||||
/* 0xAA */ { 1096, 4, 5, 4, 0, -8 },
|
||||
/* 0xAB */ { 1099, 4, 4, 6, 1, -4 },
|
||||
/* 0xAC */ { 1101, 6, 3, 7, 1, -4 },
|
||||
/* 0xAD */ { 1104, 0, 0, 0, 0, 0 },
|
||||
/* 0xAE */ { 1104, 9, 9, 10, 0, -8 },
|
||||
/* 0xAF */ { 1115, 3, 1, 4, 0, -8 },
|
||||
/* 0xB0 */ { 1116, 4, 4, 7, 2, -8 },
|
||||
/* 0xB1 */ { 1118, 5, 7, 7, 1, -6 },
|
||||
/* 0xB2 */ { 1123, 4, 5, 4, 0, -9 },
|
||||
/* 0xB3 */ { 1126, 4, 5, 4, 0, -9 },
|
||||
/* 0xB4 */ { 1129, 1, 1, 4, 1, -8 },
|
||||
/* 0xB5 */ { 1130, 6, 9, 7, 1, -6 },
|
||||
/* 0xB6 */ { 1137, 6, 10, 6, 1, -8 },
|
||||
/* 0xB7 */ { 1145, 1, 1, 3, 1, -2 },
|
||||
/* 0xB8 */ { 1146, 3, 3, 4, 1, 1 },
|
||||
/* 0xB9 */ { 1148, 2, 6, 4, 1, -9 },
|
||||
/* 0xBA */ { 1150, 4, 5, 4, 0, -8 },
|
||||
/* 0xBB */ { 1153, 4, 4, 6, 1, -5 },
|
||||
/* 0xBC */ { 1155, 10, 9, 10, 1, -8 },
|
||||
/* 0xBD */ { 1167, 9, 9, 10, 1, -8 },
|
||||
/* 0xBE */ { 1178, 10, 9, 11, 0, -8 },
|
||||
/* 0xBF */ { 1190, 5, 9, 7, 1, -5 },
|
||||
/* 0xC0 */ { 1196, 4, 10, 3, -1, -10 },
|
||||
/* 0xC1 */ { 1201, 7, 9, 7, 0, -9 },
|
||||
/* 0xC2 */ { 1209, 6, 9, 8, 1, -9 },
|
||||
/* 0xC3 */ { 1216, 6, 9, 7, 1, -9 },
|
||||
/* 0xC4 */ { 1223, 9, 9, 7, -1, -9 },
|
||||
/* 0xC5 */ { 1234, 6, 9, 8, 1, -9 },
|
||||
/* 0xC6 */ { 1241, 7, 9, 7, 0, -9 },
|
||||
/* 0xC7 */ { 1249, 7, 9, 9, 1, -9 },
|
||||
/* 0xC8 */ { 1257, 7, 9, 9, 1, -9 },
|
||||
/* 0xC9 */ { 1265, 1, 9, 3, 1, -9 },
|
||||
/* 0xCA */ { 1267, 7, 9, 8, 1, -9 },
|
||||
/* 0xCB */ { 1275, 9, 9, 7, -1, -9 },
|
||||
/* 0xCC */ { 1286, 7, 9, 9, 1, -9 },
|
||||
/* 0xCD */ { 1294, 7, 9, 9, 1, -9 },
|
||||
/* 0xCE */ { 1302, 6, 9, 8, 1, -9 },
|
||||
/* 0xCF */ { 1309, 7, 9, 9, 1, -9 },
|
||||
/* 0xD0 */ { 1317, 7, 9, 9, 1, -9 },
|
||||
/* 0xD1 */ { 1325, 6, 9, 8, 1, -9 },
|
||||
/* 0xD2 */ { 1332, 0, 0, 5, 0, 0 },
|
||||
/* 0xD3 */ { 1332, 6, 9, 7, 1, -9 },
|
||||
/* 0xD4 */ { 1339, 7, 9, 7, 0, -9 },
|
||||
/* 0xD5 */ { 1347, 7, 9, 7, 0, -9 },
|
||||
/* 0xD6 */ { 1355, 7, 9, 9, 1, -9 },
|
||||
/* 0xD7 */ { 1363, 7, 9, 7, 0, -9 },
|
||||
/* 0xD8 */ { 1371, 7, 9, 9, 1, -9 },
|
||||
/* 0xD9 */ { 1379, 7, 9, 9, 1, -9 },
|
||||
/* 0xDA */ { 1387, 3, 11, 3, 0, -11 },
|
||||
/* 0xDB */ { 1392, 7, 11, 7, 0, -11 },
|
||||
/* 0xDC */ { 1402, 5, 10, 7, 1, -10 },
|
||||
/* 0xDD */ { 1409, 5, 10, 5, 0, -10 },
|
||||
/* 0xDE */ { 1416, 5, 12, 7, 1, -10 },
|
||||
/* 0xDF */ { 1424, 2, 10, 3, 1, -10 },
|
||||
/* 0xE0 */ { 1427, 5, 10, 7, 1, -10 },
|
||||
/* 0xE1 */ { 1434, 5, 7, 7, 1, -7 },
|
||||
/* 0xE2 */ { 1439, 5, 11, 7, 1, -9 },
|
||||
/* 0xE3 */ { 1446, 7, 9, 5, -1, -7 },
|
||||
/* 0xE4 */ { 1454, 5, 9, 7, 1, -9 },
|
||||
/* 0xE5 */ { 1460, 5, 7, 5, 0, -7 },
|
||||
/* 0xE6 */ { 1465, 4, 11, 5, 1, -9 },
|
||||
/* 0xE7 */ { 1471, 5, 9, 7, 1, -7 },
|
||||
/* 0xE8 */ { 1477, 5, 9, 7, 1, -9 },
|
||||
/* 0xE9 */ { 1483, 1, 7, 3, 1, -7 },
|
||||
/* 0xEA */ { 1484, 6, 7, 7, 1, -7 },
|
||||
/* 0xEB */ { 1490, 6, 9, 5, -1, -9 },
|
||||
/* 0xEC */ { 1497, 5, 9, 7, 1, -7 },
|
||||
/* 0xED */ { 1503, 5, 7, 5, 0, -7 },
|
||||
/* 0xEE */ { 1508, 4, 11, 5, 1, -9 },
|
||||
/* 0xEF */ { 1514, 5, 7, 7, 1, -7 },
|
||||
/* 0xF0 */ { 1519, 8, 7, 8, 0, -7 },
|
||||
/* 0xF1 */ { 1526, 5, 9, 7, 1, -7 },
|
||||
/* 0xF2 */ { 1532, 4, 9, 6, 1, -7 },
|
||||
/* 0xF3 */ { 1537, 7, 7, 7, 1, -7 },
|
||||
/* 0xF4 */ { 1544, 3, 7, 5, 1, -7 },
|
||||
/* 0xF5 */ { 1547, 5, 7, 7, 1, -7 },
|
||||
/* 0xF6 */ { 1552, 6, 9, 8, 1, -7 },
|
||||
/* 0xF7 */ { 1559, 6, 9, 6, 0, -7 },
|
||||
/* 0xF8 */ { 1566, 7, 9, 9, 1, -7 },
|
||||
/* 0xF9 */ { 1574, 7, 7, 9, 1, -7 },
|
||||
/* 0xFA */ { 1581, 3, 9, 3, 0, -9 },
|
||||
/* 0xFB */ { 1585, 5, 9, 7, 1, -9 },
|
||||
/* 0xFC */ { 1591, 5, 10, 7, 1, -10 },
|
||||
/* 0xFD */ { 1598, 5, 10, 7, 1, -10 },
|
||||
/* 0xFE */ { 1605, 7, 10, 9, 1, -10 },
|
||||
/* 0xFF */ { 1614, 0, 0, 5, 0, 0 },
|
||||
};
|
||||
|
||||
const GFXfont FreeSans6pt_Win1253 PROGMEM = {
|
||||
(uint8_t*)FreeSans6pt_Win1253Bitmaps,
|
||||
(GFXglyph*)FreeSans6pt_Win1253Glyphs,
|
||||
0x01, 0xFF, 10
|
||||
};
|
||||
527
src/graphics/niche/Fonts/FreeSans9pt_Win1253.h
Normal file
527
src/graphics/niche/Fonts/FreeSans9pt_Win1253.h
Normal file
@@ -0,0 +1,527 @@
|
||||
// trunk-ignore-all(clang-format)
|
||||
#pragma once
|
||||
/* PROPERTIES
|
||||
|
||||
FONT_NAME FreeSans9pt_Win1253
|
||||
*/
|
||||
const uint8_t FreeSans9pt_Win1253Bitmaps[] PROGMEM = {
|
||||
/* 0x01 */ 0x07, 0x00, 0x0A, 0x00, 0x24, 0x00, 0x48, 0x01, 0x10, 0x04, 0x40, 0x10, 0xFF, 0x20, 0x02, 0x81, 0xFD, 0x00, 0x06, 0x07, 0xF4, 0x08, 0x24, 0x0F, 0x88, 0x11, 0x0F, 0xDC, 0x00,
|
||||
/* 0x02 */ 0x3F, 0x70, 0x81, 0x11, 0x03, 0xE4, 0x08, 0x28, 0x1F, 0xD0, 0x00, 0x60, 0x7F, 0x20, 0x02, 0x43, 0xFC, 0x44, 0x00, 0x44, 0x00, 0x48, 0x00, 0x90, 0x00, 0xA0, 0x01, 0xC0, 0x00,
|
||||
/* 0x03 */ 0x07, 0xC0, 0x30, 0x60, 0x80, 0x22, 0x00, 0x28, 0x00, 0x31, 0x8C, 0x63, 0x18, 0xC0, 0x01, 0x80, 0x03, 0x00, 0x06, 0x20, 0x8C, 0x3E, 0x14, 0x00, 0x44, 0x01, 0x06, 0x0C, 0x03, 0xE0,
|
||||
/* 0x04 */ 0x07, 0xC0, 0x30, 0x60, 0x80, 0x22, 0x00, 0x28, 0x82, 0x30, 0x88, 0x62, 0x08, 0xC0, 0x01, 0x80, 0x03, 0x00, 0x06, 0x3F, 0x8C, 0x3E, 0x14, 0x00, 0x44, 0x01, 0x06, 0x0C, 0x03, 0xE0,
|
||||
/* 0x05 */ 0x0B, 0x10, 0x14, 0xA8, 0x12, 0x50, 0x29, 0x42, 0x24, 0xA5, 0x32, 0x95, 0x5A, 0x09, 0x48, 0x09, 0x24, 0x01, 0x10, 0x01, 0x48, 0x02, 0xA4, 0x02, 0x42, 0x04, 0x01, 0x98, 0x00, 0x60,
|
||||
/* 0x06 */ 0x00, 0x80, 0x22, 0x80, 0x65, 0x00, 0xBE, 0xE1, 0x82, 0x4E, 0x03, 0x24, 0x04, 0x28, 0x06, 0x30, 0x12, 0x20, 0x3C, 0xA0, 0xC3, 0xFE, 0x80, 0x4D, 0x00, 0xA6, 0x01, 0x80, 0x00,
|
||||
/* 0x07 */
|
||||
/* 0x08 */ 0x00, 0xF8, 0x00, 0x82, 0x00, 0x80, 0x83, 0xE0, 0x41, 0x10, 0x21, 0x04, 0x1B, 0x00, 0x03, 0x00, 0x01, 0x80, 0x00, 0xE0, 0x00, 0x4F, 0xE1, 0xC0, 0x0F, 0x02, 0x00, 0x03, 0x01, 0x00, 0x09, 0x88, 0x0C, 0x0C,
|
||||
/* 0x09 */ 0x00, 0xF8, 0x00, 0x82, 0x00, 0x80, 0x83, 0xE0, 0x41, 0x10, 0x21, 0x04, 0x1B, 0x00, 0x03, 0x00, 0x01, 0x80, 0x00, 0xE0, 0x00, 0x4F, 0xE1, 0xC0, 0x0F, 0x00,
|
||||
/* 0x0A */
|
||||
/* 0x0B */ 0x1C, 0x1C, 0x31, 0xB1, 0x90, 0x50, 0x50, 0x10, 0x18, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x02, 0x80, 0x02, 0x40, 0x01, 0x10, 0x01, 0x04, 0x01, 0x01, 0x01, 0x00, 0x41, 0x00, 0x11, 0x00, 0x07, 0x00, 0x01, 0x00,
|
||||
/* 0x0C */ 0x06, 0x00, 0x0A, 0x00, 0x12, 0x00, 0x32, 0x01, 0x84, 0x04, 0x10, 0x08, 0x98, 0x1C, 0x18, 0x40, 0x48, 0x82, 0x11, 0xF0, 0x74, 0x02, 0x18, 0x70, 0x2F, 0x9F, 0x80,
|
||||
/* 0x0D */
|
||||
/* 0x0E */ 0x01, 0x00, 0x05, 0x00, 0x0A, 0x00, 0x3E, 0x00, 0x82, 0x02, 0x82, 0x06, 0x04, 0x10, 0x04, 0x20, 0x08, 0x40, 0x10, 0xFF, 0x22, 0x00, 0x29, 0xFF, 0x3F, 0x8F, 0xDF, 0x9F, 0x01, 0xC0,
|
||||
/* 0x0F */ 0x07, 0xC0, 0x30, 0x60, 0x80, 0x22, 0x00, 0x28, 0x82, 0x36, 0x03, 0x60, 0x00, 0xCC, 0x19, 0xA4, 0x4B, 0x00, 0x06, 0x8E, 0x2B, 0x22, 0x66, 0x7C, 0xCC, 0x71, 0x98, 0x03, 0x00,
|
||||
/* 0x10 */ 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1E, 0x00, 0x54, 0x00, 0xA8, 0x01, 0x50, 0x02, 0xA0, 0x05, 0x20, 0x32, 0x61, 0xC4, 0x74, 0x49, 0x10, 0x6C, 0x00, 0xD8, 0x01, 0x10, 0x00,
|
||||
/* 0x11 */ 0x07, 0xC0, 0x30, 0x60, 0x80, 0x22, 0x40, 0x29, 0x00, 0x31, 0x84, 0x63, 0x18, 0xC0, 0x00, 0x80, 0x15, 0x03, 0x7E, 0x02, 0xFA, 0x04, 0xE4, 0x18, 0x84, 0x00, 0x06, 0x0C, 0x03, 0xE0,
|
||||
/* 0x12 */ 0x02, 0x08, 0x01, 0x08, 0x40, 0x10, 0xC0, 0x08, 0xC0, 0x60, 0x80, 0x28, 0x04, 0x12, 0x4C, 0x10, 0x80, 0x08, 0x23, 0x0E, 0x08, 0xC4, 0x82, 0x04, 0x20, 0x83, 0x09, 0x82, 0x47, 0x01, 0x1C, 0x01, 0x30, 0x00, 0xE0, 0x00, 0x00,
|
||||
/* 0x13 */ 0x07, 0xC0, 0x30, 0x60, 0x80, 0x22, 0x00, 0x28, 0x00, 0x31, 0x08, 0x65, 0x28, 0xC0, 0x01, 0x80, 0x03, 0x00, 0x06, 0x3F, 0x8C, 0x3E, 0x14, 0x00, 0x44, 0x01, 0x06, 0x0C, 0x03, 0xE0,
|
||||
/* 0x14 */ 0x07, 0xC0, 0x30, 0x60, 0x80, 0x22, 0x22, 0x29, 0x83, 0x30, 0x00, 0x65, 0x14, 0xD3, 0x4D, 0xBA, 0xEB, 0x38, 0xE6, 0x00, 0x0A, 0x00, 0x24, 0x38, 0x44, 0x01, 0x07, 0x1C, 0x01, 0xC0,
|
||||
/* 0x15 */ 0x07, 0xC0, 0x30, 0x18, 0x80, 0x32, 0x00, 0xF8, 0x01, 0xF1, 0x09, 0xA5, 0x28, 0x40, 0x01, 0x80, 0x03, 0x00, 0x06, 0x3F, 0x8C, 0x3E, 0x14, 0x00, 0x44, 0x01, 0x06, 0x0C, 0x03, 0xE0,
|
||||
/* 0x16 */ 0x0C, 0x00, 0xC0, 0x1C, 0x03, 0x80, 0xF8, 0xBB, 0x36, 0xC7, 0x99, 0xF3, 0xFE, 0x3F, 0xC3, 0xF0, 0x7E, 0x0E, 0xC1, 0x8E, 0xE0, 0x20,
|
||||
/* 0x17 */ 0x07, 0xC0, 0x30, 0x60, 0x80, 0x22, 0x00, 0x28, 0x00, 0x10, 0x01, 0x20, 0x1D, 0x44, 0x42, 0x84, 0x85, 0x00, 0x86, 0x00, 0xC4, 0x00, 0x44, 0x7C, 0x44, 0x00, 0x06, 0x0C, 0x03, 0xE0,
|
||||
/* 0x18 */ 0x01, 0xE0, 0x00, 0x84, 0x00, 0x40, 0x80, 0x20, 0x10, 0x08, 0x24, 0x02, 0x41, 0x00, 0x86, 0x03, 0x12, 0x03, 0xB4, 0x03, 0x52, 0x81, 0x23, 0x80, 0x70, 0xA0, 0x14, 0x28, 0x05, 0x0A, 0x01, 0x42, 0x80, 0x50,
|
||||
/* 0x19 */ 0x07, 0xC0, 0x30, 0x60, 0x80, 0x22, 0x00, 0x28, 0x00, 0x33, 0x18, 0x60, 0x00, 0xDC, 0xE1, 0xB9, 0xC3, 0x7B, 0xC6, 0x63, 0x0A, 0x00, 0x24, 0xF0, 0x44, 0x01, 0x06, 0x0C, 0x03, 0xE0,
|
||||
/* 0x1A */ 0xFF, 0xFC, 0x00, 0x63, 0xE3, 0x31, 0x99, 0x04, 0xC8, 0x66, 0x06, 0x30, 0x61, 0x82, 0x0C, 0x10, 0x60, 0x03, 0x04, 0x18, 0x00, 0xFF, 0xFC,
|
||||
/* 0x1B */ 0x07, 0xF0, 0x06, 0x0C, 0x04, 0x01, 0x04, 0x00, 0x44, 0x22, 0x12, 0x2A, 0x89, 0x00, 0x04, 0x80, 0x02, 0x44, 0x11, 0x01, 0xF0, 0x04, 0x01, 0x0D, 0x01, 0x6A, 0x41, 0x2C, 0x00, 0x05, 0xC0, 0x0E, 0x18, 0x18,
|
||||
/* 0x1C */ 0x07, 0xC0, 0x30, 0x60, 0x80, 0x22, 0xC0, 0x2A, 0x00, 0x33, 0x00, 0x66, 0x00, 0xCC, 0x39, 0x80, 0x83, 0x00, 0x06, 0x00, 0x8C, 0x3E, 0x14, 0x00, 0x44, 0x01, 0x06, 0x0C, 0x03, 0xE0,
|
||||
/* 0x1D */ 0x07, 0xC0, 0x30, 0x60, 0x80, 0x22, 0x70, 0x28, 0x00, 0x31, 0x80, 0x63, 0x18, 0xC0, 0x31, 0x80, 0x03, 0x00, 0x06, 0x60, 0x0D, 0x33, 0x12, 0x10, 0x48, 0x21, 0x23, 0x8C, 0x00,
|
||||
/* 0x1E */ 0x03, 0x00, 0x07, 0x9E, 0x07, 0x00, 0x86, 0x00, 0x27, 0xC0, 0x0F, 0xC0, 0x07, 0x8C, 0x62, 0x06, 0x31, 0x20, 0x00, 0x90, 0x00, 0x48, 0x00, 0x24, 0x3E, 0x11, 0x00, 0x10, 0x40, 0x10, 0x18, 0x30, 0x03, 0xE0,
|
||||
/* 0x1F */ 0x18, 0x02, 0x80, 0x4C, 0x16, 0x41, 0x24, 0x3C, 0x88, 0x6E, 0x65, 0xF2, 0x78, 0x46, 0x88, 0xCF, 0x18, 0x02, 0x80, 0x8C, 0x60, 0x70,
|
||||
/* ' ' 0x20 */
|
||||
/* '!' 0x21 */ 0xFF, 0xFF, 0xF0, 0xC0,
|
||||
/* '"' 0x22 */ 0xDE, 0xF7, 0x20,
|
||||
/* '#' 0x23 */ 0x09, 0x86, 0x41, 0x91, 0xFF, 0x13, 0x04, 0xC3, 0x20, 0xC8, 0xFF, 0x89, 0x82, 0x61, 0x90,
|
||||
/* '$' 0x24 */ 0x10, 0x1F, 0x14, 0xDA, 0x3D, 0x1E, 0x83, 0x40, 0x78, 0x17, 0x08, 0xF4, 0x7A, 0x35, 0x33, 0xF0, 0x40, 0x20,
|
||||
/* '%' 0x25 */ 0x38, 0x10, 0xEC, 0x20, 0xC6, 0x20, 0xC6, 0x40, 0xC6, 0x40, 0x6C, 0x80, 0x39, 0x00, 0x01, 0x3C, 0x02, 0x77, 0x02, 0x63, 0x04, 0x63, 0x04, 0x77, 0x08, 0x3C,
|
||||
/* '&' 0x26 */ 0x0E, 0x0C, 0xC3, 0x30, 0xCC, 0x1E, 0x03, 0x03, 0xC1, 0x9B, 0xC2, 0xF0, 0xEC, 0x19, 0x8F, 0x3C, 0x40,
|
||||
/* ''' 0x27 */ 0xFE,
|
||||
/* '(' 0x28 */ 0x13, 0x26, 0x6C, 0xCC, 0xCC, 0xC4, 0x66, 0x23, 0x10,
|
||||
/* ')' 0x29 */ 0x8C, 0x46, 0x63, 0x33, 0x33, 0x32, 0x66, 0x4C, 0x80,
|
||||
/* '*' 0x2A */ 0x25, 0x7E, 0xA5, 0x00,
|
||||
/* '+' 0x2B */ 0x30, 0xC3, 0x3F, 0x30, 0xC3, 0x0C,
|
||||
/* ',' 0x2C */ 0xD6,
|
||||
/* '-' 0x2D */ 0xF0,
|
||||
/* '.' 0x2E */ 0xC0,
|
||||
/* '/' 0x2F */ 0x08, 0x44, 0x21, 0x10, 0x84, 0x42, 0x11, 0x08, 0x00,
|
||||
/* '0' 0x30 */ 0x3C, 0x66, 0x42, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x42, 0x66, 0x3C,
|
||||
/* '1' 0x31 */ 0x11, 0x3F, 0x33, 0x33, 0x33, 0x33, 0x30,
|
||||
/* '2' 0x32 */ 0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x1C, 0x1C, 0x1C, 0x18, 0x18, 0x10, 0x08, 0x07, 0xF8,
|
||||
/* '3' 0x33 */ 0x3C, 0x66, 0xC3, 0xC3, 0x03, 0x06, 0x1C, 0x07, 0x03, 0xC3, 0xC3, 0x66, 0x3C,
|
||||
/* '4' 0x34 */ 0x0C, 0x18, 0x71, 0x62, 0xC9, 0xA3, 0x46, 0xFE, 0x18, 0x30, 0x60, 0xC0,
|
||||
/* '5' 0x35 */ 0x7F, 0x20, 0x10, 0x08, 0x08, 0x07, 0xF3, 0x8C, 0x03, 0x01, 0x80, 0xF0, 0x6C, 0x63, 0xE0,
|
||||
/* '6' 0x36 */ 0x1E, 0x31, 0x98, 0x78, 0x0C, 0x06, 0xF3, 0x8D, 0x83, 0xC1, 0xE0, 0xD0, 0x6C, 0x63, 0xE0,
|
||||
/* '7' 0x37 */ 0xFF, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x18, 0x18, 0x18, 0x10, 0x30, 0x30,
|
||||
/* '8' 0x38 */ 0x3E, 0x31, 0xB0, 0x78, 0x3C, 0x1B, 0x18, 0xF8, 0xC6, 0xC1, 0xE0, 0xF0, 0x6C, 0x63, 0xE0,
|
||||
/* '9' 0x39 */ 0x3C, 0x66, 0xC2, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0xC2, 0x66, 0x3C,
|
||||
/* ':' 0x3A */ 0xC0, 0x00, 0x30,
|
||||
/* ';' 0x3B */ 0xC0, 0x00, 0x00, 0x64, 0xA0,
|
||||
/* '<' 0x3C */ 0x00, 0x81, 0xC7, 0x8E, 0x0C, 0x07, 0x80, 0x70, 0x0E, 0x01, 0x80,
|
||||
/* '=' 0x3D */ 0xFF, 0x80, 0x00, 0x1F, 0xF0,
|
||||
/* '>' 0x3E */ 0xE0, 0x1C, 0x03, 0x80, 0x30, 0x70, 0xE3, 0x81, 0x00,
|
||||
/* '?' 0x3F */ 0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x18, 0x38, 0x18, 0x18, 0x0C, 0x00, 0x00, 0x01, 0x80,
|
||||
/* '@' 0x40 */ 0x03, 0xF0, 0x06, 0x0E, 0x06, 0x01, 0x86, 0x00, 0x66, 0x1D, 0xBB, 0x31, 0xCF, 0x18, 0xC7, 0x98, 0x63, 0xCC, 0x31, 0xE6, 0x11, 0xB3, 0x99, 0xCC, 0xF7, 0x86, 0x00, 0x01, 0x80, 0x00, 0x70, 0x40, 0x0F, 0xE0,
|
||||
/* 'A' 0x41 */ 0x06, 0x00, 0xF0, 0x0F, 0x00, 0x90, 0x19, 0x81, 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2, 0x04, 0x60, 0x66, 0x06, 0xC0, 0x30,
|
||||
/* 'B' 0x42 */ 0xFF, 0x18, 0x33, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x3F, 0xC6, 0x06, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8,
|
||||
/* 'C' 0x43 */ 0x1F, 0x86, 0x19, 0x81, 0xA0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0x61, 0xF0,
|
||||
/* 'D' 0x44 */ 0xFF, 0x18, 0x33, 0x03, 0x60, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x03, 0x60, 0xCF, 0xF0,
|
||||
/* 'E' 0x45 */ 0xFF, 0xE0, 0x30, 0x18, 0x0C, 0x06, 0x03, 0xFD, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0F, 0xF8,
|
||||
/* 'F' 0x46 */ 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
|
||||
/* 'G' 0x47 */ 0x0F, 0x83, 0x0E, 0x60, 0x66, 0x03, 0xC0, 0x0C, 0x00, 0xC1, 0xFC, 0x03, 0xC0, 0x36, 0x03, 0x60, 0x73, 0x0F, 0x0F, 0x10,
|
||||
/* 'H' 0x48 */ 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06,
|
||||
/* 'I' 0x49 */ 0xFF, 0xFF, 0xFF, 0xC0,
|
||||
/* 'J' 0x4A */ 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x07, 0x8F, 0x1E, 0x27, 0x80,
|
||||
/* 'K' 0x4B */ 0xC0, 0xF0, 0x6C, 0x33, 0x18, 0xCC, 0x37, 0x0F, 0xC3, 0x98, 0xC3, 0x30, 0xCC, 0x1B, 0x03, 0xC0, 0xC0,
|
||||
/* 'L' 0x4C */ 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF,
|
||||
/* 'M' 0x4D */ 0xE0, 0x3F, 0x01, 0xFC, 0x1F, 0xE0, 0xFD, 0x05, 0xEC, 0x6F, 0x63, 0x79, 0x13, 0xCD, 0x9E, 0x6C, 0xF1, 0x47, 0x8E, 0x3C, 0x71, 0x80,
|
||||
/* 'N' 0x4E */ 0xE0, 0x7C, 0x0F, 0xC1, 0xE8, 0x3D, 0x87, 0x98, 0xF1, 0x1E, 0x33, 0xC3, 0x78, 0x6F, 0x07, 0xE0, 0x7C, 0x0E,
|
||||
/* 'O' 0x4F */ 0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x0C, 0x60, 0xC0, 0xF8, 0x00,
|
||||
/* 'P' 0x50 */ 0xFF, 0x30, 0x6C, 0x0F, 0x03, 0xC0, 0xF0, 0x6F, 0xF3, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00,
|
||||
/* 'Q' 0x51 */ 0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x6C, 0x60, 0xC0, 0xFB, 0x00, 0x08,
|
||||
/* 'R' 0x52 */ 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0, 0x70,
|
||||
/* 'S' 0x53 */ 0x3F, 0x18, 0x6C, 0x0F, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x0E, 0x00, 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x00,
|
||||
/* 'T' 0x54 */ 0xFF, 0x86, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0,
|
||||
/* 'U' 0x55 */ 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xB0, 0x61, 0xF0,
|
||||
/* 'V' 0x56 */ 0xC0, 0x6C, 0x0D, 0x81, 0x10, 0x63, 0x0C, 0x61, 0x04, 0x60, 0xCC, 0x19, 0x01, 0x60, 0x3C, 0x07, 0x00, 0x60,
|
||||
/* 'W' 0x57 */ 0xC1, 0x81, 0x61, 0xC3, 0x61, 0xC3, 0x61, 0x43, 0x62, 0x62, 0x22, 0x66, 0x32, 0x26, 0x36, 0x26, 0x14, 0x34, 0x14, 0x34, 0x1C, 0x1C, 0x18, 0x1C, 0x08, 0x18,
|
||||
/* 'X' 0x58 */ 0xC0, 0xD8, 0x66, 0x18, 0xCC, 0x1E, 0x07, 0x00, 0xC0, 0x78, 0x32, 0x0C, 0xC6, 0x1B, 0x07, 0xC0, 0xC0,
|
||||
/* 'Y' 0x59 */ 0xC0, 0x36, 0x06, 0x30, 0xC3, 0x0C, 0x19, 0x81, 0xD8, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00,
|
||||
/* 'Z' 0x5A */ 0xFF, 0xC0, 0x60, 0x30, 0x0C, 0x06, 0x03, 0x01, 0xC0, 0x60, 0x30, 0x18, 0x06, 0x03, 0x00, 0xFF, 0xC0,
|
||||
/* '[' 0x5B */ 0xFB, 0x6D, 0xB6, 0xDB, 0x6D, 0xB6, 0xE0,
|
||||
/* '\' 0x5C */ 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x80,
|
||||
/* ']' 0x5D */ 0xED, 0xB6, 0xDB, 0x6D, 0xB6, 0xDB, 0xE0,
|
||||
/* '^' 0x5E */ 0x30, 0x60, 0xA2, 0x44, 0xD8, 0xA1, 0x80,
|
||||
/* '_' 0x5F */ 0xFF, 0xC0,
|
||||
/* '`' 0x60 */ 0xC6, 0x30,
|
||||
/* 'a' 0x61 */ 0x7E, 0x71, 0xB0, 0xC0, 0x60, 0xF3, 0xDB, 0x0D, 0x86, 0xC7, 0x3D, 0xC0,
|
||||
/* 'b' 0x62 */ 0xC0, 0x60, 0x30, 0x1B, 0xCE, 0x36, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE0,
|
||||
/* 'c' 0x63 */ 0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C,
|
||||
/* 'd' 0x64 */ 0x03, 0x03, 0x03, 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B,
|
||||
/* 'e' 0x65 */ 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C,
|
||||
/* 'f' 0x66 */ 0x36, 0x6F, 0x66, 0x66, 0x66, 0x66, 0x60,
|
||||
/* 'g' 0x67 */ 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0xC6, 0x7C,
|
||||
/* 'h' 0x68 */ 0xC0, 0xC0, 0xC0, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
|
||||
/* 'i' 0x69 */ 0xC3, 0xFF, 0xFF, 0xC0,
|
||||
/* 'j' 0x6A */ 0x30, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xE0,
|
||||
/* 'k' 0x6B */ 0xC0, 0xC0, 0xC0, 0xC2, 0xC4, 0xCC, 0xD8, 0xF8, 0xEC, 0xC4, 0xC6, 0xC3, 0xC3,
|
||||
/* 'l' 0x6C */ 0xFF, 0xFF, 0xFF, 0xC0,
|
||||
/* 'm' 0x6D */ 0xDE, 0xF7, 0x1C, 0xF0, 0xC7, 0x86, 0x3C, 0x31, 0xE1, 0x8F, 0x0C, 0x78, 0x63, 0xC3, 0x1E, 0x18, 0xC0,
|
||||
/* 'n' 0x6E */ 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
|
||||
/* 'o' 0x6F */ 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C,
|
||||
/* 'p' 0x70 */ 0xDE, 0x71, 0xB0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xE3, 0x6F, 0x30, 0x18, 0x0C, 0x00,
|
||||
/* 'q' 0x71 */ 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0x03,
|
||||
/* 'r' 0x72 */ 0xDF, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x00,
|
||||
/* 's' 0x73 */ 0x3E, 0xE3, 0xC0, 0xC0, 0xE0, 0x3C, 0x07, 0xC3, 0xE3, 0x7E,
|
||||
/* 't' 0x74 */ 0x66, 0xF6, 0x66, 0x66, 0x66, 0x67,
|
||||
/* 'u' 0x75 */ 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B,
|
||||
/* 'v' 0x76 */ 0xC1, 0xA0, 0x98, 0xCC, 0x42, 0x21, 0xB0, 0xD0, 0x28, 0x1C, 0x0C, 0x00,
|
||||
/* 'w' 0x77 */ 0xC6, 0x1E, 0x38, 0x91, 0xC4, 0xCA, 0x66, 0xD3, 0x16, 0xD0, 0xA6, 0x87, 0x1C, 0x38, 0xC0, 0xC6, 0x00,
|
||||
/* 'x' 0x78 */ 0x87, 0x89, 0xB1, 0xC3, 0x07, 0x1E, 0x26, 0xC5, 0x0C,
|
||||
/* 'y' 0x79 */ 0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60,
|
||||
/* 'z' 0x7A */ 0xFE, 0x0C, 0x30, 0xC1, 0x86, 0x18, 0x20, 0xC1, 0xFC,
|
||||
/* '{' 0x7B */ 0x36, 0x66, 0x66, 0x6E, 0xCE, 0x66, 0x66, 0x66, 0x30,
|
||||
/* '|' 0x7C */ 0xFF, 0xFF, 0xFF, 0xFF, 0xC0,
|
||||
/* '}' 0x7D */ 0xC6, 0x66, 0x66, 0x67, 0x37, 0x66, 0x66, 0x66, 0xC0,
|
||||
/* '~' 0x7E */ 0x61, 0x24, 0x38,
|
||||
/* 0x7F */
|
||||
/* 0x80 */ 0x07, 0xC6, 0x13, 0x00, 0xC0, 0x60, 0x3F, 0xE6, 0x03, 0xFC, 0x60, 0x0C, 0x03, 0x00, 0x61, 0x07, 0xC0,
|
||||
/* 0x81 */
|
||||
/* 0x82 */ 0xDC,
|
||||
/* 0x83 */ 0x19, 0x8C, 0xF3, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0xE0,
|
||||
/* 0x84 */ 0xDA, 0x76,
|
||||
/* 0x85 */ 0xCC, 0xC0,
|
||||
/* 0x86 */ 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
/* 0x87 */ 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18,
|
||||
/* 0x88 */ 0x72, 0xA2,
|
||||
/* 0x89 */ 0x70, 0x80, 0x22, 0x20, 0x08, 0x90, 0x02, 0x24, 0x00, 0x72, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x10, 0x00, 0x09, 0xC7, 0x84, 0x8B, 0x31, 0x22, 0x84, 0x88, 0xB3, 0x21, 0xC7, 0x80,
|
||||
/* 0x8A */ 0x1B, 0x03, 0x80, 0x00, 0xFC, 0x61, 0xB0, 0x3C, 0x0F, 0x00, 0x78, 0x07, 0xC0, 0x38, 0x03, 0xC0, 0xF0, 0x36, 0x18, 0xFC,
|
||||
/* 0x8B */ 0x69,
|
||||
/* 0x8C */ 0x1E, 0xFE, 0x43, 0x81, 0x83, 0x06, 0x06, 0x0C, 0x0C, 0x18, 0x18, 0x30, 0x3F, 0xE0, 0x60, 0xC0, 0xC1, 0x81, 0x81, 0x83, 0x01, 0x8E, 0x01, 0xEF, 0xE0,
|
||||
/* 0x8D */
|
||||
/* 0x8E */ 0x1B, 0x03, 0x80, 0x03, 0xFF, 0x01, 0x80, 0xC0, 0x30, 0x18, 0x0C, 0x07, 0x01, 0x80, 0xC0, 0x60, 0x18, 0x0C, 0x03, 0xFF,
|
||||
/* 0x8F */
|
||||
/* 0x90 */
|
||||
/* 0x91 */ 0x6B,
|
||||
/* 0x92 */ 0xD6,
|
||||
/* 0x93 */ 0x4C, 0xA5, 0xB0,
|
||||
/* 0x94 */ 0xDA, 0x53, 0x20,
|
||||
/* 0x95 */ 0x6F, 0xFF, 0x60,
|
||||
/* 0x96 */ 0xFE,
|
||||
/* 0x97 */ 0xFF, 0xFF,
|
||||
/* 0x98 */ 0x4D, 0xC0,
|
||||
/* 0x99 */ 0xFC, 0xE1, 0xCC, 0x38, 0x73, 0x0E, 0x1C, 0xC3, 0x8F, 0x30, 0xD2, 0xCC, 0x34, 0xB3, 0x0D, 0x6C, 0xC3, 0x53, 0x30, 0xCC, 0xCC, 0x33, 0x30,
|
||||
/* 0x9A */ 0x24, 0x3C, 0x18, 0x7E, 0xE3, 0xC0, 0xC0, 0x60, 0x3C, 0x07, 0xC3, 0xE3, 0x7E,
|
||||
/* 0x9B */ 0x96,
|
||||
/* 0x9C */ 0x3C, 0xF8, 0xCF, 0x1B, 0x0C, 0x1E, 0x18, 0x3C, 0x3F, 0xF8, 0x60, 0x30, 0xC0, 0x61, 0x83, 0x67, 0x8C, 0x79, 0xF0,
|
||||
/* 0x9D */
|
||||
/* 0x9E */ 0x48, 0xF0, 0xC7, 0xF0, 0x61, 0x86, 0x0C, 0x30, 0xC1, 0x06, 0x0F, 0xE0,
|
||||
/* 0x9F */ 0x19, 0x80, 0x00, 0xC0, 0x36, 0x06, 0x30, 0xC3, 0x0C, 0x19, 0x81, 0xD8, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60,
|
||||
/* 0xA0 */
|
||||
/* 0xA1 */ 0xCF, 0xFF, 0xFF, 0xC0,
|
||||
/* 0xA2 */ 0x08, 0x04, 0x0F, 0x8D, 0x6C, 0x9E, 0x43, 0x21, 0x90, 0xC8, 0x64, 0xDA, 0xC7, 0xC0, 0x80, 0x40,
|
||||
/* 0xA3 */ 0x1F, 0x0C, 0x66, 0x0D, 0x83, 0x60, 0x0C, 0x0F, 0xC0, 0x60, 0x18, 0x06, 0x03, 0x01, 0xF1, 0x43, 0xC0,
|
||||
/* 0xA4 */ 0xFF, 0xDF, 0x1E, 0x3E, 0xFF, 0xC0,
|
||||
/* 0xA5 */ 0xC3, 0x42, 0x42, 0x24, 0x24, 0x3C, 0x18, 0x7E, 0x18, 0x7E, 0x18, 0x18, 0x18,
|
||||
/* 0xA6 */ 0xFF, 0xFC, 0x0F, 0xFF, 0xC0,
|
||||
/* 0xA7 */ 0x0C, 0x09, 0x0C, 0xC6, 0x63, 0x81, 0xE3, 0x19, 0x87, 0xE1, 0xB8, 0xC6, 0x41, 0xC0, 0x73, 0x19, 0x8C, 0x66, 0x1E, 0x00,
|
||||
/* 0xA8 */ 0xCC,
|
||||
/* 0xA9 */ 0x0F, 0xC0, 0x61, 0x87, 0x03, 0x9B, 0xC6, 0xD9, 0x8F, 0x60, 0x3D, 0x00, 0xF4, 0x03, 0xD8, 0x0D, 0xE6, 0x67, 0xF3, 0x86, 0x18, 0x0F, 0xC0,
|
||||
/* 0xAA */ 0x74, 0x8D, 0xA9, 0x7C, 0x1F,
|
||||
/* 0xAB */ 0x22, 0xCF, 0x26, 0x46, 0x64, 0x40,
|
||||
/* 0xAC */ 0xFF, 0x80, 0xC0, 0x60, 0x30, 0x18,
|
||||
/* 0xAD */
|
||||
/* 0xAE */ 0x0F, 0xC0, 0x61, 0x87, 0x03, 0x9F, 0xE6, 0xD0, 0x8F, 0x42, 0x3D, 0xF0, 0xF4, 0x23, 0xD0, 0x8D, 0xC2, 0x67, 0x0B, 0x86, 0x18, 0x0F, 0xC0,
|
||||
/* 0xAF */ 0xF8,
|
||||
/* 0xB0 */ 0x74, 0x63, 0x17, 0x00,
|
||||
/* 0xB1 */ 0x0C, 0x06, 0x03, 0x07, 0xE0, 0xC0, 0x60, 0x30, 0x18, 0x00, 0x00, 0x3F, 0xE0,
|
||||
/* 0xB2 */ 0x7B, 0x30, 0xC3, 0x11, 0x84, 0x3F,
|
||||
/* 0xB3 */ 0x7D, 0x8C, 0x18, 0xC0, 0x60, 0xF1, 0xBE,
|
||||
/* 0xB4 */ 0x36, 0xC0,
|
||||
/* 0xB5 */ 0xC3, 0x61, 0xB0, 0xD8, 0x6C, 0x36, 0x1B, 0x0D, 0x86, 0xE7, 0x7D, 0xF0, 0x18, 0x0C, 0x00,
|
||||
/* 0xB6 */ 0x3F, 0x7E, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0x72, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
|
||||
/* 0xB7 */ 0xE0,
|
||||
/* 0xB8 */ 0x21, 0xC7, 0xE0,
|
||||
/* 0xB9 */ 0x3D, 0xB6, 0xD8,
|
||||
/* 0xBA */ 0x74, 0x63, 0x18, 0xB8, 0x1F,
|
||||
/* 0xBB */ 0x89, 0x98, 0x99, 0x3C, 0xD1, 0x00,
|
||||
/* 0xBC */ 0x20, 0x43, 0x81, 0x06, 0x08, 0x18, 0x20, 0x61, 0x01, 0x84, 0x06, 0x21, 0x80, 0x86, 0x04, 0x78, 0x32, 0x60, 0x87, 0xC4, 0x06, 0x10, 0x18,
|
||||
/* 0xBD */ 0x20, 0x43, 0x81, 0x06, 0x08, 0x18, 0x20, 0x61, 0x01, 0x8D, 0xE6, 0x2C, 0xC1, 0x03, 0x0C, 0x0C, 0x20, 0x41, 0x86, 0x0C, 0x30, 0x20, 0xFC,
|
||||
/* 0xBE */ 0x78, 0x11, 0x98, 0x40, 0x31, 0x00, 0x82, 0x00, 0xC8, 0x01, 0x90, 0x33, 0x43, 0x3D, 0x06, 0x02, 0x3C, 0x08, 0x98, 0x10, 0xF8, 0x40, 0x61, 0x00, 0xC0,
|
||||
/* 0xBF */ 0x0C, 0x00, 0x00, 0x01, 0x80, 0xC0, 0xC0, 0xE0, 0xC0, 0xC0, 0x60, 0xF0, 0x6C, 0x63, 0xE0,
|
||||
/* 0xC0 */ 0x0C, 0xDB, 0xD3, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
/* 0xC1 */ 0x0E, 0x01, 0xC0, 0x6C, 0x0D, 0x81, 0xB0, 0x63, 0x0C, 0x61, 0xFC, 0x7F, 0xCC, 0x19, 0x83, 0x60, 0x3C, 0x06,
|
||||
/* 0xC2 */ 0xFF, 0x3F, 0xEC, 0x0F, 0x03, 0xC0, 0xFF, 0xEF, 0xFB, 0x03, 0xC0, 0xF0, 0x3C, 0x1F, 0xFE, 0xFF, 0x00,
|
||||
/* 0xC3 */ 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
|
||||
/* 0xC4 */ 0x07, 0x00, 0x38, 0x01, 0xC0, 0x1B, 0x00, 0xD8, 0x0C, 0x60, 0x63, 0x03, 0x18, 0x30, 0x61, 0x83, 0x18, 0x0C, 0xFF, 0xE7, 0xFF, 0x00,
|
||||
/* 0xC5 */ 0xFF, 0xFF, 0xFC, 0x03, 0x00, 0xC0, 0x3F, 0xEF, 0xFB, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0xFF, 0xFF, 0xC0,
|
||||
/* 0xC6 */ 0x7F, 0xDF, 0xF0, 0x18, 0x0C, 0x07, 0x01, 0x80, 0xC0, 0x60, 0x38, 0x0C, 0x06, 0x03, 0xFF, 0xFF, 0xC0,
|
||||
/* 0xC7 */ 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0xFF, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06,
|
||||
/* 0xC8 */ 0x0F, 0x03, 0xFC, 0x70, 0xE6, 0x06, 0xC0, 0x3C, 0xF3, 0xCF, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x70, 0xE3, 0xFC, 0x1F, 0x80,
|
||||
/* 0xC9 */ 0xFF, 0xFF, 0xFF, 0xC0,
|
||||
/* 0xCA */ 0xC1, 0xD8, 0x73, 0x1C, 0x67, 0x0D, 0xC1, 0xF0, 0x3F, 0x07, 0x70, 0xC7, 0x18, 0x63, 0x0E, 0x60, 0xEC, 0x0E,
|
||||
/* 0xCB */ 0x07, 0x00, 0x38, 0x01, 0xC0, 0x1B, 0x00, 0xD8, 0x0C, 0x60, 0x63, 0x03, 0x18, 0x30, 0x61, 0x83, 0x1C, 0x1C, 0xC0, 0x66, 0x03, 0x00,
|
||||
/* 0xCC */ 0xE0, 0x3F, 0x83, 0xFC, 0x1F, 0xE0, 0xFD, 0x8D, 0xEC, 0x6F, 0x63, 0x79, 0x13, 0xCD, 0x9E, 0x6C, 0xF3, 0x67, 0x8E, 0x3C, 0x71, 0x80,
|
||||
/* 0xCD */ 0xC0, 0x7C, 0x0F, 0xC1, 0xF8, 0x3D, 0x87, 0x98, 0xF3, 0x9E, 0x33, 0xC3, 0x78, 0x3F, 0x07, 0xE0, 0x7C, 0x06,
|
||||
/* 0xCE */ 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x1F, 0xE7, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xC0,
|
||||
/* 0xCF */ 0x0F, 0x83, 0xFC, 0x70, 0xE6, 0x06, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x70, 0xE3, 0xFC, 0x0F, 0x00,
|
||||
/* 0xD0 */ 0xFF, 0xFF, 0xFF, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06,
|
||||
/* 0xD1 */ 0xFF, 0x3F, 0xEC, 0x1F, 0x03, 0xC0, 0xF0, 0x7F, 0xFB, 0xFC, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00,
|
||||
/* 0xD2 */
|
||||
/* 0xD3 */ 0xFF, 0xFF, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xFF, 0xFF,
|
||||
/* 0xD4 */ 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x00,
|
||||
/* 0xD5 */ 0xE0, 0x76, 0x06, 0x30, 0xC3, 0x9C, 0x19, 0x80, 0xF0, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00,
|
||||
/* 0xD6 */ 0x06, 0x00, 0x60, 0x1F, 0x87, 0xFE, 0xE6, 0x7C, 0x63, 0xC6, 0x3C, 0x63, 0xE6, 0x77, 0xFE, 0x1F, 0x80, 0x60, 0x06, 0x00,
|
||||
/* 0xD7 */ 0x71, 0xC6, 0x30, 0x6C, 0x0D, 0x80, 0xE0, 0x1C, 0x03, 0x80, 0xD8, 0x1B, 0x07, 0x70, 0xC6, 0x30, 0x6E, 0x0E,
|
||||
/* 0xD8 */ 0xC6, 0x3C, 0x63, 0xC6, 0x3C, 0x63, 0xC6, 0x3C, 0x63, 0x46, 0x66, 0x66, 0x3F, 0xC0, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00,
|
||||
/* 0xD9 */ 0x1F, 0x07, 0xF1, 0xC7, 0x70, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0x40, 0x4C, 0x18, 0xEE, 0x7D, 0xFF, 0xBE,
|
||||
/* 0xDA */ 0xCF, 0x30, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C,
|
||||
/* 0xDB */ 0x19, 0x81, 0x98, 0x00, 0x0E, 0x07, 0x60, 0x63, 0x0C, 0x39, 0xC1, 0x98, 0x0F, 0x00, 0xF0, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60,
|
||||
/* 0xDC */ 0x06, 0x0C, 0x00, 0x3B, 0x7B, 0xEE, 0xC6, 0xC6, 0xC6, 0xC6, 0xEE, 0x7B, 0x3B,
|
||||
/* 0xDD */ 0x18, 0x20, 0x03, 0xCF, 0xF8, 0xB0, 0x38, 0x71, 0x83, 0x17, 0xF7, 0x80,
|
||||
/* 0xDE */ 0x0C, 0x18, 0x00, 0xDE, 0xFF, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x03, 0x03, 0x03, 0x03,
|
||||
/* 0xDF */ 0x78, 0x6D, 0xB6, 0xDB, 0x6C,
|
||||
/* 0xE0 */ 0x0C, 0xDB, 0xD3, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7E, 0x3C,
|
||||
/* 0xE1 */ 0x3B, 0x7B, 0xEE, 0xC6, 0xC6, 0xC6, 0xC6, 0xEE, 0x7B, 0x3B,
|
||||
/* 0xE2 */ 0x3C, 0x7E, 0xC6, 0xC6, 0xC4, 0xD8, 0xDE, 0xC7, 0xC3, 0xC3, 0xE7, 0xFE, 0xDC, 0xC0, 0xC0, 0xC0, 0xC0,
|
||||
/* 0xE3 */ 0x61, 0x98, 0x66, 0x18, 0xCC, 0x33, 0x0C, 0xC1, 0xE0, 0x78, 0x1E, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00,
|
||||
/* 0xE4 */ 0x7E, 0x7E, 0x30, 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7E, 0x3C,
|
||||
/* 0xE5 */ 0x79, 0xFF, 0x16, 0x07, 0x0E, 0x30, 0x62, 0xFE, 0xF0,
|
||||
/* 0xE6 */ 0x7E, 0xFC, 0x30, 0xC3, 0x0C, 0x18, 0x60, 0xC1, 0x83, 0x07, 0xE7, 0xE0, 0xC1, 0x83, 0x0C,
|
||||
/* 0xE7 */ 0xDE, 0xFF, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x03, 0x03, 0x03, 0x03,
|
||||
/* 0xE8 */ 0x3C, 0x7E, 0x66, 0xC3, 0xC3, 0xFF, 0xFF, 0xC3, 0xC3, 0xC3, 0x66, 0x7E, 0x3C,
|
||||
/* 0xE9 */ 0xFF, 0xFF, 0xF0,
|
||||
/* 0xEA */ 0xC3, 0x63, 0x33, 0x1B, 0x0F, 0x06, 0xC3, 0x31, 0x8C, 0xC6, 0x61, 0x80,
|
||||
/* 0xEB */ 0x30, 0x0C, 0x06, 0x03, 0x01, 0xC1, 0xE0, 0xD0, 0x6C, 0x36, 0x33, 0x18, 0xCC, 0x66, 0x30,
|
||||
/* 0xEC */ 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0xFF, 0xDB, 0xC0, 0xC0, 0xC0, 0xC0,
|
||||
/* 0xED */ 0xC1, 0xE0, 0xD8, 0xCC, 0x66, 0x31, 0xB0, 0xD8, 0x38, 0x1C, 0x04, 0x00,
|
||||
/* 0xEE */ 0x7D, 0xFB, 0x06, 0x07, 0xC7, 0x9C, 0x70, 0xC1, 0x83, 0x83, 0xE3, 0xE0, 0xC1, 0x8E, 0x18,
|
||||
/* 0xEF */ 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7E, 0x3C,
|
||||
/* 0xF0 */ 0xFF, 0xFF, 0xFF, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C,
|
||||
/* 0xF1 */ 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0xFE, 0xDC, 0xC0, 0xC0, 0xC0, 0xC0,
|
||||
/* 0xF2 */ 0x1E, 0xFD, 0x86, 0x0C, 0x18, 0x30, 0x70, 0x7C, 0x7C, 0x18, 0x33, 0xE7, 0x00,
|
||||
/* 0xF3 */ 0x3F, 0xDF, 0xFE, 0x63, 0x0C, 0xC3, 0x30, 0xCC, 0x33, 0x9C, 0x7E, 0x0F, 0x00,
|
||||
/* 0xF4 */ 0xFF, 0xF3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC0,
|
||||
/* 0xF5 */ 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7E, 0x3C,
|
||||
/* 0xF6 */ 0x2F, 0x1B, 0xEC, 0xDF, 0x33, 0xCC, 0xF3, 0x3C, 0xCD, 0xB6, 0x7F, 0x8F, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x00,
|
||||
/* 0xF7 */ 0x63, 0x31, 0x8D, 0x86, 0xC3, 0x60, 0xE0, 0x70, 0x38, 0x1C, 0x1B, 0x0D, 0x86, 0xC6, 0x33, 0x18,
|
||||
/* 0xF8 */ 0xCC, 0xF3, 0x3C, 0xCF, 0x33, 0xCC, 0xF3, 0x3C, 0xCF, 0x33, 0x6D, 0x8F, 0xC0, 0xC0, 0x30, 0x0C, 0x03, 0x00,
|
||||
/* 0xF9 */ 0x30, 0xC6, 0x06, 0x66, 0x6C, 0x63, 0xC6, 0x3C, 0x63, 0xC6, 0x3E, 0xF7, 0x79, 0xE3, 0x9C,
|
||||
/* 0xFA */ 0xCF, 0x30, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30,
|
||||
/* 0xFB */ 0x66, 0x66, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7E, 0x3C,
|
||||
/* 0xFC */ 0x0C, 0x18, 0x00, 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7E, 0x3C,
|
||||
/* 0xFD */ 0x08, 0x10, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7E, 0x3C,
|
||||
/* 0xFE */ 0x03, 0x00, 0x60, 0x00, 0x03, 0x0C, 0x60, 0x66, 0x66, 0xC6, 0x3C, 0x63, 0xC6, 0x3C, 0x63, 0xEF, 0x77, 0x9E, 0x39, 0xC0,
|
||||
/* 0xFF */
|
||||
};
|
||||
|
||||
const GFXglyph FreeSans9pt_Win1253Glyphs[] PROGMEM = {
|
||||
/* 0x01 */ { 0, 15, 15, 17, 1, -13 },
|
||||
/* 0x02 */ { 29, 15, 15, 17, 1, -13 },
|
||||
/* 0x03 */ { 58, 15, 16, 17, 1, -14 },
|
||||
/* 0x04 */ { 88, 15, 16, 17, 1, -14 },
|
||||
/* 0x05 */ { 118, 16, 15, 18, 1, -13 },
|
||||
/* 0x06 */ { 148, 15, 15, 17, 1, -13 },
|
||||
/* 0x07 */ { 177, 0, 0, 8, 0, 0 },
|
||||
/* 0x08 */ { 177, 17, 16, 19, 1, -14 },
|
||||
/* 0x09 */ { 211, 17, 12, 19, 1, -12 },
|
||||
/* 0x0A */ { 237, 0, 0, 8, 0, 0 },
|
||||
/* 0x0B */ { 237, 17, 16, 19, 1, -14 },
|
||||
/* 0x0C */ { 271, 15, 14, 17, 1, -12 },
|
||||
/* 0x0D */ { 298, 0, 0, 8, 0, 0 },
|
||||
/* 0x0E */ { 298, 15, 16, 17, 1, -14 },
|
||||
/* 0x0F */ { 328, 15, 15, 17, 1, -13 },
|
||||
/* 0x10 */ { 357, 15, 15, 17, 1, -13 },
|
||||
/* 0x11 */ { 386, 15, 16, 17, 1, -14 },
|
||||
/* 0x12 */ { 416, 17, 17, 19, 1, -15 },
|
||||
/* 0x13 */ { 453, 15, 16, 17, 1, -14 },
|
||||
/* 0x14 */ { 483, 15, 16, 17, 1, -14 },
|
||||
/* 0x15 */ { 513, 15, 16, 17, 1, -14 },
|
||||
/* 0x16 */ { 543, 11, 16, 13, 1, -14 },
|
||||
/* 0x17 */ { 565, 15, 16, 17, 1, -14 },
|
||||
/* 0x18 */ { 595, 18, 15, 20, 1, -13 },
|
||||
/* 0x19 */ { 629, 15, 16, 17, 1, -14 },
|
||||
/* 0x1A */ { 659, 13, 14, 15, 1, -12 },
|
||||
/* 0x1B */ { 682, 17, 16, 19, 1, -14 },
|
||||
/* 0x1C */ { 716, 15, 16, 17, 1, -14 },
|
||||
/* 0x1D */ { 746, 15, 15, 17, 1, -13 },
|
||||
/* 0x1E */ { 775, 17, 16, 19, 1, -14 },
|
||||
/* 0x1F */ { 809, 11, 16, 13, 1, -14 },
|
||||
/* ' ' 0x20 */ { 831, 0, 0, 5, 0, 0 },
|
||||
/* '!' 0x21 */ { 831, 2, 13, 6, 2, -12 },
|
||||
/* '"' 0x22 */ { 835, 5, 4, 6, 1, -12 },
|
||||
/* '#' 0x23 */ { 838, 10, 12, 10, 0, -11 },
|
||||
/* '$' 0x24 */ { 853, 9, 16, 10, 1, -13 },
|
||||
/* '%' 0x25 */ { 871, 16, 13, 16, 1, -12 },
|
||||
/* '&' 0x26 */ { 897, 10, 13, 12, 1, -12 },
|
||||
/* ''' 0x27 */ { 914, 2, 4, 4, 1, -12 },
|
||||
/* '(' 0x28 */ { 915, 4, 17, 6, 1, -12 },
|
||||
/* ')' 0x29 */ { 924, 4, 17, 6, 1, -12 },
|
||||
/* '*' 0x2A */ { 933, 5, 5, 7, 1, -12 },
|
||||
/* '+' 0x2B */ { 937, 6, 8, 11, 3, -7 },
|
||||
/* ',' 0x2C */ { 943, 2, 4, 5, 2, 0 },
|
||||
/* '-' 0x2D */ { 944, 4, 1, 6, 1, -4 },
|
||||
/* '.' 0x2E */ { 945, 2, 1, 5, 1, 0 },
|
||||
/* '/' 0x2F */ { 946, 5, 13, 5, 0, -12 },
|
||||
/* '0' 0x30 */ { 955, 8, 13, 10, 1, -12 },
|
||||
/* '1' 0x31 */ { 968, 4, 13, 10, 3, -12 },
|
||||
/* '2' 0x32 */ { 975, 9, 13, 10, 1, -12 },
|
||||
/* '3' 0x33 */ { 990, 8, 13, 10, 1, -12 },
|
||||
/* '4' 0x34 */ { 1003, 7, 13, 10, 2, -12 },
|
||||
/* '5' 0x35 */ { 1015, 9, 13, 10, 1, -12 },
|
||||
/* '6' 0x36 */ { 1030, 9, 13, 10, 1, -12 },
|
||||
/* '7' 0x37 */ { 1045, 8, 13, 10, 0, -12 },
|
||||
/* '8' 0x38 */ { 1058, 9, 13, 10, 1, -12 },
|
||||
/* '9' 0x39 */ { 1073, 8, 13, 10, 1, -12 },
|
||||
/* ':' 0x3A */ { 1086, 2, 10, 5, 1, -9 },
|
||||
/* ';' 0x3B */ { 1089, 3, 12, 5, 1, -8 },
|
||||
/* '<' 0x3C */ { 1094, 9, 9, 11, 1, -8 },
|
||||
/* '=' 0x3D */ { 1105, 9, 4, 11, 1, -5 },
|
||||
/* '>' 0x3E */ { 1110, 9, 8, 11, 1, -7 },
|
||||
/* '?' 0x3F */ { 1119, 9, 13, 10, 1, -12 },
|
||||
/* '@' 0x40 */ { 1134, 17, 16, 18, 1, -12 },
|
||||
/* 'A' 0x41 */ { 1168, 12, 13, 12, 0, -12 },
|
||||
/* 'B' 0x42 */ { 1188, 11, 13, 12, 1, -12 },
|
||||
/* 'C' 0x43 */ { 1206, 11, 13, 13, 1, -12 },
|
||||
/* 'D' 0x44 */ { 1224, 11, 13, 13, 1, -12 },
|
||||
/* 'E' 0x45 */ { 1242, 9, 13, 11, 1, -12 },
|
||||
/* 'F' 0x46 */ { 1257, 8, 13, 11, 1, -12 },
|
||||
/* 'G' 0x47 */ { 1270, 12, 13, 14, 1, -12 },
|
||||
/* 'H' 0x48 */ { 1290, 11, 13, 13, 1, -12 },
|
||||
/* 'I' 0x49 */ { 1308, 2, 13, 5, 2, -12 },
|
||||
/* 'J' 0x4A */ { 1312, 7, 13, 10, 1, -12 },
|
||||
/* 'K' 0x4B */ { 1324, 10, 13, 12, 1, -12 },
|
||||
/* 'L' 0x4C */ { 1341, 8, 13, 10, 1, -12 },
|
||||
/* 'M' 0x4D */ { 1354, 13, 13, 15, 1, -12 },
|
||||
/* 'N' 0x4E */ { 1376, 11, 13, 13, 1, -12 },
|
||||
/* 'O' 0x4F */ { 1394, 13, 13, 14, 1, -12 },
|
||||
/* 'P' 0x50 */ { 1416, 10, 13, 12, 1, -12 },
|
||||
/* 'Q' 0x51 */ { 1433, 13, 14, 14, 1, -12 },
|
||||
/* 'R' 0x52 */ { 1456, 12, 13, 13, 1, -12 },
|
||||
/* 'S' 0x53 */ { 1476, 10, 13, 12, 1, -12 },
|
||||
/* 'T' 0x54 */ { 1493, 9, 13, 11, 1, -12 },
|
||||
/* 'U' 0x55 */ { 1508, 11, 13, 13, 1, -12 },
|
||||
/* 'V' 0x56 */ { 1526, 11, 13, 11, 0, -12 },
|
||||
/* 'W' 0x57 */ { 1544, 16, 13, 17, 0, -12 },
|
||||
/* 'X' 0x58 */ { 1570, 10, 13, 12, 1, -12 },
|
||||
/* 'Y' 0x59 */ { 1587, 12, 13, 12, 0, -12 },
|
||||
/* 'Z' 0x5A */ { 1607, 10, 13, 11, 1, -12 },
|
||||
/* '[' 0x5B */ { 1624, 3, 17, 5, 1, -12 },
|
||||
/* '\' 0x5C */ { 1631, 5, 13, 5, 0, -12 },
|
||||
/* ']' 0x5D */ { 1640, 3, 17, 5, 0, -12 },
|
||||
/* '^' 0x5E */ { 1647, 7, 7, 8, 1, -12 },
|
||||
/* '_' 0x5F */ { 1654, 10, 1, 10, 0, 3 },
|
||||
/* '`' 0x60 */ { 1656, 4, 3, 5, 0, -12 },
|
||||
/* 'a' 0x61 */ { 1658, 9, 10, 10, 1, -9 },
|
||||
/* 'b' 0x62 */ { 1670, 9, 13, 10, 1, -12 },
|
||||
/* 'c' 0x63 */ { 1685, 8, 10, 9, 1, -9 },
|
||||
/* 'd' 0x64 */ { 1695, 8, 13, 10, 1, -12 },
|
||||
/* 'e' 0x65 */ { 1708, 8, 10, 10, 1, -9 },
|
||||
/* 'f' 0x66 */ { 1718, 4, 13, 5, 1, -12 },
|
||||
/* 'g' 0x67 */ { 1725, 8, 14, 10, 1, -9 },
|
||||
/* 'h' 0x68 */ { 1739, 8, 13, 10, 1, -12 },
|
||||
/* 'i' 0x69 */ { 1752, 2, 13, 4, 1, -12 },
|
||||
/* 'j' 0x6A */ { 1756, 4, 17, 4, 0, -12 },
|
||||
/* 'k' 0x6B */ { 1765, 8, 13, 9, 1, -12 },
|
||||
/* 'l' 0x6C */ { 1778, 2, 13, 4, 1, -12 },
|
||||
/* 'm' 0x6D */ { 1782, 13, 10, 15, 1, -9 },
|
||||
/* 'n' 0x6E */ { 1799, 8, 10, 10, 1, -9 },
|
||||
/* 'o' 0x6F */ { 1809, 8, 10, 10, 1, -9 },
|
||||
/* 'p' 0x70 */ { 1819, 9, 13, 10, 1, -9 },
|
||||
/* 'q' 0x71 */ { 1834, 8, 13, 10, 1, -9 },
|
||||
/* 'r' 0x72 */ { 1847, 5, 10, 6, 1, -9 },
|
||||
/* 's' 0x73 */ { 1854, 8, 10, 9, 1, -9 },
|
||||
/* 't' 0x74 */ { 1864, 4, 12, 5, 1, -11 },
|
||||
/* 'u' 0x75 */ { 1870, 8, 10, 10, 1, -9 },
|
||||
/* 'v' 0x76 */ { 1880, 9, 10, 9, 0, -9 },
|
||||
/* 'w' 0x77 */ { 1892, 13, 10, 13, 0, -9 },
|
||||
/* 'x' 0x78 */ { 1909, 7, 10, 9, 1, -9 },
|
||||
/* 'y' 0x79 */ { 1918, 8, 14, 9, 0, -9 },
|
||||
/* 'z' 0x7A */ { 1932, 7, 10, 9, 1, -9 },
|
||||
/* '{' 0x7B */ { 1941, 4, 17, 6, 1, -12 },
|
||||
/* '|' 0x7C */ { 1950, 2, 17, 4, 2, -12 },
|
||||
/* '}' 0x7D */ { 1955, 4, 17, 6, 1, -12 },
|
||||
/* '~' 0x7E */ { 1964, 7, 3, 9, 1, -7 },
|
||||
/* 0x7F */ { 1967, 0, 0, 0, 0, 0 },
|
||||
/* 0x80 */ { 1967, 10, 13, 12, 1, -12 },
|
||||
/* 0x81 */ { 1984, 0, 0, 8, 0, 0 },
|
||||
/* 0x82 */ { 1984, 2, 3, 5, 1, 0 },
|
||||
/* 0x83 */ { 1985, 5, 17, 5, 0, -12 },
|
||||
/* 0x84 */ { 1996, 5, 3, 7, 1, 0 },
|
||||
/* 0x85 */ { 1998, 10, 1, 12, 1, 0 },
|
||||
/* 0x86 */ { 2000, 8, 16, 10, 1, -12 },
|
||||
/* 0x87 */ { 2016, 8, 16, 10, 1, -12 },
|
||||
/* 0x88 */ { 2032, 5, 3, 6, 0, -12 },
|
||||
/* 0x89 */ { 2034, 18, 13, 18, 0, -12 },
|
||||
/* 0x8A */ { 2064, 10, 16, 12, 1, -15 },
|
||||
/* 0x8B */ { 2084, 2, 4, 4, 1, -6 },
|
||||
/* 0x8C */ { 2085, 15, 13, 18, 1, -12 },
|
||||
/* 0x8D */ { 2110, 0, 0, 8, 0, 0 },
|
||||
/* 0x8E */ { 2110, 10, 16, 11, 1, -15 },
|
||||
/* 0x8F */ { 2130, 0, 0, 8, 0, 0 },
|
||||
/* 0x90 */ { 2130, 0, 0, 8, 0, 0 },
|
||||
/* 0x91 */ { 2130, 2, 4, 4, 2, -12 },
|
||||
/* 0x92 */ { 2131, 2, 4, 4, 1, -12 },
|
||||
/* 0x93 */ { 2132, 5, 4, 7, 2, -12 },
|
||||
/* 0x94 */ { 2135, 5, 4, 7, 1, -12 },
|
||||
/* 0x95 */ { 2138, 4, 5, 7, 1, -8 },
|
||||
/* 0x96 */ { 2141, 7, 1, 9, 1, -4 },
|
||||
/* 0x97 */ { 2142, 16, 1, 18, 1, -4 },
|
||||
/* 0x98 */ { 2144, 5, 2, 6, 0, -12 },
|
||||
/* 0x99 */ { 2146, 18, 10, 18, 1, -13 },
|
||||
/* 0x9A */ { 2169, 8, 13, 9, 1, -12 },
|
||||
/* 0x9B */ { 2182, 2, 4, 5, 2, -6 },
|
||||
/* 0x9C */ { 2183, 15, 10, 17, 1, -9 },
|
||||
/* 0x9D */ { 2202, 0, 0, 8, 0, 0 },
|
||||
/* 0x9E */ { 2202, 7, 13, 9, 1, -12 },
|
||||
/* 0x9F */ { 2214, 12, 14, 12, 0, -13 },
|
||||
/* 0xA0 */ { 2235, 0, 0, 5, 0, 0 },
|
||||
/* 0xA1 */ { 2235, 2, 13, 6, 2, -8 },
|
||||
/* 0xA2 */ { 2239, 9, 14, 10, 1, -11 },
|
||||
/* 0xA3 */ { 2255, 10, 13, 10, 0, -12 },
|
||||
/* 0xA4 */ { 2272, 7, 6, 10, 2, -8 },
|
||||
/* 0xA5 */ { 2278, 8, 13, 10, 1, -12 },
|
||||
/* 0xA6 */ { 2291, 2, 17, 5, 2, -12 },
|
||||
/* 0xA7 */ { 2296, 9, 17, 10, 1, -12 },
|
||||
/* 0xA8 */ { 2316, 6, 1, 6, 0, -11 },
|
||||
/* 0xA9 */ { 2317, 14, 13, 14, 1, -12 },
|
||||
/* 0xAA */ { 2340, 5, 8, 7, 1, -12 },
|
||||
/* 0xAB */ { 2345, 7, 6, 9, 1, -7 },
|
||||
/* 0xAC */ { 2351, 9, 5, 11, 2, -5 },
|
||||
/* 0xAD */ { 2357, 0, 0, 0, 0, 0 },
|
||||
/* 0xAE */ { 2357, 14, 13, 14, 1, -12 },
|
||||
/* 0xAF */ { 2380, 5, 1, 6, 0, -12 },
|
||||
/* 0xB0 */ { 2381, 5, 5, 11, 3, -11 },
|
||||
/* 0xB1 */ { 2385, 9, 11, 11, 1, -10 },
|
||||
/* 0xB2 */ { 2398, 6, 8, 6, 1, -13 },
|
||||
/* 0xB3 */ { 2404, 7, 8, 6, 0, -13 },
|
||||
/* 0xB4 */ { 2411, 4, 3, 6, 2, -12 },
|
||||
/* 0xB5 */ { 2413, 9, 13, 10, 1, -9 },
|
||||
/* 0xB6 */ { 2428, 8, 16, 10, 2, -12 },
|
||||
/* 0xB7 */ { 2444, 3, 1, 5, 1, -4 },
|
||||
/* 0xB8 */ { 2445, 5, 4, 6, 1, 1 },
|
||||
/* 0xB9 */ { 2448, 3, 7, 6, 2, -13 },
|
||||
/* 0xBA */ { 2451, 5, 8, 7, 1, -12 },
|
||||
/* 0xBB */ { 2456, 7, 6, 9, 1, -7 },
|
||||
/* 0xBC */ { 2462, 14, 13, 16, 2, -12 },
|
||||
/* 0xBD */ { 2485, 14, 13, 16, 2, -12 },
|
||||
/* 0xBE */ { 2508, 15, 13, 16, 1, -12 },
|
||||
/* 0xBF */ { 2533, 9, 13, 10, 1, -8 },
|
||||
/* 0xC0 */ { 2548, 8, 15, 4, -2, -15 },
|
||||
/* 0xC1 */ { 2563, 11, 13, 11, 0, -13 },
|
||||
/* 0xC2 */ { 2581, 10, 13, 12, 1, -13 },
|
||||
/* 0xC3 */ { 2598, 8, 13, 10, 2, -13 },
|
||||
/* 0xC4 */ { 2611, 13, 13, 12, -1, -13 },
|
||||
/* 0xC5 */ { 2633, 10, 13, 12, 1, -13 },
|
||||
/* 0xC6 */ { 2650, 10, 13, 11, 0, -13 },
|
||||
/* 0xC7 */ { 2667, 11, 13, 13, 1, -13 },
|
||||
/* 0xC8 */ { 2685, 12, 13, 14, 1, -13 },
|
||||
/* 0xC9 */ { 2705, 2, 13, 4, 1, -13 },
|
||||
/* 0xCA */ { 2709, 11, 13, 12, 1, -13 },
|
||||
/* 0xCB */ { 2727, 13, 13, 12, -1, -13 },
|
||||
/* 0xCC */ { 2749, 13, 13, 15, 1, -13 },
|
||||
/* 0xCD */ { 2771, 11, 13, 13, 1, -13 },
|
||||
/* 0xCE */ { 2789, 10, 13, 12, 1, -13 },
|
||||
/* 0xCF */ { 2806, 12, 13, 14, 1, -13 },
|
||||
/* 0xD0 */ { 2826, 11, 13, 13, 1, -13 },
|
||||
/* 0xD1 */ { 2844, 10, 13, 12, 1, -13 },
|
||||
/* 0xD2 */ { 2861, 0, 0, 5, 0, 0 },
|
||||
/* 0xD3 */ { 2861, 8, 13, 11, 2, -13 },
|
||||
/* 0xD4 */ { 2874, 10, 13, 12, 1, -13 },
|
||||
/* 0xD5 */ { 2891, 12, 13, 12, 0, -13 },
|
||||
/* 0xD6 */ { 2911, 12, 13, 14, 1, -13 },
|
||||
/* 0xD7 */ { 2931, 11, 13, 11, 0, -13 },
|
||||
/* 0xD8 */ { 2949, 12, 13, 14, 1, -13 },
|
||||
/* 0xD9 */ { 2969, 11, 13, 13, 1, -13 },
|
||||
/* 0xDA */ { 2987, 6, 16, 4, -1, -16 },
|
||||
/* 0xDB */ { 2999, 12, 16, 12, 0, -16 },
|
||||
/* 0xDC */ { 3023, 8, 13, 10, 1, -13 },
|
||||
/* 0xDD */ { 3036, 7, 13, 8, 1, -13 },
|
||||
/* 0xDE */ { 3048, 8, 17, 10, 1, -13 },
|
||||
/* 0xDF */ { 3065, 3, 13, 4, 1, -13 },
|
||||
/* 0xE0 */ { 3070, 8, 14, 10, 1, -14 },
|
||||
/* 0xE1 */ { 3084, 8, 10, 10, 1, -10 },
|
||||
/* 0xE2 */ { 3094, 8, 17, 10, 1, -13 },
|
||||
/* 0xE3 */ { 3111, 10, 14, 8, -1, -10 },
|
||||
/* 0xE4 */ { 3129, 8, 13, 10, 1, -13 },
|
||||
/* 0xE5 */ { 3142, 7, 10, 8, 1, -10 },
|
||||
/* 0xE6 */ { 3151, 7, 17, 8, 1, -13 },
|
||||
/* 0xE7 */ { 3166, 8, 14, 10, 1, -10 },
|
||||
/* 0xE8 */ { 3180, 8, 13, 10, 1, -13 },
|
||||
/* 0xE9 */ { 3193, 2, 10, 4, 1, -10 },
|
||||
/* 0xEA */ { 3196, 9, 10, 9, 1, -10 },
|
||||
/* 0xEB */ { 3208, 9, 13, 9, 0, -13 },
|
||||
/* 0xEC */ { 3223, 8, 14, 10, 1, -10 },
|
||||
/* 0xED */ { 3237, 9, 10, 9, 0, -10 },
|
||||
/* 0xEE */ { 3249, 7, 17, 8, 1, -13 },
|
||||
/* 0xEF */ { 3264, 8, 10, 10, 1, -10 },
|
||||
/* 0xF0 */ { 3274, 12, 10, 12, 0, -10 },
|
||||
/* 0xF1 */ { 3289, 8, 14, 10, 1, -10 },
|
||||
/* 0xF2 */ { 3303, 7, 14, 9, 1, -10 },
|
||||
/* 0xF3 */ { 3316, 10, 10, 11, 1, -10 },
|
||||
/* 0xF4 */ { 3329, 6, 10, 8, 1, -10 },
|
||||
/* 0xF5 */ { 3337, 8, 10, 10, 1, -10 },
|
||||
/* 0xF6 */ { 3347, 10, 14, 12, 1, -10 },
|
||||
/* 0xF7 */ { 3365, 9, 14, 9, 0, -10 },
|
||||
/* 0xF8 */ { 3381, 10, 14, 12, 1, -10 },
|
||||
/* 0xF9 */ { 3399, 12, 10, 14, 1, -10 },
|
||||
/* 0xFA */ { 3414, 6, 13, 4, -1, -13 },
|
||||
/* 0xFB */ { 3424, 8, 13, 10, 1, -13 },
|
||||
/* 0xFC */ { 3437, 8, 13, 10, 1, -13 },
|
||||
/* 0xFD */ { 3450, 8, 13, 10, 1, -13 },
|
||||
/* 0xFE */ { 3463, 12, 13, 14, 1, -13 },
|
||||
/* 0xFF */ { 3483, 0, 0, 5, 0, 0 },
|
||||
};
|
||||
|
||||
const GFXfont FreeSans9pt_Win1253 PROGMEM = {
|
||||
(uint8_t*)FreeSans9pt_Win1253Bitmaps,
|
||||
(GFXglyph*)FreeSans9pt_Win1253Glyphs,
|
||||
0x01, 0xFF, 16
|
||||
};
|
||||
@@ -88,8 +88,14 @@ class Applet : public GFX
|
||||
virtual void onForeground() {}
|
||||
virtual void onBackground() {}
|
||||
virtual void onShutdown() {}
|
||||
virtual void onButtonShortPress() {} // (System Applets only)
|
||||
virtual void onButtonLongPress() {} // (System Applets only)
|
||||
virtual void onButtonShortPress() {}
|
||||
virtual void onButtonLongPress() {}
|
||||
virtual void onExitShort() {}
|
||||
virtual void onExitLong() {}
|
||||
virtual void onNavUp() {}
|
||||
virtual void onNavDown() {}
|
||||
virtual void onNavLeft() {}
|
||||
virtual void onNavRight() {}
|
||||
|
||||
virtual bool approveNotification(Notification &n); // Allow an applet to veto a notification
|
||||
|
||||
|
||||
@@ -616,6 +616,101 @@ char InkHUD::AppletFont::applyEncoding(std::string utf8)
|
||||
}
|
||||
}
|
||||
|
||||
else if (encoding == WINDOWS_1253) {
|
||||
// Greek
|
||||
// 1-Byte chars: no remapping
|
||||
if (utf8.length() == 1)
|
||||
return utf8.at(0);
|
||||
|
||||
// Multi-byte chars:
|
||||
switch (toUtf32(utf8)) {
|
||||
// Windows-1253 special characters (0x80-0xBF range)
|
||||
REMAP(0x20AC, 0x80) // EURO SIGN
|
||||
REMAP(0x2018, 0x91) // LEFT SINGLE QUOTATION MARK
|
||||
REMAP(0x2019, 0x92) // RIGHT SINGLE QUOTATION MARK
|
||||
REMAP(0x201C, 0x93) // LEFT DOUBLE QUOTATION MARK
|
||||
REMAP(0x201D, 0x94) // RIGHT DOUBLE QUOTATION MARK
|
||||
REMAP(0x2022, 0x95) // BULLET
|
||||
REMAP(0x2013, 0x96) // EN DASH
|
||||
REMAP(0x2014, 0x97) // EM DASH
|
||||
|
||||
// Greek accented capitals
|
||||
REMAP(0x0386, 0xA2) // GREEK CAPITAL LETTER ALPHA WITH TONOS
|
||||
REMAP(0x0388, 0xB8) // GREEK CAPITAL LETTER EPSILON WITH TONOS
|
||||
REMAP(0x0389, 0xB9) // GREEK CAPITAL LETTER ETA WITH TONOS
|
||||
REMAP(0x038A, 0xBA) // GREEK CAPITAL LETTER IOTA WITH TONOS
|
||||
REMAP(0x038C, 0xBC) // GREEK CAPITAL LETTER OMICRON WITH TONOS
|
||||
REMAP(0x038E, 0xBE) // GREEK CAPITAL LETTER UPSILON WITH TONOS
|
||||
REMAP(0x038F, 0xBF) // GREEK CAPITAL LETTER OMEGA WITH TONOS
|
||||
|
||||
// Greek capital letters (U+0391-U+03A9 -> 0xC1-0xD1, with gaps)
|
||||
REMAP(0x0391, 0xC1) // GREEK CAPITAL LETTER ALPHA
|
||||
REMAP(0x0392, 0xC2) // GREEK CAPITAL LETTER BETA
|
||||
REMAP(0x0393, 0xC3) // GREEK CAPITAL LETTER GAMMA
|
||||
REMAP(0x0394, 0xC4) // GREEK CAPITAL LETTER DELTA
|
||||
REMAP(0x0395, 0xC5) // GREEK CAPITAL LETTER EPSILON
|
||||
REMAP(0x0396, 0xC6) // GREEK CAPITAL LETTER ZETA
|
||||
REMAP(0x0397, 0xC7) // GREEK CAPITAL LETTER ETA
|
||||
REMAP(0x0398, 0xC8) // GREEK CAPITAL LETTER THETA
|
||||
REMAP(0x0399, 0xC9) // GREEK CAPITAL LETTER IOTA
|
||||
REMAP(0x039A, 0xCA) // GREEK CAPITAL LETTER KAPPA
|
||||
REMAP(0x039B, 0xCB) // GREEK CAPITAL LETTER LAMDA
|
||||
REMAP(0x039C, 0xCC) // GREEK CAPITAL LETTER MU
|
||||
REMAP(0x039D, 0xCD) // GREEK CAPITAL LETTER NU
|
||||
REMAP(0x039E, 0xCE) // GREEK CAPITAL LETTER XI
|
||||
REMAP(0x039F, 0xCF) // GREEK CAPITAL LETTER OMICRON
|
||||
REMAP(0x03A0, 0xD0) // GREEK CAPITAL LETTER PI
|
||||
REMAP(0x03A1, 0xD1) // GREEK CAPITAL LETTER RHO
|
||||
REMAP(0x03A3, 0xD3) // GREEK CAPITAL LETTER SIGMA
|
||||
REMAP(0x03A4, 0xD4) // GREEK CAPITAL LETTER TAU
|
||||
REMAP(0x03A5, 0xD5) // GREEK CAPITAL LETTER UPSILON
|
||||
REMAP(0x03A6, 0xD6) // GREEK CAPITAL LETTER PHI
|
||||
REMAP(0x03A7, 0xD7) // GREEK CAPITAL LETTER CHI
|
||||
REMAP(0x03A8, 0xD8) // GREEK CAPITAL LETTER PSI
|
||||
REMAP(0x03A9, 0xD9) // GREEK CAPITAL LETTER OMEGA
|
||||
|
||||
// Greek small letters with tonos (accented)
|
||||
REMAP(0x03AC, 0xDC) // GREEK SMALL LETTER ALPHA WITH TONOS
|
||||
REMAP(0x03AD, 0xDD) // GREEK SMALL LETTER EPSILON WITH TONOS
|
||||
REMAP(0x03AE, 0xDE) // GREEK SMALL LETTER ETA WITH TONOS
|
||||
REMAP(0x03AF, 0xDF) // GREEK SMALL LETTER IOTA WITH TONOS
|
||||
|
||||
// Greek small letters (U+03B1-U+03C9 -> 0xE1-0xF9)
|
||||
REMAP(0x03B1, 0xE1) // GREEK SMALL LETTER ALPHA
|
||||
REMAP(0x03B2, 0xE2) // GREEK SMALL LETTER BETA
|
||||
REMAP(0x03B3, 0xE3) // GREEK SMALL LETTER GAMMA
|
||||
REMAP(0x03B4, 0xE4) // GREEK SMALL LETTER DELTA
|
||||
REMAP(0x03B5, 0xE5) // GREEK SMALL LETTER EPSILON
|
||||
REMAP(0x03B6, 0xE6) // GREEK SMALL LETTER ZETA
|
||||
REMAP(0x03B7, 0xE7) // GREEK SMALL LETTER ETA
|
||||
REMAP(0x03B8, 0xE8) // GREEK SMALL LETTER THETA
|
||||
REMAP(0x03B9, 0xE9) // GREEK SMALL LETTER IOTA
|
||||
REMAP(0x03BA, 0xEA) // GREEK SMALL LETTER KAPPA
|
||||
REMAP(0x03BB, 0xEB) // GREEK SMALL LETTER LAMDA
|
||||
REMAP(0x03BC, 0xEC) // GREEK SMALL LETTER MU
|
||||
REMAP(0x03BD, 0xED) // GREEK SMALL LETTER NU
|
||||
REMAP(0x03BE, 0xEE) // GREEK SMALL LETTER XI
|
||||
REMAP(0x03BF, 0xEF) // GREEK SMALL LETTER OMICRON
|
||||
REMAP(0x03C0, 0xF0) // GREEK SMALL LETTER PI
|
||||
REMAP(0x03C1, 0xF1) // GREEK SMALL LETTER RHO
|
||||
REMAP(0x03C2, 0xF2) // GREEK SMALL LETTER FINAL SIGMA
|
||||
REMAP(0x03C3, 0xF3) // GREEK SMALL LETTER SIGMA
|
||||
REMAP(0x03C4, 0xF4) // GREEK SMALL LETTER TAU
|
||||
REMAP(0x03C5, 0xF5) // GREEK SMALL LETTER UPSILON
|
||||
REMAP(0x03C6, 0xF6) // GREEK SMALL LETTER PHI
|
||||
REMAP(0x03C7, 0xF7) // GREEK SMALL LETTER CHI
|
||||
REMAP(0x03C8, 0xF8) // GREEK SMALL LETTER PSI
|
||||
REMAP(0x03C9, 0xF9) // GREEK SMALL LETTER OMEGA
|
||||
|
||||
// More accented small letters
|
||||
REMAP(0x03CA, 0xFA) // GREEK SMALL LETTER IOTA WITH DIALYTIKA
|
||||
REMAP(0x03CB, 0xFB) // GREEK SMALL LETTER UPSILON WITH DIALYTIKA
|
||||
REMAP(0x03CC, 0xFC) // GREEK SMALL LETTER OMICRON WITH TONOS
|
||||
REMAP(0x03CD, 0xFD) // GREEK SMALL LETTER UPSILON WITH TONOS
|
||||
REMAP(0x03CE, 0xFE) // GREEK SMALL LETTER OMEGA WITH TONOS
|
||||
}
|
||||
}
|
||||
|
||||
else /*ASCII or Unhandled*/ {
|
||||
if (utf8.length() == 1)
|
||||
return utf8.at(0);
|
||||
|
||||
@@ -26,6 +26,7 @@ class AppletFont
|
||||
WINDOWS_1250,
|
||||
WINDOWS_1251,
|
||||
WINDOWS_1252,
|
||||
WINDOWS_1253,
|
||||
};
|
||||
|
||||
AppletFont();
|
||||
@@ -84,4 +85,12 @@ class AppletFont
|
||||
#define FREESANS_9PT_WIN1252 InkHUD::AppletFont(FreeSans9pt_Win1252, InkHUD::AppletFont::WINDOWS_1252, -2, -1)
|
||||
#define FREESANS_6PT_WIN1252 InkHUD::AppletFont(FreeSans6pt_Win1252, InkHUD::AppletFont::WINDOWS_1252, -1, -2)
|
||||
|
||||
// Greek
|
||||
#include "graphics/niche/Fonts/FreeSans12pt_Win1253.h"
|
||||
#include "graphics/niche/Fonts/FreeSans6pt_Win1253.h"
|
||||
#include "graphics/niche/Fonts/FreeSans9pt_Win1253.h"
|
||||
#define FREESANS_12PT_WIN1253 InkHUD::AppletFont(FreeSans12pt_Win1253, InkHUD::AppletFont::WINDOWS_1253, -3, 1)
|
||||
#define FREESANS_9PT_WIN1253 InkHUD::AppletFont(FreeSans9pt_Win1253, InkHUD::AppletFont::WINDOWS_1253, -2, -1)
|
||||
#define FREESANS_6PT_WIN1253 InkHUD::AppletFont(FreeSans6pt_Win1253, InkHUD::AppletFont::WINDOWS_1253, -1, -2)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,205 @@
|
||||
#ifdef MESHTASTIC_INCLUDE_INKHUD
|
||||
|
||||
#include "./AlignStickApplet.h"
|
||||
|
||||
using namespace NicheGraphics;
|
||||
|
||||
InkHUD::AlignStickApplet::AlignStickApplet()
|
||||
{
|
||||
if (!settings->joystick.aligned)
|
||||
bringToForeground();
|
||||
}
|
||||
|
||||
void InkHUD::AlignStickApplet::onRender()
|
||||
{
|
||||
setFont(fontMedium);
|
||||
printAt(0, 0, "Align Joystick:");
|
||||
setFont(fontSmall);
|
||||
std::string instructions = "Move joystick in the direction indicated";
|
||||
printWrapped(0, fontMedium.lineHeight() * 1.5, width(), instructions);
|
||||
|
||||
// Size of the region in which the joystick graphic should fit
|
||||
uint16_t joyXLimit = X(0.8);
|
||||
uint16_t contentH = fontMedium.lineHeight() * 1.5 + fontSmall.lineHeight() * 1;
|
||||
if (getTextWidth(instructions) > width())
|
||||
contentH += fontSmall.lineHeight();
|
||||
uint16_t freeY = height() - contentH - fontSmall.lineHeight() * 1.2;
|
||||
uint16_t joyYLimit = freeY * 0.8;
|
||||
|
||||
// Use the shorter of the two
|
||||
uint16_t joyWidth = joyXLimit < joyYLimit ? joyXLimit : joyYLimit;
|
||||
|
||||
// Center the joystick graphic
|
||||
uint16_t centerX = X(0.5);
|
||||
uint16_t centerY = contentH + freeY * 0.5;
|
||||
|
||||
// Draw joystick graphic
|
||||
drawStick(centerX, centerY, joyWidth);
|
||||
|
||||
setFont(fontSmall);
|
||||
printAt(X(0.5), Y(1.0) - fontSmall.lineHeight() * 0.2, "Long press to skip", CENTER, BOTTOM);
|
||||
}
|
||||
|
||||
// Draw a scalable joystick graphic
|
||||
void InkHUD::AlignStickApplet::drawStick(uint16_t centerX, uint16_t centerY, uint16_t width)
|
||||
{
|
||||
if (width < 9) // too small to draw
|
||||
return;
|
||||
|
||||
else if (width < 40) { // only draw up arrow
|
||||
uint16_t chamfer = width < 20 ? 1 : 2;
|
||||
|
||||
// Draw filled up arrow
|
||||
drawDirection(centerX, centerY - width / 4, Direction::UP, width, chamfer, BLACK);
|
||||
|
||||
} else { // large enough to draw the full thing
|
||||
uint16_t chamfer = width < 80 ? 1 : 2;
|
||||
uint16_t stroke = 3; // pixels
|
||||
uint16_t arrowW = width * 0.22;
|
||||
uint16_t hollowW = arrowW - stroke * 2;
|
||||
|
||||
// Draw center circle
|
||||
fillCircle((int16_t)centerX, (int16_t)centerY, (int16_t)(width * 0.2), BLACK);
|
||||
fillCircle((int16_t)centerX, (int16_t)centerY, (int16_t)(width * 0.2) - stroke, WHITE);
|
||||
|
||||
// Draw filled up arrow
|
||||
drawDirection(centerX, centerY - width / 2, Direction::UP, arrowW, chamfer, BLACK);
|
||||
|
||||
// Draw down arrow
|
||||
drawDirection(centerX, centerY + width / 2, Direction::DOWN, arrowW, chamfer, BLACK);
|
||||
drawDirection(centerX, centerY + width / 2 - stroke, Direction::DOWN, hollowW, 0, WHITE);
|
||||
|
||||
// Draw left arrow
|
||||
drawDirection(centerX - width / 2, centerY, Direction::LEFT, arrowW, chamfer, BLACK);
|
||||
drawDirection(centerX - width / 2 + stroke, centerY, Direction::LEFT, hollowW, 0, WHITE);
|
||||
|
||||
// Draw right arrow
|
||||
drawDirection(centerX + width / 2, centerY, Direction::RIGHT, arrowW, chamfer, BLACK);
|
||||
drawDirection(centerX + width / 2 - stroke, centerY, Direction::RIGHT, hollowW, 0, WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a scalable joystick direction arrow
|
||||
// a right-triangle with blunted tips
|
||||
/*
|
||||
_ <--point
|
||||
^ / \
|
||||
| / \
|
||||
size / \
|
||||
| / \
|
||||
v |_________|
|
||||
|
||||
*/
|
||||
void InkHUD::AlignStickApplet::drawDirection(uint16_t pointX, uint16_t pointY, Direction direction, uint16_t size,
|
||||
uint16_t chamfer, Color color)
|
||||
{
|
||||
uint16_t chamferW = chamfer * 2 + 1;
|
||||
uint16_t triangleW = size - chamferW;
|
||||
|
||||
// Draw arrow
|
||||
switch (direction) {
|
||||
case Direction::UP:
|
||||
fillRect(pointX - chamfer, pointY, chamferW, triangleW, color);
|
||||
fillRect(pointX - chamfer - triangleW, pointY + triangleW, chamferW + triangleW * 2, chamferW, color);
|
||||
fillTriangle(pointX - chamfer, pointY, pointX - chamfer - triangleW, pointY + triangleW, pointX - chamfer,
|
||||
pointY + triangleW, color);
|
||||
fillTriangle(pointX + chamfer, pointY, pointX + chamfer + triangleW, pointY + triangleW, pointX + chamfer,
|
||||
pointY + triangleW, color);
|
||||
break;
|
||||
case Direction::DOWN:
|
||||
fillRect(pointX - chamfer, pointY - triangleW + 1, chamferW, triangleW, color);
|
||||
fillRect(pointX - chamfer - triangleW, pointY - size + 1, chamferW + triangleW * 2, chamferW, color);
|
||||
fillTriangle(pointX - chamfer, pointY, pointX - chamfer - triangleW, pointY - triangleW, pointX - chamfer,
|
||||
pointY - triangleW, color);
|
||||
fillTriangle(pointX + chamfer, pointY, pointX + chamfer + triangleW, pointY - triangleW, pointX + chamfer,
|
||||
pointY - triangleW, color);
|
||||
break;
|
||||
case Direction::LEFT:
|
||||
fillRect(pointX, pointY - chamfer, triangleW, chamferW, color);
|
||||
fillRect(pointX + triangleW, pointY - chamfer - triangleW, chamferW, chamferW + triangleW * 2, color);
|
||||
fillTriangle(pointX, pointY - chamfer, pointX + triangleW, pointY - chamfer - triangleW, pointX + triangleW,
|
||||
pointY - chamfer, color);
|
||||
fillTriangle(pointX, pointY + chamfer, pointX + triangleW, pointY + chamfer + triangleW, pointX + triangleW,
|
||||
pointY + chamfer, color);
|
||||
break;
|
||||
case Direction::RIGHT:
|
||||
fillRect(pointX - triangleW + 1, pointY - chamfer, triangleW, chamferW, color);
|
||||
fillRect(pointX - size + 1, pointY - chamfer - triangleW, chamferW, chamferW + triangleW * 2, color);
|
||||
fillTriangle(pointX, pointY - chamfer, pointX - triangleW, pointY - chamfer - triangleW, pointX - triangleW,
|
||||
pointY - chamfer, color);
|
||||
fillTriangle(pointX, pointY + chamfer, pointX - triangleW, pointY + chamfer + triangleW, pointX - triangleW,
|
||||
pointY + chamfer, color);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InkHUD::AlignStickApplet::onForeground()
|
||||
{
|
||||
// Prevent most other applets from requesting update, and skip their rendering entirely
|
||||
// Another system applet with a higher precedence can potentially ignore this
|
||||
SystemApplet::lockRendering = true;
|
||||
SystemApplet::lockRequests = true;
|
||||
|
||||
handleInput = true; // Intercept the button input for our applet
|
||||
}
|
||||
|
||||
void InkHUD::AlignStickApplet::onBackground()
|
||||
{
|
||||
// Allow normal update behavior to resume
|
||||
SystemApplet::lockRendering = false;
|
||||
SystemApplet::lockRequests = false;
|
||||
SystemApplet::handleInput = false;
|
||||
|
||||
// Need to force an update, as a polite request wouldn't be honored, seeing how we are now in the background
|
||||
// Usually, onBackground is followed by another applet's onForeground (which requests update), but not in this case
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
void InkHUD::AlignStickApplet::onButtonLongPress()
|
||||
{
|
||||
sendToBackground();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
void InkHUD::AlignStickApplet::onExitLong()
|
||||
{
|
||||
sendToBackground();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
void InkHUD::AlignStickApplet::onNavUp()
|
||||
{
|
||||
settings->joystick.aligned = true;
|
||||
|
||||
sendToBackground();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
void InkHUD::AlignStickApplet::onNavDown()
|
||||
{
|
||||
inkhud->rotateJoystick(2); // 180 deg
|
||||
settings->joystick.aligned = true;
|
||||
|
||||
sendToBackground();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
void InkHUD::AlignStickApplet::onNavLeft()
|
||||
{
|
||||
inkhud->rotateJoystick(3); // 270 deg
|
||||
settings->joystick.aligned = true;
|
||||
|
||||
sendToBackground();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
void InkHUD::AlignStickApplet::onNavRight()
|
||||
{
|
||||
inkhud->rotateJoystick(1); // 90 deg
|
||||
settings->joystick.aligned = true;
|
||||
|
||||
sendToBackground();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifdef MESHTASTIC_INCLUDE_INKHUD
|
||||
|
||||
/*
|
||||
|
||||
System Applet for manually aligning the joystick with the screen
|
||||
|
||||
should be run at startup if the joystick is enabled
|
||||
and not aligned to the screen
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "graphics/niche/InkHUD/SystemApplet.h"
|
||||
|
||||
namespace NicheGraphics::InkHUD
|
||||
{
|
||||
|
||||
class AlignStickApplet : public SystemApplet
|
||||
{
|
||||
public:
|
||||
AlignStickApplet();
|
||||
|
||||
void onRender() override;
|
||||
void onForeground() override;
|
||||
void onBackground() override;
|
||||
void onButtonLongPress() override;
|
||||
void onExitLong() override;
|
||||
void onNavUp() override;
|
||||
void onNavDown() override;
|
||||
void onNavLeft() override;
|
||||
void onNavRight() override;
|
||||
|
||||
protected:
|
||||
enum Direction {
|
||||
UP,
|
||||
DOWN,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
};
|
||||
|
||||
void drawStick(uint16_t centerX, uint16_t centerY, uint16_t width);
|
||||
void drawDirection(uint16_t pointX, uint16_t pointY, Direction direction, uint16_t size, uint16_t chamfer, Color color);
|
||||
};
|
||||
|
||||
} // namespace NicheGraphics::InkHUD
|
||||
|
||||
#endif
|
||||
@@ -30,6 +30,7 @@ enum MenuAction {
|
||||
TOGGLE_AUTOSHOW_APPLET,
|
||||
SET_RECENTS,
|
||||
ROTATE,
|
||||
ALIGN_JOYSTICK,
|
||||
LAYOUT,
|
||||
TOGGLE_BATTERY_ICON,
|
||||
TOGGLE_NOTIFICATIONS,
|
||||
|
||||
@@ -178,6 +178,10 @@ void InkHUD::MenuApplet::execute(MenuItem item)
|
||||
inkhud->rotate();
|
||||
break;
|
||||
|
||||
case ALIGN_JOYSTICK:
|
||||
inkhud->openAlignStick();
|
||||
break;
|
||||
|
||||
case LAYOUT:
|
||||
// Todo: smarter incrementing of tile count
|
||||
settings->userTiles.count++;
|
||||
@@ -287,14 +291,17 @@ void InkHUD::MenuApplet::showPage(MenuPage page)
|
||||
// items.push_back(MenuItem("Display Off", MenuPage::EXIT)); // TODO
|
||||
items.push_back(MenuItem("Save & Shut Down", MenuAction::SHUTDOWN));
|
||||
items.push_back(MenuItem("Exit", MenuPage::EXIT));
|
||||
previousPage = MenuPage::EXIT;
|
||||
break;
|
||||
|
||||
case SEND:
|
||||
populateSendPage();
|
||||
previousPage = MenuPage::ROOT;
|
||||
break;
|
||||
|
||||
case CANNEDMESSAGE_RECIPIENT:
|
||||
populateRecipientPage();
|
||||
previousPage = MenuPage::OPTIONS;
|
||||
break;
|
||||
|
||||
case OPTIONS:
|
||||
@@ -321,6 +328,8 @@ void InkHUD::MenuApplet::showPage(MenuPage page)
|
||||
if (settings->userTiles.maxCount > 1)
|
||||
items.push_back(MenuItem("Layout", MenuAction::LAYOUT, MenuPage::OPTIONS));
|
||||
items.push_back(MenuItem("Rotate", MenuAction::ROTATE, MenuPage::OPTIONS));
|
||||
if (settings->joystick.enabled)
|
||||
items.push_back(MenuItem("Align Joystick", MenuAction::ALIGN_JOYSTICK, MenuPage::EXIT));
|
||||
items.push_back(MenuItem("Notifications", MenuAction::TOGGLE_NOTIFICATIONS, MenuPage::OPTIONS,
|
||||
&settings->optionalFeatures.notifications));
|
||||
items.push_back(MenuItem("Battery Icon", MenuAction::TOGGLE_BATTERY_ICON, MenuPage::OPTIONS,
|
||||
@@ -332,20 +341,24 @@ void InkHUD::MenuApplet::showPage(MenuPage page)
|
||||
items.push_back(
|
||||
MenuItem("12-Hour Clock", MenuAction::TOGGLE_12H_CLOCK, MenuPage::OPTIONS, &config.display.use_12h_clock));
|
||||
items.push_back(MenuItem("Exit", MenuPage::EXIT));
|
||||
previousPage = MenuPage::ROOT;
|
||||
break;
|
||||
|
||||
case APPLETS:
|
||||
populateAppletPage();
|
||||
items.push_back(MenuItem("Exit", MenuPage::EXIT));
|
||||
previousPage = MenuPage::OPTIONS;
|
||||
break;
|
||||
|
||||
case AUTOSHOW:
|
||||
populateAutoshowPage();
|
||||
items.push_back(MenuItem("Exit", MenuPage::EXIT));
|
||||
previousPage = MenuPage::OPTIONS;
|
||||
break;
|
||||
|
||||
case RECENTS:
|
||||
populateRecentsPage();
|
||||
previousPage = MenuPage::OPTIONS;
|
||||
break;
|
||||
|
||||
case EXIT:
|
||||
@@ -479,12 +492,21 @@ void InkHUD::MenuApplet::onButtonShortPress()
|
||||
// Push the auto-close timer back
|
||||
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
|
||||
|
||||
// Move menu cursor to next entry, then update
|
||||
if (cursorShown)
|
||||
cursor = (cursor + 1) % items.size();
|
||||
else
|
||||
cursorShown = true;
|
||||
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
|
||||
if (!settings->joystick.enabled) {
|
||||
// Move menu cursor to next entry, then update
|
||||
if (cursorShown)
|
||||
cursor = (cursor + 1) % items.size();
|
||||
else
|
||||
cursorShown = true;
|
||||
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
|
||||
} else {
|
||||
if (cursorShown)
|
||||
execute(items.at(cursor));
|
||||
else
|
||||
showPage(MenuPage::EXIT);
|
||||
if (!wantsToRender())
|
||||
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
|
||||
}
|
||||
}
|
||||
|
||||
void InkHUD::MenuApplet::onButtonLongPress()
|
||||
@@ -504,6 +526,62 @@ void InkHUD::MenuApplet::onButtonLongPress()
|
||||
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
|
||||
}
|
||||
|
||||
void InkHUD::MenuApplet::onExitShort()
|
||||
{
|
||||
// Exit the menu
|
||||
showPage(MenuPage::EXIT);
|
||||
|
||||
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
|
||||
}
|
||||
|
||||
void InkHUD::MenuApplet::onNavUp()
|
||||
{
|
||||
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
|
||||
|
||||
// Move menu cursor to previous entry, then update
|
||||
if (cursor == 0)
|
||||
cursor = items.size() - 1;
|
||||
else
|
||||
cursor--;
|
||||
|
||||
if (!cursorShown)
|
||||
cursorShown = true;
|
||||
|
||||
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
|
||||
}
|
||||
|
||||
void InkHUD::MenuApplet::onNavDown()
|
||||
{
|
||||
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
|
||||
|
||||
// Move menu cursor to next entry, then update
|
||||
if (cursorShown)
|
||||
cursor = (cursor + 1) % items.size();
|
||||
else
|
||||
cursorShown = true;
|
||||
|
||||
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
|
||||
}
|
||||
|
||||
void InkHUD::MenuApplet::onNavLeft()
|
||||
{
|
||||
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
|
||||
|
||||
// Go to the previous menu page
|
||||
showPage(previousPage);
|
||||
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
|
||||
}
|
||||
|
||||
void InkHUD::MenuApplet::onNavRight()
|
||||
{
|
||||
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
|
||||
|
||||
if (cursorShown)
|
||||
execute(items.at(cursor));
|
||||
if (!wantsToRender())
|
||||
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
|
||||
}
|
||||
|
||||
// Dynamically create MenuItem entries for activating / deactivating Applets, for the "Applet Selection" submenu
|
||||
void InkHUD::MenuApplet::populateAppletPage()
|
||||
{
|
||||
@@ -796,4 +874,4 @@ void InkHUD::MenuApplet::freeCannedMessageResources()
|
||||
cm.recipientItems.clear();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,11 @@ class MenuApplet : public SystemApplet, public concurrency::OSThread
|
||||
void onBackground() override;
|
||||
void onButtonShortPress() override;
|
||||
void onButtonLongPress() override;
|
||||
void onExitShort() override;
|
||||
void onNavUp() override;
|
||||
void onNavDown() override;
|
||||
void onNavLeft() override;
|
||||
void onNavRight() override;
|
||||
void onRender() override;
|
||||
|
||||
void show(Tile *t); // Open the menu, onto a user tile
|
||||
@@ -52,6 +57,7 @@ class MenuApplet : public SystemApplet, public concurrency::OSThread
|
||||
void freeCannedMessageResources(); // Clear MenuApplet's canned message processing data
|
||||
|
||||
MenuPage currentPage = MenuPage::ROOT;
|
||||
MenuPage previousPage = MenuPage::EXIT;
|
||||
uint8_t cursor = 0; // Which menu item is currently highlighted
|
||||
bool cursorShown = false; // Is *any* item highlighted? (Root menu: no initial selection)
|
||||
|
||||
@@ -97,4 +103,4 @@ class MenuApplet : public SystemApplet, public concurrency::OSThread
|
||||
|
||||
} // namespace NicheGraphics::InkHUD
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -153,6 +153,42 @@ void InkHUD::NotificationApplet::onButtonLongPress()
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
void InkHUD::NotificationApplet::onExitShort()
|
||||
{
|
||||
dismiss();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
void InkHUD::NotificationApplet::onExitLong()
|
||||
{
|
||||
dismiss();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
void InkHUD::NotificationApplet::onNavUp()
|
||||
{
|
||||
dismiss();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
void InkHUD::NotificationApplet::onNavDown()
|
||||
{
|
||||
dismiss();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
void InkHUD::NotificationApplet::onNavLeft()
|
||||
{
|
||||
dismiss();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
void InkHUD::NotificationApplet::onNavRight()
|
||||
{
|
||||
dismiss();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
// Ask the WindowManager to check whether any displayed applets are already displaying the info from this notification
|
||||
// Called internally when we first get a "notifiable event", and then again before render,
|
||||
// in case autoshow swapped which applet was displayed
|
||||
|
||||
@@ -31,6 +31,12 @@ class NotificationApplet : public SystemApplet
|
||||
void onBackground() override;
|
||||
void onButtonShortPress() override;
|
||||
void onButtonLongPress() override;
|
||||
void onExitShort() override;
|
||||
void onExitLong() override;
|
||||
void onNavUp() override;
|
||||
void onNavDown() override;
|
||||
void onNavLeft() override;
|
||||
void onNavRight() override;
|
||||
|
||||
int onReceiveTextMessage(const meshtastic_MeshPacket *p);
|
||||
|
||||
|
||||
@@ -112,12 +112,21 @@ void InkHUD::TipsApplet::onRender()
|
||||
setFont(fontSmall);
|
||||
int16_t cursorY = fontMedium.lineHeight() * 1.5;
|
||||
|
||||
printAt(0, cursorY, "User Button");
|
||||
cursorY += fontSmall.lineHeight() * 1.2;
|
||||
printAt(0, cursorY, "- short press: next");
|
||||
cursorY += fontSmall.lineHeight() * 1.2;
|
||||
printAt(0, cursorY, "- long press: select / open menu");
|
||||
cursorY += fontSmall.lineHeight() * 1.5;
|
||||
if (!settings->joystick.enabled) {
|
||||
printAt(0, cursorY, "User Button");
|
||||
cursorY += fontSmall.lineHeight() * 1.2;
|
||||
printAt(0, cursorY, "- short press: next");
|
||||
cursorY += fontSmall.lineHeight() * 1.2;
|
||||
printAt(0, cursorY, "- long press: select / open menu");
|
||||
} else {
|
||||
printAt(0, cursorY, "Joystick");
|
||||
cursorY += fontSmall.lineHeight() * 1.2;
|
||||
printAt(0, cursorY, "- open menu / select");
|
||||
cursorY += fontSmall.lineHeight() * 1.5;
|
||||
printAt(0, cursorY, "Exit Button");
|
||||
cursorY += fontSmall.lineHeight() * 1.2;
|
||||
printAt(0, cursorY, "- switch tile / close menu");
|
||||
}
|
||||
|
||||
printAt(0, Y(1.0), "Press button to continue", LEFT, BOTTOM);
|
||||
} break;
|
||||
@@ -127,8 +136,13 @@ void InkHUD::TipsApplet::onRender()
|
||||
printAt(0, 0, "Tip: Rotation");
|
||||
|
||||
setFont(fontSmall);
|
||||
printWrapped(0, fontMedium.lineHeight() * 1.5, width(),
|
||||
"To rotate the display, use the InkHUD menu. Long-press the user button > Options > Rotate.");
|
||||
if (!settings->joystick.enabled) {
|
||||
printWrapped(0, fontMedium.lineHeight() * 1.5, width(),
|
||||
"To rotate the display, use the InkHUD menu. Long-press the user button > Options > Rotate.");
|
||||
} else {
|
||||
printWrapped(0, fontMedium.lineHeight() * 1.5, width(),
|
||||
"To rotate the display, use the InkHUD menu. Press the user button > Options > Rotate.");
|
||||
}
|
||||
|
||||
printAt(0, Y(1.0), "Press button to continue", LEFT, BOTTOM);
|
||||
|
||||
@@ -232,4 +246,10 @@ void InkHUD::TipsApplet::onButtonShortPress()
|
||||
requestUpdate();
|
||||
}
|
||||
|
||||
// Functions the same as the user button in this instance
|
||||
void InkHUD::TipsApplet::onExitShort()
|
||||
{
|
||||
onButtonShortPress();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -36,6 +36,7 @@ class TipsApplet : public SystemApplet
|
||||
void onForeground() override;
|
||||
void onBackground() override;
|
||||
void onButtonShortPress() override;
|
||||
void onExitShort() override;
|
||||
|
||||
protected:
|
||||
void renderWelcome(); // Very first screen of tutorial
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifdef MESHTASTIC_INCLUDE_INKHUD
|
||||
|
||||
#include "./PositionsApplet.h"
|
||||
#include "NodeDB.h"
|
||||
|
||||
using namespace NicheGraphics;
|
||||
|
||||
@@ -49,8 +50,8 @@ ProcessMessage InkHUD::PositionsApplet::handleReceived(const meshtastic_MeshPack
|
||||
if (!hasPosition)
|
||||
return ProcessMessage::CONTINUE;
|
||||
|
||||
bool hasHopsAway = (mp.hop_start != 0 && mp.hop_limit <= mp.hop_start); // From NodeDB::updateFrom
|
||||
uint8_t hopsAway = mp.hop_start - mp.hop_limit;
|
||||
const int8_t hopsAway = getHopsAway(mp);
|
||||
const bool hasHopsAway = hopsAway >= 0;
|
||||
|
||||
// Determine if the position packet would change anything on-screen
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
@@ -55,10 +55,15 @@ void InkHUD::Events::onButtonShort()
|
||||
}
|
||||
|
||||
// If no system applet is handling input, default behavior instead is to cycle applets
|
||||
if (consumer)
|
||||
// or open menu if joystick is enabled
|
||||
if (consumer) {
|
||||
consumer->onButtonShortPress();
|
||||
else if (!dismissedExt) // Don't change applet if this button press silenced the external notification module
|
||||
inkhud->nextApplet();
|
||||
} else if (!dismissedExt) { // Don't change applet if this button press silenced the external notification module
|
||||
if (!settings->joystick.enabled)
|
||||
inkhud->nextApplet();
|
||||
else
|
||||
inkhud->openMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void InkHUD::Events::onButtonLong()
|
||||
@@ -83,6 +88,156 @@ void InkHUD::Events::onButtonLong()
|
||||
inkhud->openMenu();
|
||||
}
|
||||
|
||||
void InkHUD::Events::onExitShort()
|
||||
{
|
||||
if (settings->joystick.enabled) {
|
||||
// Audio feedback (via buzzer)
|
||||
// Short tone
|
||||
playChirp();
|
||||
// Cancel any beeping, buzzing, blinking
|
||||
// Some button handling suppressed if we are dismissing an external notification (see below)
|
||||
bool dismissedExt = dismissExternalNotification();
|
||||
|
||||
// Check which system applet wants to handle the button press (if any)
|
||||
SystemApplet *consumer = nullptr;
|
||||
for (SystemApplet *sa : inkhud->systemApplets) {
|
||||
if (sa->handleInput) {
|
||||
consumer = sa;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no system applet is handling input, default behavior instead is change tiles
|
||||
if (consumer)
|
||||
consumer->onExitShort();
|
||||
else if (!dismissedExt) // Don't change tile if this button press silenced the external notification module
|
||||
inkhud->nextTile();
|
||||
}
|
||||
}
|
||||
|
||||
void InkHUD::Events::onExitLong()
|
||||
{
|
||||
if (settings->joystick.enabled) {
|
||||
// Audio feedback (via buzzer)
|
||||
// Slightly longer than playChirp
|
||||
playBoop();
|
||||
|
||||
// Check which system applet wants to handle the button press (if any)
|
||||
SystemApplet *consumer = nullptr;
|
||||
for (SystemApplet *sa : inkhud->systemApplets) {
|
||||
if (sa->handleInput) {
|
||||
consumer = sa;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (consumer)
|
||||
consumer->onExitLong();
|
||||
}
|
||||
}
|
||||
|
||||
void InkHUD::Events::onNavUp()
|
||||
{
|
||||
if (settings->joystick.enabled) {
|
||||
// Audio feedback (via buzzer)
|
||||
// Short tone
|
||||
playChirp();
|
||||
// Cancel any beeping, buzzing, blinking
|
||||
// Some button handling suppressed if we are dismissing an external notification (see below)
|
||||
bool dismissedExt = dismissExternalNotification();
|
||||
|
||||
// Check which system applet wants to handle the button press (if any)
|
||||
SystemApplet *consumer = nullptr;
|
||||
for (SystemApplet *sa : inkhud->systemApplets) {
|
||||
if (sa->handleInput) {
|
||||
consumer = sa;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (consumer)
|
||||
consumer->onNavUp();
|
||||
}
|
||||
}
|
||||
|
||||
void InkHUD::Events::onNavDown()
|
||||
{
|
||||
if (settings->joystick.enabled) {
|
||||
// Audio feedback (via buzzer)
|
||||
// Short tone
|
||||
playChirp();
|
||||
// Cancel any beeping, buzzing, blinking
|
||||
// Some button handling suppressed if we are dismissing an external notification (see below)
|
||||
bool dismissedExt = dismissExternalNotification();
|
||||
|
||||
// Check which system applet wants to handle the button press (if any)
|
||||
SystemApplet *consumer = nullptr;
|
||||
for (SystemApplet *sa : inkhud->systemApplets) {
|
||||
if (sa->handleInput) {
|
||||
consumer = sa;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (consumer)
|
||||
consumer->onNavDown();
|
||||
}
|
||||
}
|
||||
|
||||
void InkHUD::Events::onNavLeft()
|
||||
{
|
||||
if (settings->joystick.enabled) {
|
||||
// Audio feedback (via buzzer)
|
||||
// Short tone
|
||||
playChirp();
|
||||
// Cancel any beeping, buzzing, blinking
|
||||
// Some button handling suppressed if we are dismissing an external notification (see below)
|
||||
bool dismissedExt = dismissExternalNotification();
|
||||
|
||||
// Check which system applet wants to handle the button press (if any)
|
||||
SystemApplet *consumer = nullptr;
|
||||
for (SystemApplet *sa : inkhud->systemApplets) {
|
||||
if (sa->handleInput) {
|
||||
consumer = sa;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no system applet is handling input, default behavior instead is to cycle applets
|
||||
if (consumer)
|
||||
consumer->onNavLeft();
|
||||
else if (!dismissedExt) // Don't change applet if this button press silenced the external notification module
|
||||
inkhud->prevApplet();
|
||||
}
|
||||
}
|
||||
|
||||
void InkHUD::Events::onNavRight()
|
||||
{
|
||||
if (settings->joystick.enabled) {
|
||||
// Audio feedback (via buzzer)
|
||||
// Short tone
|
||||
playChirp();
|
||||
// Cancel any beeping, buzzing, blinking
|
||||
// Some button handling suppressed if we are dismissing an external notification (see below)
|
||||
bool dismissedExt = dismissExternalNotification();
|
||||
|
||||
// Check which system applet wants to handle the button press (if any)
|
||||
SystemApplet *consumer = nullptr;
|
||||
for (SystemApplet *sa : inkhud->systemApplets) {
|
||||
if (sa->handleInput) {
|
||||
consumer = sa;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no system applet is handling input, default behavior instead is to cycle applets
|
||||
if (consumer)
|
||||
consumer->onNavRight();
|
||||
else if (!dismissedExt) // Don't change applet if this button press silenced the external notification module
|
||||
inkhud->nextApplet();
|
||||
}
|
||||
}
|
||||
|
||||
// Callback for deepSleepObserver
|
||||
// Returns 0 to signal that we agree to sleep now
|
||||
int InkHUD::Events::beforeDeepSleep(void *unused)
|
||||
|
||||
@@ -29,6 +29,12 @@ class Events
|
||||
|
||||
void onButtonShort(); // User button: short press
|
||||
void onButtonLong(); // User button: long press
|
||||
void onExitShort(); // Exit button: short press
|
||||
void onExitLong(); // Exit button: long press
|
||||
void onNavUp(); // Navigate up
|
||||
void onNavDown(); // Navigate down
|
||||
void onNavLeft(); // Navigate left
|
||||
void onNavRight(); // Navigate right
|
||||
|
||||
int beforeDeepSleep(void *unused); // Prepare for shutdown
|
||||
int beforeReboot(void *unused); // Prepare for reboot
|
||||
|
||||
@@ -80,6 +80,94 @@ void InkHUD::InkHUD::longpress()
|
||||
events->onButtonLong();
|
||||
}
|
||||
|
||||
// Call this when your exit button gets a short press
|
||||
void InkHUD::InkHUD::exitShort()
|
||||
{
|
||||
events->onExitShort();
|
||||
}
|
||||
|
||||
// Call this when your exit button gets a long press
|
||||
void InkHUD::InkHUD::exitLong()
|
||||
{
|
||||
events->onExitLong();
|
||||
}
|
||||
|
||||
// Call this when your joystick gets an up input
|
||||
void InkHUD::InkHUD::navUp()
|
||||
{
|
||||
switch ((persistence->settings.rotation + persistence->settings.joystick.alignment) % 4) {
|
||||
case 1: // 90 deg
|
||||
events->onNavLeft();
|
||||
break;
|
||||
case 2: // 180 deg
|
||||
events->onNavDown();
|
||||
break;
|
||||
case 3: // 270 deg
|
||||
events->onNavRight();
|
||||
break;
|
||||
default: // 0 deg
|
||||
events->onNavUp();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Call this when your joystick gets a down input
|
||||
void InkHUD::InkHUD::navDown()
|
||||
{
|
||||
switch ((persistence->settings.rotation + persistence->settings.joystick.alignment) % 4) {
|
||||
case 1: // 90 deg
|
||||
events->onNavRight();
|
||||
break;
|
||||
case 2: // 180 deg
|
||||
events->onNavUp();
|
||||
break;
|
||||
case 3: // 270 deg
|
||||
events->onNavLeft();
|
||||
break;
|
||||
default: // 0 deg
|
||||
events->onNavDown();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Call this when your joystick gets a left input
|
||||
void InkHUD::InkHUD::navLeft()
|
||||
{
|
||||
switch ((persistence->settings.rotation + persistence->settings.joystick.alignment) % 4) {
|
||||
case 1: // 90 deg
|
||||
events->onNavDown();
|
||||
break;
|
||||
case 2: // 180 deg
|
||||
events->onNavRight();
|
||||
break;
|
||||
case 3: // 270 deg
|
||||
events->onNavUp();
|
||||
break;
|
||||
default: // 0 deg
|
||||
events->onNavLeft();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Call this when your joystick gets a right input
|
||||
void InkHUD::InkHUD::navRight()
|
||||
{
|
||||
switch ((persistence->settings.rotation + persistence->settings.joystick.alignment) % 4) {
|
||||
case 1: // 90 deg
|
||||
events->onNavUp();
|
||||
break;
|
||||
case 2: // 180 deg
|
||||
events->onNavLeft();
|
||||
break;
|
||||
case 3: // 270 deg
|
||||
events->onNavDown();
|
||||
break;
|
||||
default: // 0 deg
|
||||
events->onNavRight();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cycle the next user applet to the foreground
|
||||
// Only activated applets are cycled
|
||||
// If user has a multi-applet layout, the applets will cycle on the "focused tile"
|
||||
@@ -88,6 +176,14 @@ void InkHUD::InkHUD::nextApplet()
|
||||
windowManager->nextApplet();
|
||||
}
|
||||
|
||||
// Cycle the previous user applet to the foreground
|
||||
// Only activated applets are cycled
|
||||
// If user has a multi-applet layout, the applets will cycle on the "focused tile"
|
||||
void InkHUD::InkHUD::prevApplet()
|
||||
{
|
||||
windowManager->prevApplet();
|
||||
}
|
||||
|
||||
// Show the menu (on the the focused tile)
|
||||
// The applet previously displayed there will be restored once the menu closes
|
||||
void InkHUD::InkHUD::openMenu()
|
||||
@@ -95,6 +191,12 @@ void InkHUD::InkHUD::openMenu()
|
||||
windowManager->openMenu();
|
||||
}
|
||||
|
||||
// Bring AlignStick applet to the foreground
|
||||
void InkHUD::InkHUD::openAlignStick()
|
||||
{
|
||||
windowManager->openAlignStick();
|
||||
}
|
||||
|
||||
// In layouts where multiple applets are shown at once, change which tile is focused
|
||||
// The focused tile in the one which cycles applets on button short press, and displays menu on long press
|
||||
void InkHUD::InkHUD::nextTile()
|
||||
@@ -102,12 +204,26 @@ void InkHUD::InkHUD::nextTile()
|
||||
windowManager->nextTile();
|
||||
}
|
||||
|
||||
// In layouts where multiple applets are shown at once, change which tile is focused
|
||||
// The focused tile in the one which cycles applets on button short press, and displays menu on long press
|
||||
void InkHUD::InkHUD::prevTile()
|
||||
{
|
||||
windowManager->prevTile();
|
||||
}
|
||||
|
||||
// Rotate the display image by 90 degrees
|
||||
void InkHUD::InkHUD::rotate()
|
||||
{
|
||||
windowManager->rotate();
|
||||
}
|
||||
|
||||
// rotate the joystick in 90 degree increments
|
||||
void InkHUD::InkHUD::rotateJoystick(uint8_t angle)
|
||||
{
|
||||
persistence->settings.joystick.alignment += angle;
|
||||
persistence->settings.joystick.alignment %= 4;
|
||||
}
|
||||
|
||||
// Show / hide the battery indicator in top-right
|
||||
void InkHUD::InkHUD::toggleBatteryIcon()
|
||||
{
|
||||
|
||||
@@ -55,15 +55,25 @@ class InkHUD
|
||||
|
||||
void shortpress();
|
||||
void longpress();
|
||||
void exitShort();
|
||||
void exitLong();
|
||||
void navUp();
|
||||
void navDown();
|
||||
void navLeft();
|
||||
void navRight();
|
||||
|
||||
// Trigger UI changes
|
||||
// - called by various InkHUD components
|
||||
// - suitable(?) for use by aux button, connected in variant nicheGraphics.h
|
||||
|
||||
void nextApplet();
|
||||
void prevApplet();
|
||||
void openMenu();
|
||||
void openAlignStick();
|
||||
void nextTile();
|
||||
void prevTile();
|
||||
void rotate();
|
||||
void rotateJoystick(uint8_t angle = 1); // rotate 90 deg by default
|
||||
void toggleBatteryIcon();
|
||||
|
||||
// Updating the display
|
||||
|
||||
@@ -29,7 +29,7 @@ class Persistence
|
||||
|
||||
// Used to invalidate old settings, if needed
|
||||
// Version 0 is reserved for testing, and will always load defaults
|
||||
static constexpr uint32_t SETTINGS_VERSION = 2;
|
||||
static constexpr uint32_t SETTINGS_VERSION = 3;
|
||||
|
||||
struct Settings {
|
||||
struct Meta {
|
||||
@@ -96,6 +96,19 @@ class Persistence
|
||||
bool safeShutdownSeen = false;
|
||||
} tips;
|
||||
|
||||
// Joystick settings for enabling and aligning to the screen
|
||||
struct Joystick {
|
||||
// Modifies the UI for joystick use
|
||||
bool enabled = false;
|
||||
|
||||
// gets set to true when AlignStick applet is completed
|
||||
bool aligned = false;
|
||||
|
||||
// Rotation of the joystick
|
||||
// Multiples of 90 degrees clockwise
|
||||
uint8_t alignment = 0;
|
||||
} joystick;
|
||||
|
||||
// Rotation of the display
|
||||
// Multiples of 90 degrees clockwise
|
||||
// Most commonly: rotation is 0 when flex connector is oriented below display
|
||||
|
||||
@@ -8,4 +8,5 @@ build_flags =
|
||||
-D MESHTASTIC_EXCLUDE_INPUTBROKER ; Suppress default input handling
|
||||
-D HAS_BUTTON=0 ; Suppress default ButtonThread
|
||||
lib_deps =
|
||||
https://github.com/ZinggJM/GFX_Root#2.0.0 ; Used by InkHUD as a "slimmer" version of AdafruitGFX
|
||||
# TODO renovate
|
||||
https://github.com/ZinggJM/GFX_Root#2.0.0 ; Used by InkHUD as a "slimmer" version of AdafruitGFX
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "./WindowManager.h"
|
||||
|
||||
#include "./Applets/System/AlignStick/AlignStickApplet.h"
|
||||
#include "./Applets/System/BatteryIcon/BatteryIconApplet.h"
|
||||
#include "./Applets/System/Logo/LogoApplet.h"
|
||||
#include "./Applets/System/Menu/MenuApplet.h"
|
||||
@@ -98,6 +99,38 @@ void InkHUD::WindowManager::nextTile()
|
||||
userTiles.at(settings->userTiles.focused)->requestHighlight();
|
||||
}
|
||||
|
||||
// Focus on a different tile but decrement index
|
||||
void InkHUD::WindowManager::prevTile()
|
||||
{
|
||||
// Close the menu applet if open
|
||||
// We don't *really* want to do this, but it simplifies handling *a lot*
|
||||
MenuApplet *menu = (MenuApplet *)inkhud->getSystemApplet("Menu");
|
||||
bool menuWasOpen = false;
|
||||
if (menu->isForeground()) {
|
||||
menu->sendToBackground();
|
||||
menuWasOpen = true;
|
||||
}
|
||||
|
||||
// Swap to next tile
|
||||
if (settings->userTiles.focused == 0)
|
||||
settings->userTiles.focused = settings->userTiles.count - 1;
|
||||
else
|
||||
settings->userTiles.focused--;
|
||||
|
||||
// Make sure that we don't get stuck on the placeholder tile
|
||||
refocusTile();
|
||||
|
||||
if (menuWasOpen)
|
||||
menu->show(userTiles.at(settings->userTiles.focused));
|
||||
|
||||
// Ask the tile to draw an indicator showing which tile is now focused
|
||||
// Requests a render
|
||||
// We only draw this indicator if the device uses an aux button to switch tiles.
|
||||
// Assume aux button is used to switch tiles if the "next tile" menu item is hidden
|
||||
if (!settings->optionalMenuItems.nextTile)
|
||||
userTiles.at(settings->userTiles.focused)->requestHighlight();
|
||||
}
|
||||
|
||||
// Show the menu (on the the focused tile)
|
||||
// The applet previously displayed there will be restored once the menu closes
|
||||
void InkHUD::WindowManager::openMenu()
|
||||
@@ -106,6 +139,15 @@ void InkHUD::WindowManager::openMenu()
|
||||
menu->show(userTiles.at(settings->userTiles.focused));
|
||||
}
|
||||
|
||||
// Bring the AlignStick applet to the foreground
|
||||
void InkHUD::WindowManager::openAlignStick()
|
||||
{
|
||||
if (settings->joystick.enabled) {
|
||||
AlignStickApplet *alignStick = (AlignStickApplet *)inkhud->getSystemApplet("AlignStick");
|
||||
alignStick->bringToForeground();
|
||||
}
|
||||
}
|
||||
|
||||
// On the currently focussed tile: cycle to the next available user applet
|
||||
// Applets available for this must be activated, and not already displayed on another tile
|
||||
void InkHUD::WindowManager::nextApplet()
|
||||
@@ -155,6 +197,59 @@ void InkHUD::WindowManager::nextApplet()
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FAST); // bringToForeground already requested, but we're manually forcing FAST
|
||||
}
|
||||
|
||||
// On the currently focussed tile: cycle to the previous available user applet
|
||||
// Applets available for this must be activated, and not already displayed on another tile
|
||||
void InkHUD::WindowManager::prevApplet()
|
||||
{
|
||||
Tile *t = userTiles.at(settings->userTiles.focused);
|
||||
|
||||
// Abort if zero applets available
|
||||
// nullptr means WindowManager::refocusTile determined that there were no available applets
|
||||
if (!t->getAssignedApplet())
|
||||
return;
|
||||
|
||||
// Find the index of the applet currently shown on the tile
|
||||
uint8_t appletIndex = -1;
|
||||
for (uint8_t i = 0; i < inkhud->userApplets.size(); i++) {
|
||||
if (inkhud->userApplets.at(i) == t->getAssignedApplet()) {
|
||||
appletIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Confirm that we did find the applet
|
||||
assert(appletIndex != (uint8_t)-1);
|
||||
|
||||
// Iterate forward through the WindowManager::applets, looking for the previous valid applet
|
||||
Applet *prevValidApplet = nullptr;
|
||||
for (uint8_t i = 1; i < inkhud->userApplets.size(); i++) {
|
||||
uint8_t newAppletIndex = 0;
|
||||
if (i > appletIndex)
|
||||
newAppletIndex = inkhud->userApplets.size() + appletIndex - i;
|
||||
else
|
||||
newAppletIndex = (appletIndex - i);
|
||||
Applet *a = inkhud->userApplets.at(newAppletIndex);
|
||||
|
||||
// Looking for an applet which is active (enabled by user), but currently in background
|
||||
if (a->isActive() && !a->isForeground()) {
|
||||
prevValidApplet = a;
|
||||
settings->userTiles.displayedUserApplet[settings->userTiles.focused] =
|
||||
newAppletIndex; // Remember this setting between boots!
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Confirm that we found another applet
|
||||
if (!prevValidApplet)
|
||||
return;
|
||||
|
||||
// Hide old applet, show new applet
|
||||
t->getAssignedApplet()->sendToBackground();
|
||||
t->assignApplet(prevValidApplet);
|
||||
prevValidApplet->bringToForeground();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FAST); // bringToForeground already requested, but we're manually forcing FAST
|
||||
}
|
||||
|
||||
// Rotate the display image by 90 degrees
|
||||
void InkHUD::WindowManager::rotate()
|
||||
{
|
||||
@@ -338,6 +433,8 @@ void InkHUD::WindowManager::createSystemApplets()
|
||||
addSystemApplet("Logo", new LogoApplet, new Tile);
|
||||
addSystemApplet("Pairing", new PairingApplet, new Tile);
|
||||
addSystemApplet("Tips", new TipsApplet, new Tile);
|
||||
if (settings->joystick.enabled)
|
||||
addSystemApplet("AlignStick", new AlignStickApplet, new Tile);
|
||||
|
||||
addSystemApplet("Menu", new MenuApplet, nullptr);
|
||||
|
||||
@@ -360,6 +457,8 @@ void InkHUD::WindowManager::placeSystemTiles()
|
||||
inkhud->getSystemApplet("Logo")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height());
|
||||
inkhud->getSystemApplet("Pairing")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height());
|
||||
inkhud->getSystemApplet("Tips")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height());
|
||||
if (settings->joystick.enabled)
|
||||
inkhud->getSystemApplet("AlignStick")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height());
|
||||
|
||||
inkhud->getSystemApplet("Notification")->getTile()->setRegion(0, 0, inkhud->width(), 20);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user