From 7b763a7da7286813b48a92c1716af3c1c6e99831 Mon Sep 17 00:00:00 2001 From: liuyihui Date: Tue, 30 May 2023 11:03:11 +0800 Subject: [PATCH] remove: sstv --- include/MMA8451Q.h | 32 ++++++++++++ include/adc.h | 6 --- include/sstv.h | 15 ------ include/tpm.h | 49 ++++++++++++++++++ main.c | 120 ++++++++++++++++++++++++++++++++++++++++----- src/MMA8451Q.c | 110 +++++++++++++++++++++++++++++++++++++++++ src/adc.c | 21 -------- src/sstv.c | 101 -------------------------------------- 8 files changed, 298 insertions(+), 156 deletions(-) create mode 100644 include/MMA8451Q.h delete mode 100644 include/sstv.h create mode 100644 include/tpm.h create mode 100644 src/MMA8451Q.c delete mode 100644 src/sstv.c diff --git a/include/MMA8451Q.h b/include/MMA8451Q.h new file mode 100644 index 0000000..542c6ce --- /dev/null +++ b/include/MMA8451Q.h @@ -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); diff --git a/include/adc.h b/include/adc.h index 0f67a22..2c33cb1 100644 --- a/include/adc.h +++ b/include/adc.h @@ -2,12 +2,6 @@ #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(); int16_t adc0_TR_DATA(); void adc0_read_buf(int16_t *data, uint16_t len); diff --git a/include/sstv.h b/include/sstv.h deleted file mode 100644 index 9e7082c..0000000 --- a/include/sstv.h +++ /dev/null @@ -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(); diff --git a/include/tpm.h b/include/tpm.h new file mode 100644 index 0000000..18cc41e --- /dev/null +++ b/include/tpm.h @@ -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; +} diff --git a/main.c b/main.c index 9fa4841..d3b4a0b 100644 --- a/main.c +++ b/main.c @@ -1,24 +1,118 @@ -#include "adc.h" +#include "MMA8451Q.h" #include "derivative.h" -#include "sstv.h" #include "systick.h" #include "tftlcd.h" +#include "tpm.h" #include "uart.h" #include -#include + +#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) { // Initialize - uart_init(UART_MSG, 9600); // Initialize UART1 with PC - uart_rie_enable(UART_MSG); // Enable UART1 receive interrupt - LCD_Init(); // Initialize LCD - adc0_Init(); // Initialize ADC0 + SysTick_Config(CORCLK / 1000); // Period of systick timer : 1 ms + tpm_init(TPM0, 4); // Initialize TPM0_CH4 + LCD_Init(); // Initialize LCD - uart_printf(UART_MSG, "System Clock: %lu\r\n", CORCLK); - uart_printf(UART_MSG, "Bus Clock: %lu\r\n", BUSCLK); + // TMP0_CH4 -> PTC8 + SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK; + PORTC->PCR[8] = PORT_PCR_MUX(3); // Select TPM0_CH4 - fADC = 1; - for (;;) { - decode_sstv(); - } + LCD_ShowChar(30, 30, 65, 12, 0); + + // 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); + // } } diff --git a/src/MMA8451Q.c b/src/MMA8451Q.c new file mode 100644 index 0000000..b24d714 --- /dev/null +++ b/src/MMA8451Q.c @@ -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; +} diff --git a/src/adc.c b/src/adc.c index 1637eec..7f59a56 100644 --- a/src/adc.c +++ b/src/adc.c @@ -1,11 +1,6 @@ #include "adc.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() { // Enable ADC0 and PORTE clock SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; @@ -28,19 +23,3 @@ int16_t adc0_TR_DATA() { ADC0->SC1[0] &= ~ADC_SC1_COCO_MASK; 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--; - } - } -} diff --git a/src/sstv.c b/src/sstv.c deleted file mode 100644 index 25de35c..0000000 --- a/src/sstv.c +++ /dev/null @@ -1,101 +0,0 @@ -#include "adc.h" -#include "derivative.h" -#include "fft/fft.h" -#include "sstv.h" -#include "tftlcd.h" -#include "uart.h" -#include -#include -#include - -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; -}