SSTV-Decoder/src/sstv.c

102 lines
2.9 KiB
C

#include "adc.h"
#include "derivative.h"
#include "fft/fft.h"
#include "sstv.h"
#include "tftlcd.h"
#include "uart.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
static q15_t data[FFT_N];
static q15_t buffer[BUF_M];
static q15_t *pData = &data[0];
static const float32_t color_re = (float32_t)(FREQ_RANGE) / (COLOR_SCALE - 1);
#define fre2lum(fre) (uint8_t)((fre - FREQ_BLACK) / color_re)
static uint16_t find_peak(uint16_t L, uint16_t R) {
q15_t peak = 0;
uint16_t index = 0;
for (uint16_t i = L; i <= R; i++)
if (data[i] > peak) {
index = i;
peak = data[i];
}
return index;
}
static uint32_t cSample = 0;
static uint16_t preLen = 0;
static void read_samples(uint32_t start, uint16_t len) {
int16_t offset = start - cSample;
if (offset >= 0) {
adc0_read_buf(pData, offset);
adc0_read_buf(pData, len);
} else {
for (uint16_t i = 0; i < -offset; i++) data[i] = buffer[preLen + offset + i];
adc0_read_buf(pData - offset, len + offset);
}
for (uint16_t i = 0; i < len; i++) buffer[i] = data[i];
cSample += offset + len;
preLen = len;
}
static void decode_martin1() {
uart_printf(UART_MSG, "Mode: 44 - Martin 1\r\n");
const uint16_t WIDTH = 240;
const uint16_t HEIGHT = 240;
const float32_t SCAN_TIME = 0.146432;
const float32_t SYNC_PULSE = 0.004862;
const float32_t SYNC_PORCH = 0.000572;
const float32_t CHAN_TIME = SYNC_PORCH + SCAN_TIME;
const float32_t LINE_TIME = SYNC_PULSE + SYNC_PORCH + CHAN_TIME;
const float32_t PIXEL_TIME = SCAN_TIME / WIDTH;
const float32_t CHAN_OFFSETS = SYNC_PULSE + SYNC_PORCH;
const float32_t FWHM = 2.34;
const float32_t HALF_SAMPLE_TIME = (PIXEL_TIME * FWHM) / 2;
const uint8_t len = (uint8_t)(HALF_SAMPLE_TIME * 2 * FS);
uint16_t idx, fre, rgb;
uint32_t start, cSampleI = 0;
float32_t cSampleF = 0;
char buf[15];
uart_printf(UART_MSG, "Start Decoding\r\n");
for (uint16_t h = 0; h < HEIGHT; h = (h + 1) % HEIGHT) {
string_format(buf, "Line: %3d/240", h);
LCD_ShowString(LCD_W - 8, 0, &buf[0], 16, 1, 0);
if (h) {
cSampleF += LINE_TIME * FS;
cSampleI = (uint32_t)round(cSampleF);
}
// RGB 565: 5 bit R, 6 bit G, 5 bit B
for (uint16_t w = 0; w < WIDTH; w++) {
start = (uint32_t)round(cSampleI + (CHAN_OFFSETS + w * PIXEL_TIME - HALF_SAMPLE_TIME) * FS);
read_samples(start, len);
FFT(pData, len);
idx = find_peak(119, 457); // 1875 - 7125 Hz
fre = FFT_BIN(idx, RE);
rgb = fre2lum(fre);
rgb = (uint16_t)(((rgb / 2) & 0x1F) << 11) // R
| (uint16_t)((rgb & 0x3F) << 5) // G
| (uint16_t)((rgb / 2) & 0x1F); // B
LCD_DrawPoint(h, w, rgb);
}
}
}
uint8_t decode_sstv() {
decode_martin1();
return 0;
}