remove: sstv
This commit is contained in:
parent
085242a154
commit
7b763a7da7
32
include/MMA8451Q.h
Normal file
32
include/MMA8451Q.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "derivative.h"
|
||||||
|
|
||||||
|
#define MMA8451Q_I2C_ADDRESS 0x1D
|
||||||
|
|
||||||
|
#define I2C_MWSR 0x00 /* Master write */
|
||||||
|
#define I2C_MRSW 0x01 /* Master read */
|
||||||
|
|
||||||
|
#define MMA8451Q_I2C_Start() I2C0->C1 |= 0x30;
|
||||||
|
|
||||||
|
#define MMA8451Q_I2C_Stop() I2C0->C1 &= (~0x30);
|
||||||
|
|
||||||
|
#define MMA8451Q_I2C_RepeatedStart() I2C0->C1 |= 0x04;
|
||||||
|
|
||||||
|
#define MMA8451Q_I2C_Disable_Ack() I2C0->C1 |= 0x08;
|
||||||
|
|
||||||
|
#define MMA8451Q_I2C_Enable_Ack() I2C0->C1 &= (~0x08);
|
||||||
|
|
||||||
|
#define MMA8451Q_I2C_Wait() \
|
||||||
|
while ((I2C0->S & 0x02) == 0) \
|
||||||
|
; \
|
||||||
|
I2C0->S |= 0x02;
|
||||||
|
|
||||||
|
#define MMA8451Q_I2C_EnterRxMode() I2C0->C1 &= (~0x10);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////
|
||||||
|
void MMA8451Q_I2C_Init(void);
|
||||||
|
void MMA8451Q_Init();
|
||||||
|
|
||||||
|
void MMA8451Q_WriteRegister(unsigned char u8RegisterAddress, unsigned char u8Data);
|
||||||
|
unsigned char MMA8451Q_ReadRegister(unsigned char u8RegisterAddress);
|
@ -2,12 +2,6 @@
|
|||||||
|
|
||||||
#include "derivative.h"
|
#include "derivative.h"
|
||||||
|
|
||||||
#define ADC_M 2048
|
|
||||||
extern int16_t adc_buf[ADC_M];
|
|
||||||
extern uint16_t pADC;
|
|
||||||
extern uint16_t cADC;
|
|
||||||
extern uint8_t fADC;
|
|
||||||
|
|
||||||
void adc0_Init();
|
void adc0_Init();
|
||||||
int16_t adc0_TR_DATA();
|
int16_t adc0_TR_DATA();
|
||||||
void adc0_read_buf(int16_t *data, uint16_t len);
|
void adc0_read_buf(int16_t *data, uint16_t len);
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "derivative.h"
|
|
||||||
#include "fft/fft.h"
|
|
||||||
|
|
||||||
#define FS 10000
|
|
||||||
#define RE FS / FFT_N
|
|
||||||
|
|
||||||
#define FREQ_BLACK 1500
|
|
||||||
#define FREQ_WHITE 4000
|
|
||||||
#define FREQ_SYNC 4500
|
|
||||||
#define FREQ_RANGE FREQ_WHITE - FREQ_BLACK
|
|
||||||
#define COLOR_SCALE 32
|
|
||||||
|
|
||||||
uint8_t decode_sstv();
|
|
49
include/tpm.h
Normal file
49
include/tpm.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "derivative.h"
|
||||||
|
|
||||||
|
#define PWMCLK 163828 // 20.97 MHz / 128
|
||||||
|
|
||||||
|
/*
|
||||||
|
@brief Timer / PWM Initialization
|
||||||
|
@param TPM (TPM0, TPM1, TPM2)
|
||||||
|
@param cha channel
|
||||||
|
*/
|
||||||
|
static inline void tpm_init(TPM_Type* TPM, uint8_t cha) {
|
||||||
|
SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); // MCGFLLCLK clock or MCGPLLCLK/2
|
||||||
|
SIM->SOPT2 &= ~SIM_SOPT2_PLLFLLSEL_MASK; // MCGFLLCLK clock
|
||||||
|
|
||||||
|
/*
|
||||||
|
CNT: Current Counter Value, 16 bits
|
||||||
|
MOD: Modulo Value, 16 bits -> Frequency
|
||||||
|
SC: Status and Control
|
||||||
|
CnSC: Channel (n) Status and Control
|
||||||
|
CnV: Channel (n) Value, 16 bits -> duty cycle
|
||||||
|
*/
|
||||||
|
if (TPM == TPM0) {
|
||||||
|
SIM->SCGC6 |= SIM_SCGC6_TPM0_MASK;
|
||||||
|
} else if (TPM == TPM1) {
|
||||||
|
SIM->SCGC6 |= SIM_SCGC6_TPM1_MASK;
|
||||||
|
} else if (TPM == TPM2) {
|
||||||
|
SIM->SCGC6 |= SIM_SCGC6_TPM2_MASK;
|
||||||
|
}
|
||||||
|
TPM->CNT = 0x0;
|
||||||
|
TPM->MOD = 0x0;
|
||||||
|
TPM->SC |= TPM_SC_CMOD(1) // LPTPM counter increments on every LPTPM counter clock
|
||||||
|
| TPM_SC_PS(7); // Prescaler Factor, Divide by 128
|
||||||
|
TPM->CONTROLS[cha].CnSC |= TPM_CnSC_ELSB(1) | TPM_CnSC_ELSA(0) // High-true pulses
|
||||||
|
| TPM_CnSC_MSB(1) | TPM_CnSC_MSA(0); // Edge-aligned PWM
|
||||||
|
TPM->CONTROLS[cha].CnV = 0x0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@brief Set the frequency and duty cycle of the PWM
|
||||||
|
@param TPM (TPM0, TPM1, TPM2)
|
||||||
|
@param mod modulo value -> frequency
|
||||||
|
@param val threshold value, when the count exceeds the threshold output toggles -> duty cycle
|
||||||
|
@param cha channel
|
||||||
|
*/
|
||||||
|
static inline void tpm_set(TPM_Type* TPM, uint16_t mod, uint16_t val, uint8_t cha) {
|
||||||
|
TPM->MOD = mod;
|
||||||
|
TPM->CONTROLS[cha].CnV = val;
|
||||||
|
}
|
118
main.c
118
main.c
@ -1,24 +1,118 @@
|
|||||||
#include "adc.h"
|
#include "MMA8451Q.h"
|
||||||
#include "derivative.h"
|
#include "derivative.h"
|
||||||
#include "sstv.h"
|
|
||||||
#include "systick.h"
|
#include "systick.h"
|
||||||
#include "tftlcd.h"
|
#include "tftlcd.h"
|
||||||
|
#include "tpm.h"
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
|
||||||
|
#define L1 M1 * 2 // 低八度
|
||||||
|
#define L2 M2 * 2
|
||||||
|
#define L3 M3 * 2
|
||||||
|
#define L4 M4 * 2
|
||||||
|
#define L5 M5 * 2
|
||||||
|
#define L6 M6 * 2
|
||||||
|
#define L7 M7 * 2
|
||||||
|
#define M1 (unsigned short)(PWMCLK / 523)
|
||||||
|
#define M2 (unsigned short)(PWMCLK / 587)
|
||||||
|
#define M3 (unsigned short)(PWMCLK / 659)
|
||||||
|
#define M4 (unsigned short)(PWMCLK / 698)
|
||||||
|
#define M5 (unsigned short)(PWMCLK / 784)
|
||||||
|
#define M6 (unsigned short)(PWMCLK / 880)
|
||||||
|
#define M7 (unsigned short)(PWMCLK / 988)
|
||||||
|
#define H1 M1 / 2 // 高八度
|
||||||
|
#define H2 M2 / 2
|
||||||
|
#define H3 M3 / 2
|
||||||
|
#define H4 M4 / 2
|
||||||
|
#define H5 M5 / 2
|
||||||
|
#define H6 M6 / 2
|
||||||
|
#define H7 M7 / 2
|
||||||
|
#define NN 0 // 休止符
|
||||||
|
|
||||||
|
// 晴天 4/4拍 (以1/4音符为1拍,每小节4拍)
|
||||||
|
#define N 204
|
||||||
|
#define BPM 67 // Beats Per Minute
|
||||||
|
const unsigned short note[] = {
|
||||||
|
NN, M5, M5, M1, M1, M2, M3, // 故事的小黄花
|
||||||
|
NN, M5, M5, M1, M1, M2, M3, M2, M1, L5, // 从出生那年就飘着
|
||||||
|
NN, M5, M5, M1, M1, M2, M3, // 童年的荡秋千
|
||||||
|
NN, M3, M2, M3, M4, M3, M2, M4, M3, M2, M1, // 随记忆一直晃到现在
|
||||||
|
L5, M1, M1, M3, M4, M3, M2, M1, M2, // rui sou sou xi dou xi la sou la
|
||||||
|
M3, M3, M3, M3, M2, M3, M2, M1, // xi xi xi xi la xi la sou
|
||||||
|
L5, M1, M2, M3, M4, M3, M2, M1, M2, // 吹着前奏望着天空 我
|
||||||
|
M3, M3, M3, M3, M2, M3, M2, M1, L7, // 想起花瓣试着掉落 为
|
||||||
|
M1, M1, M1, M1, L7, M1, M1, M1, M1, M1, M1, L7, M1, M1, // 你翘课的那一天 花落的那一天
|
||||||
|
M1, M1, M1, M1, L7, M1, M1, M1, M1, M1, M1, M5, M5, M5, // 教室的那一间 我怎么看不见
|
||||||
|
NN, M5, M5, M5, M5, M5, M5, M5, M5, M5, M5, M5, M4, M3, M3, // 消失的下雨天 我好想再淋一遍
|
||||||
|
M3, M3, NN, M1, M1, M1, M1, // 没想到失
|
||||||
|
L6, L7, M1, M5, M4, M3, M1, M1, // 去的勇气我还留着
|
||||||
|
M1, NN, M1, M1, M1, M1, M3, M1, // 好想再问一遍
|
||||||
|
L6, L7, M1, M5, M4, M3, M1, M2, // 你会等待还是离开
|
||||||
|
M2, M2, NN, NN, // Null
|
||||||
|
M3, M2, M4, M3, M1, M5, M7, // 刮风这天 我试过
|
||||||
|
H1, M7, M1, M1, M1, M6, M6, // 握着你手 但偏偏
|
||||||
|
NN, M6, M5, M5, M5, M4, M3, // 雨渐渐 大到我
|
||||||
|
M2, M3, M4, M3, M3, M3, // 看你不见
|
||||||
|
M3, M4, M5, M3, M4, M5, M7, // 还有多久 我才能
|
||||||
|
H2, M7, H1, H1, NN, H1, // 在你身边 等
|
||||||
|
H1, M5, M5, M6, M5, M4, M4, M2, M3, // 到放晴的那天 也许
|
||||||
|
M4, M5, M6, M1, M6, M7, M7, // 我会比较好一点
|
||||||
|
};
|
||||||
|
const unsigned short duration[] = {
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x04, 0x02, 0x02, // 故事的小黄花
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, // 从出生那年就飘着
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x04, 0x02, 0x02, // 童年的荡秋千
|
||||||
|
0x02, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, // 随记忆一直晃到现在
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, // rui sou sou xi dou xi la sou la
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x04, // xi xi xi xi la xi la sou
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, // 吹着前奏望着天空 我
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x03, 0x01, // 想起花瓣试着掉落 为
|
||||||
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, // 你翘课的那一天 花落的那一天
|
||||||
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, // 教室的那一间 我怎么看不见
|
||||||
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||||
|
0x01, // 消失的下雨天 我好想再淋一遍
|
||||||
|
0x04, 0x04, 0x04, 0x01, 0x01, 0x01, 0x01, // 没想到失
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 去的勇气我还留着
|
||||||
|
0x04, 0x04, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, // 好想再问一遍
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 你会等待还是离开
|
||||||
|
0x04, 0x04, 0x00, 0x00, // Null
|
||||||
|
0x02, 0x02, 0x02, 0x04, 0x02, 0x02, 0x02, // 刮风这天 我试过
|
||||||
|
0x02, 0x02, 0x02, 0x04, 0x02, 0x02, 0x02, // 握着你手 但偏偏
|
||||||
|
0x02, 0x02, 0x02, 0x04, 0x02, 0x02, 0x02, // 雨渐渐 大到我
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x04, 0x04, // 看你不见
|
||||||
|
0x02, 0x02, 0x02, 0x04, 0x02, 0x02, 0x02, // 还有多久 我才能
|
||||||
|
0x02, 0x02, 0x02, 0x06, 0x02, 0x02, // 在你身边 等
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, // 到放晴的那天 也许
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x03, 0x01, 0x04, // 我会比较好一点
|
||||||
|
}; // 1/4音符为0x04, 最短为1/16音符
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
// Initialize
|
// Initialize
|
||||||
uart_init(UART_MSG, 9600); // Initialize UART1 with PC
|
SysTick_Config(CORCLK / 1000); // Period of systick timer : 1 ms
|
||||||
uart_rie_enable(UART_MSG); // Enable UART1 receive interrupt
|
tpm_init(TPM0, 4); // Initialize TPM0_CH4
|
||||||
LCD_Init(); // Initialize LCD
|
LCD_Init(); // Initialize LCD
|
||||||
adc0_Init(); // Initialize ADC0
|
|
||||||
|
|
||||||
uart_printf(UART_MSG, "System Clock: %lu\r\n", CORCLK);
|
// TMP0_CH4 -> PTC8
|
||||||
uart_printf(UART_MSG, "Bus Clock: %lu\r\n", BUSCLK);
|
SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
|
||||||
|
PORTC->PCR[8] = PORT_PCR_MUX(3); // Select TPM0_CH4
|
||||||
|
|
||||||
fADC = 1;
|
LCD_ShowChar(30, 30, 65, 12, 0);
|
||||||
for (;;) {
|
|
||||||
decode_sstv();
|
// uint16_t beat_time = (uint16_t)(60 * 1000.0 / BPM);
|
||||||
}
|
// uint32_t timer, period;
|
||||||
|
|
||||||
|
// for (uint8_t i = 0;;) {
|
||||||
|
// period = (uint32_t)(duration[i] * beat_time / 0x04);
|
||||||
|
// timer = tick_cnt + period;
|
||||||
|
// while (tick_cnt < timer) {
|
||||||
|
// uint16_t delta = (uint16_t)(timer - tick_cnt);
|
||||||
|
// uint16_t val = (uint16_t)(note[i] / 2 * (period - delta) / period);
|
||||||
|
// tpm_set(TPM0, note[i], val, 4);
|
||||||
|
// }
|
||||||
|
// i = (uint8_t)((i + 1) % N);
|
||||||
|
|
||||||
|
// if (timer_expired(&timer, period)) {
|
||||||
|
// tpm_set(TPM0, note[i], note[i] / 2, 4);
|
||||||
|
// i = (uint8_t)((i + 1) % N);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
110
src/MMA8451Q.c
Normal file
110
src/MMA8451Q.c
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#include "MMA8451Q.h"
|
||||||
|
#include "derivative.h"
|
||||||
|
#include "systick.h"
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
/*!
|
||||||
|
* I2C Initialization
|
||||||
|
* Set Baud Rate and turn on I2C0
|
||||||
|
*/
|
||||||
|
/*******************************************************************/
|
||||||
|
void MMA8451Q_I2C_Init(void) {
|
||||||
|
SIM->SCGC4 |= SIM_SCGC4_I2C0_MASK; // Turn on clock to I2C0 module
|
||||||
|
SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK; // Turn on clock to PORTB module
|
||||||
|
|
||||||
|
/* configure GPIO for I2C0 function */
|
||||||
|
PORTE->PCR[24] = PORT_PCR_MUX(5);
|
||||||
|
PORTE->PCR[25] = PORT_PCR_MUX(5);
|
||||||
|
|
||||||
|
I2C0->F = 0x14; /* set MULT and ICR */
|
||||||
|
I2C0->C1 = 0x80; /* enable IIC */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
/*!
|
||||||
|
* MMA8451Q Initialization
|
||||||
|
* Set MMA8451Q Control Register
|
||||||
|
*/
|
||||||
|
/*******************************************************************/
|
||||||
|
void MMA8451Q_Init() {
|
||||||
|
MMA8451Q_I2C_Init();
|
||||||
|
|
||||||
|
// MMA8451Q_ID=MMA8451Q_ReadRegister(0x0D); //read device ID
|
||||||
|
|
||||||
|
MMA8451Q_WriteRegister(0x2A, 0x01); // set MMA8451Q in ACTIVE mode
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
/*!
|
||||||
|
* Write a byte of Data to specified register on MMA8451Q
|
||||||
|
* @param u8RegisterAddress is Register Address
|
||||||
|
* @param u8Data is Data to write
|
||||||
|
*/
|
||||||
|
void MMA8451Q_WriteRegister(unsigned char u8RegisterAddress, unsigned char u8Data) {
|
||||||
|
/* send start signal */
|
||||||
|
MMA8451Q_I2C_Start();
|
||||||
|
|
||||||
|
/* send ID with W bit */
|
||||||
|
I2C0->D = ((MMA8451Q_I2C_ADDRESS << 1) | I2C_MWSR);
|
||||||
|
MMA8451Q_I2C_Wait();
|
||||||
|
|
||||||
|
/* Write Register Address */
|
||||||
|
I2C0->D = (u8RegisterAddress);
|
||||||
|
MMA8451Q_I2C_Wait();
|
||||||
|
|
||||||
|
/* Write Register Data */
|
||||||
|
I2C0->D = (u8Data);
|
||||||
|
MMA8451Q_I2C_Wait();
|
||||||
|
|
||||||
|
MMA8451Q_I2C_Stop();
|
||||||
|
|
||||||
|
spin(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
/*!
|
||||||
|
* Read a register from the MMA8451Q
|
||||||
|
* @param u8RegisterAddress is Register Address
|
||||||
|
* @return Data stored in Register
|
||||||
|
*/
|
||||||
|
unsigned char MMA8451Q_ReadRegister(unsigned char u8RegisterAddress) {
|
||||||
|
unsigned char result;
|
||||||
|
|
||||||
|
/* send start signal */
|
||||||
|
MMA8451Q_I2C_Start();
|
||||||
|
|
||||||
|
/* send ID with W bit */
|
||||||
|
I2C0->D = ((MMA8451Q_I2C_ADDRESS << 1) | I2C_MWSR);
|
||||||
|
MMA8451Q_I2C_Wait();
|
||||||
|
|
||||||
|
/* Write Register Address */
|
||||||
|
I2C0->D = (u8RegisterAddress);
|
||||||
|
MMA8451Q_I2C_Wait();
|
||||||
|
|
||||||
|
/* Do a repeated start */
|
||||||
|
MMA8451Q_I2C_RepeatedStart();
|
||||||
|
|
||||||
|
/* send ID with R bit */
|
||||||
|
I2C0->D = ((MMA8451Q_I2C_ADDRESS << 1) | I2C_MRSW);
|
||||||
|
MMA8451Q_I2C_Wait();
|
||||||
|
|
||||||
|
/* Put in Rx Mode */
|
||||||
|
MMA8451Q_I2C_EnterRxMode();
|
||||||
|
|
||||||
|
/* Turn off ACK */
|
||||||
|
MMA8451Q_I2C_Disable_Ack();
|
||||||
|
|
||||||
|
/* Dummy read */
|
||||||
|
result = I2C0->D;
|
||||||
|
MMA8451Q_I2C_Wait();
|
||||||
|
|
||||||
|
/* Send stop */
|
||||||
|
MMA8451Q_I2C_Stop();
|
||||||
|
result = I2C0->D;
|
||||||
|
|
||||||
|
/* Turn on ACK */
|
||||||
|
MMA8451Q_I2C_Enable_Ack();
|
||||||
|
|
||||||
|
spin(50);
|
||||||
|
return result;
|
||||||
|
}
|
21
src/adc.c
21
src/adc.c
@ -1,11 +1,6 @@
|
|||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "derivative.h"
|
#include "derivative.h"
|
||||||
|
|
||||||
int16_t adc_buf[ADC_M];
|
|
||||||
uint16_t pADC = 0;
|
|
||||||
uint16_t cADC = 0;
|
|
||||||
uint8_t fADC = 0;
|
|
||||||
|
|
||||||
void adc0_Init() {
|
void adc0_Init() {
|
||||||
// Enable ADC0 and PORTE clock
|
// Enable ADC0 and PORTE clock
|
||||||
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK;
|
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK;
|
||||||
@ -28,19 +23,3 @@ int16_t adc0_TR_DATA() {
|
|||||||
ADC0->SC1[0] &= ~ADC_SC1_COCO_MASK;
|
ADC0->SC1[0] &= ~ADC_SC1_COCO_MASK;
|
||||||
return ADC_Result;
|
return ADC_Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t lastPos = 0;
|
|
||||||
void adc0_read_buf(int16_t *data, uint16_t len) {
|
|
||||||
if (cADC > ADC_M) {
|
|
||||||
cADC = ADC_M;
|
|
||||||
lastPos = pADC;
|
|
||||||
}
|
|
||||||
while (len) {
|
|
||||||
if (cADC) {
|
|
||||||
*data++ = adc_buf[lastPos];
|
|
||||||
lastPos = (lastPos + 1) % ADC_M;
|
|
||||||
cADC--;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
101
src/sstv.c
101
src/sstv.c
@ -1,101 +0,0 @@
|
|||||||
#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;
|
|
||||||
}
|
|
Reference in New Issue
Block a user