Base para um projeto decodificador RTTY , utilizando tv antiga como terminal
Segue um projeto em andamento, um decodificador RTTY , está implementado em um ESP32.
Tom de áudio em 2000Hz
Tons de áudio 2125Hz e 2295Hz
Tom de áudio 2295Hz
Sem áudio
Tom da áudio 2125Hz
O código
Biblioteca para a geração do vídeo composto Bitluni https://github.com/bitluni/ESP32Lib
#include <Arduino.h>
#include <ESP32Video.h> // < ----Fonte https://github.com/bitluni/ESP32Lib //https://www.youtube.com/watch?v=-JXuwwXQh8c&list=PLjUbKCHhzPEzCm2_KFAICIN-7QTap_s72&index=4
#include <esp_task_wdt.h>
// --- HARDWARE ---
#define VIDEO_PIN 25
#define ADC_PIN 34
// --- RTTY SETTINGS ---
#define SAMPLE_RATE 8000
#define BLOCK_SIZE 160
const float targetFreqs[] = {2125.0, 2295.0};
CompositeGrayDAC display;
float coeffs[2];
float q1[2], q2[2];
int16_t samples[BLOCK_SIZE];
/* ================= FONTE 16x16 PARA RTTY ================= */
static const uint16_t font16x16_basic[128][16] = {
{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},
{0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x1DB8, 0x0FF0, 0x07E0, 0x03C0, 0x0180, 0x0000, 0x0000}, // LF
{0},{0},
{0x0000, 0x0000, 0x0000, 0x0000, 0x0070, 0x0038, 0x3FFF, 0x3FFF, 0x3838, 0x1C70, 0x0EE0, 0x07C0, 0x0380, 0x0000, 0x0000, 0x0000}, // CR
{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // SPACE
{0x0180,0x03C0,0x03C0,0x03C0,0x03C0,0x0180,0x0180,0x0180,0x0180,0x0180,0x0000,0x0180,0x0180,0x0000,0x0000,0x0000}, // !
{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},
{0x03C0,0x0FF0,0x1C38,0x381C,0x300C,0x300C,0x300C,0x300C,0x300C,0x300C,0x381C,0x1C38,0x0FF0,0x03C0,0x0000,0x0000}, // 0
{0x0180,0x0380,0x0780,0x0D80,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x1FF8,0x1FF8,0x0000,0x0000}, // 1
{0x07E0,0x1FF8,0x381C,0x300C,0x001C,0x0038,0x0070,0x00E0,0x01C0,0x0380,0x0700,0x0E00,0x3FFC,0x3FFC,0x0000,0x0000}, // 2
{0x07E0,0x1FF8,0x381C,0x300C,0x001C,0x03F0,0x03F0,0x001C,0x000C,0x300C,0x381C,0x1FF8,0x07E0,0x0000,0x0000,0x0000}, // 3
{0x0030,0x0070,0x00F0,0x01B0,0x0330,0x0630,0x0C30,0x1830,0x3FFF,0x3FFF,0x0030,0x0030,0x0030,0x0030,0x0000,0x0000}, // 4
{0x3FFC,0x3FFC,0x3000,0x3000,0x3FC0,0x3FE0,0x0070,0x0038,0x001C,0x001C,0x301C,0x1FF8,0x0FE0,0x0000,0x0000,0x0000}, // 5
{0x01F0,0x07F8,0x0E1C,0x1C00,0x1C00,0x1BF0,0x1FF8,0x3C1C,0x380C,0x380C,0x3C1C,0x1FF8,0x0FF0,0x0000,0x0000,0x0000}, // 6
{0x3FFF,0x3FFF,0x001C,0x0038,0x0070,0x00E0,0x01C0,0x0380,0x0700,0x0E00,0x1C00,0x1C00,0x1C00,0x1C00,0x0000,0x0000}, // 7
{0x07E0,0x1FF8,0x381C,0x381C,0x1C38,0x0FF0,0x0FF0,0x1C38,0x381C,0x381C,0x381C,0x1FF8,0x07E0,0x0000,0x0000,0x0000}, // 8
{0x0FF0,0x1FF8,0x381C,0x300C,0x300C,0x381C,0x1FFC,0x0FDC,0x001C,0x001C,0x3838,0x1FF0,0x0F80,0x0000,0x0000,0x0000}, // 9
{0}, {0}, {0}, {0}, {0}, {0}, {0}, // Símbolos extras
{0x03C0,0x0FF0,0x1C38,0x381C,0x381C,0x381C,0x3FFC,0x3FFC,0x381C,0x381C,0x381C,0x381C,0x381C,0x0000,0x0000,0x0000}, // A
{0x3FF0,0x3FF8,0x381C,0x381C,0x381C,0x3FF8,0x3FF0,0x381C,0x381C,0x381C,0x381C,0x3FF8,0x3FF0,0x0000,0x0000,0x0000}, // B
{0x03F0,0x0FFC,0x1C1C,0x3800,0x3000,0x3000,0x3000,0x3000,0x3000,0x3800,0x1C1C,0x0FFC,0x03F0,0x0000,0x0000,0x0000}, // C
{0x3FE0,0x3FF8,0x381C,0x380E,0x380E,0x380E,0x380E,0x380E,0x380E,0x380E,0x381C,0x3FF8,0x3FE0,0x0000,0x0000,0x0000}, // D
{0x3FFF,0x3FFF,0x3000,0x3000,0x3000,0x3FC0,0x3FC0,0x3000,0x3000,0x3000,0x3000,0x3FFF,0x3FFF,0x0000,0x0000,0x0000}, // E
{0x3FFF,0x3FFF,0x3000,0x3000,0x3000,0x3FC0,0x3FC0,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000}, // F
{0x03F0,0x0FFC,0x1C1C,0x3800,0x3000,0x3000,0x307E,0x307E,0x300E,0x380E,0x1C1C,0x0FFC,0x03F0,0x0000,0x0000,0x0000}, // G
{0x381C,0x381C,0x381C,0x381C,0x381C,0x3FFC,0x3FFC,0x381C,0x381C,0x381C,0x381C,0x381C,0x381C,0x0000,0x0000,0x0000}, // H
{0x1FF8,0x1FF8,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x1FF8,0x1FF8,0x0000,0x0000,0x0000}, // I
{0x007E,0x007E,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x1818,0x1C18,0x0FF8,0x07F0,0x0000,0x0000,0x0000}, // J
{0x381C,0x3838,0x3870,0x38E0,0x39C0,0x3F80,0x3F80,0x39C0,0x38E0,0x3870,0x3838,0x381C,0x380E,0x0000,0x0000,0x0000}, // K
{0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3FFF,0x3FFF,0x0000,0x0000,0x0000}, // L
{0xC003,0xE007,0xF00F,0xD81B,0xCC33,0xC663,0xC3C3,0xC183,0xC003,0xC003,0xC003,0xC003,0xC003,0x0000,0x0000,0x0000}, // M
{0xC003,0xE003,0xF003,0xD803,0xCC03,0xC603,0xC303,0xC183,0xC0C3,0xC063,0xC033,0xC01B,0xC00F,0x0000,0x0000,0x0000}, // N
{0x07E0,0x1FF8,0x381C,0x300C,0x300C,0x300C,0x300C,0x300C,0x300C,0x300C,0x381C,0x1FF8,0x07E0,0x0000,0x0000,0x0000}, // O
{0x3FF0,0x3FF8,0x381C,0x381C,0x381C,0x3FF8,0x3FF0,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000}, // P
{0x07E0,0x1FF8,0x381C,0x300C,0x300C,0x300C,0x300C,0x300C,0x300C,0x306C,0x387C,0x1FF8,0x07E0,0x003C,0x003C,0x0000}, // Q
{0x3FF0,0x3FF8,0x381C,0x381C,0x381C,0x3FF8,0x3FF0,0x38E0,0x3870,0x3838,0x381C,0x380E,0x3807,0x0000,0x0000,0x0000}, // R
{0x07E0,0x1FF8,0x381C,0x300C,0x3000,0x1F80,0x07E0,0x003E,0x000C,0x300C,0x381C,0x1FF8,0x07E0,0x0000,0x0000,0x0000}, // S
{0x7FFF,0x7FFF,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x0000,0x0000,0x0000}, // T
{0x300C,0x300C,0x300C,0x300C,0x300C,0x300C,0x300C,0x300C,0x300C,0x300C,0x381C,0x1FF8,0x07E0,0x0000,0x0000,0x0000}, // U
{0x300C,0x300C,0x300C,0x1818,0x1818,0x0C30,0x0C30,0x0660,0x0660,0x03C0,0x03C0,0x0180,0x0180,0x0000,0x0000,0x0000}, // V
{0xC003,0xC003,0xC003,0xC183,0xC3C3,0x6666,0x6666,0x3C3C,0x3C3C,0x1818,0x1818,0x1818,0x1818,0x0000,0x0000,0x0000}, // W
{0x300C,0x1818,0x0C30,0x0660,0x03C0,0x0180,0x0180,0x03C0,0x0660,0x0C30,0x1818,0x300C,0x6006,0x0000,0x0000,0x0000}, // X
{0x300C,0x1818,0x0C30,0x0660,0x03C0,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x0180,0x0000,0x0000,0x0000}, // Y
{0x7FFF,0x7FFF,0x000E,0x001C,0x0038,0x0070,0x01E0,0x0380,0x0700,0x0E00,0x1C00,0x7FFF,0x7FFF,0x0000,0x0000,0x0000} // Z
};
// Função para desenhar um caractere
void drawChar(int x, int y, char c) {
if (c < 0 || c > 127) return;
const uint16_t* f = font16x16_basic[(uint8_t)c];
for(int r=0; r<16; r++) {
uint16_t row = f[r];
for(int b=0; b<16; b++) {
if (row & (0x8000 >> b)) display.dot(x + b, y + r, 255);
}
}
}
// Função para escrever uma frase
void printString(int x, int y, const char* str) {
while(*str) {
drawChar(x, y, *str++);
x += 12; // Espaçamento entre letras
}
}
void setup() {
Serial.begin(115200);
display.init(CompMode::MODEPAL288P, VIDEO_PIN);
display.clear();
analogReadResolution(12);
analogSetPinAttenuation(ADC_PIN, ADC_11db);
// Pré-cálculo Goertzel
for (int i = 0; i < 2; i++) {
float normalizedFreq = targetFreqs[i] / (float)SAMPLE_RATE;
coeffs[i] = 2.0 * cos(2.0 * PI * normalizedFreq);
}
// --- DESENHO DA INTERFACE ESTÁTICA ---
// Título Centralizado (Largura da tela ~320px, texto ~250px)
printString(40, 30, "DETECTOR MARK SPACE RTTY"); // Linha e coluna do título
// Legendas abaixo das barras
printString(50, 210, "MARK");
printString(150, 210, "SPACE");
// Configuração Watchdog
esp_task_wdt_config_t wdt_config = { .timeout_ms = 5000, .idle_core_mask = 0, .trigger_panic = true };
esp_task_wdt_init(&wdt_config);
esp_task_wdt_add(NULL);
}
void loop() {
int sampleInterval = 1000000 / SAMPLE_RATE;
for (int i = 0; i < BLOCK_SIZE; i++) {
unsigned long start = micros();
samples[i] = analogRead(ADC_PIN) - 2048;
while (micros() - start < sampleInterval);
}
float mag[2];
for (int f = 0; f < 2; f++) {
q1[f] = 0; q2[f] = 0;
for (int i = 0; i < BLOCK_SIZE; i++) {
float q0 = coeffs[f] * q1[f] - q2[f] + (float)samples[i];
q2[f] = q1[f]; q1[f] = q0;
}
mag[f] = (q1[f]*q1[f] + q2[f]*q2[f] - q1[f]*q2[f]*coeffs[f]) / (BLOCK_SIZE*BLOCK_SIZE);
}
// --- ATUALIZAÇÃO DINÂMICA DAS BARRAS ---
int hMark = map(constrain((int)mag[0], 0, 5000), 0, 5000, 0, 100);
int hSpace = map(constrain((int)mag[1], 0, 5000), 0, 5000, 0, 100);
// Barra MARK
display.fillRect(55, 100, 30, 100, 40); // Fundo cinza
display.fillRect(55, 200 - hMark, 30, hMark, 255); // Barra branca
// Barra SPACE
display.fillRect(155, 100, 30, 100, 40); // Fundo cinza
display.fillRect(155, 200 - hSpace, 30, hSpace, 255); // Barra branca
esp_task_wdt_reset();
}
Ainda em testes , depois modificarei para a detecção dos caracteres, que já estão inseridos no código !





Comentários
Postar um comentário