CQ Publishing
/
FftTest
Interface 2015年4月号 第1部 第7章のプログラム
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 /** 00002 * @file Main.cpp 00003 * @brief Send 1ch waveform and FFT data to PC via USB serial 00004 * @date 2015.02.24 00005 * @version 1.0.2 00006 */ 00007 #include "mbed.h" 00008 #include "USBSerial.h" 00009 #include "FilterTest.h" 00010 #include "FftTest.h" 00011 00012 #define ON (1) 00013 #define OFF (0) 00014 00015 #define LED_ON (0) 00016 #define LED_OFF (1) 00017 00018 #define BYTE_MASK (0xFF) 00019 #define INT16_MAX (32767) 00020 #define INT16_MIN (-32768) 00021 #define UINT16_MAX (65535) 00022 #define UINT16_MIN (0) 00023 00024 #define SAMPLING_RATE (0.001) /* A/D sampling rate (1kHz) */ 00025 #define DEC_COUNT (5) /* Decimation count (sampling 200Hz)*/ 00026 00027 #define PACKET_HEADER (0xAA) 00028 #define WAVEFORM_ID (0x01) 00029 #define FFT_ID (0x02) 00030 #define PACKET_SIZE (34) /* 64 -> 34 for PC to receive waveform data smoothly */ 00031 #define PAYLOAD_SIZE (30) /* PACKET_SIZE - 4(Header size) */ 00032 #define WAV_BUF_NUM (2) /* Double buffer */ 00033 #define WV_PKT_CNTR_NUM (100) 00034 /* [ Packet format ] */ 00035 /* ---------------- */ 00036 /* 0x00 | Header byte | Fixed value (PACKET_HEADER:0xAA) */ 00037 /* 0x01 | Data type | ID value (0x01:Waveform, 0x02:FFT) */ 00038 /* 0x02 | Packet counter | Count value (0to99 < CNTR_SIZE:100) */ 00039 /* 0x03 | Payload size | Fixed value (DATA_NUM:30) */ 00040 /* 0x04 | Data0 (MSBside)| Short type (signed, big endian) */ 00041 /* ... | ... | */ 00042 /* 0x21 | Data29(LSBside)| */ 00043 /* ---------------- */ 00044 00045 #define FFT_LENGTH (256) /* FFT data length */ 00046 #define FFT_INTERVAL (200) /* FFT calc interval */ 00047 #define FFT_OVERLAP_LEN (56) /* FFT overlap length */ 00048 #define FFT_BUF_NUM (2) /* Double buffer */ 00049 #define FFT_SEND_LEN (90) /* FFT send data length */ 00050 00051 00052 Ticker sampling; /* Interval timer for A/D sampling */ 00053 AnalogIn wave_in(p20); /* Waveform input */ 00054 USBSerial serial; 00055 FilterTest filter; 00056 FftTest fft; 00057 00058 /* DIP switch for filter ON/OFF */ 00059 DigitalIn hpf_on(p28); 00060 DigitalIn lpf_on(p27); 00061 DigitalIn brf_on(p26); 00062 /* [ DIP switch ] */ 00063 /* TG-LPC11U35-501 +3.3V */ 00064 /* | CN1 CN2 | --- */ 00065 /* | mbed BD | | */ 00066 /* | 13 | p28 -/ -+ Hiph pass filter */ 00067 /* | 14 | p27 -/ -+ Low pass filter */ 00068 /* | 15 | p26 -/ -+ Notch filter */ 00069 /* | | */ 00070 /* pull-down is default as below. */ 00071 /* http://developer.mbed.org/handbook/DigitalIn */ 00072 /* It says "By default, the DigitalIn is setup */ 00073 /* with an internal pull-down resistor." */ 00074 /* Better to set the pins to pull-up mode and the */ 00075 /* switch connected to GND. */ 00076 00077 /* For debug pins */ 00078 DigitalOut dbg_p21(p21); 00079 DigitalOut dbg_p22(p22); 00080 DigitalOut dbg_led1(LED1); 00081 DigitalOut dbg_led2(LED2); 00082 00083 /* Variables */ 00084 int32_t wav_dec_cntr; /* Decimation counter */ 00085 00086 uint8_t wav_pkt_buf[WAV_BUF_NUM][PACKET_SIZE]; /* Waveform packet buffer */ 00087 int32_t wav_pkt_idx; /* Packet buffer index */ 00088 int32_t wav_tgl; /* Packet buffer toggle */ 00089 int32_t wav_send_flag; /* Waveform sending flag */ 00090 uint8_t wav_pkt_cntr; /* Waveform packet counter */ 00091 00092 float fft_buf[FFT_BUF_NUM][FFT_LENGTH]; /* FFT data buffer */ 00093 uint8_t pkt_buf_fft[PACKET_SIZE] = {0}; /* FFT packet buffer */ 00094 int32_t fft_dat_idx; /* FFT buffer index */ 00095 int32_t fft_tgl; /* FFT buffer toggle */ 00096 int32_t fft_send_flag; /* FFT sendign flag */ 00097 00098 float fft_out_re[FFT_LENGTH] = {0.0f}; /* FFT result real */ 00099 float fft_out_im[FFT_LENGTH] = {0.0f}; /* FFT result imaginary */ 00100 uint16_t fft_res[FFT_SEND_LEN] = {0}; /* FFT result */ 00101 00102 /** Initialize waveform packet buffer 00103 * @param tgl buffer wav_tgl index 00104 * @param ctr packet counter 00105 */ 00106 void init_wav_pkt_buf(int32_t tgl, uint8_t ctr) 00107 { 00108 int i; 00109 if(tgl>WAV_BUF_NUM) { 00110 return; 00111 } 00112 wav_pkt_buf[tgl][0] = PACKET_HEADER; 00113 wav_pkt_buf[tgl][1] = WAVEFORM_ID; 00114 wav_pkt_buf[tgl][2] = ctr; /* Packet counter */ 00115 wav_pkt_buf[tgl][3] = PAYLOAD_SIZE; /* Payload size */ 00116 wav_pkt_idx = 4; /* Start index of waveform */ 00117 for(i=4; i<PACKET_SIZE; i++) { 00118 wav_pkt_buf[tgl][i] = 0; 00119 } 00120 } 00121 00122 /** Set FFT packet buffer 00123 * @param buf Source data buffer 00124 * @param ctr packet counter 00125 */ 00126 void set_fft_pkt_buf(uint16_t* buf, uint8_t ctr) 00127 { 00128 int i; 00129 pkt_buf_fft[0] = PACKET_HEADER; 00130 pkt_buf_fft[1] = FFT_ID; 00131 pkt_buf_fft[2] = ctr; /* Packet counter */ 00132 pkt_buf_fft[3] = PAYLOAD_SIZE; /* Payload size */ 00133 i=0; 00134 while(i<PAYLOAD_SIZE) { 00135 pkt_buf_fft[i + 4] = (uint8_t)((buf[i / 2] >> 8 ) & BYTE_MASK); 00136 i++; 00137 pkt_buf_fft[i + 4] = (uint8_t)(buf[i / 2] & BYTE_MASK); 00138 i++; 00139 } 00140 } 00141 00142 /** Interval timer for read A/D value 00143 */ 00144 void ad_sampling() 00145 { 00146 int32_t wav_temp; 00147 dbg_led2 = lpf_on; /* for debug */ 00148 00149 /* Read and filter data */ 00150 wav_temp = (int32_t)filter.calc( (double)(wave_in.read_u16() - INT16_MAX), hpf_on, lpf_on, brf_on ); 00151 00152 /* Store data */ 00153 wav_dec_cntr = (wav_dec_cntr + 1) % DEC_COUNT; 00154 if(wav_dec_cntr == 0) { /* Decimation */ 00155 00156 dbg_p21 = ON; /* for debug */ 00157 /* Waveform */ 00158 wav_temp = (wav_temp > INT16_MAX) ? INT16_MAX : wav_temp; 00159 wav_temp = (wav_temp < INT16_MIN) ? INT16_MIN : wav_temp; 00160 wav_pkt_buf[wav_tgl][wav_pkt_idx] = (uint8_t)((wav_temp >> 8 ) & BYTE_MASK); 00161 wav_pkt_idx++; 00162 wav_pkt_buf[wav_tgl][wav_pkt_idx] = (uint8_t)(wav_temp & BYTE_MASK); 00163 wav_pkt_idx++; 00164 00165 if(wav_pkt_idx >= PACKET_SIZE) { /* Counter reached */ 00166 wav_tgl = !wav_tgl; 00167 wav_pkt_cntr = (wav_pkt_cntr + 1 ) % WV_PKT_CNTR_NUM; 00168 init_wav_pkt_buf(wav_tgl, wav_pkt_cntr); 00169 wav_send_flag = ON; /* Set flag */ 00170 } 00171 00172 /* FFT */ 00173 fft_buf[fft_tgl][fft_dat_idx + FFT_OVERLAP_LEN] = (float)wav_temp; 00174 if(fft_dat_idx >= (FFT_INTERVAL - FFT_OVERLAP_LEN)) { 00175 fft_buf[!fft_tgl][fft_dat_idx + FFT_OVERLAP_LEN - FFT_INTERVAL] = (float)wav_temp; 00176 } 00177 00178 fft_dat_idx = (fft_dat_idx + 1) % FFT_INTERVAL; 00179 if(fft_dat_idx == 0) { 00180 fft_tgl = !fft_tgl; 00181 fft_send_flag = ON; /* Set flag */ 00182 } 00183 00184 dbg_p21 = OFF; /* for debug */ 00185 } 00186 } 00187 00188 /** Send data packet 00189 * @param p_buf Data array 00190 * @param size Data length 00191 */ 00192 bool send_packet(uint8_t *p_buf, uint16_t size) 00193 { 00194 if(serial.writeable()) { 00195 dbg_p22 = ON; /* for debug */ 00196 serial.writeBlock (p_buf, size); /* Send data via USB */ 00197 dbg_p22 = OFF; /* for debug */ 00198 return true; 00199 } else { 00200 return false; 00201 } 00202 } 00203 00204 /** Main function 00205 */ 00206 int main() 00207 { 00208 int i; 00209 uint16_t fft_temp; 00210 00211 /* Initialization */ 00212 wav_dec_cntr = 0; 00213 00214 init_wav_pkt_buf(wav_tgl, wav_pkt_cntr); 00215 init_wav_pkt_buf(!wav_tgl, wav_pkt_cntr); 00216 wav_pkt_idx = 0; 00217 wav_tgl = 0; 00218 wav_send_flag = OFF; 00219 wav_pkt_cntr = 0; 00220 00221 fft_dat_idx = 0; 00222 fft_tgl = 0; 00223 fft_send_flag = OFF; 00224 00225 dbg_p21 = OFF; 00226 dbg_p22 = OFF; 00227 dbg_led1 = LED_OFF; 00228 dbg_led2 = LED_OFF; 00229 00230 /* Start interval timer */ 00231 sampling.attach(&ad_sampling, SAMPLING_RATE); 00232 00233 /* Main loop */ 00234 while(1) { 00235 /* Waveform */ 00236 if(wav_send_flag != OFF) { 00237 /* Send data */ 00238 send_packet(wav_pkt_buf[!wav_tgl], (uint16_t)PACKET_SIZE); 00239 00240 /* Disable interrupt */ 00241 __disable_irq(); 00242 wav_send_flag = OFF; /* Clear flag */ 00243 __enable_irq(); 00244 } 00245 00246 /* FFT */ 00247 if(fft_send_flag != OFF) { 00248 dbg_led1 = LED_ON; /* for debug */ 00249 00250 /* Calculate FFT and normalized amplitude spectrum */ 00251 fft.apply_window(fft_buf[!fft_tgl], fft_buf[!fft_tgl]); 00252 fft.calc_fft(fft_buf[!fft_tgl], fft_out_re, fft_out_im); 00253 fft.calc_power(fft_out_re, fft_out_im, fft_out_re, FFT_SEND_LEN); 00254 fft.calc_amplitude(fft_out_re, fft_out_re, FFT_SEND_LEN); 00255 fft.norm_amplitude(fft_out_re, FFT_SEND_LEN); 00256 for(i=0; i<FFT_SEND_LEN; i++) { 00257 fft_temp = (fft_out_re[i] > UINT16_MAX) ? UINT16_MAX : (uint16_t)fft_out_re[i]; 00258 fft_temp = (fft_out_re[i] < UINT16_MIN) ? UINT16_MIN : fft_temp; 00259 fft_res[i] = fft_temp; 00260 } 00261 00262 /* Send data */ 00263 i=0; 00264 while((PAYLOAD_SIZE * i) < FFT_SEND_LEN * sizeof(fft_res[0])) { 00265 set_fft_pkt_buf((fft_res + (PAYLOAD_SIZE/sizeof(fft_res[0])) * i), i); 00266 send_packet(pkt_buf_fft, (uint16_t)PACKET_SIZE); 00267 i++; 00268 } 00269 00270 /* Disable interrupt */ 00271 __disable_irq(); 00272 fft_send_flag = OFF; /* Clear flag */ 00273 __enable_irq(); 00274 00275 dbg_led1 = LED_OFF; /* for debug */ 00276 } 00277 } 00278 }
Generated on Wed Jul 13 2022 17:36:59 by 1.7.2