├── .gitignore ├── .gitmodules ├── CMSIS ├── .DS_Store └── DSP_Lib │ ├── Source │ ├── CommonTables │ │ └── arm_common_tables.c │ ├── FilteringFunctions │ │ └── arm_biquad_cascade_df1_q15.c │ └── TransformFunctions │ │ ├── arm_bitreversal.c │ │ ├── arm_cfft_radix4_init_q31.c │ │ └── arm_cfft_radix4_q31.c │ └── license.txt ├── Font5x7.c ├── Makefile ├── NANOSDR_STM32_F303 ├── board.c ├── board.h └── board.mk ├── README.md ├── STM32F303xB.ld ├── build.sh ├── ccmfunc.ld ├── chconf.h ├── crt2.c ├── display.c ├── doc ├── centsdr-blockdiagram.png ├── centsdr.jpg └── plot-waveform.png ├── dsp.c ├── ffconf.h ├── flash-openocd.gdb ├── flash-stutil.gdb ├── flash.c ├── halconf.h ├── icons.c ├── ili9341.c ├── main.c ├── mcuconf.h ├── nanosdr.h ├── numfont20x24.c ├── numfont32x24.c ├── prog.sh ├── python ├── CW-Filter-Design.ipynb ├── README.md ├── SSB-Filter-Design.ipynb ├── TLV320AIC3204-1st-IIR-HPF.ipynb └── centsdr.py ├── rules_code.ld ├── si5351.c ├── si5351.h ├── si5351_low.c ├── tlv320aic3204.c ├── ui.c ├── usbcfg.c └── usbcfg.h /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .dep 3 | build 4 | TAGS 5 | *.cap 6 | .ipynb_checkpoints -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ChibiOS"] 2 | path = ChibiOS 3 | url = https://github.com/edy555/ChibiOS.git 4 | -------------------------------------------------------------------------------- /CMSIS/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttrftech/CentSDR/e4079566e42790497f004e16f9ebf68c83d024a0/CMSIS/.DS_Store -------------------------------------------------------------------------------- /CMSIS/DSP_Lib/Source/FilteringFunctions/arm_biquad_cascade_df1_q15.c: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------- 2 | * Copyright (C) 2010-2014 ARM Limited. All rights reserved. 3 | * 4 | * $Date: 19. March 2015 5 | * $Revision: V.1.4.5 6 | * 7 | * Project: CMSIS DSP Library 8 | * Title: arm_biquad_cascade_df1_q15.c 9 | * 10 | * Description: Processing function for the 11 | * Q15 Biquad cascade DirectFormI(DF1) filter. 12 | * 13 | * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 14 | * 15 | * Redistribution and use in source and binary forms, with or without 16 | * modification, are permitted provided that the following conditions 17 | * are met: 18 | * - Redistributions of source code must retain the above copyright 19 | * notice, this list of conditions and the following disclaimer. 20 | * - Redistributions in binary form must reproduce the above copyright 21 | * notice, this list of conditions and the following disclaimer in 22 | * the documentation and/or other materials provided with the 23 | * distribution. 24 | * - Neither the name of ARM LIMITED nor the names of its contributors 25 | * may be used to endorse or promote products derived from this 26 | * software without specific prior written permission. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 31 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 32 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 33 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 34 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 35 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 36 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 | * POSSIBILITY OF SUCH DAMAGE. 40 | * -------------------------------------------------------------------- */ 41 | 42 | #include "arm_math.h" 43 | 44 | /** 45 | * @ingroup groupFilters 46 | */ 47 | 48 | /** 49 | * @addtogroup BiquadCascadeDF1 50 | * @{ 51 | */ 52 | 53 | /** 54 | * @brief Processing function for the Q15 Biquad cascade filter. 55 | * @param[in] *S points to an instance of the Q15 Biquad cascade structure. 56 | * @param[in] *pSrc points to the block of input data. 57 | * @param[out] *pDst points to the location where the output result is written. 58 | * @param[in] blockSize number of samples to process per call. 59 | * @return none. 60 | * 61 | * 62 | * Scaling and Overflow Behavior: 63 | * \par 64 | * The function is implemented using a 64-bit internal accumulator. 65 | * Both coefficients and state variables are represented in 1.15 format and multiplications yield a 2.30 result. 66 | * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. 67 | * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. 68 | * The accumulator is then shifted by postShift bits to truncate the result to 1.15 format by discarding the low 16 bits. 69 | * Finally, the result is saturated to 1.15 format. 70 | * 71 | * \par 72 | * Refer to the function arm_biquad_cascade_df1_fast_q15() for a faster but less precise implementation of this filter for Cortex-M3 and Cortex-M4. 73 | */ 74 | 75 | void arm_biquad_cascade_df1_q15( 76 | const arm_biquad_casd_df1_inst_q15 * S, 77 | q15_t * pSrc, 78 | q15_t * pDst, 79 | uint32_t blockSize) 80 | { 81 | 82 | 83 | #ifndef ARM_MATH_CM0_FAMILY 84 | 85 | /* Run the below code for Cortex-M4 and Cortex-M3 */ 86 | 87 | q15_t *pIn = pSrc; /* Source pointer */ 88 | q15_t *pOut = pDst; /* Destination pointer */ 89 | q31_t in; /* Temporary variable to hold input value */ 90 | q31_t out; /* Temporary variable to hold output value */ 91 | q31_t b0; /* Temporary variable to hold bo value */ 92 | q31_t b1, a1; /* Filter coefficients */ 93 | q31_t state_in, state_out; /* Filter state variables */ 94 | q31_t acc_l, acc_h; 95 | q63_t acc; /* Accumulator */ 96 | int32_t lShift = (15 - (int32_t) S->postShift); /* Post shift */ 97 | q15_t *pState = S->pState; /* State pointer */ 98 | q15_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ 99 | uint32_t sample, stage = (uint32_t) S->numStages; /* Stage loop counter */ 100 | int32_t uShift = (32 - lShift); 101 | 102 | do 103 | { 104 | /* Read the b0 and 0 coefficients using SIMD */ 105 | b0 = *__SIMD32(pCoeffs)++; 106 | 107 | /* Read the b1 and b2 coefficients using SIMD */ 108 | b1 = *__SIMD32(pCoeffs)++; 109 | 110 | /* Read the a1 and a2 coefficients using SIMD */ 111 | a1 = *__SIMD32(pCoeffs)++; 112 | 113 | /* Read the input state values from the state buffer: x[n-1], x[n-2] */ 114 | state_in = *__SIMD32(pState)++; 115 | 116 | /* Read the output state values from the state buffer: y[n-1], y[n-2] */ 117 | state_out = *__SIMD32(pState)--; 118 | 119 | /* Apply loop unrolling and compute 2 output values simultaneously. */ 120 | /* The variable acc hold output values that are being computed: 121 | * 122 | * acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] 123 | * acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] 124 | */ 125 | sample = blockSize >> 1u; 126 | 127 | /* First part of the processing with loop unrolling. Compute 2 outputs at a time. 128 | ** a second loop below computes the remaining 1 sample. */ 129 | while(sample > 0u) 130 | { 131 | 132 | /* Read the input */ 133 | in = *__SIMD32(pIn)++; 134 | 135 | /* out = b0 * x[n] + 0 * 0 */ 136 | out = __SMUAD(b0, in); 137 | 138 | /* acc += b1 * x[n-1] + b2 * x[n-2] + out */ 139 | acc = __SMLALD(b1, state_in, out); 140 | /* acc += a1 * y[n-1] + a2 * y[n-2] */ 141 | acc = __SMLALD(a1, state_out, acc); 142 | 143 | /* FIX: compensate dc offset caused from bit shift operation */ 144 | acc += 1 << lShift; 145 | 146 | /* The result is converted from 3.29 to 1.31 if postShift = 1, and then saturation is applied */ 147 | /* Calc lower part of acc */ 148 | acc_l = acc & 0xffffffff; 149 | 150 | /* Calc upper part of acc */ 151 | acc_h = (acc >> 32) & 0xffffffff; 152 | 153 | /* Apply shift for lower part of acc and upper part of acc */ 154 | out = (uint32_t) acc_l >> lShift | acc_h << uShift; 155 | 156 | out = __SSAT(out, 16); 157 | 158 | /* Every time after the output is computed state should be updated. */ 159 | /* The states should be updated as: */ 160 | /* Xn2 = Xn1 */ 161 | /* Xn1 = Xn */ 162 | /* Yn2 = Yn1 */ 163 | /* Yn1 = acc */ 164 | /* x[n-N], x[n-N-1] are packed together to make state_in of type q31 */ 165 | /* y[n-N], y[n-N-1] are packed together to make state_out of type q31 */ 166 | 167 | #ifndef ARM_MATH_BIG_ENDIAN 168 | 169 | state_in = __PKHBT(in, state_in, 16); 170 | state_out = __PKHBT(out, state_out, 16); 171 | 172 | #else 173 | 174 | state_in = __PKHBT(state_in >> 16, (in >> 16), 16); 175 | state_out = __PKHBT(state_out >> 16, (out), 16); 176 | 177 | #endif /* #ifndef ARM_MATH_BIG_ENDIAN */ 178 | 179 | /* out = b0 * x[n] + 0 * 0 */ 180 | out = __SMUADX(b0, in); 181 | /* acc += b1 * x[n-1] + b2 * x[n-2] + out */ 182 | acc = __SMLALD(b1, state_in, out); 183 | /* acc += a1 * y[n-1] + a2 * y[n-2] */ 184 | acc = __SMLALD(a1, state_out, acc); 185 | 186 | /* The result is converted from 3.29 to 1.31 if postShift = 1, and then saturation is applied */ 187 | /* Calc lower part of acc */ 188 | acc_l = acc & 0xffffffff; 189 | 190 | /* Calc upper part of acc */ 191 | acc_h = (acc >> 32) & 0xffffffff; 192 | 193 | /* Apply shift for lower part of acc and upper part of acc */ 194 | out = (uint32_t) acc_l >> lShift | acc_h << uShift; 195 | 196 | out = __SSAT(out, 16); 197 | 198 | /* Store the output in the destination buffer. */ 199 | 200 | #ifndef ARM_MATH_BIG_ENDIAN 201 | 202 | *__SIMD32(pOut)++ = __PKHBT(state_out, out, 16); 203 | 204 | #else 205 | 206 | *__SIMD32(pOut)++ = __PKHBT(out, state_out >> 16, 16); 207 | 208 | #endif /* #ifndef ARM_MATH_BIG_ENDIAN */ 209 | 210 | /* Every time after the output is computed state should be updated. */ 211 | /* The states should be updated as: */ 212 | /* Xn2 = Xn1 */ 213 | /* Xn1 = Xn */ 214 | /* Yn2 = Yn1 */ 215 | /* Yn1 = acc */ 216 | /* x[n-N], x[n-N-1] are packed together to make state_in of type q31 */ 217 | /* y[n-N], y[n-N-1] are packed together to make state_out of type q31 */ 218 | #ifndef ARM_MATH_BIG_ENDIAN 219 | 220 | state_in = __PKHBT(in >> 16, state_in, 16); 221 | state_out = __PKHBT(out, state_out, 16); 222 | 223 | #else 224 | 225 | state_in = __PKHBT(state_in >> 16, in, 16); 226 | state_out = __PKHBT(state_out >> 16, out, 16); 227 | 228 | #endif /* #ifndef ARM_MATH_BIG_ENDIAN */ 229 | 230 | 231 | /* Decrement the loop counter */ 232 | sample--; 233 | 234 | } 235 | 236 | /* If the blockSize is not a multiple of 2, compute any remaining output samples here. 237 | ** No loop unrolling is used. */ 238 | 239 | if((blockSize & 0x1u) != 0u) 240 | { 241 | /* Read the input */ 242 | in = *pIn++; 243 | 244 | /* out = b0 * x[n] + 0 * 0 */ 245 | 246 | #ifndef ARM_MATH_BIG_ENDIAN 247 | 248 | out = __SMUAD(b0, in); 249 | 250 | #else 251 | 252 | out = __SMUADX(b0, in); 253 | 254 | #endif /* #ifndef ARM_MATH_BIG_ENDIAN */ 255 | 256 | /* acc = b1 * x[n-1] + b2 * x[n-2] + out */ 257 | acc = __SMLALD(b1, state_in, out); 258 | /* acc += a1 * y[n-1] + a2 * y[n-2] */ 259 | acc = __SMLALD(a1, state_out, acc); 260 | 261 | /* The result is converted from 3.29 to 1.31 if postShift = 1, and then saturation is applied */ 262 | /* Calc lower part of acc */ 263 | acc_l = acc & 0xffffffff; 264 | 265 | /* Calc upper part of acc */ 266 | acc_h = (acc >> 32) & 0xffffffff; 267 | 268 | /* Apply shift for lower part of acc and upper part of acc */ 269 | out = (uint32_t) acc_l >> lShift | acc_h << uShift; 270 | 271 | out = __SSAT(out, 16); 272 | 273 | /* Store the output in the destination buffer. */ 274 | *pOut++ = (q15_t) out; 275 | 276 | /* Every time after the output is computed state should be updated. */ 277 | /* The states should be updated as: */ 278 | /* Xn2 = Xn1 */ 279 | /* Xn1 = Xn */ 280 | /* Yn2 = Yn1 */ 281 | /* Yn1 = acc */ 282 | /* x[n-N], x[n-N-1] are packed together to make state_in of type q31 */ 283 | /* y[n-N], y[n-N-1] are packed together to make state_out of type q31 */ 284 | 285 | #ifndef ARM_MATH_BIG_ENDIAN 286 | 287 | state_in = __PKHBT(in, state_in, 16); 288 | state_out = __PKHBT(out, state_out, 16); 289 | 290 | #else 291 | 292 | state_in = __PKHBT(state_in >> 16, in, 16); 293 | state_out = __PKHBT(state_out >> 16, out, 16); 294 | 295 | #endif /* #ifndef ARM_MATH_BIG_ENDIAN */ 296 | 297 | } 298 | 299 | /* The first stage goes from the input wire to the output wire. */ 300 | /* Subsequent numStages occur in-place in the output wire */ 301 | pIn = pDst; 302 | 303 | /* Reset the output pointer */ 304 | pOut = pDst; 305 | 306 | /* Store the updated state variables back into the state array */ 307 | *__SIMD32(pState)++ = state_in; 308 | *__SIMD32(pState)++ = state_out; 309 | 310 | 311 | /* Decrement the loop counter */ 312 | stage--; 313 | 314 | } while(stage > 0u); 315 | 316 | #else 317 | 318 | /* Run the below code for Cortex-M0 */ 319 | 320 | q15_t *pIn = pSrc; /* Source pointer */ 321 | q15_t *pOut = pDst; /* Destination pointer */ 322 | q15_t b0, b1, b2, a1, a2; /* Filter coefficients */ 323 | q15_t Xn1, Xn2, Yn1, Yn2; /* Filter state variables */ 324 | q15_t Xn; /* temporary input */ 325 | q63_t acc; /* Accumulator */ 326 | int32_t shift = (15 - (int32_t) S->postShift); /* Post shift */ 327 | q15_t *pState = S->pState; /* State pointer */ 328 | q15_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */ 329 | uint32_t sample, stage = (uint32_t) S->numStages; /* Stage loop counter */ 330 | 331 | do 332 | { 333 | /* Reading the coefficients */ 334 | b0 = *pCoeffs++; 335 | pCoeffs++; // skip the 0 coefficient 336 | b1 = *pCoeffs++; 337 | b2 = *pCoeffs++; 338 | a1 = *pCoeffs++; 339 | a2 = *pCoeffs++; 340 | 341 | /* Reading the state values */ 342 | Xn1 = pState[0]; 343 | Xn2 = pState[1]; 344 | Yn1 = pState[2]; 345 | Yn2 = pState[3]; 346 | 347 | /* The variables acc holds the output value that is computed: 348 | * acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] 349 | */ 350 | 351 | sample = blockSize; 352 | 353 | while(sample > 0u) 354 | { 355 | /* Read the input */ 356 | Xn = *pIn++; 357 | 358 | /* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */ 359 | /* acc = b0 * x[n] */ 360 | acc = (q31_t) b0 *Xn; 361 | 362 | /* acc += b1 * x[n-1] */ 363 | acc += (q31_t) b1 *Xn1; 364 | /* acc += b[2] * x[n-2] */ 365 | acc += (q31_t) b2 *Xn2; 366 | /* acc += a1 * y[n-1] */ 367 | acc += (q31_t) a1 *Yn1; 368 | /* acc += a2 * y[n-2] */ 369 | acc += (q31_t) a2 *Yn2; 370 | 371 | /* The result is converted to 1.31 */ 372 | acc = __SSAT((acc >> shift), 16); 373 | 374 | /* Every time after the output is computed state should be updated. */ 375 | /* The states should be updated as: */ 376 | /* Xn2 = Xn1 */ 377 | /* Xn1 = Xn */ 378 | /* Yn2 = Yn1 */ 379 | /* Yn1 = acc */ 380 | Xn2 = Xn1; 381 | Xn1 = Xn; 382 | Yn2 = Yn1; 383 | Yn1 = (q15_t) acc; 384 | 385 | /* Store the output in the destination buffer. */ 386 | *pOut++ = (q15_t) acc; 387 | 388 | /* decrement the loop counter */ 389 | sample--; 390 | } 391 | 392 | /* The first stage goes from the input buffer to the output buffer. */ 393 | /* Subsequent stages occur in-place in the output buffer */ 394 | pIn = pDst; 395 | 396 | /* Reset to destination pointer */ 397 | pOut = pDst; 398 | 399 | /* Store the updated state variables back into the pState array */ 400 | *pState++ = Xn1; 401 | *pState++ = Xn2; 402 | *pState++ = Yn1; 403 | *pState++ = Yn2; 404 | 405 | } while(--stage); 406 | 407 | #endif /* #ifndef ARM_MATH_CM0_FAMILY */ 408 | 409 | } 410 | 411 | 412 | /** 413 | * @} end of BiquadCascadeDF1 group 414 | */ 415 | -------------------------------------------------------------------------------- /CMSIS/DSP_Lib/Source/TransformFunctions/arm_bitreversal.c: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------- 2 | * Copyright (C) 2010-2014 ARM Limited. All rights reserved. 3 | * 4 | * $Date: 19. March 2015 5 | * $Revision: V.1.4.5 6 | * 7 | * Project: CMSIS DSP Library 8 | * Title: arm_bitreversal.c 9 | * 10 | * Description: This file has common tables like Bitreverse, reciprocal etc which are used across different functions 11 | * 12 | * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 13 | * 14 | * Redistribution and use in source and binary forms, with or without 15 | * modification, are permitted provided that the following conditions 16 | * are met: 17 | * - Redistributions of source code must retain the above copyright 18 | * notice, this list of conditions and the following disclaimer. 19 | * - Redistributions in binary form must reproduce the above copyright 20 | * notice, this list of conditions and the following disclaimer in 21 | * the documentation and/or other materials provided with the 22 | * distribution. 23 | * - Neither the name of ARM LIMITED nor the names of its contributors 24 | * may be used to endorse or promote products derived from this 25 | * software without specific prior written permission. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 30 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 31 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 32 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 33 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 34 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 37 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 | * POSSIBILITY OF SUCH DAMAGE. 39 | * -------------------------------------------------------------------- */ 40 | 41 | #include "arm_math.h" 42 | #include "arm_common_tables.h" 43 | 44 | /* 45 | * @brief In-place bit reversal function. 46 | * @param[in, out] *pSrc points to the in-place buffer of floating-point data type. 47 | * @param[in] fftSize length of the FFT. 48 | * @param[in] bitRevFactor bit reversal modifier that supports different size FFTs with the same bit reversal table. 49 | * @param[in] *pBitRevTab points to the bit reversal table. 50 | * @return none. 51 | */ 52 | 53 | void arm_bitreversal_f32( 54 | float32_t * pSrc, 55 | uint16_t fftSize, 56 | uint16_t bitRevFactor, 57 | uint16_t * pBitRevTab) 58 | { 59 | uint16_t fftLenBy2, fftLenBy2p1; 60 | uint16_t i, j; 61 | float32_t in; 62 | 63 | /* Initializations */ 64 | j = 0u; 65 | fftLenBy2 = fftSize >> 1u; 66 | fftLenBy2p1 = (fftSize >> 1u) + 1u; 67 | 68 | /* Bit Reversal Implementation */ 69 | for (i = 0u; i <= (fftLenBy2 - 2u); i += 2u) 70 | { 71 | if(i < j) 72 | { 73 | /* pSrc[i] <-> pSrc[j]; */ 74 | in = pSrc[2u * i]; 75 | pSrc[2u * i] = pSrc[2u * j]; 76 | pSrc[2u * j] = in; 77 | 78 | /* pSrc[i+1u] <-> pSrc[j+1u] */ 79 | in = pSrc[(2u * i) + 1u]; 80 | pSrc[(2u * i) + 1u] = pSrc[(2u * j) + 1u]; 81 | pSrc[(2u * j) + 1u] = in; 82 | 83 | /* pSrc[i+fftLenBy2p1] <-> pSrc[j+fftLenBy2p1] */ 84 | in = pSrc[2u * (i + fftLenBy2p1)]; 85 | pSrc[2u * (i + fftLenBy2p1)] = pSrc[2u * (j + fftLenBy2p1)]; 86 | pSrc[2u * (j + fftLenBy2p1)] = in; 87 | 88 | /* pSrc[i+fftLenBy2p1+1u] <-> pSrc[j+fftLenBy2p1+1u] */ 89 | in = pSrc[(2u * (i + fftLenBy2p1)) + 1u]; 90 | pSrc[(2u * (i + fftLenBy2p1)) + 1u] = 91 | pSrc[(2u * (j + fftLenBy2p1)) + 1u]; 92 | pSrc[(2u * (j + fftLenBy2p1)) + 1u] = in; 93 | 94 | } 95 | 96 | /* pSrc[i+1u] <-> pSrc[j+1u] */ 97 | in = pSrc[2u * (i + 1u)]; 98 | pSrc[2u * (i + 1u)] = pSrc[2u * (j + fftLenBy2)]; 99 | pSrc[2u * (j + fftLenBy2)] = in; 100 | 101 | /* pSrc[i+2u] <-> pSrc[j+2u] */ 102 | in = pSrc[(2u * (i + 1u)) + 1u]; 103 | pSrc[(2u * (i + 1u)) + 1u] = pSrc[(2u * (j + fftLenBy2)) + 1u]; 104 | pSrc[(2u * (j + fftLenBy2)) + 1u] = in; 105 | 106 | /* Reading the index for the bit reversal */ 107 | j = *pBitRevTab; 108 | 109 | /* Updating the bit reversal index depending on the fft length */ 110 | pBitRevTab += bitRevFactor; 111 | } 112 | } 113 | 114 | 115 | 116 | /* 117 | * @brief In-place bit reversal function. 118 | * @param[in, out] *pSrc points to the in-place buffer of Q31 data type. 119 | * @param[in] fftLen length of the FFT. 120 | * @param[in] bitRevFactor bit reversal modifier that supports different size FFTs with the same bit reversal table 121 | * @param[in] *pBitRevTab points to bit reversal table. 122 | * @return none. 123 | */ 124 | 125 | void arm_bitreversal_q31( 126 | q31_t * pSrc, 127 | uint32_t fftLen, 128 | uint16_t bitRevFactor, 129 | uint16_t * pBitRevTable) 130 | { 131 | uint32_t fftLenBy2, fftLenBy2p1, i, j; 132 | q31_t in; 133 | 134 | /* Initializations */ 135 | j = 0u; 136 | fftLenBy2 = fftLen / 2u; 137 | fftLenBy2p1 = (fftLen / 2u) + 1u; 138 | 139 | /* Bit Reversal Implementation */ 140 | for (i = 0u; i <= (fftLenBy2 - 2u); i += 2u) 141 | { 142 | if(i < j) 143 | { 144 | /* pSrc[i] <-> pSrc[j]; */ 145 | in = pSrc[2u * i]; 146 | pSrc[2u * i] = pSrc[2u * j]; 147 | pSrc[2u * j] = in; 148 | 149 | /* pSrc[i+1u] <-> pSrc[j+1u] */ 150 | in = pSrc[(2u * i) + 1u]; 151 | pSrc[(2u * i) + 1u] = pSrc[(2u * j) + 1u]; 152 | pSrc[(2u * j) + 1u] = in; 153 | 154 | /* pSrc[i+fftLenBy2p1] <-> pSrc[j+fftLenBy2p1] */ 155 | in = pSrc[2u * (i + fftLenBy2p1)]; 156 | pSrc[2u * (i + fftLenBy2p1)] = pSrc[2u * (j + fftLenBy2p1)]; 157 | pSrc[2u * (j + fftLenBy2p1)] = in; 158 | 159 | /* pSrc[i+fftLenBy2p1+1u] <-> pSrc[j+fftLenBy2p1+1u] */ 160 | in = pSrc[(2u * (i + fftLenBy2p1)) + 1u]; 161 | pSrc[(2u * (i + fftLenBy2p1)) + 1u] = 162 | pSrc[(2u * (j + fftLenBy2p1)) + 1u]; 163 | pSrc[(2u * (j + fftLenBy2p1)) + 1u] = in; 164 | 165 | } 166 | 167 | /* pSrc[i+1u] <-> pSrc[j+1u] */ 168 | in = pSrc[2u * (i + 1u)]; 169 | pSrc[2u * (i + 1u)] = pSrc[2u * (j + fftLenBy2)]; 170 | pSrc[2u * (j + fftLenBy2)] = in; 171 | 172 | /* pSrc[i+2u] <-> pSrc[j+2u] */ 173 | in = pSrc[(2u * (i + 1u)) + 1u]; 174 | pSrc[(2u * (i + 1u)) + 1u] = pSrc[(2u * (j + fftLenBy2)) + 1u]; 175 | pSrc[(2u * (j + fftLenBy2)) + 1u] = in; 176 | 177 | /* Reading the index for the bit reversal */ 178 | j = *pBitRevTable; 179 | 180 | /* Updating the bit reversal index depending on the fft length */ 181 | pBitRevTable += bitRevFactor; 182 | } 183 | } 184 | 185 | 186 | 187 | /* 188 | * @brief In-place bit reversal function. 189 | * @param[in, out] *pSrc points to the in-place buffer of Q15 data type. 190 | * @param[in] fftLen length of the FFT. 191 | * @param[in] bitRevFactor bit reversal modifier that supports different size FFTs with the same bit reversal table 192 | * @param[in] *pBitRevTab points to bit reversal table. 193 | * @return none. 194 | */ 195 | 196 | void arm_bitreversal_q15( 197 | q15_t * pSrc16, 198 | uint32_t fftLen, 199 | uint16_t bitRevFactor, 200 | uint16_t * pBitRevTab) 201 | { 202 | q31_t *pSrc = (q31_t *) pSrc16; 203 | q31_t in; 204 | uint32_t fftLenBy2, fftLenBy2p1; 205 | uint32_t i, j; 206 | 207 | /* Initializations */ 208 | j = 0u; 209 | fftLenBy2 = fftLen / 2u; 210 | fftLenBy2p1 = (fftLen / 2u) + 1u; 211 | 212 | /* Bit Reversal Implementation */ 213 | for (i = 0u; i <= (fftLenBy2 - 2u); i += 2u) 214 | { 215 | if(i < j) 216 | { 217 | /* pSrc[i] <-> pSrc[j]; */ 218 | /* pSrc[i+1u] <-> pSrc[j+1u] */ 219 | in = pSrc[i]; 220 | pSrc[i] = pSrc[j]; 221 | pSrc[j] = in; 222 | 223 | /* pSrc[i + fftLenBy2p1] <-> pSrc[j + fftLenBy2p1]; */ 224 | /* pSrc[i + fftLenBy2p1+1u] <-> pSrc[j + fftLenBy2p1+1u] */ 225 | in = pSrc[i + fftLenBy2p1]; 226 | pSrc[i + fftLenBy2p1] = pSrc[j + fftLenBy2p1]; 227 | pSrc[j + fftLenBy2p1] = in; 228 | } 229 | 230 | /* pSrc[i+1u] <-> pSrc[j+fftLenBy2]; */ 231 | /* pSrc[i+2] <-> pSrc[j+fftLenBy2+1u] */ 232 | in = pSrc[i + 1u]; 233 | pSrc[i + 1u] = pSrc[j + fftLenBy2]; 234 | pSrc[j + fftLenBy2] = in; 235 | 236 | /* Reading the index for the bit reversal */ 237 | j = *pBitRevTab; 238 | 239 | /* Updating the bit reversal index depending on the fft length */ 240 | pBitRevTab += bitRevFactor; 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /CMSIS/DSP_Lib/Source/TransformFunctions/arm_cfft_radix4_init_q31.c: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------- 2 | * Copyright (C) 2010-2014 ARM Limited. All rights reserved. 3 | * 4 | * $Date: 19. March 2015 5 | * $Revision: V.1.4.5 6 | * 7 | * Project: CMSIS DSP Library 8 | * Title: arm_cfft_radix4_init_q31.c 9 | * 10 | * Description: Radix-4 Decimation in Frequency Q31 FFT & IFFT initialization function 11 | * 12 | * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 13 | * 14 | * Redistribution and use in source and binary forms, with or without 15 | * modification, are permitted provided that the following conditions 16 | * are met: 17 | * - Redistributions of source code must retain the above copyright 18 | * notice, this list of conditions and the following disclaimer. 19 | * - Redistributions in binary form must reproduce the above copyright 20 | * notice, this list of conditions and the following disclaimer in 21 | * the documentation and/or other materials provided with the 22 | * distribution. 23 | * - Neither the name of ARM LIMITED nor the names of its contributors 24 | * may be used to endorse or promote products derived from this 25 | * software without specific prior written permission. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 30 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 31 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 32 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 33 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 34 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 37 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 | * POSSIBILITY OF SUCH DAMAGE. 39 | * -------------------------------------------------------------------- */ 40 | 41 | #include "arm_math.h" 42 | #include "arm_common_tables.h" 43 | 44 | /** 45 | * @ingroup groupTransforms 46 | */ 47 | 48 | /** 49 | * @addtogroup ComplexFFT 50 | * @{ 51 | */ 52 | 53 | /** 54 | * 55 | * @brief Initialization function for the Q31 CFFT/CIFFT. 56 | * @deprecated Do not use this function. It has been superseded by \ref arm_cfft_q31 and will be removed 57 | * @param[in,out] *S points to an instance of the Q31 CFFT/CIFFT structure. 58 | * @param[in] fftLen length of the FFT. 59 | * @param[in] ifftFlag flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. 60 | * @param[in] bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. 61 | * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if fftLen is not a supported value. 62 | * 63 | * \par Description: 64 | * \par 65 | * The parameter ifftFlag controls whether a forward or inverse transform is computed. 66 | * Set(=1) ifftFlag for calculation of CIFFT otherwise CFFT is calculated 67 | * \par 68 | * The parameter bitReverseFlag controls whether output is in normal order or bit reversed order. 69 | * Set(=1) bitReverseFlag for output to be in normal order otherwise output is in bit reversed order. 70 | * \par 71 | * The parameter fftLen Specifies length of CFFT/CIFFT process. Supported FFT Lengths are 16, 64, 256, 1024. 72 | * \par 73 | * This Function also initializes Twiddle factor table pointer and Bit reversal table pointer. 74 | */ 75 | 76 | arm_status arm_cfft_radix4_init_q31( 77 | arm_cfft_radix4_instance_q31 * S, 78 | uint16_t fftLen, 79 | uint8_t ifftFlag, 80 | uint8_t bitReverseFlag) 81 | { 82 | /* Initialise the default arm status */ 83 | arm_status status = ARM_MATH_SUCCESS; 84 | /* Initialise the FFT length */ 85 | S->fftLen = fftLen; 86 | /* Initialise the Twiddle coefficient pointer */ 87 | S->pTwiddle = (q31_t *) twiddleCoef_4096_q31; 88 | /* Initialise the Flag for selection of CFFT or CIFFT */ 89 | S->ifftFlag = ifftFlag; 90 | /* Initialise the Flag for calculation Bit reversal or not */ 91 | S->bitReverseFlag = bitReverseFlag; 92 | 93 | /* Initializations of Instance structure depending on the FFT length */ 94 | switch (S->fftLen) 95 | { 96 | /* Initializations of structure parameters for 4096 point FFT */ 97 | case 4096u: 98 | /* Initialise the twiddle coef modifier value */ 99 | S->twidCoefModifier = 1u; 100 | /* Initialise the bit reversal table modifier */ 101 | S->bitRevFactor = 1u; 102 | /* Initialise the bit reversal table pointer */ 103 | S->pBitRevTable = (uint16_t *) armBitRevTable; 104 | break; 105 | 106 | /* Initializations of structure parameters for 1024 point FFT */ 107 | case 1024u: 108 | /* Initialise the twiddle coef modifier value */ 109 | S->twidCoefModifier = 4u; 110 | /* Initialise the bit reversal table modifier */ 111 | S->bitRevFactor = 4u; 112 | /* Initialise the bit reversal table pointer */ 113 | S->pBitRevTable = (uint16_t *) & armBitRevTable[3]; 114 | break; 115 | 116 | case 256u: 117 | /* Initializations of structure parameters for 256 point FFT */ 118 | S->twidCoefModifier = 16u; 119 | S->bitRevFactor = 16u; 120 | S->pBitRevTable = (uint16_t *) & armBitRevTable[15]; 121 | break; 122 | 123 | case 64u: 124 | /* Initializations of structure parameters for 64 point FFT */ 125 | S->twidCoefModifier = 64u; 126 | S->bitRevFactor = 64u; 127 | S->pBitRevTable = (uint16_t *) & armBitRevTable[63]; 128 | break; 129 | 130 | case 16u: 131 | /* Initializations of structure parameters for 16 point FFT */ 132 | S->twidCoefModifier = 256u; 133 | S->bitRevFactor = 256u; 134 | S->pBitRevTable = (uint16_t *) & armBitRevTable[255]; 135 | break; 136 | 137 | default: 138 | /* Reporting argument error if fftSize is not valid value */ 139 | status = ARM_MATH_ARGUMENT_ERROR; 140 | break; 141 | } 142 | 143 | return (status); 144 | } 145 | 146 | /** 147 | * @} end of ComplexFFT group 148 | */ 149 | -------------------------------------------------------------------------------- /CMSIS/DSP_Lib/license.txt: -------------------------------------------------------------------------------- 1 | All files contained in the folders "CMSIS\DSP-Lib\Source" and "CMSIS\DSP-Lib\Examples" 2 | are guided by the following license: 3 | 4 | Copyright (C) 2009-2015 ARM Limited. 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | - Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | - Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | - Neither the name of ARM nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE 22 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Build global options 3 | # NOTE: Can be overridden externally. 4 | # 5 | 6 | # Compiler options here. 7 | ifeq ($(USE_OPT),) 8 | USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16 9 | endif 10 | 11 | # C specific options here (added to USE_OPT). 12 | ifeq ($(USE_COPT),) 13 | USE_COPT = 14 | endif 15 | 16 | # C++ specific options here (added to USE_OPT). 17 | ifeq ($(USE_CPPOPT),) 18 | USE_CPPOPT = -fno-rtti 19 | endif 20 | 21 | # Enable this if you want the linker to remove unused code and data 22 | ifeq ($(USE_LINK_GC),) 23 | USE_LINK_GC = yes 24 | endif 25 | 26 | # Linker extra options here. 27 | ifeq ($(USE_LDOPT),) 28 | USE_LDOPT = 29 | endif 30 | 31 | # Enable this if you want link time optimizations (LTO) 32 | ifeq ($(USE_LTO),) 33 | USE_LTO = no 34 | endif 35 | 36 | # If enabled, this option allows to compile the application in THUMB mode. 37 | ifeq ($(USE_THUMB),) 38 | USE_THUMB = yes 39 | endif 40 | 41 | # Enable this if you want to see the full log while compiling. 42 | ifeq ($(USE_VERBOSE_COMPILE),) 43 | USE_VERBOSE_COMPILE = no 44 | endif 45 | 46 | # If enabled, this option makes the build process faster by not compiling 47 | # modules not used in the current configuration. 48 | ifeq ($(USE_SMART_BUILD),) 49 | USE_SMART_BUILD = yes 50 | endif 51 | 52 | # 53 | # Build global options 54 | ############################################################################## 55 | 56 | ############################################################################## 57 | # Architecture or project specific options 58 | # 59 | 60 | # Enables the use of FPU on Cortex-M4 (no, softfp, hard). 61 | ifeq ($(USE_FPU),) 62 | USE_FPU = hard 63 | endif 64 | 65 | # Stack size to be allocated to the Cortex-M process stack. This stack is 66 | # the stack used by the main() thread. 67 | ifeq ($(USE_PROCESS_STACKSIZE),) 68 | USE_PROCESS_STACKSIZE = 0x400 69 | endif 70 | 71 | # Stack size to the allocated to the Cortex-M main/exceptions stack. This 72 | # stack is used for processing interrupts and exceptions. 73 | ifeq ($(USE_EXCEPTIONS_STACKSIZE),) 74 | USE_EXCEPTIONS_STACKSIZE = 0x400 75 | endif 76 | 77 | # 78 | # Architecture or project specific options 79 | ############################################################################## 80 | 81 | ############################################################################## 82 | # Project, sources and paths 83 | # 84 | 85 | # Define project name here 86 | PROJECT = ch 87 | 88 | # Imported source files and paths 89 | CHIBIOS = ChibiOS 90 | PROJ = . 91 | # Startup files. 92 | include $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f3xx.mk 93 | # HAL-OSAL files (optional). 94 | include $(CHIBIOS)/os/hal/hal.mk 95 | include $(CHIBIOS)/os/hal/ports/STM32/STM32F3xx/platform.mk 96 | #include $(CHIBIOS)/os/hal/boards/NANOSDR_STM32_F303/board.mk 97 | include NANOSDR_STM32_F303/board.mk 98 | include $(CHIBIOS)/os/hal/osal/rt/osal.mk 99 | # RTOS files (optional). 100 | include $(CHIBIOS)/os/rt/rt.mk 101 | include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk 102 | # Other files (optional). 103 | #include $(CHIBIOS)/test/rt/test.mk 104 | include $(CHIBIOS)/os/hal/lib/streams/streams.mk 105 | include $(CHIBIOS)/os/various/shell/shell.mk 106 | 107 | # Define linker script file here 108 | #LDSCRIPT= $(STARTUPLD)/STM32F303xC.ld 109 | LDSCRIPT= STM32F303xB.ld 110 | 111 | CMSIS = CMSIS 112 | DSPLIBINC = ${CMSIS}/Include 113 | DSPLIBSRC = ${CMSIS}/DSP_Lib/Source/FilteringFunctions/arm_biquad_cascade_df1_q15.c \ 114 | ${CMSIS}/DSP_Lib/Source/TransformFunctions/arm_cfft_radix4_init_q31.c \ 115 | ${CMSIS}/DSP_Lib/Source/TransformFunctions/arm_cfft_radix4_q31.c \ 116 | ${CMSIS}/DSP_Lib/Source/TransformFunctions/arm_bitreversal.c \ 117 | ${CMSIS}/DSP_Lib/Source/CommonTables/arm_common_tables.c 118 | 119 | # C sources that can be compiled in ARM or THUMB mode depending on the global 120 | # setting. 121 | CSRC = $(STARTUPSRC) \ 122 | $(KERNSRC) \ 123 | $(PORTSRC) \ 124 | $(OSALSRC) \ 125 | $(HALSRC) \ 126 | $(PLATFORMSRC) \ 127 | $(BOARDSRC) \ 128 | $(STREAMSSRC) \ 129 | $(SHELLSRC) \ 130 | $(DSPLIBSRC) \ 131 | usbcfg.c \ 132 | si5351.c si5351_low.c tlv320aic3204.c ui.c \ 133 | display.c ili9341.c numfont20x24.c numfont32x24.c Font5x7.c icons.c \ 134 | dsp.c main.c flash.c crt2.c 135 | 136 | # C++ sources that can be compiled in ARM or THUMB mode depending on the global 137 | # setting. 138 | CPPSRC = 139 | 140 | # C sources to be compiled in ARM mode regardless of the global setting. 141 | # NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler 142 | # option that results in lower performance and larger code size. 143 | ACSRC = 144 | 145 | # C++ sources to be compiled in ARM mode regardless of the global setting. 146 | # NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler 147 | # option that results in lower performance and larger code size. 148 | ACPPSRC = 149 | 150 | # C sources to be compiled in THUMB mode regardless of the global setting. 151 | # NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler 152 | # option that results in lower performance and larger code size. 153 | TCSRC = 154 | 155 | # C sources to be compiled in THUMB mode regardless of the global setting. 156 | # NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler 157 | # option that results in lower performance and larger code size. 158 | TCPPSRC = 159 | 160 | # List ASM source files here 161 | ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM) 162 | 163 | INCDIR = $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \ 164 | $(HALINC) $(PLATFORMINC) $(BOARDINC) \ 165 | $(DSPLIBINC) \ 166 | $(STREAMSINC) $(SHELLINC) 167 | 168 | # 169 | # Project, sources and paths 170 | ############################################################################## 171 | 172 | ############################################################################## 173 | # Compiler settings 174 | # 175 | 176 | MCU = cortex-m4 177 | 178 | #TRGT = arm-elf- 179 | TRGT = arm-none-eabi- 180 | CC = $(TRGT)gcc 181 | CPPC = $(TRGT)g++ 182 | # Enable loading with g++ only if you need C++ runtime support. 183 | # NOTE: You can use C++ even without C++ support if you are careful. C++ 184 | # runtime support makes code size explode. 185 | LD = $(TRGT)gcc 186 | #LD = $(TRGT)g++ 187 | CP = $(TRGT)objcopy 188 | AS = $(TRGT)gcc -x assembler-with-cpp 189 | AR = $(TRGT)ar 190 | OD = $(TRGT)objdump 191 | SZ = $(TRGT)size 192 | HEX = $(CP) -O ihex 193 | BIN = $(CP) -O binary 194 | 195 | # ARM-specific options here 196 | AOPT = 197 | 198 | # THUMB-specific options here 199 | TOPT = -mthumb -DTHUMB 200 | 201 | # Define C warning options here 202 | CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes 203 | 204 | # Define C++ warning options here 205 | CPPWARN = -Wall -Wextra -Wundef 206 | 207 | # 208 | # Compiler settings 209 | ############################################################################## 210 | 211 | ############################################################################## 212 | # Start of user section 213 | # 214 | 215 | # List all user C define here, like -D_DEBUG=1 216 | UDEFS = -DSHELL_CMD_TEST_ENABLED=0 -DARM_MATH_CM4 -D__FPU_PRESENT -D__FPU_USED 217 | 218 | # Define ASM defines here 219 | UADEFS = 220 | 221 | # List all user directories here 222 | UINCDIR = 223 | 224 | # List the user directory to look for the libraries here 225 | ULIBDIR = 226 | 227 | # List all user libraries here 228 | ULIBS = -lm 229 | 230 | # 231 | # End of user defines 232 | ############################################################################## 233 | 234 | RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC 235 | include $(RULESPATH)/rules.mk 236 | 237 | OS_SRCS=$(shell find ChibiOS/os/hal/ports/STM32/STM32F3xx ChibiOS/os -name \*.\[ch\] -print) 238 | 239 | TAGS: Makefile 240 | @etags *.[ch] NANOSDR_STM32_F303/*.[ch] $(OS_SRCS) 241 | @ls -l TAGS 242 | 243 | .PHONY: flash 244 | 245 | flash: all 246 | arm-none-eabi-gdb -x flash-stutil.gdb --silent 247 | @#arm-none-eabi-gdb -x flash-openocd.gdb --silent 248 | 249 | RELEASE=$(shell date +%Y%m%d) 250 | DIST_FILES= build/ch.bin build/ch.hex build/ch.elf 251 | 252 | release: all 253 | zip centsdr-${RELEASE}.zip ${DIST_FILES} 254 | -------------------------------------------------------------------------------- /NANOSDR_STM32_F303/board.c: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include "hal.h" 18 | 19 | #if HAL_USE_PAL || defined(__DOXYGEN__) 20 | /** 21 | * @brief PAL setup. 22 | * @details Digital I/O ports static configuration as defined in @p board.h. 23 | * This variable is used by the HAL when initializing the PAL driver. 24 | */ 25 | const PALConfig pal_default_config = { 26 | #if STM32_HAS_GPIOA 27 | {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, 28 | VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, 29 | #endif 30 | #if STM32_HAS_GPIOB 31 | {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, 32 | VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, 33 | #endif 34 | #if STM32_HAS_GPIOC 35 | {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, 36 | VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, 37 | #endif 38 | #if STM32_HAS_GPIOD 39 | {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, 40 | VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, 41 | #endif 42 | #if STM32_HAS_GPIOE 43 | {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, 44 | VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, 45 | #endif 46 | #if STM32_HAS_GPIOF 47 | {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, 48 | VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, 49 | #endif 50 | #if STM32_HAS_GPIOG 51 | {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, 52 | VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, 53 | #endif 54 | #if STM32_HAS_GPIOH 55 | {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, 56 | VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, 57 | #endif 58 | #if STM32_HAS_GPIOI 59 | {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, 60 | VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH} 61 | #endif 62 | }; 63 | #endif 64 | 65 | extern void si5351_setup(void); 66 | 67 | /* 68 | * Early initialization code. 69 | * This initialization must be performed just after stack setup and before 70 | * any other initialization. 71 | */ 72 | void __early_init(void) { 73 | si5351_setup(); 74 | stm32_clock_init(); 75 | } 76 | 77 | /* 78 | * Board-specific initialization code. 79 | */ 80 | void boardInit(void) { 81 | } 82 | -------------------------------------------------------------------------------- /NANOSDR_STM32_F303/board.mk: -------------------------------------------------------------------------------- 1 | # List of all the board related files. 2 | #BOARDSRC = ${CHIBIOS}/os/hal/boards/NANOSDR_STM32_F303/board.c 3 | BOARDSRC = ${PROJ}/NANOSDR_STM32_F303/board.c 4 | 5 | # Required include directories 6 | #BOARDINC = ${CHIBIOS}/os/hal/boards/NANOSDR_STM32_F303 7 | BOARDINC = ${PROJ}/NANOSDR_STM32_F303 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CentSDR - Tiny Standalone Software Defined Receiver 2 | ========================================================== 3 | 4 |
5 | 6 |
7 | 8 | # About 9 | 10 | CentSDR is tiny handheld standalone software defined receiver with LCD display, 11 | that is simple, low budget, but has reasonable perfomance. 12 | This project is aimed at contributing to studies, experiments and educations around 13 | RF technology. 14 | 15 | # Block Diagram 16 | 17 |
18 | 19 |
20 | 21 | # Build Firmware 22 | 23 | ## Prepare ARM Cross Tools 24 | 25 | Install cross tools and firmware updating tool. 26 | 27 | $ brew cask install gcc-arm-embedded 28 | 29 | ## Fetch Source 30 | 31 | Clone source code from github. 32 | 33 | $ git clone https://github.com/ttrftech/CentSDR centsdr 34 | 35 | Then fetch ChibiOS submodule into tree. 36 | 37 | $ cd centsdr 38 | $ git submodule update --init --recursive 39 | 40 | Just make in the top directory. 41 | 42 | $ make 43 | 44 | ## Flash firmware 45 | 46 | ### Using OpenOCD and gdb 47 | 48 | Prepare openocd. 49 | 50 | $ brew install openocd 51 | 52 | Connect ST-Link2 to target board, then launch openocd as follows. 53 | 54 | $ openocd -f board/stm32f3discovery.cfg 55 | 56 | Flash firmware using gdb. 57 | 58 | $ arm-none-eabi-gdb 59 | > target extended-remote :4242 60 | > exec build/ch.elf 61 | > load 62 | > quit 63 | 64 | Or use gdb script to flash. 65 | 66 | $ arm-none-eabi-gdb -x flash-openocd.gdb --silent 67 | 68 | ### Using st-util and gdb 69 | 70 | Prepare stlink utilities. 71 | 72 | $ brew install stlink 73 | 74 | Connect target board via SWD with ST-Link2, In other terminal, launch st-util 75 | 76 | $ st-util 77 | 78 | Then, flash the firmware. 79 | 80 | $ arm-none-eabi-gdb -x flash-stutil.gdb --silent 81 | 82 | ## Flash firmware using Nucleo st-link v2.1 83 | 84 | Or you can flash the firmware using Nucleo. First, mount as usb mass storage device, then copy 'build/ch.bin' file into mounted volume. 85 | 86 | ## Attention 87 | 88 | This repository contains only source of CentSDR firmware, but NO hardware design resources. 89 | 90 | ## Reference 91 | 92 | * Kit available from http://ttrftech.tumblr.com/kit/centsdr 93 | * Credit: @edy555 94 | 95 | [EOF] 96 | -------------------------------------------------------------------------------- /STM32F303xB.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | * STM32F303xB memory setup. 19 | */ 20 | MEMORY 21 | { 22 | flash0 : org = 0x08000000, len = 128k 23 | flash1 : org = 0x00000000, len = 0 24 | flash2 : org = 0x00000000, len = 0 25 | flash3 : org = 0x00000000, len = 0 26 | flash4 : org = 0x00000000, len = 0 27 | flash5 : org = 0x00000000, len = 0 28 | flash6 : org = 0x00000000, len = 0 29 | flash7 : org = 0x00000000, len = 0 30 | ram0 : org = 0x20000000, len = 40k 31 | ram1 : org = 0x00000000, len = 0 32 | ram2 : org = 0x00000000, len = 0 33 | ram3 : org = 0x00000000, len = 0 34 | ram4 : org = 0x10000000, len = 8k 35 | ram5 : org = 0x00000000, len = 0 36 | ram6 : org = 0x00000000, len = 0 37 | ram7 : org = 0x00000000, len = 0 38 | } 39 | 40 | /* For each data/text section two region are defined, a virtual region 41 | and a load region (_LMA suffix).*/ 42 | 43 | /* Flash region to be used for exception vectors.*/ 44 | REGION_ALIAS("VECTORS_FLASH", flash0); 45 | REGION_ALIAS("VECTORS_FLASH_LMA", flash0); 46 | 47 | /* Flash region to be used for constructors and destructors.*/ 48 | REGION_ALIAS("XTORS_FLASH", flash0); 49 | REGION_ALIAS("XTORS_FLASH_LMA", flash0); 50 | 51 | /* Flash region to be used for code text.*/ 52 | REGION_ALIAS("TEXT_FLASH", flash0); 53 | REGION_ALIAS("TEXT_FLASH_LMA", flash0); 54 | 55 | /* Flash region to be used for read only data.*/ 56 | REGION_ALIAS("RODATA_FLASH", flash0); 57 | REGION_ALIAS("RODATA_FLASH_LMA", flash0); 58 | 59 | /* Flash region to be used for various.*/ 60 | REGION_ALIAS("VARIOUS_FLASH", flash0); 61 | REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); 62 | 63 | /* Flash region to be used for RAM(n) initialization data.*/ 64 | REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); 65 | 66 | /* RAM region to be used for Main stack. This stack accommodates the processing 67 | of all exceptions and interrupts.*/ 68 | REGION_ALIAS("MAIN_STACK_RAM", ram0); 69 | 70 | /* RAM region to be used for the process stack. This is the stack used by 71 | the main() function.*/ 72 | REGION_ALIAS("PROCESS_STACK_RAM", ram0); 73 | 74 | /* RAM region to be used for data segment.*/ 75 | REGION_ALIAS("DATA_RAM", ram0); 76 | REGION_ALIAS("DATA_RAM_LMA", flash0); 77 | 78 | /* RAM region to be used for BSS segment.*/ 79 | REGION_ALIAS("BSS_RAM", ram0); 80 | 81 | /* RAM region to be used for the default heap.*/ 82 | REGION_ALIAS("HEAP_RAM", ram0); 83 | 84 | /* Generic rules inclusion.*/ 85 | INCLUDE rules.ld 86 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | set -e 3 | set -x 4 | 5 | make 6 | -------------------------------------------------------------------------------- /ccmfunc.ld: -------------------------------------------------------------------------------- 1 | .ccmfunc : ALIGN(4) 2 | { 3 | . = ALIGN(4); 4 | __ccmfunc_init_text__ = LOADADDR(.ccmfunc); 5 | __ccmfunc_init__ = .; 6 | *dsp.o(.text.*) 7 | *dsp.o(.rodata.arctantbl) 8 | *arm_biquad_cascade_df1_q15.o(.text.*) 9 | *arm_cfft_radix4_q31.o(.text.*) 10 | *arm_bitreversal.o(.text.*) 11 | *display.o(.text.draw_waveform) 12 | *display.o(.text.draw_waterfall) 13 | *display.o(.text.draw_spectrogram) 14 | *display.o(.text.disp_fetch_samples) 15 | __ccmfunc_end__ = .; 16 | . = ALIGN(4); 17 | } > ram4 AT > RAM_INIT_FLASH_LMA 18 | -------------------------------------------------------------------------------- /chconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /** 18 | * @file templates/chconf.h 19 | * @brief Configuration file template. 20 | * @details A copy of this file must be placed in each project directory, it 21 | * contains the application specific kernel settings. 22 | * 23 | * @addtogroup config 24 | * @details Kernel related settings and hooks. 25 | * @{ 26 | */ 27 | 28 | #ifndef _CHCONF_H_ 29 | #define _CHCONF_H_ 30 | 31 | #define _CHIBIOS_RT_CONF_ 32 | 33 | /*===========================================================================*/ 34 | /** 35 | * @name System timers settings 36 | * @{ 37 | */ 38 | /*===========================================================================*/ 39 | 40 | /** 41 | * @brief System time counter resolution. 42 | * @note Allowed values are 16 or 32 bits. 43 | */ 44 | #define CH_CFG_ST_RESOLUTION 32 45 | 46 | /** 47 | * @brief System tick frequency. 48 | * @details Frequency of the system timer that drives the system ticks. This 49 | * setting also defines the system tick time unit. 50 | */ 51 | #define CH_CFG_ST_FREQUENCY 10000 52 | 53 | /** 54 | * @brief Time delta constant for the tick-less mode. 55 | * @note If this value is zero then the system uses the classic 56 | * periodic tick. This value represents the minimum number 57 | * of ticks that is safe to specify in a timeout directive. 58 | * The value one is not valid, timeouts are rounded up to 59 | * this value. 60 | */ 61 | #define CH_CFG_ST_TIMEDELTA 2 62 | 63 | /** @} */ 64 | 65 | /*===========================================================================*/ 66 | /** 67 | * @name Kernel parameters and options 68 | * @{ 69 | */ 70 | /*===========================================================================*/ 71 | 72 | /** 73 | * @brief Round robin interval. 74 | * @details This constant is the number of system ticks allowed for the 75 | * threads before preemption occurs. Setting this value to zero 76 | * disables the preemption for threads with equal priority and the 77 | * round robin becomes cooperative. Note that higher priority 78 | * threads can still preempt, the kernel is always preemptive. 79 | * @note Disabling the round robin preemption makes the kernel more compact 80 | * and generally faster. 81 | * @note The round robin preemption is not supported in tickless mode and 82 | * must be set to zero in that case. 83 | */ 84 | #define CH_CFG_TIME_QUANTUM 0 85 | 86 | /** 87 | * @brief Managed RAM size. 88 | * @details Size of the RAM area to be managed by the OS. If set to zero 89 | * then the whole available RAM is used. The core memory is made 90 | * available to the heap allocator and/or can be used directly through 91 | * the simplified core memory allocator. 92 | * 93 | * @note In order to let the OS manage the whole RAM the linker script must 94 | * provide the @p __heap_base__ and @p __heap_end__ symbols. 95 | * @note Requires @p CH_CFG_USE_MEMCORE. 96 | */ 97 | #define CH_CFG_MEMCORE_SIZE 0 98 | 99 | /** 100 | * @brief Idle thread automatic spawn suppression. 101 | * @details When this option is activated the function @p chSysInit() 102 | * does not spawn the idle thread. The application @p main() 103 | * function becomes the idle thread and must implement an 104 | * infinite loop. */ 105 | #define CH_CFG_NO_IDLE_THREAD FALSE 106 | 107 | /** @} */ 108 | 109 | /*===========================================================================*/ 110 | /** 111 | * @name Performance options 112 | * @{ 113 | */ 114 | /*===========================================================================*/ 115 | 116 | /** 117 | * @brief OS optimization. 118 | * @details If enabled then time efficient rather than space efficient code 119 | * is used when two possible implementations exist. 120 | * 121 | * @note This is not related to the compiler optimization options. 122 | * @note The default is @p TRUE. 123 | */ 124 | #define CH_CFG_OPTIMIZE_SPEED TRUE 125 | 126 | /** @} */ 127 | 128 | /*===========================================================================*/ 129 | /** 130 | * @name Subsystem options 131 | * @{ 132 | */ 133 | /*===========================================================================*/ 134 | 135 | /** 136 | * @brief Time Measurement APIs. 137 | * @details If enabled then the time measurement APIs are included in 138 | * the kernel. 139 | * 140 | * @note The default is @p TRUE. 141 | */ 142 | #define CH_CFG_USE_TM FALSE 143 | 144 | /** 145 | * @brief Threads registry APIs. 146 | * @details If enabled then the registry APIs are included in the kernel. 147 | * 148 | * @note The default is @p TRUE. 149 | */ 150 | #define CH_CFG_USE_REGISTRY TRUE 151 | 152 | /** 153 | * @brief Threads synchronization APIs. 154 | * @details If enabled then the @p chThdWait() function is included in 155 | * the kernel. 156 | * 157 | * @note The default is @p TRUE. 158 | */ 159 | #define CH_CFG_USE_WAITEXIT TRUE 160 | 161 | /** 162 | * @brief Semaphores APIs. 163 | * @details If enabled then the Semaphores APIs are included in the kernel. 164 | * 165 | * @note The default is @p TRUE. 166 | */ 167 | #define CH_CFG_USE_SEMAPHORES TRUE 168 | 169 | /** 170 | * @brief Semaphores queuing mode. 171 | * @details If enabled then the threads are enqueued on semaphores by 172 | * priority rather than in FIFO order. 173 | * 174 | * @note The default is @p FALSE. Enable this if you have special 175 | * requirements. 176 | * @note Requires @p CH_CFG_USE_SEMAPHORES. 177 | */ 178 | #define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE 179 | 180 | /** 181 | * @brief Mutexes APIs. 182 | * @details If enabled then the mutexes APIs are included in the kernel. 183 | * 184 | * @note The default is @p TRUE. 185 | */ 186 | #define CH_CFG_USE_MUTEXES TRUE 187 | 188 | /** 189 | * @brief Enables recursive behavior on mutexes. 190 | * @note Recursive mutexes are heavier and have an increased 191 | * memory footprint. 192 | * 193 | * @note The default is @p FALSE. 194 | * @note Requires @p CH_CFG_USE_MUTEXES. 195 | */ 196 | #define CH_CFG_USE_MUTEXES_RECURSIVE FALSE 197 | 198 | /** 199 | * @brief Conditional Variables APIs. 200 | * @details If enabled then the conditional variables APIs are included 201 | * in the kernel. 202 | * 203 | * @note The default is @p TRUE. 204 | * @note Requires @p CH_CFG_USE_MUTEXES. 205 | */ 206 | #define CH_CFG_USE_CONDVARS TRUE 207 | 208 | /** 209 | * @brief Conditional Variables APIs with timeout. 210 | * @details If enabled then the conditional variables APIs with timeout 211 | * specification are included in the kernel. 212 | * 213 | * @note The default is @p TRUE. 214 | * @note Requires @p CH_CFG_USE_CONDVARS. 215 | */ 216 | #define CH_CFG_USE_CONDVARS_TIMEOUT TRUE 217 | 218 | /** 219 | * @brief Events Flags APIs. 220 | * @details If enabled then the event flags APIs are included in the kernel. 221 | * 222 | * @note The default is @p TRUE. 223 | */ 224 | #define CH_CFG_USE_EVENTS TRUE 225 | 226 | /** 227 | * @brief Events Flags APIs with timeout. 228 | * @details If enabled then the events APIs with timeout specification 229 | * are included in the kernel. 230 | * 231 | * @note The default is @p TRUE. 232 | * @note Requires @p CH_CFG_USE_EVENTS. 233 | */ 234 | #define CH_CFG_USE_EVENTS_TIMEOUT TRUE 235 | 236 | /** 237 | * @brief Synchronous Messages APIs. 238 | * @details If enabled then the synchronous messages APIs are included 239 | * in the kernel. 240 | * 241 | * @note The default is @p TRUE. 242 | */ 243 | #define CH_CFG_USE_MESSAGES TRUE 244 | 245 | /** 246 | * @brief Synchronous Messages queuing mode. 247 | * @details If enabled then messages are served by priority rather than in 248 | * FIFO order. 249 | * 250 | * @note The default is @p FALSE. Enable this if you have special 251 | * requirements. 252 | * @note Requires @p CH_CFG_USE_MESSAGES. 253 | */ 254 | #define CH_CFG_USE_MESSAGES_PRIORITY FALSE 255 | 256 | /** 257 | * @brief Mailboxes APIs. 258 | * @details If enabled then the asynchronous messages (mailboxes) APIs are 259 | * included in the kernel. 260 | * 261 | * @note The default is @p TRUE. 262 | * @note Requires @p CH_CFG_USE_SEMAPHORES. 263 | */ 264 | #define CH_CFG_USE_MAILBOXES TRUE 265 | 266 | /** 267 | * @brief I/O Queues APIs. 268 | * @details If enabled then the I/O queues APIs are included in the kernel. 269 | * 270 | * @note The default is @p TRUE. 271 | */ 272 | #define CH_CFG_USE_QUEUES TRUE 273 | 274 | /** 275 | * @brief Core Memory Manager APIs. 276 | * @details If enabled then the core memory manager APIs are included 277 | * in the kernel. 278 | * 279 | * @note The default is @p TRUE. 280 | */ 281 | #define CH_CFG_USE_MEMCORE TRUE 282 | 283 | /** 284 | * @brief Heap Allocator APIs. 285 | * @details If enabled then the memory heap allocator APIs are included 286 | * in the kernel. 287 | * 288 | * @note The default is @p TRUE. 289 | * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or 290 | * @p CH_CFG_USE_SEMAPHORES. 291 | * @note Mutexes are recommended. 292 | */ 293 | #define CH_CFG_USE_HEAP TRUE 294 | 295 | /** 296 | * @brief Memory Pools Allocator APIs. 297 | * @details If enabled then the memory pools allocator APIs are included 298 | * in the kernel. 299 | * 300 | * @note The default is @p TRUE. 301 | */ 302 | #define CH_CFG_USE_MEMPOOLS TRUE 303 | 304 | /** 305 | * @brief Dynamic Threads APIs. 306 | * @details If enabled then the dynamic threads creation APIs are included 307 | * in the kernel. 308 | * 309 | * @note The default is @p TRUE. 310 | * @note Requires @p CH_CFG_USE_WAITEXIT. 311 | * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. 312 | */ 313 | #define CH_CFG_USE_DYNAMIC TRUE 314 | 315 | /** @} */ 316 | 317 | /*===========================================================================*/ 318 | /** 319 | * @name Debug options 320 | * @{ 321 | */ 322 | /*===========================================================================*/ 323 | 324 | /** 325 | * @brief Debug option, kernel statistics. 326 | * 327 | * @note The default is @p FALSE. 328 | */ 329 | #define CH_DBG_STATISTICS FALSE 330 | 331 | /** 332 | * @brief Debug option, system state check. 333 | * @details If enabled the correct call protocol for system APIs is checked 334 | * at runtime. 335 | * 336 | * @note The default is @p FALSE. 337 | */ 338 | #define CH_DBG_SYSTEM_STATE_CHECK TRUE 339 | 340 | /** 341 | * @brief Debug option, parameters checks. 342 | * @details If enabled then the checks on the API functions input 343 | * parameters are activated. 344 | * 345 | * @note The default is @p FALSE. 346 | */ 347 | #define CH_DBG_ENABLE_CHECKS TRUE 348 | 349 | /** 350 | * @brief Debug option, consistency checks. 351 | * @details If enabled then all the assertions in the kernel code are 352 | * activated. This includes consistency checks inside the kernel, 353 | * runtime anomalies and port-defined checks. 354 | * 355 | * @note The default is @p FALSE. 356 | */ 357 | #define CH_DBG_ENABLE_ASSERTS TRUE 358 | 359 | /** 360 | * @brief Debug option, trace buffer. 361 | * @details If enabled then the trace buffer is activated. 362 | * 363 | * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. 364 | */ 365 | #define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED 366 | 367 | /** 368 | * @brief Trace buffer entries. 369 | * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is 370 | * different from @p CH_DBG_TRACE_MASK_DISABLED. 371 | */ 372 | #define CH_DBG_TRACE_BUFFER_SIZE 128 373 | 374 | /** 375 | * @brief Debug option, stack checks. 376 | * @details If enabled then a runtime stack check is performed. 377 | * 378 | * @note The default is @p FALSE. 379 | * @note The stack check is performed in a architecture/port dependent way. 380 | * It may not be implemented or some ports. 381 | * @note The default failure mode is to halt the system with the global 382 | * @p panic_msg variable set to @p NULL. 383 | */ 384 | #define CH_DBG_ENABLE_STACK_CHECK TRUE 385 | 386 | /** 387 | * @brief Debug option, stacks initialization. 388 | * @details If enabled then the threads working area is filled with a byte 389 | * value when a thread is created. This can be useful for the 390 | * runtime measurement of the used stack. 391 | * 392 | * @note The default is @p FALSE. 393 | */ 394 | #define CH_DBG_FILL_THREADS TRUE 395 | 396 | /** 397 | * @brief Debug option, threads profiling. 398 | * @details If enabled then a field is added to the @p thread_t structure that 399 | * counts the system ticks occurred while executing the thread. 400 | * 401 | * @note The default is @p FALSE. 402 | * @note This debug option is not currently compatible with the 403 | * tickless mode. 404 | */ 405 | #define CH_DBG_THREADS_PROFILING FALSE 406 | 407 | /** @} */ 408 | 409 | /*===========================================================================*/ 410 | /** 411 | * @name Kernel hooks 412 | * @{ 413 | */ 414 | /*===========================================================================*/ 415 | 416 | /** 417 | * @brief Threads descriptor structure extension. 418 | * @details User fields added to the end of the @p thread_t structure. 419 | */ 420 | #define CH_CFG_THREAD_EXTRA_FIELDS \ 421 | /* Add threads custom fields here.*/ 422 | 423 | /** 424 | * @brief Threads initialization hook. 425 | * @details User initialization code added to the @p chThdInit() API. 426 | * 427 | * @note It is invoked from within @p chThdInit() and implicitly from all 428 | * the threads creation APIs. 429 | */ 430 | #define CH_CFG_THREAD_INIT_HOOK(tp) { \ 431 | /* Add threads initialization code here.*/ \ 432 | } 433 | 434 | /** 435 | * @brief Threads finalization hook. 436 | * @details User finalization code added to the @p chThdExit() API. 437 | * 438 | * @note It is inserted into lock zone. 439 | * @note It is also invoked when the threads simply return in order to 440 | * terminate. 441 | */ 442 | #define CH_CFG_THREAD_EXIT_HOOK(tp) { \ 443 | /* Add threads finalization code here.*/ \ 444 | } 445 | 446 | /** 447 | * @brief Context switch hook. 448 | * @details This hook is invoked just before switching between threads. 449 | */ 450 | #define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ 451 | /* System halt code here.*/ \ 452 | } 453 | 454 | /** 455 | * @brief ISR enter hook. 456 | */ 457 | #define CH_CFG_IRQ_PROLOGUE_HOOK() { \ 458 | /* IRQ prologue code here.*/ \ 459 | } 460 | 461 | /** 462 | * @brief ISR exit hook. 463 | */ 464 | #define CH_CFG_IRQ_EPILOGUE_HOOK() { \ 465 | /* IRQ epilogue code here.*/ \ 466 | } 467 | 468 | /** 469 | * @brief Idle thread enter hook. 470 | * @note This hook is invoked within a critical zone, no OS functions 471 | * should be invoked from here. 472 | * @note This macro can be used to activate a power saving mode. 473 | */ 474 | #define CH_CFG_IDLE_ENTER_HOOK() { \ 475 | } 476 | 477 | /** 478 | * @brief Idle thread leave hook. 479 | * @note This hook is invoked within a critical zone, no OS functions 480 | * should be invoked from here. 481 | * @note This macro can be used to deactivate a power saving mode. 482 | */ 483 | #define CH_CFG_IDLE_LEAVE_HOOK() { \ 484 | } 485 | 486 | /** 487 | * @brief Idle Loop hook. 488 | * @details This hook is continuously invoked by the idle thread loop. 489 | */ 490 | #define CH_CFG_IDLE_LOOP_HOOK() { \ 491 | /* Idle loop code here.*/ \ 492 | } 493 | 494 | /** 495 | * @brief System tick event hook. 496 | * @details This hook is invoked in the system tick handler immediately 497 | * after processing the virtual timers queue. 498 | */ 499 | #define CH_CFG_SYSTEM_TICK_HOOK() { \ 500 | /* System tick event code here.*/ \ 501 | } 502 | 503 | /** 504 | * @brief System halt hook. 505 | * @details This hook is invoked in case to a system halting error before 506 | * the system is halted. 507 | */ 508 | #define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ 509 | /* System halt code here.*/ \ 510 | } 511 | 512 | /** 513 | * @brief Trace hook. 514 | * @details This hook is invoked each time a new record is written in the 515 | * trace buffer. 516 | */ 517 | #define CH_CFG_TRACE_HOOK(tep) { \ 518 | /* Trace code here.*/ \ 519 | } 520 | 521 | /** @} */ 522 | 523 | /*===========================================================================*/ 524 | /* Port-specific settings (override port settings defaulted in chcore.h). */ 525 | /*===========================================================================*/ 526 | 527 | #endif /* _CHCONF_H_ */ 528 | 529 | /** @} */ 530 | -------------------------------------------------------------------------------- /crt2.c: -------------------------------------------------------------------------------- 1 | #include "ch.h" 2 | #include "hal.h" 3 | 4 | extern uint32_t __ccmfunc_init_text__, __ccmfunc_init__, __ccmfunc_end__; 5 | 6 | /* 7 | * Late initialization code. 8 | */ 9 | void __late_init(void) { 10 | // CCM RAM protection register 11 | SYSCFG->RCR = 0x0000; 12 | 13 | /* Copying CCM initialization code. */ 14 | uint32_t *tp = &__ccmfunc_init_text__; 15 | uint32_t *p = &__ccmfunc_init__; 16 | 17 | while (p < &__ccmfunc_end__) { 18 | *p = *tp; 19 | p++; 20 | tp++; 21 | } 22 | 23 | // CCM RAM protection register 24 | SYSCFG->RCR = 0x00ff; 25 | } 26 | -------------------------------------------------------------------------------- /doc/centsdr-blockdiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttrftech/CentSDR/e4079566e42790497f004e16f9ebf68c83d024a0/doc/centsdr-blockdiagram.png -------------------------------------------------------------------------------- /doc/centsdr.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttrftech/CentSDR/e4079566e42790497f004e16f9ebf68c83d024a0/doc/centsdr.jpg -------------------------------------------------------------------------------- /doc/plot-waveform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttrftech/CentSDR/e4079566e42790497f004e16f9ebf68c83d024a0/doc/plot-waveform.png -------------------------------------------------------------------------------- /ffconf.h: -------------------------------------------------------------------------------- 1 | /* CHIBIOS FIX */ 2 | #include "ch.h" 3 | 4 | /*---------------------------------------------------------------------------/ 5 | / FatFs - FAT file system module configuration file R0.09 (C)ChaN, 2011 6 | /----------------------------------------------------------------------------/ 7 | / 8 | / CAUTION! Do not forget to make clean the project after any changes to 9 | / the configuration options. 10 | / 11 | /----------------------------------------------------------------------------*/ 12 | #ifndef _FFCONF 13 | #define _FFCONF 6502 /* Revision ID */ 14 | 15 | 16 | /*---------------------------------------------------------------------------/ 17 | / Functions and Buffer Configurations 18 | /----------------------------------------------------------------------------*/ 19 | 20 | #define _FS_TINY 0 /* 0:Normal or 1:Tiny */ 21 | /* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system 22 | / object instead of the sector buffer in the individual file object for file 23 | / data transfer. This reduces memory consumption 512 bytes each file object. */ 24 | 25 | 26 | #define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */ 27 | /* Setting _FS_READONLY to 1 defines read only configuration. This removes 28 | / writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename, 29 | / f_truncate and useless f_getfree. */ 30 | 31 | 32 | #define _FS_MINIMIZE 0 /* 0 to 3 */ 33 | /* The _FS_MINIMIZE option defines minimization level to remove some functions. 34 | / 35 | / 0: Full function. 36 | / 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename 37 | / are removed. 38 | / 2: f_opendir and f_readdir are removed in addition to 1. 39 | / 3: f_lseek is removed in addition to 2. */ 40 | 41 | 42 | #define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */ 43 | /* To enable string functions, set _USE_STRFUNC to 1 or 2. */ 44 | 45 | 46 | #define _USE_MKFS 1 /* 0:Disable or 1:Enable */ 47 | /* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */ 48 | 49 | 50 | #define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ 51 | /* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ 52 | 53 | 54 | #define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */ 55 | /* To enable fast seek feature, set _USE_FASTSEEK to 1. */ 56 | 57 | 58 | 59 | /*---------------------------------------------------------------------------/ 60 | / Locale and Namespace Configurations 61 | /----------------------------------------------------------------------------*/ 62 | 63 | #define _CODE_PAGE 1251 64 | /* The _CODE_PAGE specifies the OEM code page to be used on the target system. 65 | / Incorrect setting of the code page can cause a file open failure. 66 | / 67 | / 932 - Japanese Shift-JIS (DBCS, OEM, Windows) 68 | / 936 - Simplified Chinese GBK (DBCS, OEM, Windows) 69 | / 949 - Korean (DBCS, OEM, Windows) 70 | / 950 - Traditional Chinese Big5 (DBCS, OEM, Windows) 71 | / 1250 - Central Europe (Windows) 72 | / 1251 - Cyrillic (Windows) 73 | / 1252 - Latin 1 (Windows) 74 | / 1253 - Greek (Windows) 75 | / 1254 - Turkish (Windows) 76 | / 1255 - Hebrew (Windows) 77 | / 1256 - Arabic (Windows) 78 | / 1257 - Baltic (Windows) 79 | / 1258 - Vietnam (OEM, Windows) 80 | / 437 - U.S. (OEM) 81 | / 720 - Arabic (OEM) 82 | / 737 - Greek (OEM) 83 | / 775 - Baltic (OEM) 84 | / 850 - Multilingual Latin 1 (OEM) 85 | / 858 - Multilingual Latin 1 + Euro (OEM) 86 | / 852 - Latin 2 (OEM) 87 | / 855 - Cyrillic (OEM) 88 | / 866 - Russian (OEM) 89 | / 857 - Turkish (OEM) 90 | / 862 - Hebrew (OEM) 91 | / 874 - Thai (OEM, Windows) 92 | / 1 - ASCII only (Valid for non LFN cfg.) 93 | */ 94 | 95 | 96 | #define _USE_LFN 1 /* 0 to 3 */ 97 | #define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ 98 | /* The _USE_LFN option switches the LFN support. 99 | / 100 | / 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect. 101 | / 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant. 102 | / 2: Enable LFN with dynamic working buffer on the STACK. 103 | / 3: Enable LFN with dynamic working buffer on the HEAP. 104 | / 105 | / The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN, 106 | / Unicode handling functions ff_convert() and ff_wtoupper() must be added 107 | / to the project. When enable to use heap, memory control functions 108 | / ff_memalloc() and ff_memfree() must be added to the project. */ 109 | 110 | 111 | #define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ 112 | /* To switch the character code set on FatFs API to Unicode, 113 | / enable LFN feature and set _LFN_UNICODE to 1. */ 114 | 115 | 116 | #define _FS_RPATH 0 /* 0 to 2 */ 117 | /* The _FS_RPATH option configures relative path feature. 118 | / 119 | / 0: Disable relative path feature and remove related functions. 120 | / 1: Enable relative path. f_chdrive() and f_chdir() are available. 121 | / 2: f_getcwd() is available in addition to 1. 122 | / 123 | / Note that output of the f_readdir fnction is affected by this option. */ 124 | 125 | 126 | 127 | /*---------------------------------------------------------------------------/ 128 | / Physical Drive Configurations 129 | /----------------------------------------------------------------------------*/ 130 | 131 | #define _VOLUMES 1 132 | /* Number of volumes (logical drives) to be used. */ 133 | 134 | 135 | #define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ 136 | /* Maximum sector size to be handled. 137 | / Always set 512 for memory card and hard disk but a larger value may be 138 | / required for on-board flash memory, floppy disk and optical disk. 139 | / When _MAX_SS is larger than 512, it configures FatFs to variable sector size 140 | / and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */ 141 | 142 | 143 | #define _MULTI_PARTITION 0 /* 0:Single partition, 1/2:Enable multiple partition */ 144 | /* When set to 0, each volume is bound to the same physical drive number and 145 | / it can mount only first primaly partition. When it is set to 1, each volume 146 | / is tied to the partitions listed in VolToPart[]. */ 147 | 148 | 149 | #define _USE_ERASE 1 /* 0:Disable or 1:Enable */ 150 | /* To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command 151 | / should be added to the disk_ioctl functio. */ 152 | 153 | 154 | 155 | /*---------------------------------------------------------------------------/ 156 | / System Configurations 157 | /----------------------------------------------------------------------------*/ 158 | 159 | #define _WORD_ACCESS 1 /* 0 or 1 */ 160 | /* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS 161 | / option defines which access method is used to the word data on the FAT volume. 162 | / 163 | / 0: Byte-by-byte access. 164 | / 1: Word access. Do not choose this unless following condition is met. 165 | / 166 | / When the byte order on the memory is big-endian or address miss-aligned word 167 | / access results incorrect behavior, the _WORD_ACCESS must be set to 0. 168 | / If it is not the case, the value can also be set to 1 to improve the 169 | / performance and code size. 170 | */ 171 | 172 | 173 | /* A header file that defines sync object types on the O/S, such as 174 | / windows.h, ucos_ii.h and semphr.h, must be included prior to ff.h. */ 175 | 176 | #define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ 177 | #define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ 178 | #define _SYNC_t Semaphore * /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ 179 | 180 | /* The _FS_REENTRANT option switches the reentrancy (thread safe) of the FatFs module. 181 | / 182 | / 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect. 183 | / 1: Enable reentrancy. Also user provided synchronization handlers, 184 | / ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj 185 | / function must be added to the project. */ 186 | 187 | 188 | #define _FS_SHARE 0 /* 0:Disable or >=1:Enable */ 189 | /* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value 190 | defines how many files can be opened simultaneously. */ 191 | 192 | 193 | #endif /* _FFCONFIG */ 194 | -------------------------------------------------------------------------------- /flash-openocd.gdb: -------------------------------------------------------------------------------- 1 | # 1) start openocd in other terminal 2 | # $ openocd -f board/stm32f3discovery.cfg 3 | # 2) arm-none-eabi-gdb -x flash-openocd.gdb 4 | 5 | target extended-remote :3333 6 | exec build/ch.elf 7 | load 8 | continue 9 | quit 10 | -------------------------------------------------------------------------------- /flash-stutil.gdb: -------------------------------------------------------------------------------- 1 | # 1) start st-util in background 2 | # 2) arm-none-eabi-gdb -x flash-stutil.gdb 3 | 4 | target extended-remote :4242 5 | exec build/ch.elf 6 | load 7 | quit 8 | -------------------------------------------------------------------------------- /flash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com 3 | * All rights reserved. 4 | * 5 | * This is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3, or (at your option) 8 | * any later version. 9 | * 10 | * The software is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with GNU Radio; see the file COPYING. If not, write to 17 | * the Free Software Foundation, Inc., 51 Franklin Street, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | #include "ch.h" 21 | #include "hal.h" 22 | #include "nanosdr.h" 23 | #include 24 | 25 | static int flash_wait_for_last_operation(void) 26 | { 27 | while (FLASH->SR == FLASH_SR_BSY) { 28 | //WWDG->CR = WWDG_CR_T; 29 | } 30 | return FLASH->SR; 31 | } 32 | 33 | static void flash_erase_page0(uint32_t page_address) 34 | { 35 | flash_wait_for_last_operation(); 36 | FLASH->CR |= FLASH_CR_PER; 37 | FLASH->AR = page_address; 38 | FLASH->CR |= FLASH_CR_STRT; 39 | flash_wait_for_last_operation(); 40 | FLASH->CR &= ~FLASH_CR_PER; 41 | } 42 | 43 | int flash_erase_page(uint32_t page_address) 44 | { 45 | chSysLock(); 46 | flash_erase_page0(page_address); 47 | chSysUnlock(); 48 | return 0; 49 | } 50 | 51 | void flash_program_half_word(uint32_t address, uint16_t data) 52 | { 53 | flash_wait_for_last_operation(); 54 | FLASH->CR |= FLASH_CR_PG; 55 | *(__IO uint16_t*)address = data; 56 | flash_wait_for_last_operation(); 57 | FLASH->CR &= ~FLASH_CR_PG; 58 | } 59 | 60 | void flash_unlock(void) 61 | { 62 | // unlock sequence 63 | FLASH->KEYR = 0x45670123; 64 | FLASH->KEYR = 0xCDEF89AB; 65 | } 66 | 67 | 68 | static uint32_t 69 | checksum(const void *start, size_t len) 70 | { 71 | uint32_t *p = (uint32_t*)start; 72 | uint32_t *tail = (uint32_t*)(start + len); 73 | uint32_t value = len; 74 | while (p < tail) 75 | value ^= *p++; 76 | return value; 77 | } 78 | 79 | 80 | #define FLASH_PAGESIZE 0x800 81 | 82 | // last page of flash memory. assume STM32F303CBT6 flash 128k Device 83 | const uint32_t save_config_area = 0x0801f800; 84 | const uint32_t save_config_prop_area_size = 0x800; 85 | 86 | int 87 | config_save(void) 88 | { 89 | uint16_t *src = (uint16_t*)&config; 90 | uint16_t *dst = (uint16_t*)save_config_area; 91 | int count = sizeof(config_t) / sizeof(uint16_t); 92 | 93 | config.magic = CONFIG_MAGIC; 94 | config.checksum = 0; 95 | config.checksum = checksum(&config, sizeof config); 96 | 97 | flash_unlock(); 98 | 99 | /* erase flash pages */ 100 | flash_erase_page((uint32_t)dst); 101 | 102 | /* write to flahs */ 103 | while(count-- > 0) { 104 | flash_program_half_word((uint32_t)dst, *src++); 105 | dst++; 106 | } 107 | 108 | return 0; 109 | } 110 | 111 | int 112 | config_recall(void) 113 | { 114 | const config_t *src = (const config_t*)save_config_area; 115 | void *dst = &config; 116 | 117 | if (src->magic != CONFIG_MAGIC) 118 | return -1; 119 | if (checksum(src, sizeof(config_t)) != 0) 120 | return -1; 121 | 122 | /* duplicated saved data onto sram to be able to modify marker/trace */ 123 | memcpy(dst, src, sizeof(config_t)); 124 | return 0; 125 | } 126 | 127 | void 128 | clear_all_config_prop_data(void) 129 | { 130 | flash_unlock(); 131 | 132 | /* erase flash pages */ 133 | void *p = (void*)save_config_area; 134 | void *tail = p + save_config_prop_area_size; 135 | while (p < tail) { 136 | flash_erase_page((uint32_t)p); 137 | p += FLASH_PAGESIZE; 138 | } 139 | } 140 | 141 | -------------------------------------------------------------------------------- /halconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /** 18 | * @file templates/halconf.h 19 | * @brief HAL configuration header. 20 | * @details HAL configuration file, this file allows to enable or disable the 21 | * various device drivers from your application. You may also use 22 | * this file in order to override the device drivers default settings. 23 | * 24 | * @addtogroup HAL_CONF 25 | * @{ 26 | */ 27 | 28 | #ifndef _HALCONF_H_ 29 | #define _HALCONF_H_ 30 | 31 | #include "mcuconf.h" 32 | 33 | /** 34 | * @brief Enables the PAL subsystem. 35 | */ 36 | #if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) 37 | #define HAL_USE_PAL TRUE 38 | #endif 39 | 40 | /** 41 | * @brief Enables the ADC subsystem. 42 | */ 43 | #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) 44 | #define HAL_USE_ADC TRUE 45 | #endif 46 | 47 | /** 48 | * @brief Enables the CAN subsystem. 49 | */ 50 | #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) 51 | #define HAL_USE_CAN FALSE 52 | #endif 53 | 54 | /** 55 | * @brief Enables the DAC subsystem. 56 | */ 57 | #if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) 58 | #define HAL_USE_DAC TRUE 59 | #endif 60 | 61 | /** 62 | * @brief Enables the EXT subsystem. 63 | */ 64 | #if !defined(HAL_USE_EXT) || defined(__DOXYGEN__) 65 | #define HAL_USE_EXT TRUE 66 | #endif 67 | 68 | /** 69 | * @brief Enables the GPT subsystem. 70 | */ 71 | #if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) 72 | #define HAL_USE_GPT FALSE 73 | #endif 74 | 75 | /** 76 | * @brief Enables the I2C subsystem. 77 | */ 78 | #if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) 79 | #define HAL_USE_I2C TRUE 80 | #endif 81 | 82 | /** 83 | * @brief Enables the I2S subsystem. 84 | */ 85 | #if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) 86 | #define HAL_USE_I2S TRUE 87 | #endif 88 | 89 | /** 90 | * @brief Enables the ICU subsystem. 91 | */ 92 | #if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) 93 | #define HAL_USE_ICU FALSE 94 | #endif 95 | 96 | /** 97 | * @brief Enables the MAC subsystem. 98 | */ 99 | #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) 100 | #define HAL_USE_MAC FALSE 101 | #endif 102 | 103 | /** 104 | * @brief Enables the MMC_SPI subsystem. 105 | */ 106 | #if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) 107 | #define HAL_USE_MMC_SPI FALSE 108 | #endif 109 | 110 | /** 111 | * @brief Enables the PWM subsystem. 112 | */ 113 | #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) 114 | #define HAL_USE_PWM FALSE 115 | #endif 116 | 117 | /** 118 | * @brief Enables the RTC subsystem. 119 | */ 120 | #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) 121 | #define HAL_USE_RTC FALSE 122 | #endif 123 | 124 | /** 125 | * @brief Enables the SDC subsystem. 126 | */ 127 | #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) 128 | #define HAL_USE_SDC FALSE 129 | #endif 130 | 131 | /** 132 | * @brief Enables the SERIAL subsystem. 133 | */ 134 | #if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) 135 | #define HAL_USE_SERIAL TRUE 136 | #endif 137 | 138 | /** 139 | * @brief Enables the SERIAL over USB subsystem. 140 | */ 141 | #if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) 142 | #define HAL_USE_SERIAL_USB TRUE 143 | #endif 144 | 145 | /** 146 | * @brief Enables the SPI subsystem. 147 | */ 148 | #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) 149 | #define HAL_USE_SPI TRUE 150 | #endif 151 | 152 | /** 153 | * @brief Enables the UART subsystem. 154 | */ 155 | #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) 156 | #define HAL_USE_UART FALSE 157 | #endif 158 | 159 | /** 160 | * @brief Enables the USB subsystem. 161 | */ 162 | #if !defined(HAL_USE_USB) || defined(__DOXYGEN__) 163 | #define HAL_USE_USB TRUE 164 | #endif 165 | 166 | /** 167 | * @brief Enables the WDG subsystem. 168 | */ 169 | #if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) 170 | #define HAL_USE_WDG FALSE 171 | #endif 172 | 173 | /*===========================================================================*/ 174 | /* ADC driver related settings. */ 175 | /*===========================================================================*/ 176 | 177 | /** 178 | * @brief Enables synchronous APIs. 179 | * @note Disabling this option saves both code and data space. 180 | */ 181 | #if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) 182 | #define ADC_USE_WAIT TRUE 183 | #endif 184 | 185 | /** 186 | * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. 187 | * @note Disabling this option saves both code and data space. 188 | */ 189 | #if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) 190 | #define ADC_USE_MUTUAL_EXCLUSION TRUE 191 | #endif 192 | 193 | /*===========================================================================*/ 194 | /* CAN driver related settings. */ 195 | /*===========================================================================*/ 196 | 197 | /** 198 | * @brief Sleep mode related APIs inclusion switch. 199 | */ 200 | #if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) 201 | #define CAN_USE_SLEEP_MODE TRUE 202 | #endif 203 | 204 | /*===========================================================================*/ 205 | /* I2C driver related settings. */ 206 | /*===========================================================================*/ 207 | 208 | /** 209 | * @brief Enables the mutual exclusion APIs on the I2C bus. 210 | */ 211 | #if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) 212 | #define I2C_USE_MUTUAL_EXCLUSION TRUE 213 | #endif 214 | 215 | /*===========================================================================*/ 216 | /* MAC driver related settings. */ 217 | /*===========================================================================*/ 218 | 219 | /** 220 | * @brief Enables an event sources for incoming packets. 221 | */ 222 | #if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) 223 | #define MAC_USE_ZERO_COPY FALSE 224 | #endif 225 | 226 | /** 227 | * @brief Enables an event sources for incoming packets. 228 | */ 229 | #if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) 230 | #define MAC_USE_EVENTS TRUE 231 | #endif 232 | 233 | /*===========================================================================*/ 234 | /* MMC_SPI driver related settings. */ 235 | /*===========================================================================*/ 236 | 237 | /** 238 | * @brief Delays insertions. 239 | * @details If enabled this options inserts delays into the MMC waiting 240 | * routines releasing some extra CPU time for the threads with 241 | * lower priority, this may slow down the driver a bit however. 242 | * This option is recommended also if the SPI driver does not 243 | * use a DMA channel and heavily loads the CPU. 244 | */ 245 | #if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) 246 | #define MMC_NICE_WAITING TRUE 247 | #endif 248 | 249 | /*===========================================================================*/ 250 | /* SDC driver related settings. */ 251 | /*===========================================================================*/ 252 | 253 | /** 254 | * @brief Number of initialization attempts before rejecting the card. 255 | * @note Attempts are performed at 10mS intervals. 256 | */ 257 | #if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) 258 | #define SDC_INIT_RETRY 100 259 | #endif 260 | 261 | /** 262 | * @brief Include support for MMC cards. 263 | * @note MMC support is not yet implemented so this option must be kept 264 | * at @p FALSE. 265 | */ 266 | #if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) 267 | #define SDC_MMC_SUPPORT FALSE 268 | #endif 269 | 270 | /** 271 | * @brief Delays insertions. 272 | * @details If enabled this options inserts delays into the MMC waiting 273 | * routines releasing some extra CPU time for the threads with 274 | * lower priority, this may slow down the driver a bit however. 275 | */ 276 | #if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) 277 | #define SDC_NICE_WAITING TRUE 278 | #endif 279 | 280 | /*===========================================================================*/ 281 | /* SERIAL driver related settings. */ 282 | /*===========================================================================*/ 283 | 284 | /** 285 | * @brief Default bit rate. 286 | * @details Configuration parameter, this is the baud rate selected for the 287 | * default configuration. 288 | */ 289 | #if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) 290 | #define SERIAL_DEFAULT_BITRATE 38400 291 | #endif 292 | 293 | /** 294 | * @brief Serial buffers size. 295 | * @details Configuration parameter, you can change the depth of the queue 296 | * buffers depending on the requirements of your application. 297 | * @note The default is 64 bytes for both the transmission and receive 298 | * buffers. 299 | */ 300 | #if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) 301 | #define SERIAL_BUFFERS_SIZE 16 302 | #endif 303 | 304 | /*===========================================================================*/ 305 | /* SERIAL_USB driver related setting. */ 306 | /*===========================================================================*/ 307 | 308 | /** 309 | * @brief Serial over USB buffers size. 310 | * @details Configuration parameter, the buffer size must be a multiple of 311 | * the USB data endpoint maximum packet size. 312 | * @note The default is 64 bytes for both the transmission and receive 313 | * buffers. 314 | */ 315 | #if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) 316 | #define SERIAL_USB_BUFFERS_SIZE 256 317 | #endif 318 | 319 | /*===========================================================================*/ 320 | /* SPI driver related settings. */ 321 | /*===========================================================================*/ 322 | 323 | /** 324 | * @brief Enables synchronous APIs. 325 | * @note Disabling this option saves both code and data space. 326 | */ 327 | #if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) 328 | #define SPI_USE_WAIT TRUE 329 | #endif 330 | 331 | /** 332 | * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. 333 | * @note Disabling this option saves both code and data space. 334 | */ 335 | #if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) 336 | #define SPI_USE_MUTUAL_EXCLUSION TRUE 337 | #endif 338 | 339 | /*===========================================================================*/ 340 | /* UART driver related settings. */ 341 | /*===========================================================================*/ 342 | 343 | /** 344 | * @brief Enables synchronous APIs. 345 | * @note Disabling this option saves both code and data space. 346 | */ 347 | #if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) 348 | #define UART_USE_WAIT FALSE 349 | #endif 350 | 351 | /** 352 | * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. 353 | * @note Disabling this option saves both code and data space. 354 | */ 355 | #if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) 356 | #define UART_USE_MUTUAL_EXCLUSION FALSE 357 | #endif 358 | 359 | /*===========================================================================*/ 360 | /* USB driver related settings. */ 361 | /*===========================================================================*/ 362 | 363 | /** 364 | * @brief Enables synchronous APIs. 365 | * @note Disabling this option saves both code and data space. 366 | */ 367 | #if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) 368 | #define USB_USE_WAIT FALSE 369 | #endif 370 | 371 | #endif /* _HALCONF_H_ */ 372 | 373 | /** @} */ 374 | -------------------------------------------------------------------------------- /icons.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com 3 | * All rights reserved. 4 | * 5 | * This is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3, or (at your option) 8 | * any later version. 9 | * 10 | * The software is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with GNU Radio; see the file COPYING. If not, write to 17 | * the Free Software Foundation, Inc., 51 Franklin Street, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #include 22 | 23 | const uint32_t icons48x20[][2*20] = { 24 | { // CW 25 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 26 | 0b00111111111111111111111111111111, 0b11111111111111000000000000000000, 27 | 0b01111111111000000001111110000111, 0b10111100001111100000000000000000, 28 | 0b01111111100000000000011110000111, 0b00011100001111100000000000000000, 29 | 0b11111111000000000000001110000111, 0b00011100001111110000000000000000, 30 | 0b11111110000000000000001110000110, 0b00001100001111110000000000000000, 31 | 0b11111110000001111000000110000110, 0b00001100001111110000000000000000, 32 | 0b11111100000111111100000110000100, 0b00000100001111110000000000000000, 33 | 34 | 0b11111100001111111111111110000000, 0b00000000001111110000000000000000, 35 | 0b11111100001111111111111110000000, 0b00000000001111110000000000000000, 36 | 0b11111100001111111111111110000000, 0b00000000001111110000000000000000, 37 | 0b11111100001111111111111111000000, 0b01000000011111110000000000000000, 38 | 0b11111100000111111100000111000000, 0b11100000011111110000000000000000, 39 | 0b11111110000001111000000111000000, 0b11100000011111110000000000000000, 40 | 0b11111110000000000000001111000001, 0b11110000011111110000000000000000, 41 | 0b11111111000000000000001111000001, 0b11110000011111110000000000000000, 42 | 43 | 0b01111111100000000000111111000011, 0b11111000011111100000000000000000, 44 | 0b01111111111000000011111111000011, 0b11111000011111100000000000000000, 45 | 0b00111111111111111111111111111111, 0b11111111111111000000000000000000, 46 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 47 | }, 48 | { // LSB 49 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 50 | 0b00111111111111111111111101111111, 0b11111111111111000000000000000000, 51 | 0b01111100001111111111110000011110, 0b00000001111111100000000000000000, 52 | 0b01111100001111111111000000000110, 0b00000000011111100000000000000000, 53 | 0b11111100001111111110000000000010, 0b00000000001111110000000000000000, 54 | 0b11111100001111111100000110000010, 0b00000000000111110000000000000000, 55 | 0b11111100001111111100001111000010, 0b00011100000111110000000000000000, 56 | 0b11111100001111111100000111111110, 0b00011110000111110000000000000000, 57 | 58 | 0b11111100001111111110000001111110, 0b00011100001111110000000000000000, 59 | 0b11111100001111111111000000011110, 0b00000000011111110000000000000000, 60 | 0b11111100001111111111110000001110, 0b00000000011111110000000000000000, 61 | 0b11111100001111111111111100000110, 0b00011100001111110000000000000000, 62 | 0b11111100001111111111111110000010, 0b00011110000111110000000000000000, 63 | 0b11111100001111111100001111000010, 0b00011100000111110000000000000000, 64 | 0b11111100000000000100000110000010, 0b00000000000111110000000000000000, 65 | 0b11111100000000000110000000000110, 0b00000000001111110000000000000000, 66 | 67 | 0b01111100000000000111000000001110, 0b00000000011111100000000000000000, 68 | 0b01111100000000000111100000011110, 0b00000001111111100000000000000000, 69 | 0b00111111111111111111111101111111, 0b11111111111111000000000000000000, 70 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 71 | }, 72 | { // USB 73 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 74 | 0b00111111111111111111111101111111, 0b11111111111111000000000000000000, 75 | 0b01111000011110000111100000001110, 0b00000001111111100000000000000000, 76 | 0b01111000011110000111000000000110, 0b00000000011111100000000000000000, 77 | 0b11111000011110000110000000000010, 0b00000000001111110000000000000000, 78 | 0b11111000011110000100000110000010, 0b00000000000111110000000000000000, 79 | 0b11111000011110000100001111000010, 0b00011100000111110000000000000000, 80 | 0b11111000011110000100000111111110, 0b00011110000111110000000000000000, 81 | 82 | 0b11111000011110000110000011111110, 0b00011100001111110000000000000000, 83 | 0b11111000011110000111000000111110, 0b00000000011111110000000000000000, 84 | 0b11111000011110000111100000001110, 0b00000000011111110000000000000000, 85 | 0b11111000011110000111111000000110, 0b00011100001111110000000000000000, 86 | 0b11111000011110000111111110000010, 0b00011110000111110000000000000000, 87 | 0b11111000001100000100001111000010, 0b00011100000111110000000000000000, 88 | 0b11111000000000000100000110000010, 0b00000000000111110000000000000000, 89 | 0b11111100000000001110000000000010, 0b00000000001111110000000000000000, 90 | 91 | 0b01111110000000011111000000000110, 0b00000000011111100000000000000000, 92 | 0b01111111000000111111100000001110, 0b00000001111111100000000000000000, 93 | 0b00111111111111111111111101111111, 0b11111111111111000000000000000000, 94 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 95 | }, 96 | { // AM 97 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 98 | 0b00111111111111111111111111111111, 0b11111111111111000000000000000000, 99 | 0b01111111111100000111111110000111, 0b11111100001111100000000000000000, 100 | 0b01111111111100000111111110000011, 0b11111000001111100000000000000000, 101 | 0b11111111111000000011111110000011, 0b11111000001111110000000000000000, 102 | 0b11111111111000000011111110000001, 0b11110000001111110000000000000000, 103 | 0b11111111110000000001111110000000, 0b11100000001111110000000000000000, 104 | 0b11111111110000000001111110000000, 0b11100000001111110000000000000000, 105 | 106 | 0b11111111100000100000111110000000, 0b01000000001111110000000000000000, 107 | 0b11111111100000100000111110000000, 0b00000000001111110000000000000000, 108 | 0b11111111000001110000011110000000, 0b00000000001111110000000000000000, 109 | 0b11111111000001110000011110000100, 0b00000100001111110000000000000000, 110 | 0b11111110000011111000001110000100, 0b00000100001111110000000000000000, 111 | 0b11111110000000000000001110000110, 0b00001100001111110000000000000000, 112 | 0b11111110000000000000001110000110, 0b00001100001111110000000000000000, 113 | 0b11111100000000000000000110000111, 0b00011100001111110000000000000000, 114 | 115 | 0b01111100000111111100000110000111, 0b00011100001111100000000000000000, 116 | 0b01111100000111111100000110000111, 0b10111100001111100000000000000000, 117 | 0b00111111111111111111111111111111, 0b11111111111111000000000000000000, 118 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 119 | }, 120 | { // FM 121 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 122 | 0b00111111111111111111111111111111, 0b11111111111111000000000000000000, 123 | 0b01111110000000000000001110000111, 0b11111100001111100000000000000000, 124 | 0b01111110000000000000001110000011, 0b11111000001111100000000000000000, 125 | 0b11111110000000000000001110000011, 0b11111000001111110000000000000000, 126 | 0b11111110000000000000001110000001, 0b11110000001111110000000000000000, 127 | 0b11111110000011111111111110000000, 0b11100000001111110000000000000000, 128 | 0b11111110000011111111111110000000, 0b11100000001111110000000000000000, 129 | 130 | 0b11111110000011111111111110000000, 0b01000000001111110000000000000000, 131 | 0b11111110000000000000011110000000, 0b00000000001111110000000000000000, 132 | 0b11111110000000000000011110000000, 0b00000000001111110000000000000000, 133 | 0b11111110000000000000011110000100, 0b00000100001111110000000000000000, 134 | 0b11111110000000000000011110000100, 0b00000100001111110000000000000000, 135 | 0b11111110000011111111111110000110, 0b00001100001111110000000000000000, 136 | 0b11111110000011111111111110000110, 0b00001100001111110000000000000000, 137 | 0b11111110000011111111111110000111, 0b00011100001111110000000000000000, 138 | 139 | 0b01111110000011111111111110000111, 0b00011100001111100000000000000000, 140 | 0b01111110000011111111111110000111, 0b10111100001111100000000000000000, 141 | 0b00111111111111111111111111111111, 0b11111111111111000000000000000000, 142 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 143 | }, 144 | { // STEREO 145 | 0b00001111111111111111111111111111, 0b11111111111110001000000000000000, 146 | 0b00111111111111111111111111111111, 0b11111111111111100000000000000000, 147 | 0b01111100011100000010000010000011, 0b00000110000111100000000000000000, 148 | 0b01111000001100000010000010000001, 0b00000100000011100000000000000000, 149 | 0b11110000000100000010000010000001, 0b00000100000011110000000000000000, 150 | 0b11110001000100000010000010000001, 0b00000100000011110000000000000000, 151 | 0b11110001100111001110011110011001, 0b00111100110011110000000000000000, 152 | 0b11110001100111001110011110011001, 0b00111100110011110000000000000000, 153 | 154 | 0b11111001111111001110000010011001, 0b00000100110011110000000000000000, 155 | 0b11111000111111001110000010000001, 0b00000100110011110000000000000000, 156 | 0b11111100011111001110000010000001, 0b00000100110011110000000000000000, 157 | 0b11111110001111001110000010000011, 0b00000100110011110000000000000000, 158 | 0b11110011001111001110011110010011, 0b00111100110011110000000000000000, 159 | 0b11110011000111001110011110010001, 0b00111100110011110000000000000000, 160 | 0b11110001000111001110000010010001, 0b00000100000011110000000000000000, 161 | 0b11110000000111001110000010011001, 0b00000100000011110000000000000000, 162 | 163 | 0b01111000001111001110000010011001, 0b00000100000011100000000000000000, 164 | 0b01111100011111001110000010011001, 0b00000110000111100000000000000000, 165 | 0b00111111111111111111111111111111, 0b11111111111111000000000000000000, 166 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 167 | }, 168 | { // OFF 169 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 170 | 0b00100000000000000000000000000000, 0b00000000000011000000000000000000, 171 | 0b01000000011111000001111111111101, 0b11111111110000100000000000000000, 172 | 0b10000001111111110001111111111101, 0b11111111110000100000000000000000, 173 | 0b10000011111111111001111111111101, 0b11111111110000010000000000000000, 174 | 0b10000111110001111101111111111101, 0b11111111110000010000000000000000, 175 | 0b10000111100000111101111000000001, 0b11100000000000010000000000000000, 176 | 0b10000111100000111101111000000001, 0b11100000000000010000000000000000, 177 | 178 | 0b10000111100000111101111000000001, 0b11100000000000010000000000000000, 179 | 0b10000111100000111101111111111001, 0b11111111100000010000000000000000, 180 | 0b10000111100000111101111111111001, 0b11111111100000010000000000000000, 181 | 0b10000111100000111101111111111001, 0b11111111100000010000000000000000, 182 | 0b10000111100000111101111111111001, 0b11111111100000010000000000000000, 183 | 0b10000111100000111101111000000001, 0b11100000000000010000000000000000, 184 | 0b10000111110001111101111000000001, 0b11100000000000010000000000000000, 185 | 0b10000011111111111001111000000001, 0b11100000000000010000000000000000, 186 | 187 | 0b01000001111111110001111000000001, 0b11100000000000100000000000000000, 188 | 0b01000000011111000001111000000001, 0b11100000000000100000000000000000, 189 | 0b00110000000000000000000000000000, 0b00000000000011000000000000000000, 190 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 191 | }, 192 | { // SLOW 193 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 194 | 0b00100000000000000000000000000000, 0b00000000000011000000000000000000, 195 | 0b01000001111000011100000000111110, 0b00111000001110100000000000000000, 196 | 0b10000111111110011100000001111111, 0b00111000001110100000000000000000, 197 | 0b10001111111111011100000011111111, 0b10111000001110010000000000000000, 198 | 0b10001111111111011100000011111111, 0b10111011101110010000000000000000, 199 | 0b10001110001111011100000011100011, 0b10111011101110010000000000000000, 200 | 0b10001111000111011100000011100011, 0b10111011101110010000000000000000, 201 | 202 | 0b10000111110000011100000011100011, 0b10111011101110010000000000000000, 203 | 0b10000011111100011100000011100011, 0b10111011101110010000000000000000, 204 | 0b10000001111100011100000011100011, 0b10111011101110010000000000000000, 205 | 0b10000000111110011100000011100011, 0b10111111111110010000000000000000, 206 | 0b10001110001111011100000011100011, 0b10111111111110010000000000000000, 207 | 0b10001111000111011100000011100011, 0b10011111111100010000000000000000, 208 | 0b10001111111111011111111011111111, 0b10011111111100010000000000000000, 209 | 0b10001111111111011111111011111111, 0b10011110111100010000000000000000, 210 | 211 | 0b01000111111110011111111001111111, 0b00011100011100100000000000000000, 212 | 0b01000001111000011111111000111110, 0b00011100011100100000000000000000, 213 | 0b00110000000000000000000000000000, 0b00000000000011000000000000000000, 214 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 215 | }, 216 | { // MID 217 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 218 | 0b00100000000000000000000000000000, 0b00000000000011000000000000000000, 219 | 0b01000111100000001111011111111011, 0b11111100000000100000000000000000, 220 | 0b10000111110000011111011111111011, 0b11111111000000100000000000000000, 221 | 0b10000111110000011111011111111011, 0b11111111110000010000000000000000, 222 | 0b10000111111000111111000111100011, 0b11111111110000010000000000000000, 223 | 0b10000111111000111111000111100011, 0b11000111111000010000000000000000, 224 | 0b10000111111101111111000111100011, 0b11000011111000010000000000000000, 225 | 226 | 0b10000111111111111111000111100011, 0b11000001111000010000000000000000, 227 | 0b10000111111111111111000111100011, 0b11000001111000010000000000000000, 228 | 0b10000111101111101111000111100011, 0b11000001111000010000000000000000, 229 | 0b10000111101111101111000111100011, 0b11000001111000010000000000000000, 230 | 0b10000111100111001111000111100011, 0b11000011111000010000000000000000, 231 | 0b10000111100111001111000111100011, 0b11000111111000010000000000000000, 232 | 0b10000111100111001111000111100011, 0b11111111110000010000000000000000, 233 | 0b10000111100000001111011111111011, 0b11111111110000010000000000000000, 234 | 235 | 0b01000111100000001111011111111011, 0b11111111000000100000000000000000, 236 | 0b01000111100000001111011111111011, 0b11111100000000100000000000000000, 237 | 0b00110000000000000000000000000000, 0b00000000000011000000000000000000, 238 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 239 | }, 240 | { // FAST 241 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 242 | 0b00100000000000000000000000000000, 0b00000000000011000000000000000000, 243 | 0b01001111111110001111000000011110, 0b00011111111100100000000000000000, 244 | 0b10001111111110001111000001111111, 0b10011111111100100000000000000000, 245 | 0b10001111111110011111100011111111, 0b11011111111100010000000000000000, 246 | 0b10001111111110011111100011111111, 0b11011111111100010000000000000000, 247 | 0b10001110000000011111100011100011, 0b11000011100000010000000000000000, 248 | 0b10001110000000111001110011110001, 0b11000011100000010000000000000000, 249 | 250 | 0b10001110000000111001110001111100, 0b00000011100000010000000000000000, 251 | 0b10001111111100111001110000111111, 0b00000011100000010000000000000000, 252 | 0b10001111111100111001110000011111, 0b00000011100000010000000000000000, 253 | 0b10001111111100111001110000001111, 0b10000011100000010000000000000000, 254 | 0b10001111111101111111111011100011, 0b11000011100000010000000000000000, 255 | 0b10001110000001111111111011110001, 0b11000011100000010000000000000000, 256 | 0b10001110000001111111111011111111, 0b11000011100000010000000000000000, 257 | 0b10001110000001110000111011111111, 0b11000011100000010000000000000000, 258 | 259 | 0b01001110000001110000111001111111, 0b10000011100000100000000000000000, 260 | 0b01001110000001110000111000011110, 0b00000011100000100000000000000000, 261 | 0b00110000000000000000000000000000, 0b00000000000011000000000000000000, 262 | 0b00001111111111111111111111111111, 0b11111111111100001000000000000000, 263 | }, 264 | }; 265 | 266 | #if 0 267 | const uint32_t icons64x24[][2*24] = { 268 | { // LSB 269 | 0b00001111111111111111111111111111, 0b11111111111111111111111111110000, 270 | 0b00111111111111111111111111111111, 0b11111111111111111111111111111100, 271 | 0b00111111111111111111111111111111, 0b11111111111111111111111111111100, 272 | 0b01111111100001111111111111110000, 0b01111111000000000011111111111110, 273 | 0b01111111100001111111111110000000, 0b00001111000000000000011111111110, 274 | 0b11111111100001111111111100000000, 0b00000111000000000000001111111111, 275 | 0b11111111100001111111111000000000, 0b00000011000000000000000111111111, 276 | 0b11111111100001111111111000001111, 0b10000011000011111100000111111111, 277 | 278 | 0b11111111100001111111111000000111, 0b11000011000011111110000111111111, 279 | 0b11111111100001111111111000000001, 0b11111111000011111000000111111111, 280 | 0b11111111100001111111111110000000, 0b11111111000000000000011111111111, 281 | 0b11111111100001111111111111100000, 0b00111111000000000000111111111111, 282 | 0b11111111100001111111111111111000, 0b00011111000000000000011111111111, 283 | 0b11111111100001111111111111111110, 0b00000111000011111000001111111111, 284 | 0b11111111100001111111111000011111, 0b00000011000011111110000111111111, 285 | 0b11111111100001111111111000001111, 0b10000011000011111100000111111111, 286 | 287 | 0b11111111100000000000001000000000, 0b00000011000000000000000111111111, 288 | 0b11111111100000000000001100000000, 0b00000111000000000000001111111111, 289 | 0b01111111100000000000001111000000, 0b00001111000000000000011111111110, 290 | 0b01111111100000000000001111111000, 0b01111111000000000011111111111110, 291 | 0b00111111111111111111111111111111, 0b11111111111111111111111111111100, 292 | 0b00111111111111111111111111111111, 0b11111111111111111111111111111100, 293 | 0b00001111111111111111111111111111, 0b11111111111111111111111111110000, 294 | 0b00000000000000000000000000000000, 0b00000000000000000000000000000000, 295 | }, 296 | }; 297 | const uint32_t icons64x16[][2*16] = { 298 | { // LSB 299 | 0b00001111111111111111111111111111, 0b11111111111111111111111111110000, 300 | 0b00111111111111111111111111111111, 0b11111111111111111111111111111100, 301 | 0b01110001111111111111111111100000, 0b00000111111000000000000001111110, 302 | 0b01110001111111111111111100000000, 0b00000000111000000000000000011110, 303 | 0b11110001111111111111110000000000, 0b00000000011000000000000000001111, 304 | 0b11110001111111111111110000011111, 0b11111000011000111111111110001111, 305 | 0b11110001111111111111111000000111, 0b11111100011000111111111100001111, 306 | 0b11110001111111111111111110000000, 0b00011111111000000000000000011111, 307 | 308 | 0b11110001111111111111111111110000, 0b00000011111000000000000000011111, 309 | 0b11110001111111111111110001111111, 0b10000000111000111111111100001111, 310 | 0b11110001111111111111110000111111, 0b11110000011000111111111110001111, 311 | 0b11110000000000000000111000000000, 0b00000000011000000000000000001111, 312 | 0b01110000000000000000111100000000, 0b00000000111000000000000000011110, 313 | 0b01110000000000000000111111100000, 0b00000111111000000000000001111110, 314 | 0b00111111111111111111111111111111, 0b11111111111111111111111111111100, 315 | 0b00001111111111111111111111111111, 0b11111111111111111111111111110000, 316 | } 317 | }; 318 | 319 | const uint32_t icons32x12[][12] = { 320 | { // LSB 321 | 0b00111111111111111111111111111000, 322 | 0b01100111111110000111100000111100, 323 | 0b11100111111100000011100000011110, 324 | 0b11100111111000110001100111001110, 325 | 0b11100111111001111001100111001110, 326 | 0b11100111111000111111100000011110, 327 | 0b11100111111100000111100000011110, 328 | 0b11100111111111110000100111001110, 329 | 330 | 0b11100111111001111000100111001110, 331 | 0b11100000001000000000100000001110, 332 | 0b01100000001110000011100000111100, 333 | 0b00111111111111111111111111111000, 334 | }, 335 | }; 336 | #endif 337 | -------------------------------------------------------------------------------- /ili9341.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com 3 | * All rights reserved. 4 | * 5 | * This is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3, or (at your option) 8 | * any later version. 9 | * 10 | * The software is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with GNU Radio; see the file COPYING. If not, write to 17 | * the Free Software Foundation, Inc., 51 Franklin Street, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | #include "ch.h" 21 | #include "hal.h" 22 | #include "nanosdr.h" 23 | 24 | #define RESET_ASSERT palClearPad(GPIOA, 15) 25 | #define RESET_NEGATE palSetPad(GPIOA, 15) 26 | #define CS_LOW palClearPad(GPIOB, 6) 27 | #define CS_HIGH palSetPad(GPIOB, 6) 28 | #define DC_CMD palClearPad(GPIOB, 7) 29 | #define DC_DATA palSetPad(GPIOB, 7) 30 | 31 | uint16_t spi_buffer[4096]; 32 | 33 | void 34 | ssp_wait(void) 35 | { 36 | while (SPI1->SR & SPI_SR_BSY) 37 | ; 38 | } 39 | 40 | void 41 | ssp_wait_slot(void) 42 | { 43 | while ((SPI1->SR & 0x1800) == 0x1800) 44 | ; 45 | } 46 | 47 | void 48 | ssp_senddata(uint8_t x) 49 | { 50 | *(uint8_t*)(&SPI1->DR) = x; 51 | while (SPI1->SR & SPI_SR_BSY) 52 | ; 53 | } 54 | 55 | void 56 | ssp_senddata16(uint16_t x) 57 | { 58 | ssp_wait_slot(); 59 | SPI1->DR = x; 60 | //while (SPI1->SR & SPI_SR_BSY) 61 | // ; 62 | } 63 | 64 | void 65 | ssp_databit8(void) 66 | { 67 | SPI1->CR2 = (SPI1->CR2 & 0xf0ff) | 0x0700; 68 | //LPC_SSP1->CR0 = (LPC_SSP1->CR0 & 0xf0) | SSP_DATABIT_8; 69 | } 70 | 71 | void 72 | ssp_databit16(void) 73 | { 74 | SPI1->CR2 = (SPI1->CR2 & 0xf0ff) | 0x0f00; 75 | //LPC_SSP1->CR0 = (LPC_SSP1->CR0 & 0xf0) | SSP_DATABIT_16; 76 | } 77 | 78 | 79 | const stm32_dma_stream_t *dmatx; 80 | uint32_t txdmamode; 81 | 82 | static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { 83 | (void)spip; 84 | (void)flags; 85 | } 86 | 87 | void 88 | spi_init(void) 89 | { 90 | rccEnableSPI1(FALSE); 91 | 92 | dmatx = STM32_DMA_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM); 93 | txdmamode = STM32_DMA_CR_CHSEL(SPI1_TX_DMA_CHANNEL) | 94 | STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) | 95 | STM32_DMA_CR_DIR_M2P | 96 | STM32_DMA_CR_DMEIE | 97 | STM32_DMA_CR_TEIE | 98 | STM32_DMA_CR_PSIZE_HWORD | 99 | STM32_DMA_CR_MSIZE_HWORD; 100 | dmaStreamAllocate(dmatx, 101 | STM32_SPI_SPI1_IRQ_PRIORITY, 102 | (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, 103 | NULL); 104 | dmaStreamSetPeripheral(dmatx, &SPI1->DR); 105 | 106 | SPI1->CR1 = 0; 107 | SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_SSM | SPI_CR1_SSI;// | SPI_CR1_BR_1; 108 | SPI1->CR2 = 0x0700 | SPI_CR2_TXDMAEN; 109 | SPI1->CR1 |= SPI_CR1_SPE; 110 | } 111 | 112 | void 113 | send_command(uint8_t cmd, int len, const uint8_t *data) 114 | { 115 | CS_LOW; 116 | DC_CMD; 117 | ssp_databit8(); 118 | ssp_senddata(cmd); 119 | DC_DATA; 120 | while (len-- > 0) { 121 | ssp_senddata(*data++); 122 | } 123 | //CS_HIGH; 124 | } 125 | 126 | const uint8_t ili9341_init_seq[] = { 127 | // cmd, len, data..., 128 | // Power control B 129 | 0xCF, 3, 0x00, 0x83, 0x30, 130 | // Power on sequence control 131 | 0xED, 4, 0x64, 0x03, 0x12, 0x81, 132 | //0xED, 4, 0x55, 0x01, 0x23, 0x01, 133 | // Driver timing control A 134 | 0xE8, 3, 0x85, 0x01, 0x79, 135 | //0xE8, 3, 0x84, 0x11, 0x7a, 136 | // Power control A 137 | 0xCB, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, 138 | // Pump ratio control 139 | 0xF7, 1, 0x20, 140 | // Driver timing control B 141 | 0xEA, 2, 0x00, 0x00, 142 | // POWER_CONTROL_1 143 | 0xC0, 1, 0x26, 144 | // POWER_CONTROL_2 145 | 0xC1, 1, 0x11, 146 | // VCOM_CONTROL_1 147 | 0xC5, 2, 0x35, 0x3E, 148 | // VCOM_CONTROL_2 149 | 0xC7, 1, 0xBE, 150 | // MEMORY_ACCESS_CONTROL 151 | //0x36, 1, 0x48, // portlait 152 | 0x36, 1, 0x28, // landscape 153 | // COLMOD_PIXEL_FORMAT_SET : 16 bit pixel 154 | 0x3A, 1, 0x55, 155 | // Frame Rate 156 | 0xB1, 2, 0x00, 0x1B, 157 | // Gamma Function Disable 158 | 0xF2, 1, 0x08, 159 | // gamma set for curve 01/2/04/08 160 | 0x26, 1, 0x01, 161 | // positive gamma correction 162 | 0xE0, 15, 0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0x87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00, 163 | // negativ gamma correction 164 | 0xE1, 15, 0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F, 165 | 166 | // Column Address Set 167 | 0x2A, 4, 0x00, 0x00, 0x01, 0x3f, // width 320 168 | // Page Address Set 169 | 0x2B, 4, 0x00, 0x00, 0x00, 0xef, // height 240 170 | 171 | // entry mode 172 | 0xB7, 1, 0x06, 173 | // display function control 174 | 0xB6, 4, 0x0A, 0x82, 0x27, 0x00, 175 | 176 | // control display 177 | //0x53, 1, 0x0c, 178 | // diaplay brightness 179 | //0x51, 1, 0xff, 180 | 181 | // sleep out 182 | 0x11, 0, 183 | 0 // sentinel 184 | }; 185 | 186 | void 187 | ili9341_init(void) 188 | { 189 | spi_init(); 190 | #if 1 191 | DC_DATA; 192 | RESET_ASSERT; 193 | chThdSleepMilliseconds(10); 194 | RESET_NEGATE; 195 | 196 | send_command(0x01, 0, NULL); // SW reset 197 | chThdSleepMilliseconds(5); 198 | send_command(0x28, 0, NULL); // display off 199 | 200 | const uint8_t *p; 201 | for (p = ili9341_init_seq; *p; ) { 202 | send_command(p[0], p[1], &p[2]); 203 | p += 2 + p[1]; 204 | chThdSleepMilliseconds(5); 205 | } 206 | 207 | chThdSleepMilliseconds(100); 208 | send_command(0x29, 0, NULL); // display on 209 | #endif 210 | } 211 | 212 | void ili9341_pixel(int x, int y, int color) 213 | { 214 | uint8_t xx[4] = { x >> 8, x, (x+1) >> 8, (x+1) }; 215 | uint8_t yy[4] = { y >> 8, y, (y+1) >> 8, (y+1) }; 216 | uint8_t cc[2] = { color >> 8, color }; 217 | send_command(0x2A, 4, xx); 218 | send_command(0x2B, 4, yy); 219 | send_command(0x2C, 2, cc); 220 | //send_command16(0x2C, color); 221 | } 222 | 223 | 224 | 225 | void ili9341_fill(int x, int y, int w, int h, int color) 226 | { 227 | uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) }; 228 | uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) }; 229 | int len = w * h; 230 | send_command(0x2A, 4, xx); 231 | send_command(0x2B, 4, yy); 232 | send_command(0x2C, 0, NULL); 233 | while (len-- > 0) 234 | ssp_senddata16(color); 235 | } 236 | 237 | void ili9341_draw_bitmap(int x, int y, int w, int h, uint16_t *buf) 238 | { 239 | uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) }; 240 | uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) }; 241 | int len = w * h; 242 | 243 | send_command(0x2A, 4, xx); 244 | send_command(0x2B, 4, yy); 245 | send_command(0x2C, 0, NULL); 246 | 247 | dmaStreamSetMemory0(dmatx, buf); 248 | dmaStreamSetTransactionSize(dmatx, len); 249 | dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_MINC); 250 | dmaStreamEnable(dmatx); 251 | dmaWaitCompletion(dmatx); 252 | } 253 | 254 | void 255 | ili9341_drawchar_5x7(uint8_t ch, int x, int y, uint16_t fg, uint16_t bg) 256 | { 257 | uint16_t *buf = spi_buffer; 258 | uint16_t bits; 259 | int c, r; 260 | for(c = 0; c < 7; c++) { 261 | bits = x5x7_bits[(ch * 7) + c]; 262 | for (r = 0; r < 5; r++) { 263 | *buf++ = (0x8000 & bits) ? fg : bg; 264 | bits <<= 1; 265 | } 266 | } 267 | ili9341_draw_bitmap(x, y, 5, 7, spi_buffer); 268 | } 269 | 270 | void 271 | ili9341_drawstring_5x7(const char *str, int x, int y, uint16_t fg, uint16_t bg) 272 | { 273 | while (*str) { 274 | ili9341_drawchar_5x7(*str, x, y, fg, bg); 275 | x += 5; 276 | str++; 277 | } 278 | } 279 | 280 | #define SWAP(x,y) do { int z=x; x = y; y = z; } while(0) 281 | 282 | const font_t NF20x24 = { 20, 24, 1, 24, 1, (const uint32_t *)numfont20x24 }; 283 | const font_t NF32x24 = { 32, 24, 1, 24, 1, (const uint32_t *)numfont32x24 }; 284 | const font_t NF32x48 = { 32, 48, 2, 24, 1, (const uint32_t *)numfont32x24 }; 285 | const font_t ICON48x20 = { 48, 20, 1, 40, 2, (const uint32_t *)icons48x20 }; 286 | 287 | void 288 | ili9341_drawfont(uint8_t ch, const font_t *font, int x, int y, uint16_t fg, uint16_t bg) 289 | { 290 | uint16_t *buf = spi_buffer; 291 | uint32_t bits; 292 | const uint32_t *bitmap = &font->bitmap[font->slide * ch]; 293 | int c, r, j, b; 294 | 295 | for (c = 0; c < font->slide; c += font->stride) { 296 | for (j = 0; j < font->scaley; j++) { 297 | int cc = c; 298 | for (r = 0; r < font->width;) { 299 | bits = bitmap[cc++]; 300 | for (b = 0; b < 32 && r < font->width; b++,r++) { 301 | *buf++ = (0x80000000UL & bits) ? fg : bg; 302 | bits <<= 1; 303 | } 304 | } 305 | } 306 | } 307 | ili9341_draw_bitmap(x, y, font->width, font->height, spi_buffer); 308 | } 309 | 310 | void 311 | ili9341_drawfont_string(const char *str, const font_t *font, int x, int y, uint16_t fg, uint16_t bg) 312 | { 313 | while (*str) { 314 | char c = *str++; 315 | if (c >= '0' && c <= '9') 316 | ili9341_drawfont(c - '0', font, x, y, fg, bg); 317 | else if (c > 0 && c < 7) 318 | ili9341_drawfont(c + 9, font, x, y, fg, bg); 319 | else if (c == '.') 320 | ili9341_drawfont(10, font, x, y, fg, bg); 321 | else if (c == '-') 322 | ili9341_drawfont(11, font, x, y, fg, bg); 323 | else 324 | ili9341_fill(x, y, font->width, font->height, bg); 325 | x += font->width; 326 | } 327 | } 328 | 329 | void 330 | ili9341_set_direction(int rot180) 331 | { 332 | char value = 0x28; // landscape 333 | if (rot180) { 334 | value |= 0xc0; // reverse X and Y axis 335 | } 336 | 337 | send_command(0x36, 1, &value); 338 | } 339 | -------------------------------------------------------------------------------- /mcuconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef MCUCONF_H 18 | #define MCUCONF_H 19 | 20 | /* 21 | * STM32F3xx drivers configuration. 22 | * The following settings override the default settings present in 23 | * the various device driver implementation headers. 24 | * Note that the settings for each driver only have effect if the whole 25 | * driver is enabled in halconf.h. 26 | * 27 | * IRQ priorities: 28 | * 15...0 Lowest...Highest. 29 | * 30 | * DMA priorities: 31 | * 0...3 Lowest...Highest. 32 | */ 33 | 34 | #define STM32F3xx_MCUCONF 35 | 36 | /* 37 | * HAL driver system settings. 38 | */ 39 | #define STM32_NO_INIT FALSE 40 | //#define STM32_NO_INIT TRUE 41 | #define STM32_PVD_ENABLE FALSE 42 | #define STM32_PLS STM32_PLS_LEV0 43 | #define STM32_HSI_ENABLED TRUE 44 | #define STM32_LSI_ENABLED TRUE 45 | #define STM32_HSE_ENABLED TRUE 46 | #define STM32_LSE_ENABLED FALSE 47 | #define STM32_SW STM32_SW_PLL 48 | //#define STM32_SW STM32_SW_HSI 49 | #define STM32_PLLSRC STM32_PLLSRC_HSE 50 | #define STM32_PREDIV_VALUE 1 51 | #define STM32_PLLMUL_VALUE 9 52 | #define STM32_HPRE STM32_HPRE_DIV1 53 | #define STM32_PPRE1 STM32_PPRE1_DIV2 54 | #define STM32_PPRE2 STM32_PPRE2_DIV1 55 | #define STM32_MCOSEL STM32_MCOSEL_PLLDIV2 56 | #define STM32_ADC12PRES STM32_ADC12PRES_DIV64 57 | #define STM32_ADC34PRES STM32_ADC34PRES_DIV1 58 | #define STM32_USART1SW STM32_USART1SW_PCLK 59 | #define STM32_USART2SW STM32_USART2SW_PCLK 60 | #define STM32_USART3SW STM32_USART3SW_PCLK 61 | #define STM32_UART4SW STM32_UART4SW_PCLK 62 | #define STM32_UART5SW STM32_UART5SW_PCLK 63 | #define STM32_I2C1SW STM32_I2C1SW_SYSCLK 64 | #define STM32_I2C2SW STM32_I2C2SW_SYSCLK 65 | #define STM32_TIM1SW STM32_TIM1SW_PCLK2 66 | #define STM32_TIM8SW STM32_TIM8SW_PCLK2 67 | #define STM32_RTCSEL STM32_RTCSEL_LSI 68 | #define STM32_USB_CLOCK_REQUIRED TRUE 69 | #define STM32_USBPRE STM32_USBPRE_DIV1P5 70 | 71 | /* 72 | * ADC driver system settings. 73 | */ 74 | #define STM32_ADC_USE_ADC1 TRUE 75 | #define STM32_ADC_USE_ADC3 FALSE 76 | #define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) 77 | #define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) 78 | #define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) 79 | #define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) 80 | #define STM32_ADC_ADC12_DMA_PRIORITY 2 81 | #define STM32_ADC_ADC34_DMA_PRIORITY 2 82 | #define STM32_ADC_ADC12_IRQ_PRIORITY 5 83 | #define STM32_ADC_ADC34_IRQ_PRIORITY 5 84 | #define STM32_ADC_ADC12_DMA_IRQ_PRIORITY 5 85 | #define STM32_ADC_ADC34_DMA_IRQ_PRIORITY 5 86 | #define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4 87 | #define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 88 | #define STM32_ADC_DUAL_MODE FALSE 89 | 90 | /* 91 | * CAN driver system settings. 92 | */ 93 | #define STM32_CAN_USE_CAN1 FALSE 94 | #define STM32_CAN_CAN1_IRQ_PRIORITY 11 95 | 96 | /* 97 | * DAC driver system settings. 98 | */ 99 | #define STM32_DAC_DUAL_MODE FALSE 100 | #define STM32_DAC_USE_DAC1_CH1 TRUE 101 | #define STM32_DAC_USE_DAC1_CH2 FALSE 102 | #define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 103 | #define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 104 | #define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 105 | #define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 106 | 107 | /* 108 | * EXT driver system settings. 109 | */ 110 | #define STM32_EXT_EXTI0_IRQ_PRIORITY 6 111 | #define STM32_EXT_EXTI1_IRQ_PRIORITY 6 112 | #define STM32_EXT_EXTI2_IRQ_PRIORITY 6 113 | #define STM32_EXT_EXTI3_IRQ_PRIORITY 6 114 | #define STM32_EXT_EXTI4_IRQ_PRIORITY 6 115 | #define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 116 | #define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6 117 | #define STM32_EXT_EXTI16_IRQ_PRIORITY 6 118 | #define STM32_EXT_EXTI17_IRQ_PRIORITY 6 119 | #define STM32_EXT_EXTI18_IRQ_PRIORITY 6 120 | #define STM32_EXT_EXTI19_IRQ_PRIORITY 6 121 | #define STM32_EXT_EXTI20_IRQ_PRIORITY 6 122 | #define STM32_EXT_EXTI21_22_29_IRQ_PRIORITY 6 123 | #define STM32_EXT_EXTI30_32_IRQ_PRIORITY 6 124 | #define STM32_EXT_EXTI33_IRQ_PRIORITY 6 125 | 126 | /* 127 | * GPT driver system settings. 128 | */ 129 | #define STM32_GPT_USE_TIM1 FALSE 130 | #define STM32_GPT_USE_TIM2 FALSE 131 | #define STM32_GPT_USE_TIM3 FALSE 132 | #define STM32_GPT_USE_TIM4 FALSE 133 | #define STM32_GPT_USE_TIM6 FALSE 134 | #define STM32_GPT_USE_TIM7 FALSE 135 | #define STM32_GPT_USE_TIM8 FALSE 136 | #define STM32_GPT_TIM1_IRQ_PRIORITY 7 137 | #define STM32_GPT_TIM2_IRQ_PRIORITY 7 138 | #define STM32_GPT_TIM3_IRQ_PRIORITY 7 139 | #define STM32_GPT_TIM4_IRQ_PRIORITY 7 140 | #define STM32_GPT_TIM6_IRQ_PRIORITY 7 141 | #define STM32_GPT_TIM7_IRQ_PRIORITY 7 142 | #define STM32_GPT_TIM8_IRQ_PRIORITY 7 143 | 144 | /* 145 | * I2C driver system settings. 146 | */ 147 | #define STM32_I2C_USE_I2C1 TRUE 148 | #define STM32_I2C_USE_I2C2 FALSE 149 | #define STM32_I2C_BUSY_TIMEOUT 50 150 | #define STM32_I2C_I2C1_IRQ_PRIORITY 10 151 | #define STM32_I2C_I2C2_IRQ_PRIORITY 10 152 | #define STM32_I2C_USE_DMA TRUE 153 | #define STM32_I2C_I2C1_DMA_PRIORITY 1 154 | #define STM32_I2C_I2C2_DMA_PRIORITY 1 155 | #define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") 156 | 157 | /* 158 | * I2S driver system settings. 159 | */ 160 | #define STM32_I2S_USE_SPI1 FALSE 161 | #define STM32_I2S_USE_SPI2 TRUE 162 | #define STM32_I2S_SPI1_MODE (STM32_I2S_MODE_MASTER | \ 163 | STM32_I2S_MODE_RX) 164 | #define STM32_I2S_SPI2_MODE (STM32_I2S_MODE_SLAVE | \ 165 | STM32_I2S_MODE_TX | \ 166 | STM32_I2S_MODE_FULLDUPLEX) 167 | #define STM32_I2S_SPI1_IRQ_PRIORITY 2 168 | #define STM32_I2S_SPI2_IRQ_PRIORITY 2 169 | #define STM32_I2S_SPI1_DMA_PRIORITY 1 170 | #define STM32_I2S_SPI2_DMA_PRIORITY 1 171 | #define STM32_I2S_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) 172 | #define STM32_I2S_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) 173 | #define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) 174 | #define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) 175 | #define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") 176 | 177 | /* 178 | * ICU driver system settings. 179 | */ 180 | #define STM32_ICU_USE_TIM1 FALSE 181 | #define STM32_ICU_USE_TIM2 FALSE 182 | #define STM32_ICU_USE_TIM3 FALSE 183 | #define STM32_ICU_USE_TIM4 FALSE 184 | #define STM32_ICU_USE_TIM8 FALSE 185 | #define STM32_ICU_TIM1_IRQ_PRIORITY 7 186 | #define STM32_ICU_TIM2_IRQ_PRIORITY 7 187 | #define STM32_ICU_TIM3_IRQ_PRIORITY 7 188 | #define STM32_ICU_TIM4_IRQ_PRIORITY 7 189 | #define STM32_ICU_TIM8_IRQ_PRIORITY 7 190 | 191 | /* 192 | * PWM driver system settings. 193 | */ 194 | #define STM32_PWM_USE_ADVANCED FALSE 195 | #define STM32_PWM_USE_TIM1 FALSE 196 | #define STM32_PWM_USE_TIM2 FALSE 197 | #define STM32_PWM_USE_TIM3 FALSE 198 | #define STM32_PWM_USE_TIM4 FALSE 199 | #define STM32_PWM_USE_TIM8 FALSE 200 | #define STM32_PWM_TIM1_IRQ_PRIORITY 7 201 | #define STM32_PWM_TIM2_IRQ_PRIORITY 7 202 | #define STM32_PWM_TIM3_IRQ_PRIORITY 7 203 | #define STM32_PWM_TIM4_IRQ_PRIORITY 7 204 | #define STM32_PWM_TIM8_IRQ_PRIORITY 7 205 | 206 | /* 207 | * SERIAL driver system settings. 208 | */ 209 | #define STM32_SERIAL_USE_USART1 TRUE 210 | #define STM32_SERIAL_USE_USART2 FALSE 211 | #define STM32_SERIAL_USE_USART3 FALSE 212 | #define STM32_SERIAL_USE_UART4 FALSE 213 | #define STM32_SERIAL_USE_UART5 FALSE 214 | #define STM32_SERIAL_USART1_PRIORITY 12 215 | #define STM32_SERIAL_USART2_PRIORITY 12 216 | #define STM32_SERIAL_USART3_PRIORITY 12 217 | #define STM32_SERIAL_UART4_PRIORITY 12 218 | #define STM32_SERIAL_UART5_PRIORITY 12 219 | 220 | /* 221 | * SPI driver system settings. 222 | */ 223 | #define STM32_SPI_USE_SPI1 TRUE 224 | #define STM32_SPI_USE_SPI2 FALSE 225 | #define STM32_SPI_USE_SPI3 FALSE 226 | #define STM32_SPI_SPI1_DMA_PRIORITY 1 227 | #define STM32_SPI_SPI2_DMA_PRIORITY 1 228 | #define STM32_SPI_SPI3_DMA_PRIORITY 1 229 | #define STM32_SPI_SPI1_IRQ_PRIORITY 10 230 | #define STM32_SPI_SPI2_IRQ_PRIORITY 10 231 | #define STM32_SPI_SPI3_IRQ_PRIORITY 10 232 | #define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") 233 | 234 | /* 235 | * ST driver system settings. 236 | */ 237 | #define STM32_ST_IRQ_PRIORITY 8 238 | #define STM32_ST_USE_TIMER 2 239 | 240 | /* 241 | * UART driver system settings. 242 | */ 243 | #define STM32_UART_USE_USART1 FALSE 244 | #define STM32_UART_USE_USART2 FALSE 245 | #define STM32_UART_USE_USART3 FALSE 246 | #define STM32_UART_USART1_IRQ_PRIORITY 12 247 | #define STM32_UART_USART2_IRQ_PRIORITY 12 248 | #define STM32_UART_USART3_IRQ_PRIORITY 12 249 | #define STM32_UART_USART1_DMA_PRIORITY 0 250 | #define STM32_UART_USART2_DMA_PRIORITY 0 251 | #define STM32_UART_USART3_DMA_PRIORITY 0 252 | #define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") 253 | 254 | /* 255 | * USB driver system settings. 256 | */ 257 | #define STM32_USB_USE_USB1 TRUE 258 | #define STM32_USB_LOW_POWER_ON_SUSPEND FALSE 259 | #define STM32_USB_USB1_HP_IRQ_PRIORITY 13 260 | #define STM32_USB_USB1_LP_IRQ_PRIORITY 14 261 | 262 | /* 263 | * WDG driver system settings. 264 | */ 265 | #define STM32_WDG_USE_IWDG FALSE 266 | 267 | #endif /* MCUCONF_H */ 268 | -------------------------------------------------------------------------------- /nanosdr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2017, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com 3 | * All rights reserved. 4 | * 5 | * This is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3, or (at your option) 8 | * any later version. 9 | * 10 | * The software is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with GNU Radio; see the file COPYING. If not, write to 17 | * the Free Software Foundation, Inc., 51 Franklin Street, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | /* 22 | * main.c 23 | */ 24 | 25 | 26 | typedef struct { 27 | int32_t rms[2]; 28 | int16_t ave[2]; 29 | int16_t min[2]; 30 | int16_t max[2]; 31 | 32 | uint32_t callback_count; 33 | int32_t last_counter_value; 34 | int32_t interval_cycles; 35 | int32_t busy_cycles; 36 | 37 | uint16_t fps_count; 38 | uint16_t fps; 39 | uint16_t overflow_count; 40 | uint16_t overflow; 41 | 42 | uint16_t vref; 43 | uint16_t temperature; 44 | uint16_t battery; 45 | } stat_t; 46 | 47 | extern int16_t measured_power_dbm; 48 | extern stat_t stat; 49 | 50 | void set_agc_mode(int agcmode); 51 | 52 | /* 53 | * tlv320aic3204.c 54 | */ 55 | 56 | typedef struct { 57 | int target_level; 58 | int gain_hysteresis; 59 | int attack; 60 | int attack_scale; 61 | int decay; 62 | int decay_scale; 63 | int maximum_gain; 64 | } tlv320aic3204_agc_config_t; 65 | 66 | extern void tlv320aic3204_init(void); 67 | extern void tlv320aic3204_set_gain(int g1, int g2); 68 | extern void tlv320aic3204_set_digital_gain(int g1, int g2); 69 | extern void tlv320aic3204_set_volume(int gain); 70 | extern void tlv320aic3204_agc_config(tlv320aic3204_agc_config_t *conf); 71 | extern void tlv320aic3204_set_fs(int fs); 72 | extern void tlv320aic3204_stop(void); 73 | 74 | extern void tlv320aic3204_config_adc_filter(int enable); 75 | extern void tlv320aic3204_config_adc_filter2(double iqbal); 76 | extern void tlv320aic3204_set_impedance(int imp); 77 | 78 | extern int tlv320aic3204_get_sticky_flag_register(void); 79 | extern int8_t tlv320aic3204_get_left_agc_gain(void); 80 | extern int8_t tlv320aic3204_get_right_agc_gain(void); 81 | extern void tlv320aic3204_set_adc_phase_adjust(int8_t adjust); 82 | extern void tlv320aic3204_set_adc_fine_gain_adjust(int8_t g1, int8_t g2); 83 | 84 | extern void tlv320aic3204_beep(void); 85 | 86 | #define AIC3204_STICKY_ADC_OVERFLOW 0x0c 87 | 88 | /* 89 | * dsp.c 90 | */ 91 | 92 | // 5ms @ 48kHz 93 | #define AUDIO_BUFFER_LEN 480 94 | 95 | extern int16_t rx_buffer[AUDIO_BUFFER_LEN * 2]; 96 | extern int16_t tx_buffer[AUDIO_BUFFER_LEN * 2]; 97 | extern int16_t buffer[2][AUDIO_BUFFER_LEN]; 98 | extern int16_t buffer2[2][AUDIO_BUFFER_LEN]; 99 | 100 | typedef enum { B_CAPTURE, B_IF1, B_IF2, B_PLAYBACK, BUFFERS_MAX } buffer_t; 101 | 102 | typedef struct { 103 | enum { BT_C_INTERLEAVE, BT_IQ, BT_R_INTERLEAVE, BT_REAL } type; 104 | int16_t length; 105 | int16_t *buf0; 106 | int16_t *buf1; 107 | } buffer_ref_t; 108 | 109 | extern const buffer_ref_t buffers_table[BUFFERS_MAX]; 110 | 111 | 112 | typedef void (*signal_process_func_t)(int16_t *src, int16_t *dst, size_t len); 113 | 114 | extern signal_process_func_t signal_process; 115 | 116 | void am_demod(int16_t *src, int16_t *dst, size_t len); 117 | void cw_demod(int16_t *src, int16_t *dst, size_t len); 118 | void lsb_demod(int16_t *src, int16_t *dst, size_t len); 119 | void usb_demod(int16_t *src, int16_t *dst, size_t len); 120 | void fm_demod(int16_t *src, int16_t *dst, size_t len); 121 | void fm_demod_stereo(int16_t *src, int16_t *dst, size_t len); 122 | 123 | void dsp_init(void); 124 | 125 | #define FS 48000 126 | #define AM_FREQ_OFFSET 10000 127 | #define SSB_FREQ_OFFSET 1300 128 | #define PHASESTEP(freq) (65536L * freq / FS) 129 | 130 | extern int32_t center_frequency; 131 | extern int16_t mode_freq_offset; 132 | extern int16_t mode_freqoffset_phasestep; 133 | extern int16_t cw_tone_phasestep; 134 | 135 | typedef struct { 136 | int16_t *buffer; 137 | int16_t stride; 138 | int16_t count; 139 | int16_t coeff; 140 | 141 | int32_t accumlate; 142 | int16_t offset; 143 | } dcrejection_t; 144 | 145 | 146 | // state variables for stereo separation 147 | 148 | typedef struct { 149 | uint32_t phase_step_default; 150 | uint32_t phase_step; 151 | uint32_t phase_accum; 152 | 153 | // average of correlation vector angle 154 | int32_t sdi; 155 | int32_t sdq; 156 | 157 | int32_t corr; 158 | int32_t corr_ave; 159 | int32_t corr_std; 160 | int16_t integrator; 161 | 162 | } stereo_separate_state_t; 163 | 164 | extern stereo_separate_state_t stereo_separate_state; 165 | 166 | 167 | /* 168 | * font: Font5x7.c numfont32x24.c numfont20x24.c icons.c 169 | */ 170 | 171 | extern const uint16_t x5x7_bits []; 172 | extern const uint32_t numfont20x24[][24]; 173 | extern const uint32_t numfont32x24[][24]; 174 | extern const uint32_t icons48x20[][20*2]; 175 | 176 | #define S_PI "\034" 177 | #define S_MICRO "\035" 178 | #define S_OHM "\036" 179 | #define S_DEGREE "\037" 180 | #define S_RARROW "\033" 181 | 182 | #define ICON_AGC_OFF 6 183 | 184 | 185 | /* 186 | * ili9341.c 187 | */ 188 | 189 | #define RGB565(b,g,r) ( (((r)<<8)&0xf800) | (((g)<<3)&0x07e0) | (((b)>>3)&0x001f) ) 190 | 191 | typedef struct { 192 | uint16_t width; 193 | uint16_t height; 194 | uint16_t scaley; 195 | uint16_t slide; 196 | uint16_t stride; 197 | const uint32_t *bitmap; 198 | } font_t; 199 | 200 | extern const font_t NF20x24; 201 | extern const font_t NF32x24; 202 | extern const font_t NF32x48; 203 | extern const font_t ICON48x20; 204 | 205 | extern uint16_t spi_buffer[]; 206 | 207 | void ili9341_init(void); 208 | void ili9341_test(int mode); 209 | void ili9341_bulk(int x, int y, int w, int h); 210 | void ili9341_fill(int x, int y, int w, int h, int color); 211 | void ili9341_draw_bitmap(int x, int y, int w, int h, uint16_t *bitmap); 212 | void ili9341_drawchar_5x7(uint8_t ch, int x, int y, uint16_t fg, uint16_t bg); 213 | void ili9341_drawstring_5x7(const char *str, int x, int y, uint16_t fg, uint16_t bg); 214 | void ili9341_drawfont(uint8_t ch, const font_t *font, int x, int y, uint16_t fg, uint16_t bg); 215 | void ili9341_drawfont_string(const char *str, const font_t *font, int x, int y, uint16_t fg, uint16_t bg); 216 | void ili9341_set_direction(int rot180); 217 | 218 | 219 | /* 220 | * display.c 221 | */ 222 | 223 | void disp_init(void); 224 | void disp_process(void); 225 | void disp_fetch_samples(int bufid, int type, int16_t *buf0, int16_t *buf1, size_t len); 226 | void disp_update(void); 227 | void disp_update_power(void); 228 | void disp_clear_aux(void); 229 | 230 | void set_window_function(int wf_type); 231 | 232 | 233 | /* 234 | * ui.c 235 | */ 236 | 237 | extern void ui_init(void); 238 | extern void ui_process(void); 239 | 240 | typedef enum { 241 | MOD_CW, 242 | MOD_LSB, 243 | MOD_USB, 244 | MOD_AM, 245 | MOD_FM, 246 | MOD_FM_STEREO, 247 | MOD_MAX 248 | } modulation_t; 249 | 250 | extern void set_tune(int hz); 251 | extern void set_modulation(modulation_t mod); 252 | extern void recall_channel(unsigned int channel); 253 | extern void set_fs(int fs); 254 | 255 | 256 | typedef struct { 257 | enum { CHANNEL, FREQ, VOLUME, MOD, AGC, RFGAIN, AGC_MAXGAIN, CWTONE, IQBAL, 258 | SPDISP, WFDISP, MODE_MAX } mode; 259 | int8_t volume; 260 | uint8_t channel; 261 | 262 | uint32_t freq; 263 | modulation_t modulation; 264 | int16_t rfgain; 265 | uint8_t fs; /* 48, 96, 192 */ 266 | 267 | enum { AGC_MANUAL, AGC_SLOW, AGC_MID, AGC_FAST, AGC_MAX } agcmode; 268 | int8_t digit; /* 0~5 */ 269 | int freq_offset; 270 | enum { SPDISP_CAP, SPDISP_CAP2, SPDISP_IF, SPDISP_AUD, SPDISP_MODE_MAX } spdispmode; 271 | enum { WATERFALL, WAVEFORM, WAVEFORM_MAG, WAVEFORM_MAG2, WFDISP_MODE_MAX } wfdispmode; 272 | int16_t cw_tone_freq; 273 | int16_t iqbal; 274 | } uistat_t; 275 | 276 | extern uistat_t uistat; 277 | 278 | /* 279 | * flash.c 280 | */ 281 | 282 | #define CHANNEL_MAX 100 283 | 284 | typedef struct { 285 | uint32_t freq; 286 | modulation_t modulation; 287 | } channel_t; 288 | 289 | typedef struct { 290 | int32_t magic; 291 | uint16_t dac_value; 292 | tlv320aic3204_agc_config_t agc; 293 | channel_t channels[CHANNEL_MAX]; 294 | uistat_t uistat; 295 | int8_t freq_inverse; 296 | uint8_t button_polarity; 297 | int8_t lcd_rotation; 298 | int32_t checksum; 299 | } config_t; 300 | 301 | extern config_t config; 302 | 303 | #define CONFIG_MAGIC 0x434f4e45 /* 'CONF' */ 304 | 305 | int config_save(void); 306 | int config_recall(void); 307 | 308 | void clear_all_config_prop_data(void); 309 | 310 | /*EOF*/ 311 | -------------------------------------------------------------------------------- /numfont32x24.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com 3 | * All rights reserved. 4 | * 5 | * This is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3, or (at your option) 8 | * any later version. 9 | * 10 | * The software is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with GNU Radio; see the file COPYING. If not, write to 17 | * the Free Software Foundation, Inc., 51 Franklin Street, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #include 22 | 23 | const uint32_t numfont32x24[][24] = { 24 | { // 0 25 | 0b00000000001111111111000000000000, 26 | 0b00000001111111111111111000000000, 27 | 0b00000111111111111111111110000000, 28 | 0b00011111111111111111111111100000, 29 | 0b00111111111000000001111111110000, 30 | 0b01111111100000000000011111111000, 31 | 0b01111111000000000000001111111000, 32 | 0b11111111000000000000001111111100, 33 | 34 | 0b11111110000000000000000111111100, 35 | 0b11111110000000000000000111111100, 36 | 0b11111110000000000000000111111100, 37 | 0b11111110000000000000000111111100, 38 | 0b11111110000000000000000111111100, 39 | 0b11111110000000000000000111111100, 40 | 0b11111111000000000000001111111100, 41 | 0b01111111000000000000001111111000, 42 | 43 | 0b01111111100000000000011111111000, 44 | 0b00111111111000000001111111110000, 45 | 0b00011111111111111111111111100000, 46 | 0b00000111111111111111111110000000, 47 | 0b00000001111111111111111000000000, 48 | 0b00000000001111111111000000000000, 49 | 0b00000000000000000000000000000000, 50 | 0b00000000000000000000000000000000 51 | }, 52 | { // 1 53 | 0b00000000000001111111000000000000, 54 | 0b00000000000011111111000000000000, 55 | 0b00000000000011111111000000000000, 56 | 0b00000000001111111111000000000000, 57 | 0b00000000011111111111000000000000, 58 | 0b00000001111111111111000000000000, 59 | 0b00000111111111111111000000000000, 60 | 0b00000111111111111111000000000000, 61 | 62 | 0b00000111111111111111000000000000, 63 | 0b00000111111011111111000000000000, 64 | 0b00000000000011111111000000000000, 65 | 0b00000000000011111111000000000000, 66 | 0b00000000000011111111000000000000, 67 | 0b00000000000011111111000000000000, 68 | 0b00000000000011111111000000000000, 69 | 0b00000000000011111111000000000000, 70 | 71 | 0b00000000000011111111000000000000, 72 | 0b00000000000011111111000000000000, 73 | 0b00000000000011111111000000000000, 74 | 0b00000000000011111111000000000000, 75 | 0b00000000000011111111000000000000, 76 | 0b00000000000011111111000000000000, 77 | 0b00000000000000000000000000000000, 78 | 0b00000000000000000000000000000000 79 | }, 80 | { // 2 81 | 0b00000000001111111111000000000000, 82 | 0b00000001111111111111111000000000, 83 | 0b00000111111111111111111110000000, 84 | 0b00011111111111111111111111100000, 85 | 0b00111111111000000001111111110000, 86 | 0b01111111100000000000011111111000, 87 | 0b11111111000000000000011111111000, 88 | 0b11111111000000000000111111111000, 89 | 90 | 0b00000000000000000011111111110000, 91 | 0b00000000000000011111111111000000, 92 | 0b00000000000011111111111100000000, 93 | 0b00000000111111111111100000000000, 94 | 0b00000011111111111100000000000000, 95 | 0b00001111111111100000000000000000, 96 | 0b00111111111100000000000000000000, 97 | 0b01111111110000000000000000000000, 98 | 99 | 0b11111111100000000000000000000000, 100 | 0b11111111000000000000000000000000, 101 | 0b11111111111111111111111111111100, 102 | 0b11111111111111111111111111111100, 103 | 0b11111111111111111111111111111100, 104 | 0b11111111111111111111111111111100, 105 | 0b00000000000000000000000000000000, 106 | 0b00000000000000000000000000000000 107 | }, 108 | { // 3 109 | 0b00000000001111111111000000000000, 110 | 0b00000001111111111111111000000000, 111 | 0b00000111111111111111111110000000, 112 | 0b00011111111111111111111111100000, 113 | 0b00111111111000000001111111110000, 114 | 0b01111111100000000000011111111000, 115 | 0b11111111000000000000001111111000, 116 | 0b11111111000000000000001111111000, 117 | 118 | 0b00000000000000000000111111110000, 119 | 0b00000000000000111111111111000000, 120 | 0b00000000000000111111111100000000, 121 | 0b00000000000000111111111100000000, 122 | 0b00000000000000111111111111000000, 123 | 0b00000000000000000000111111110000, 124 | 0b11111111000000000000001111111000, 125 | 0b11111111000000000000001111111000, 126 | 127 | 0b01111111100000000000011111111000, 128 | 0b00111111111000000001111111110000, 129 | 0b00011111111111111111111111100000, 130 | 0b00000111111111111111111110000000, 131 | 0b00000001111111111111111000000000, 132 | 0b00000000001111111111000000000000, 133 | 0b00000000000000000000000000000000, 134 | 0b00000000000000000000000000000000 135 | }, 136 | { // 4 137 | 0b00000000000000000011111110000000, 138 | 0b00000000000000000111111110000000, 139 | 0b00000000000000011111111110000000, 140 | 0b00000000000000111111111110000000, 141 | 0b00000000000011111111111110000000, 142 | 0b00000000000111111111111110000000, 143 | 0b00000000011111111001111110000000, 144 | 0b00000000111111110001111110000000, 145 | 146 | 0b00000011111111000001111110000000, 147 | 0b00000111111110000001111110000000, 148 | 0b00011111111000000001111110000000, 149 | 0b00111111110000000001111110000000, 150 | 0b11111111000000000001111110000000, 151 | 0b11111110000000000001111110000000, 152 | 0b11111111111111111111111111111000, 153 | 0b11111111111111111111111111111000, 154 | 155 | 0b11111111111111111111111111111000, 156 | 0b11111111111111111111111111111000, 157 | 0b00000000000000000001111110000000, 158 | 0b00000000000000000001111110000000, 159 | 0b00000000000000000001111110000000, 160 | 0b00000000000000000001111110000000, 161 | 0b00000000000000000000000000000000, 162 | 0b00000000000000000000000000000000 163 | }, 164 | { // 5 165 | 0b11111111111111111111111111111000, 166 | 0b11111111111111111111111111111000, 167 | 0b11111111111111111111111111111000, 168 | 0b11111111111111111111111111111000, 169 | 0b11111110000000000000000000000000, 170 | 0b11111110000000000000000000000000, 171 | 0b11111110000000000000000000000000, 172 | 0b11111110011111111111000000000000, 173 | 174 | 0b11111111111111111111111100000000, 175 | 0b11111111111111111111111111000000, 176 | 0b11111111111111111111111111100000, 177 | 0b11111111100000000011111111110000, 178 | 0b00000000000000000000111111111000, 179 | 0b00000000000000000000011111111000, 180 | 0b00000000000000000000001111111000, 181 | 0b11111111000000000000001111111000, 182 | 183 | 0b01111111100000000000011111111000, 184 | 0b00111111111000000001111111110000, 185 | 0b00011111111111111111111111100000, 186 | 0b00000111111111111111111110000000, 187 | 0b00000001111111111111111000000000, 188 | 0b00000000001111111111000000000000, 189 | 0b00000000000000000000000000000000, 190 | 0b00000000000000000000000000000000 191 | }, 192 | { // 6 193 | 0b00000000001111111111000000000000, 194 | 0b00000001111111111111111000000000, 195 | 0b00001111111111111111111110000000, 196 | 0b00111111111111111111111111100000, 197 | 0b01111111111000000001111111110000, 198 | 0b11111111100000000000000000000000, 199 | 0b11111111000000000000000000000000, 200 | 0b11111110000000000000000000000000, 201 | 202 | 0b11111110011111111111110000000000, 203 | 0b11111111111111111111111110000000, 204 | 0b11111111111111111111111111100000, 205 | 0b11111111111111111111111111110000, 206 | 0b11111111110000000001111111111000, 207 | 0b11111111000000000000011111111000, 208 | 0b11111111000000000000001111111000, 209 | 0b11111111000000000000001111111000, 210 | 211 | 0b01111111100000000000011111111000, 212 | 0b00111111111000000001111111110000, 213 | 0b00011111111111111111111111100000, 214 | 0b00000111111111111111111110000000, 215 | 0b00000001111111111111111000000000, 216 | 0b00000000001111111111000000000000, 217 | 0b00000000000000000000000000000000, 218 | 0b00000000000000000000000000000000 219 | }, 220 | { // 7 221 | 0b11111111111111111111111111111100, 222 | 0b11111111111111111111111111111100, 223 | 0b11111111111111111111111111111100, 224 | 0b11111111111111111111111111111100, 225 | 0b00000000000000000000011111111100, 226 | 0b00000000000000000001111111111100, 227 | 0b00000000000000000111111111100000, 228 | 0b00000000000000011111111110000000, 229 | 230 | 0b00000000000000111111111000000000, 231 | 0b00000000000001111111100000000000, 232 | 0b00000000000011111111000000000000, 233 | 0b00000000000111111110000000000000, 234 | 0b00000000000111111110000000000000, 235 | 0b00000000001111111100000000000000, 236 | 0b00000000001111111100000000000000, 237 | 0b00000000001111111100000000000000, 238 | 239 | 0b00000000011111111000000000000000, 240 | 0b00000000011111111000000000000000, 241 | 0b00000000011111111000000000000000, 242 | 0b00000000011111111000000000000000, 243 | 0b00000000011111111000000000000000, 244 | 0b00000000011111111000000000000000, 245 | 0b00000000000000000000000000000000, 246 | 0b00000000000000000000000000000000 247 | }, 248 | { // 8 249 | 0b00000000001111111111000000000000, 250 | 0b00000001111111111111111000000000, 251 | 0b00000111111111111111111110000000, 252 | 0b00011111111111111111111111100000, 253 | 0b00111111111000000001111111110000, 254 | 0b01111111100000000000011111111000, 255 | 0b01111111000000000000001111111000, 256 | 0b01111111100000000000011111111000, 257 | 258 | 0b00111111111000000001111111110000, 259 | 0b00011111111111111111111111100000, 260 | 0b00000111111111111111111110000000, 261 | 0b00000111111111111111111110000000, 262 | 0b00011111111111111111111111100000, 263 | 0b01111111111000000001111111111000, 264 | 0b11111111100000000000011111111100, 265 | 0b11111111000000000000001111111100, 266 | 267 | 0b11111111100000000000011111111100, 268 | 0b11111111111000000001111111111100, 269 | 0b01111111111111111111111111111000, 270 | 0b00111111111111111111111111110000, 271 | 0b00001111111111111111111111000000, 272 | 0b00000001111111111111111000000000, 273 | 0b00000000000000000000000000000000, 274 | 0b00000000000000000000000000000000 275 | }, 276 | { // 9 277 | 0b00000000011111111111110000000000, 278 | 0b00000011111111111111111110000000, 279 | 0b00001111111111111111111111100000, 280 | 0b00111111111111111111111111110000, 281 | 0b01111111111000000001111111111000, 282 | 0b01111111100000000000011111111000, 283 | 0b11111111000000000000001111111100, 284 | 0b11111111000000000000001111111100, 285 | 286 | 0b11111111100000000000011111111100, 287 | 0b11111111111000000001111111111100, 288 | 0b01111111111111111111111111111100, 289 | 0b00111111111111111111111111111100, 290 | 0b00001111111111111111111111111100, 291 | 0b00000000111111111111111111111100, 292 | 0b00000000000000000000000111111100, 293 | 0b00000000000000000000001111111000, 294 | 295 | 0b01111111100000000000011111111000, 296 | 0b00111111111000000001111111110000, 297 | 0b00011111111111111111111111100000, 298 | 0b00000111111111111111111110000000, 299 | 0b00000001111111111111111000000000, 300 | 0b00000000001111111111000000000000, 301 | 0b00000000000000000000000000000000, 302 | 0b00000000000000000000000000000000 303 | }, 304 | { // Hz = \001 305 | 0b00000000000000000000000000000000, 306 | 0b00000000000000000000000000000000, 307 | 0b00000000000000000000000000000000, 308 | 0b00000000000000000000000000000000, 309 | 0b00000000000000000000000000000000, 310 | 0b00000000000000000000000000000000, 311 | 0b00000000000000000000000000000000, 312 | 0b11111000000111110000000000000000, 313 | 314 | 0b11111000000111110000000000000000, 315 | 0b11111000000111110111111111111110, 316 | 0b11111000000111110111111111111110, 317 | 0b11111000000111110111111111111110, 318 | 0b11111000000111110000000011111100, 319 | 0b11111111111111110000000111111000, 320 | 0b11111111111111110000001111110000, 321 | 0b11111111111111110000011111100000, 322 | 323 | 0b11111000000111110000111111000000, 324 | 0b11111000000111110001111110000000, 325 | 0b11111000000111110011111100000000, 326 | 0b11111000000111110111111111111110, 327 | 0b11111000000111110111111111111110, 328 | 0b11111000000111110111111111111110, 329 | 0b00000000000000000000000000000000, 330 | 0b00000000000000000000000000000000 331 | }, 332 | { // k 333 | 0b00000000000000000000000000000000, 334 | 0b00000000000000000000000000000000, 335 | 0b00000000000000000000000000000000, 336 | 0b00000000000000000000000000000000, 337 | 0b00000000000000000000000000000000, 338 | 0b00000000000000000000000000000000, 339 | 0b00000000000000000000000000000000, 340 | 0b01111100000000000000000000000000, 341 | 342 | 0b01111100000000000000000000000000, 343 | 0b01111100000111111000000000000000, 344 | 0b01111100001111110000000000000000, 345 | 0b01111100011111100000000000000000, 346 | 0b01111100111111000000000000000000, 347 | 0b01111101111110000000000000000000, 348 | 0b01111111111100000000000000000000, 349 | 0b01111111111000000000000000000000, 350 | 351 | 0b01111111111100000000000000000000, 352 | 0b01111101111110000000000000000000, 353 | 0b01111100111111000000000000000000, 354 | 0b01111100011111100000000000000000, 355 | 0b01111100001111110000000000000000, 356 | 0b01111100000111111000100000000000, 357 | 0b00000000000000000000000000000000, 358 | 0b00000000000000000000000000000000 359 | }, 360 | }; 361 | 362 | -------------------------------------------------------------------------------- /prog.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | DFU_UTIL=../dfu-util/src/dfu-util 3 | $DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D build/ch.bin 4 | -------------------------------------------------------------------------------- /python/README.md: -------------------------------------------------------------------------------- 1 | # Python materials for CentSDR 2 | 3 | python関連のファイルです。 4 | 5 | ## DSPデザインファイル 6 | 7 | フィルタ係数の設計に使用したJupyter notebookです。 8 | 9 | - [SSB-Filter-Design.ipynb](SSB-Filter-Design.ipynb) : SSBモード用の1300Hz LPF IIRフィルタ設計 10 | - [CW-Filter-Design.ipynb](CW-Filter-Design.ipynb) : CWモード用の150Hz LPF IIRフィルタ設計 11 | - [TLV320AIC3204-1st-IIR-HPF.ipynb](TLV320AIC3204-1st-IIR-HPF.ipynb) : Codec DSP用DCリジェクトHPFフィルタ 12 | 13 | ## centsdr.py 14 | 15 | CentSDRをスクリプトやコマンドラインから制御するための、モジュール兼コマンドです。 16 | シリアル(USB-CDC)のコマンドを、Pythonスクリプトで行うものです。内部バッファの波形をプロットすることもできます。 17 | 18 | ## Requirement 19 | 20 | - python 2.7 21 | - pyserial 22 | 23 | 波形表示をするにはオプションで下記が必要です 24 | 25 | - numpy 26 | - matplotlib 27 | 28 | ## デバイスの指定 29 | 30 | シリアルポートを指定する必要があります。環境変数`CENTSDR_DEVICE`、または`-d`オプションで指定します。スクリプトの冒頭の`DEFAULT_DEVICE`を修正してもOKです。 31 | 32 | - `$ export CENTSDR_DEVICE=/dev/ttyACM1` 33 | - `$ ./centsdr.py -d /dev/cu.usbmodem401 -p 0` 34 | - `$ CENTSDR_DEVICE=/dev/cu.usbmodem401 ./centsdr.py -p 0` 35 | 36 | ## Usage 37 | 38 | ``` 39 | $ ./centsdr.py -h 40 | Usage: centsdr.py [options] 41 | 42 | Options: 43 | -h, --help show this help message and exit 44 | -d DEV, --dev=DEV device node (default from env var CENTSDR_DEVICE) 45 | -F FREQ, --freqeucy=FREQ 46 | set tuning frequency 47 | -G GAIN, --gain=GAIN gain (0-95) 48 | -V VOLUME, --volume=VOLUME 49 | set volume 50 | -A AGC, --agc=AGC set agc 51 | -M MODE, --mode=MODE set modulation 52 | -C MODE, --channel=MODE 53 | set channel 54 | -P, --power show power 55 | -s, --show show current setting 56 | -S SHOWARG, --show-arg=SHOWARG 57 | show specific setting 58 | -p BUFFER, --plot=BUFFER 59 | plot buffer 60 | -l, --loop loop continuously 61 | ``` 62 | 63 | ## コマンドラインから制御する 64 | 65 | コマンドラインからの制御例を示します。オプションは複数同時に指定できます。 66 | 67 | ### 周波数を設定する 68 | 69 | ``` 70 | $ ./centsdr.py -F 27500000 71 | ``` 72 | 73 | ### 復調モードを設定する 74 | 75 | ``` 76 | $ ./centsdr.py -M fm 77 | ``` 78 | 79 | ### ボリュームを設定する 80 | 81 | ``` 82 | $ ./centsdr.py -V 10 83 | ``` 84 | 85 | ### AGCを設定する 86 | 87 | ``` 88 | $ ./centsdr.py -A mid 89 | ``` 90 | 91 | ### RFゲインを設定する 92 | 93 | ``` 94 | $ ./centsdr.py -G 40 95 | ``` 96 | 97 | ## データ取得 98 | 99 | ### 現在状態を取得する 100 | 101 | ``` 102 | $ ./centsdr.py -s 103 | tune: 27500300 104 | volume: 10 105 | mode: fm 106 | gain: 60 107 | channel: 8 108 | agc: manual 109 | ``` 110 | 111 | ### 電力を取得する 112 | 113 | ``` 114 | $ ./centsdr.py -P 115 | -73.1 116 | ``` 117 | 118 | ### 波形を表示する 119 | 120 | 波形データが保存されているバッファ番号を指定します。 121 | 122 | - 0: Capture buffer 123 | - 1: Audio play buffer 124 | - 2: intermediate buffer 1 125 | - 3: intermediate buffer 2 126 | 127 | ``` 128 | $ ./centsdr.py -p 0 129 | ``` 130 | 131 | クローズは、ウィンドウのクローズボタンです。Ctrl-Cでは消えません。 132 | 133 | `-l`を指定すると連続して表示を行います。 134 | 135 | ``` 136 | $ ./centsdr.py -p 0 -l 137 | ``` 138 | 139 | こちらの停止はCtrl-Cです。クローズボタンでは消えません。 140 | 141 |
142 | 143 |
144 | 145 | ## スクリプトからの使用 146 | 147 | モジュールとしてimportしてスクリプトで使用することができます。 148 | 149 | ``` 150 | from centsdr import CentSDR 151 | sdr = CentSDR() 152 | sdr.set_tune(27500000) 153 | sdr.set_mode('fm') 154 | sdr.set_volume(20) 155 | ``` 156 | -------------------------------------------------------------------------------- /python/centsdr.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import numpy as np 3 | import serial 4 | import struct 5 | import os 6 | import re 7 | 8 | DEFAULT_DEVICE='/dev/cu.usbmodem401' 9 | 10 | class CentSDR(): 11 | def __init__(self, dev = None): 12 | self.dev = dev or os.getenv('CENTSDR_DEVICE') or DEFAULT_DEVICE 13 | self.serial = None 14 | 15 | def __enter__(self): 16 | self.open() 17 | return self 18 | 19 | def __exit__(self, exc_type, exc_value, traceback): 20 | self.close() 21 | 22 | def open(self): 23 | if self.serial is None: 24 | self.serial = serial.Serial(self.dev) 25 | 26 | def close(self): 27 | if self.serial: 28 | self.serial.close() 29 | self.serial = None 30 | 31 | def send_command(self, cmd): 32 | self.open() 33 | self.serial.write(cmd) 34 | self.serial.readline() # discard empty line 35 | 36 | def set_frequency(self, freq): 37 | self.send_command("freq %d\r" % freq) 38 | 39 | def set_tune(self, freq): 40 | self.send_command("tune %d\r" % freq) 41 | 42 | def set_gain(self, gain): 43 | self.send_command("gain %d\r" % gain) 44 | 45 | def set_volume(self, gain): 46 | self.send_command("volume %d\r" % gain) 47 | 48 | def set_fs(self, fs): 49 | self.send_command("fs %d\r" % fs) 50 | 51 | def set_mode(self, mode): 52 | self.send_command("mode %s\r" % mode) 53 | 54 | def set_channel(self, chan): 55 | self.send_command("channel %d\r" % chan) 56 | 57 | def set_agc(self, agc): 58 | self.send_command("agc %s\r" % agc) 59 | 60 | def fetch_data(self): 61 | result = '' 62 | line = '' 63 | while True: 64 | c = self.serial.read() 65 | if c == chr(13): 66 | next # ignore CR 67 | line += c 68 | if c == chr(10): 69 | result += line 70 | line = '' 71 | next 72 | if line.endswith('ch>'): 73 | # stop on prompt 74 | break 75 | return result 76 | 77 | def fetch_array(self, sel): 78 | def hex16(h): 79 | return struct.unpack('>h', h.decode('hex'))[0] 80 | self.send_command("data %d\r" % sel) 81 | data = self.fetch_data() 82 | x = [] 83 | for line in data.split('\n'): 84 | if line: 85 | x.extend([hex16(d) for d in line.strip().split(' ')]) 86 | return np.array(x) 87 | 88 | def data(self, sel = 0): 89 | self.send_command("data %d\r" % sel) 90 | data = self.fetch_data() 91 | x = [] 92 | for line in data.split('\n'): 93 | if line: 94 | d = line.strip().split(' ') 95 | x.append(float(d[0])+float(d[1])*1.j) 96 | return np.array(x) 97 | 98 | def read_power(self): 99 | self.send_command("power\r") 100 | resp = self.fetch_data() 101 | m = re.match(r"power: ([\d.-]+)dBm", resp) 102 | return float(m.group(1)) 103 | 104 | def read_status(self, arg = ''): 105 | self.send_command("show %s\r" % arg) 106 | return self.fetch_data() 107 | 108 | def flush_data(self): 109 | self.send_command("\r") 110 | self.fetch_data() 111 | 112 | def run_as_command(): 113 | from optparse import OptionParser 114 | parser = OptionParser(usage="%prog [options]") 115 | parser.add_option("-d", "--dev", dest="device", 116 | help="device node (default from env var CENTSDR_DEVICE)", metavar="DEV") 117 | parser.add_option("-F", "--freqeucy", type="int", dest="freq", 118 | help="set tuning frequency", metavar="FREQ") 119 | parser.add_option("-G", "--gain", type="int", dest="gain", 120 | help="gain (0-95)", metavar="GAIN") 121 | parser.add_option("-V", "--volume", type="string", dest="volume", 122 | help="set volume", metavar="VOLUME") 123 | parser.add_option("-A", "--agc", type="string", dest="agc", 124 | help="set agc", metavar="AGC") 125 | parser.add_option("-M", "--mode", type="string", dest="mode", 126 | help="set modulation", metavar="MODE") 127 | parser.add_option("-C", "--channel", type="string", dest="channel", 128 | help="set channel", metavar="MODE") 129 | parser.add_option("-P", "--power", action="store_true", dest="power", 130 | help="show power") 131 | parser.add_option("-s", "--show", action="store_true", dest="show", 132 | help="show current setting") 133 | parser.add_option("-S", "--show-arg", type='string', dest="showarg", default='', 134 | help="show specific setting") 135 | parser.add_option("-p", "--plot", dest="buffer", 136 | help="plot buffer", metavar="BUFFER") 137 | parser.add_option("-l", "--loop", action="store_true", dest="loop", default=False, 138 | help="loop continuously") 139 | (opt, args) = parser.parse_args() 140 | sdr = CentSDR(opt.device) 141 | if opt.freq: 142 | sdr.set_tune(opt.freq) 143 | if opt.gain: 144 | sdr.set_gain(opt.gain) 145 | if opt.mode: 146 | sdr.set_mode(opt.mode) 147 | if opt.volume: 148 | sdr.set_volume(int(opt.volume)) 149 | if opt.channel: 150 | sdr.set_channel(int(opt.channel)) 151 | if opt.agc: 152 | sdr.set_agc(opt.agc) 153 | if opt.show: 154 | print sdr.read_status(opt.showarg) 155 | if opt.buffer: 156 | import pylab as pl 157 | sdr.flush_data() 158 | opt.buffer = int(opt.buffer) 159 | samp = sdr.fetch_array(opt.buffer) 160 | if opt.buffer == 0: 161 | samp = np.array(samp[0::2]) + np.array(samp[1::2])*1j 162 | x = range(len(samp)) 163 | if opt.loop: 164 | from signal import signal, SIGINT 165 | def sigint_handler(signum, frame): 166 | opt.loop = False 167 | signal(SIGINT, sigint_handler) 168 | pl.ion() 169 | g1 = pl.plot(x, np.real(samp)) 170 | g2 = pl.plot(x, np.imag(samp)) 171 | pl.ylim(-10000,10000) 172 | pl.xlim(0, len(samp)) 173 | while opt.loop: 174 | samp = sdr.fetch_array(opt.buffer) 175 | if opt.buffer == 0: 176 | samp = np.array(samp[0::2]) + np.array(samp[1::2])*1j 177 | x = range(len(samp)) 178 | g1[0].set_data(x, np.real(samp)) 179 | g2[0].set_data(x, np.imag(samp)) 180 | pl.draw() 181 | pl.pause(0.01) 182 | pl.show() 183 | exit(0) 184 | if opt.power: 185 | print sdr.read_power() 186 | exit(0) 187 | 188 | if __name__ == '__main__': 189 | run_as_command() 190 | -------------------------------------------------------------------------------- /rules_code.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | ENTRY(Reset_Handler) 18 | 19 | SECTIONS 20 | { 21 | vectors : ALIGN(16) SUBALIGN(16) 22 | { 23 | KEEP(*(.vectors)) 24 | } > VECTORS_FLASH AT > VECTORS_FLASH_LMA 25 | 26 | xtors : ALIGN(4) SUBALIGN(4) 27 | { 28 | __init_array_start = .; 29 | KEEP(*(SORT(.init_array.*))) 30 | KEEP(*(.init_array)) 31 | __init_array_end = .; 32 | __fini_array_start = .; 33 | KEEP(*(.fini_array)) 34 | KEEP(*(SORT(.fini_array.*))) 35 | __fini_array_end = .; 36 | } > XTORS_FLASH AT > XTORS_FLASH_LMA 37 | 38 | INCLUDE ccmfunc.ld 39 | 40 | .text : ALIGN(16) SUBALIGN(16) 41 | { 42 | *(.text) 43 | *(.text.*) 44 | *(.glue_7t) 45 | *(.glue_7) 46 | *(.gcc*) 47 | } > TEXT_FLASH AT > TEXT_FLASH_LMA 48 | 49 | .rodata : ALIGN(4) 50 | { 51 | . = ALIGN(4); 52 | __rodata_base__ = .; 53 | *(.rodata) 54 | *(.rodata.*) 55 | . = ALIGN(4); 56 | __rodata_end__ = .; 57 | } > RODATA_FLASH AT > RODATA_FLASH_LMA 58 | 59 | .ARM.extab : 60 | { 61 | *(.ARM.extab* .gnu.linkonce.armextab.*) 62 | } > VARIOUS_FLASH AT > VARIOUS_FLASH_LMA 63 | 64 | .ARM.exidx : { 65 | __exidx_start = .; 66 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 67 | __exidx_end = .; 68 | } > VARIOUS_FLASH AT > VARIOUS_FLASH_LMA 69 | 70 | .eh_frame_hdr : 71 | { 72 | *(.eh_frame_hdr) 73 | } > VARIOUS_FLASH AT > VARIOUS_FLASH_LMA 74 | 75 | .eh_frame : ONLY_IF_RO 76 | { 77 | *(.eh_frame) 78 | } > VARIOUS_FLASH AT > VARIOUS_FLASH_LMA 79 | } 80 | -------------------------------------------------------------------------------- /si5351.c: -------------------------------------------------------------------------------- 1 | #include "hal.h" 2 | #include "si5351.h" 3 | 4 | #define SI5351_I2C_ADDR (0x60<<1) 5 | 6 | static void 7 | si5351_write(uint8_t reg, uint8_t dat) 8 | { 9 | int addr = SI5351_I2C_ADDR>>1; 10 | uint8_t buf[] = { reg, dat }; 11 | i2cAcquireBus(&I2CD1); 12 | (void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, 2, NULL, 0, 1000); 13 | i2cReleaseBus(&I2CD1); 14 | } 15 | 16 | static void 17 | si5351_bulk_write(const uint8_t *buf, int len) 18 | { 19 | int addr = SI5351_I2C_ADDR>>1; 20 | i2cAcquireBus(&I2CD1); 21 | (void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000); 22 | i2cReleaseBus(&I2CD1); 23 | } 24 | 25 | void si5351_disable_output(void) 26 | { 27 | uint8_t reg[4]; 28 | si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff); 29 | reg[0] = SI5351_REG_16_CLK0_CONTROL; 30 | reg[1] = SI5351_CLK_POWERDOWN; 31 | reg[2] = SI5351_CLK_POWERDOWN; 32 | reg[3] = SI5351_CLK_POWERDOWN; 33 | si5351_bulk_write(reg, 4); 34 | } 35 | 36 | void si5351_enable_output(void) 37 | { 38 | si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0x00); 39 | } 40 | 41 | void si5351_reset_pll(void) 42 | { 43 | //si5351_write(SI5351_REG_177_PLL_RESET, SI5351_PLL_RESET_A | SI5351_PLL_RESET_B); 44 | si5351_write(SI5351_REG_177_PLL_RESET, 0xAC); 45 | } 46 | 47 | void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */ 48 | uint8_t mult, 49 | uint32_t num, 50 | uint32_t denom) 51 | { 52 | /* Get the appropriate starting point for the PLL registers */ 53 | const uint8_t pllreg_base[] = { 54 | SI5351_REG_26_PLL_A, 55 | SI5351_REG_34_PLL_B 56 | }; 57 | uint32_t P1; 58 | uint32_t P2; 59 | uint32_t P3; 60 | 61 | /* Feedback Multisynth Divider Equation 62 | * where: a = mult, b = num and c = denom 63 | * P1 register is an 18-bit value using following formula: 64 | * P1[17:0] = 128 * mult + floor(128*(num/denom)) - 512 65 | * P2 register is a 20-bit value using the following formula: 66 | * P2[19:0] = 128 * num - denom * floor(128*(num/denom)) 67 | * P3 register is a 20-bit value using the following formula: 68 | * P3[19:0] = denom 69 | */ 70 | 71 | /* Set the main PLL config registers */ 72 | if (num == 0) 73 | { 74 | /* Integer mode */ 75 | P1 = 128 * mult - 512; 76 | P2 = 0; 77 | P3 = 1; 78 | } 79 | else 80 | { 81 | /* Fractional mode */ 82 | //P1 = (uint32_t)(128 * mult + floor(128 * ((float)num/(float)denom)) - 512); 83 | P1 = 128 * mult + ((128 * num) / denom) - 512; 84 | //P2 = (uint32_t)(128 * num - denom * floor(128 * ((float)num/(float)denom))); 85 | P2 = 128 * num - denom * ((128 * num) / denom); 86 | P3 = denom; 87 | } 88 | 89 | /* The datasheet is a nightmare of typos and inconsistencies here! */ 90 | uint8_t reg[9]; 91 | reg[0] = pllreg_base[pll]; 92 | reg[1] = (P3 & 0x0000FF00) >> 8; 93 | reg[2] = (P3 & 0x000000FF); 94 | reg[3] = (P1 & 0x00030000) >> 16; 95 | reg[4] = (P1 & 0x0000FF00) >> 8; 96 | reg[5] = (P1 & 0x000000FF); 97 | reg[6] = ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16); 98 | reg[7] = (P2 & 0x0000FF00) >> 8; 99 | reg[8] = (P2 & 0x000000FF); 100 | si5351_bulk_write(reg, 9); 101 | } 102 | 103 | void 104 | si5351_setupMultisynth(uint8_t output, 105 | uint8_t pllSource, 106 | uint32_t div, // 4,6,8, 8+ ~ 900 107 | uint32_t num, 108 | uint32_t denom, 109 | uint32_t rdiv, // SI5351_R_DIV_1~128 110 | uint8_t drive_strength) 111 | { 112 | /* Get the appropriate starting point for the PLL registers */ 113 | const uint8_t msreg_base[] = { 114 | SI5351_REG_42_MULTISYNTH0, 115 | SI5351_REG_50_MULTISYNTH1, 116 | SI5351_REG_58_MULTISYNTH2, 117 | }; 118 | const uint8_t clkctrl[] = { 119 | SI5351_REG_16_CLK0_CONTROL, 120 | SI5351_REG_17_CLK1_CONTROL, 121 | SI5351_REG_18_CLK2_CONTROL 122 | }; 123 | uint8_t dat; 124 | 125 | uint32_t P1; 126 | uint32_t P2; 127 | uint32_t P3; 128 | uint32_t div4 = 0; 129 | 130 | /* Output Multisynth Divider Equations 131 | * where: a = div, b = num and c = denom 132 | * P1 register is an 18-bit value using following formula: 133 | * P1[17:0] = 128 * a + floor(128*(b/c)) - 512 134 | * P2 register is a 20-bit value using the following formula: 135 | * P2[19:0] = 128 * b - c * floor(128*(b/c)) 136 | * P3 register is a 20-bit value using the following formula: 137 | * P3[19:0] = c 138 | */ 139 | /* Set the main PLL config registers */ 140 | if (div == 4) { 141 | div4 = SI5351_DIVBY4; 142 | P1 = P2 = 0; 143 | P3 = 1; 144 | } else if (num == 0) { 145 | /* Integer mode */ 146 | P1 = 128 * div - 512; 147 | P2 = 0; 148 | P3 = 1; 149 | } else { 150 | /* Fractional mode */ 151 | P1 = 128 * div + ((128 * num) / denom) - 512; 152 | P2 = 128 * num - denom * ((128 * num) / denom); 153 | P3 = denom; 154 | } 155 | 156 | /* Set the MSx config registers */ 157 | uint8_t reg[9]; 158 | reg[0] = msreg_base[output]; 159 | reg[1] = (P3 & 0x0000FF00) >> 8; 160 | reg[2] = (P3 & 0x000000FF); 161 | reg[3] = ((P1 & 0x00030000) >> 16) | div4 | rdiv; 162 | reg[4] = (P1 & 0x0000FF00) >> 8; 163 | reg[5] = (P1 & 0x000000FF); 164 | reg[6] = ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16); 165 | reg[7] = (P2 & 0x0000FF00) >> 8; 166 | reg[8] = (P2 & 0x000000FF); 167 | si5351_bulk_write(reg, 9); 168 | 169 | /* Configure the clk control and enable the output */ 170 | dat = drive_strength | SI5351_CLK_INPUT_MULTISYNTH_N; 171 | if (pllSource == SI5351_PLL_B) 172 | dat |= SI5351_CLK_PLL_SELECT_B; 173 | if (num == 0) 174 | dat |= SI5351_CLK_INTEGER_MODE; 175 | si5351_write(clkctrl[output], dat); 176 | } 177 | 178 | static uint32_t 179 | gcd(uint32_t x, uint32_t y) 180 | { 181 | uint32_t z; 182 | while (y != 0) { 183 | z = x % y; 184 | x = y; 185 | y = z; 186 | } 187 | return x; 188 | } 189 | 190 | #define XTALFREQ 26000000L 191 | #define PLL_N 32 192 | #define PLLFREQ (XTALFREQ * PLL_N) 193 | 194 | void 195 | si5351_set_frequency_fixedpll(int channel, int pll, int pllfreq, int freq, 196 | uint32_t rdiv, uint8_t drive_strength) 197 | { 198 | int32_t div = pllfreq / freq; // range: 8 ~ 1800 199 | int32_t num = pllfreq - freq * div; 200 | int32_t denom = freq; 201 | //int32_t k = freq / (1<<20) + 1; 202 | int32_t k = gcd(num, denom); 203 | num /= k; 204 | denom /= k; 205 | while (denom >= (1<<20)) { 206 | num >>= 1; 207 | denom >>= 1; 208 | } 209 | si5351_setupMultisynth(channel, pll, div, num, denom, rdiv, drive_strength); 210 | } 211 | 212 | void 213 | si5351_set_frequency_fixeddiv(int channel, int pll, int freq, int div, 214 | uint8_t drive_strength) 215 | { 216 | int32_t pllfreq = freq * div; 217 | int32_t multi = pllfreq / XTALFREQ; 218 | int32_t num = pllfreq - multi * XTALFREQ; 219 | int32_t denom = XTALFREQ; 220 | int32_t k = gcd(num, denom); 221 | num /= k; 222 | denom /= k; 223 | while (denom >= (1<<20)) { 224 | num >>= 1; 225 | denom >>= 1; 226 | } 227 | si5351_setupPLL(pll, multi, num, denom); 228 | si5351_setupMultisynth(channel, pll, div, 0, 1, SI5351_R_DIV_1, drive_strength); 229 | } 230 | 231 | //#define drive_strength SI5351_CLK_DRIVE_STRENGTH_2MA 232 | #define drive_strength SI5351_CLK_DRIVE_STRENGTH_8MA 233 | int current_band = -1; 234 | 235 | void 236 | si5351_set_frequency(int freq) 237 | { 238 | int band; 239 | uint32_t rdiv = SI5351_R_DIV_1; 240 | if (freq <= 100000000) { 241 | band = 0; 242 | } else if (freq < 150000000) { 243 | band = 1; 244 | } else { 245 | band = 2; 246 | } 247 | if (freq <= 500000) { 248 | rdiv = SI5351_R_DIV_64; 249 | } else if (freq <= 4000000) { 250 | rdiv = SI5351_R_DIV_8; 251 | } 252 | 253 | #if 0 254 | if (current_band != band) 255 | si5351_disable_output(); 256 | #endif 257 | 258 | switch (band) { 259 | case 0: 260 | if (rdiv == SI5351_R_DIV_8) { 261 | freq *= 8; 262 | } else if (rdiv == SI5351_R_DIV_64) { 263 | freq *= 64; 264 | } 265 | 266 | si5351_set_frequency_fixedpll(1, SI5351_PLL_A, PLLFREQ, freq, 267 | rdiv, drive_strength); 268 | break; 269 | 270 | case 1: 271 | // Set PLL twice on changing from band 2 272 | if (current_band == 2) { 273 | si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength); 274 | } 275 | 276 | // div by 6 mode. both PLL A and B are dedicated for CLK0, CLK1 277 | si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength); 278 | break; 279 | 280 | case 2: 281 | // div by 4 mode. both PLL A and B are dedicated for CLK0, CLK1 282 | si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 4, drive_strength); 283 | break; 284 | } 285 | 286 | if (current_band != band) { 287 | si5351_reset_pll(); 288 | //si5351_enable_output(); 289 | } 290 | 291 | current_band = band; 292 | } 293 | 294 | 295 | -------------------------------------------------------------------------------- /si5351.h: -------------------------------------------------------------------------------- 1 | #define SI5351_PLL_A 0 2 | #define SI5351_PLL_B 1 3 | 4 | #define SI5351_MULTISYNTH_DIV_4 4 5 | #define SI5351_MULTISYNTH_DIV_6 6 6 | #define SI5351_MULTISYNTH_DIV_8 8 7 | #define SI5351_R_DIV_1 (0<<4) 8 | #define SI5351_R_DIV_2 (1<<4) 9 | #define SI5351_R_DIV_4 (2<<4) 10 | #define SI5351_R_DIV_8 (3<<4) 11 | #define SI5351_R_DIV_16 (4<<4) 12 | #define SI5351_R_DIV_32 (5<<4) 13 | #define SI5351_R_DIV_64 (6<<4) 14 | #define SI5351_R_DIV_128 (7<<4) 15 | #define SI5351_DIVBY4 (3<<2) 16 | 17 | #define SI5351_REG_3_OUTPUT_ENABLE_CONTROL 3 18 | #define SI5351_REG_16_CLK0_CONTROL 16 19 | #define SI5351_REG_17_CLK1_CONTROL 17 20 | #define SI5351_REG_18_CLK2_CONTROL 18 21 | #define SI5351_REG_26_PLL_A 26 22 | #define SI5351_REG_34_PLL_B 34 23 | #define SI5351_REG_42_MULTISYNTH0 42 24 | #define SI5351_REG_50_MULTISYNTH1 50 25 | #define SI5351_REG_58_MULTISYNTH2 58 26 | 27 | #define SI5351_CLK_POWERDOWN (1<<7) 28 | #define SI5351_CLK_INTEGER_MODE (1<<6) 29 | #define SI5351_CLK_PLL_SELECT_B (1<<5) 30 | #define SI5351_CLK_INVERT (1<<4) 31 | 32 | #define SI5351_CLK_INPUT_MASK (3<<2) 33 | #define SI5351_CLK_INPUT_XTAL (0<<2) 34 | #define SI5351_CLK_INPUT_CLKIN (1<<2) 35 | #define SI5351_CLK_INPUT_MULTISYNTH_0_4 (2<<2) 36 | #define SI5351_CLK_INPUT_MULTISYNTH_N (3<<2) 37 | 38 | #define SI5351_CLK_DRIVE_STRENGTH_MASK (3<<0) 39 | #define SI5351_CLK_DRIVE_STRENGTH_2MA (0<<0) 40 | #define SI5351_CLK_DRIVE_STRENGTH_4MA (1<<0) 41 | #define SI5351_CLK_DRIVE_STRENGTH_6MA (2<<0) 42 | #define SI5351_CLK_DRIVE_STRENGTH_8MA (3<<0) 43 | 44 | 45 | #define SI5351_REG_177_PLL_RESET 177 46 | #define SI5351_PLL_RESET_B (1<<7) 47 | #define SI5351_PLL_RESET_A (1<<5) 48 | 49 | #define SI5351_REG_183_CRYSTAL_LOAD 183 50 | #define SI5351_CRYSTAL_LOAD_6PF (1<<6) 51 | #define SI5351_CRYSTAL_LOAD_8PF (2<<6) 52 | #define SI5351_CRYSTAL_LOAD_10PF (3<<6) 53 | 54 | #define SI5351_CRYSTAL_FREQ_25MHZ 25000000 55 | 56 | void si5351_init(void); 57 | 58 | void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */ 59 | uint8_t mult, 60 | uint32_t num, 61 | uint32_t denom); 62 | void si5351_setupMultisynth(uint8_t output, 63 | uint8_t pllSource, 64 | uint32_t div, 65 | uint32_t num, 66 | uint32_t denom, 67 | uint32_t rdiv, 68 | uint8_t drive_strength); 69 | 70 | void si5351_set_frequency(int freq); 71 | 72 | -------------------------------------------------------------------------------- /si5351_low.c: -------------------------------------------------------------------------------- 1 | #include "hal.h" 2 | #include "si5351.h" 3 | 4 | #define SI5351_I2C_ADDR (0x60<<1) 5 | 6 | static void 7 | rcc_gpio_init(void) 8 | { 9 | // Reset AHB,APB1,APB2 10 | RCC->AHBRSTR |= 0xffffffff; 11 | RCC->AHBRSTR = 0; 12 | RCC->APB1RSTR |= 0xffffffff; 13 | RCC->APB1RSTR = 0; 14 | RCC->APB2RSTR |= 0xffffffff; 15 | RCC->APB2RSTR = 0; 16 | 17 | RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_I2C1EN; 18 | RCC->AHBENR |= RCC_AHBENR_GPIOBEN; 19 | RCC->CFGR3 |= RCC_CFGR3_I2C1SW_HSI; 20 | 21 | GPIOB->AFRH = 0x55550044; // PB8,PB9 Alternate Function 4 22 | GPIOB->OTYPER |= 0x0300; // PB8,PB9 Open drain 23 | GPIOB->MODER |= 0x000A0000;// 24 | GPIOB->OSPEEDR |= 0x00050000;// 25 | } 26 | 27 | static void 28 | i2c_init(I2C_TypeDef* i2c) 29 | { 30 | // Disable the I2Cx peripheral 31 | i2c->CR1 &= ~I2C_CR1_PE; 32 | while (i2c->CR1 & I2C_CR1_PE); 33 | 34 | // 100kHz @ 8MHz 35 | i2c->TIMINGR = 0x10420F13; 36 | 37 | // Use 7-bit addresses 38 | i2c->CR2 &=~ I2C_CR2_ADD10; 39 | 40 | // Enable the analog filter 41 | i2c->CR1 &= ~I2C_CR1_ANFOFF; 42 | 43 | // Disable NOSTRETCH 44 | i2c->CR1 |= I2C_CR1_NOSTRETCH; 45 | 46 | // Enable I2Cx peripheral clock. 47 | // Select APB1 as clock source 48 | if (i2c == I2C1) { 49 | RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; 50 | } else if (i2c == I2C2) { 51 | RCC->APB1ENR |= RCC_APB1ENR_I2C2EN; 52 | } 53 | 54 | // Enable the I2Cx peripheral 55 | i2c->CR1 |= I2C_CR1_PE; 56 | } 57 | 58 | static void 59 | i2cSendByte(I2C_TypeDef* i2c, uint8_t addr, const uint8_t *buf, uint8_t len) 60 | { 61 | i2c->CR2 = (I2C_CR2_SADD & addr) // Set the slave address 62 | | (I2C_CR2_NBYTES & (len << 16)) // Send one byte 63 | | I2C_CR2_START // Generate start condition 64 | | I2C_CR2_AUTOEND; // Generate stop condition after sent 65 | 66 | // Send the data 67 | while (len-- > 0) { 68 | while (!(i2c->ISR & I2C_ISR_TXIS)); 69 | i2c->TXDR = (I2C_TXDR_TXDATA & *buf++); 70 | } 71 | } 72 | 73 | // register addr, length, data, ... 74 | const uint8_t si5351_configs[] = { 75 | 2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff, 76 | 4, SI5351_REG_16_CLK0_CONTROL, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN, 77 | 2, SI5351_REG_183_CRYSTAL_LOAD, SI5351_CRYSTAL_LOAD_8PF, 78 | // setup PLL 79 | // setup PLL (26MHz * 32 = 832MHz : 32/2-2=14) 80 | 9, SI5351_REG_26_PLL_A, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0, 81 | // RESET PLL 82 | 2, SI5351_REG_177_PLL_RESET, SI5351_PLL_RESET_A | SI5351_PLL_RESET_B, 83 | // setup multisynth (832MHz/8MHz=104,104/2-2=50) 84 | 9, SI5351_REG_58_MULTISYNTH2, /*P3*/0, 1, /*P1*/0, 50, 0, /*P2|P3*/0, 0, 0, 85 | 2, SI5351_REG_18_CLK2_CONTROL, SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_INPUT_MULTISYNTH_N | SI5351_CLK_INTEGER_MODE, 86 | 2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0, 87 | 0 // sentinel 88 | }; 89 | 90 | void 91 | si5351_init_bulk(void) 92 | { 93 | const uint8_t *p = si5351_configs; 94 | while (*p) { 95 | uint8_t len = *p++; 96 | i2cSendByte(I2C1, SI5351_I2C_ADDR, p, len); 97 | p += len; 98 | } 99 | } 100 | 101 | void 102 | si5351_setup(void) 103 | { 104 | rcc_gpio_init(); 105 | i2c_init(I2C1); 106 | si5351_init_bulk(); 107 | } 108 | -------------------------------------------------------------------------------- /tlv320aic3204.c: -------------------------------------------------------------------------------- 1 | #include "hal.h" 2 | #include "nanosdr.h" 3 | 4 | #define REFCLK_8000KHZ 5 | #define AIC3204_ADDR 0x18 6 | 7 | #define wait_ms(ms) chThdSleepMilliseconds(ms) 8 | 9 | static void 10 | tlv320aic3204_write(uint8_t reg, uint8_t dat) 11 | { 12 | int addr = AIC3204_ADDR; 13 | uint8_t buf[] = { reg, dat }; 14 | i2cAcquireBus(&I2CD1); 15 | (void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, 2, NULL, 0, 1000); 16 | i2cReleaseBus(&I2CD1); 17 | } 18 | 19 | static void 20 | tlv320aic3204_bulk_write(const uint8_t *buf, int len) 21 | { 22 | int addr = AIC3204_ADDR; 23 | i2cAcquireBus(&I2CD1); 24 | (void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000); 25 | i2cReleaseBus(&I2CD1); 26 | } 27 | 28 | static int 29 | tlv320aic3204_read(uint8_t d0) 30 | { 31 | int addr = AIC3204_ADDR; 32 | uint8_t buf[] = { d0 }; 33 | i2cAcquireBus(&I2CD1); 34 | i2cMasterTransmitTimeout(&I2CD1, addr, buf, 1, buf, 1, 1000); 35 | i2cReleaseBus(&I2CD1); 36 | return buf[0]; 37 | } 38 | 39 | 40 | static void 41 | tlv320aic3204_config(const uint8_t *data) 42 | { 43 | const uint8_t *p = data; 44 | while (*p) { 45 | uint8_t len = *p++; 46 | tlv320aic3204_bulk_write(p, len); 47 | p += len; 48 | } 49 | } 50 | 51 | static const uint8_t conf_data_pll[] = { 52 | // len, ( reg, data ), 53 | 2, 0x00, 0x00, /* Initialize to Page 0 */ 54 | 2, 0x01, 0x01, /* Initialize the device through software reset */ 55 | 2, 0x04, 0x43, /* PLL Clock High, MCLK, PLL */ 56 | #ifdef REFCLK_8000KHZ 57 | /* 8.000MHz*10.7520 = 86.016MHz, 86.016MHz/(2*7*128) = 48kHz */ 58 | 2, 0x05, 0x91, /* Power up PLL, P=1,R=1 */ 59 | 2, 0x06, 0x0a, /* J=10 */ 60 | 2, 0x07, 29, /* D=7520 = (29<<8) + 96 */ 61 | 2, 0x08, 96, 62 | #endif 63 | #ifdef REFCLK_12000KHZ 64 | /* 12.000MHz*7.1680 = 86.016MHz, 86.016MHz/(2*7*128) = 48kHz */ 65 | 2, 0x05, 0x91, /* Power up PLL, P=1,R=1 */ 66 | 2, 0x06, 0x07, /* J=7 */ 67 | 2, 0x07, 6, /* D=1680 = (6<<8) + 144 */ 68 | 2, 0x08, 144, 69 | #endif 70 | #ifdef REFCLK_19200KHZ 71 | /* 19.200MHz*4.48 = 86.016MHz, 86.016MHz/(2*7*128) = 48kHz */ 72 | 2, 0x05, 0x91, /* Power up PLL, P=1,R=1 */ 73 | 2, 0x06, 0x04, /* J=4 */ 74 | 2, 0x07, 18, /* D=4800 = (18<<8) + 192 */ 75 | 2, 0x08, 192, 76 | #endif 77 | 0 // sentinel 78 | }; 79 | 80 | // default fs=48kHz 81 | static const uint8_t conf_data_clk[] = { 82 | 2, 0x0b, 0x82, /* Power up the NDAC divider with value 2 */ 83 | 2, 0x0c, 0x87, /* Power up the MDAC divider with value 7 */ 84 | 2, 0x0d, 0x00, /* Program the OSR of DAC to 128 */ 85 | 2, 0x0e, 0x80, 86 | //2, 0x3c, 0x08, /* Set the DAC Mode to PRB_P8 */ 87 | 2, 0x3c, 25, /* Set the DAC Mode to PRB_P25 */ 88 | 2, 0x1b, 0x0c, /* Set the BCLK,WCLK as output */ 89 | 2, 0x1e, 0x80 + 28, /* Enable the BCLKN divider with value 28 */ 90 | 2, 0x25, 0xee, /* DAC power up */ 91 | 92 | 2, 0x12, 0x82, /* Power up the NADC divider with value 2 */ 93 | 2, 0x13, 0x87, /* Power up the MADC divider with value 7 */ 94 | 2, 0x14, 0x80, /* Program the OSR of ADC to 128 */ 95 | 2, 0x3d, 0x01, /* Select ADC PRB_R1 */ 96 | 0 // sentinel 97 | }; 98 | 99 | static const uint8_t conf_data_clk_96kHz[] = { 100 | 2, 0x0b, 0x82, /* Power up the NDAC divider with value 2 */ 101 | 2, 0x0c, 0x87, /* Power up the MDAC divider with value 7 */ 102 | 2, 0x0d, 0x00, /* Program the OSR of DAC to 64 */ 103 | 2, 0x0e, 0x40, 104 | 2, 0x3c, 0x08, /* Set the DAC Mode to PRB_P8 */ 105 | 2, 0x1b, 0x0c, /* Set the BCLK,WCLK as output */ 106 | 2, 0x1e, 0x80 + 14, /* Enable the BCLKN divider with value 14 */ 107 | 2, 0x25, 0xee, /* DAC power up */ 108 | 109 | 2, 0x12, 0x82, /* Power up the NADC divider with value 7 */ 110 | 2, 0x13, 0x87, /* Power up the MADC divider with value 2 */ 111 | 2, 0x14, 0x40, /* Program the OSR of ADC to 64 */ 112 | 2, 0x3d, 0x01, /* Select ADC PRB_R1 */ 113 | 0 // sentinel 114 | }; 115 | 116 | static const uint8_t conf_data_clk_192kHz[] = { 117 | 2, 0x0b, 0x82, /* Power up the NDAC divider with value 2 */ 118 | 2, 0x0c, 0x87, /* Power up the MDAC divider with value 7 */ 119 | 2, 0x0d, 0x00, /* Program the OSR of DAC to 32 */ 120 | 2, 0x0e, 0x20, 121 | 2, 0x3c, 17, //0x08, /* Set the DAC Mode to PRB_P17 (reduce resource) */ 122 | //2, 0x3c, 25, /* Set the DAC Mode to PRB_P25 */ 123 | 2, 0x1b, 0x0c, /* Set the BCLK,WCLK as output */ 124 | 2, 0x1e, 0x80 + 7, /* Enable the BCLKN divider with value 7 */ 125 | 2, 0x25, 0xee, /* DAC power up */ 126 | 127 | 2, 0x12, 0x81, /* Power up the NADC divider with value 1 */ 128 | 2, 0x13, 0x87, /* Power up the MADC divider with value 7 */ 129 | 2, 0x14, 0x40, /* Program the OSR of ADC to 64 */ 130 | 2, 0x3d, 0x01, /* Select ADC PRB_R1 */ 131 | 0 // sentinel 132 | }; 133 | 134 | static const uint8_t conf_data_routing[] = { 135 | 2, 0x00, 0x01, /* Select Page 1 */ 136 | 2, 0x01, 0x08, /* Disable Internal Crude AVdd in presence of external AVdd supply or before powering up internal AVdd LDO*/ 137 | 2, 0x02, 0x01, /* Enable Master Analog Power Control */ 138 | 2, 0x7b, 0x01, /* Set the REF charging time to 40ms */ 139 | 2, 0x14, 0x25, /* HP soft stepping settings for optimal pop performance at power up Rpop used is 6k with N = 6 and soft step = 20usec. This should work with 47uF coupling capacitor. Can try N=5,6 or 7 time constants as well. Trade-off delay vs “pop” sound. */ 140 | 2, 0x0a, 0x33, /* Set the Input Common Mode to 0.9V and Output Common Mode for Headphone to 1.65V */ 141 | 2, 0x0c, 0x08, /* Route Left DAC to HPL */ 142 | 2, 0x0d, 0x08, /* Route Right DAC to HPR */ 143 | 2, 0x03, 0x00, /* Set the DAC PTM mode to PTM_P3/4 */ 144 | 2, 0x04, 0x00, 145 | 2, 0x10, 0x0a, /* Set the HPL gain to 0dB */ 146 | 2, 0x11, 0x0a, /* Set the HPR gain to 0dB */ 147 | 2, 0x09, 0x30, /* Power up HPL and HPR drivers */ 148 | 149 | 2, 0x3d, 0x00, /* Select ADC PTM_R4 */ 150 | 2, 0x47, 0x32, /* Set MicPGA startup delay to 3.1ms */ 151 | 2, 0x7b, 0x01, /* Set the REF charging time to 40ms */ 152 | 2, 0x34, 0x10, /* Route IN2L to LEFT_P with 10K */ 153 | 2, 0x36, 0x10, /* Route IN2R to LEFT_N with 10K */ 154 | 2, 0x37, 0x04, /* Route IN3R to RIGHT_P with 10K */ 155 | 2, 0x39, 0x04, /* Route IN3L to RIGHT_N with 10K */ 156 | 2, 0x3b, 72, /* Unmute Left MICPGA, Gain selection of 32dB to make channel gain 0dB */ 157 | 2, 0x3c, 72, /* Unmute Right MICPGA, Gain selection of 32dB to make channel gain 0dB */ 158 | 2, 0x33, 0x60, /* Enable MIC bias, 2.5V */ 159 | 2, 0x00, 0x08, /* Select Page 8 */ 160 | 2, 0x01, 0x04, /* Enable Adaptive Filter mode */ 161 | 0 // sentinel 162 | }; 163 | 164 | const uint8_t conf_data_unmute[] = { 165 | 2, 0x00, 0x00, /* Select Page 0 */ 166 | 2, 0x3f, 0xd6, /* Power up the Left and Right DAC Channels with route the Left Audio digital data to Left Channel DAC and Right Audio digital data to Right Channel DAC */ 167 | 2, 0x40, 0x00, /* Unmute the DAC digital volume control */ 168 | 2, 0x51, 0xc0, /* Power up Left and Right ADC Channels */ 169 | 2, 0x52, 0x00, /* Unmute Left and Right ADC Digital Volume Control */ 170 | 2, 0x43, 0x93, /* Enable Headphone detection, Debounce 256ms, Button Debounce 32ms */ 171 | 0 // sentinel 172 | }; 173 | 174 | static const uint8_t conf_data_divoff[] = { 175 | 2, 0x51, 0x00, /* Power down Left and Right ADC Channels */ 176 | 2, 0x0b, 0x00, /* Power down NDAC divider */ 177 | 2, 0x0c, 0x00, /* Power down MDAC divider */ 178 | 2, 0x12, 0x00, /* Power down NADC divider */ 179 | 2, 0x13, 0x00, /* Power down MADC divider */ 180 | 0 // sentinel 181 | }; 182 | 183 | void tlv320aic3204_init(void) 184 | { 185 | tlv320aic3204_config(conf_data_pll); 186 | tlv320aic3204_config(conf_data_clk); 187 | tlv320aic3204_config(conf_data_routing); 188 | wait_ms(40); 189 | tlv320aic3204_config(conf_data_unmute); 190 | } 191 | 192 | void tlv320aic3204_stop(void) 193 | { 194 | tlv320aic3204_config(conf_data_divoff); 195 | } 196 | 197 | void tlv320aic3204_set_fs(int fs) 198 | { 199 | if (fs != 48 && fs != 96 && fs != 192) 200 | return; 201 | 202 | if (fs == 48) 203 | tlv320aic3204_config(conf_data_clk); 204 | else if (fs == 96) 205 | tlv320aic3204_config(conf_data_clk_96kHz); 206 | else if (fs == 192) 207 | tlv320aic3204_config(conf_data_clk_192kHz); 208 | 209 | wait_ms(10); 210 | tlv320aic3204_config(conf_data_unmute); 211 | } 212 | 213 | void tlv320aic3204_set_impedance(int imp) 214 | { 215 | imp &= 3; /* 1, 2, 3 */ 216 | tlv320aic3204_write(0x00, 0x01); /* Select Page 1 */ 217 | tlv320aic3204_write(0x34, (imp << 4)); /* Route IN2L to LEFT_P */ 218 | tlv320aic3204_write(0x36, (imp << 4)); /* Route IN2R to LEFT_N */ 219 | tlv320aic3204_write(0x37, (imp << 2)); /* Route IN3R to RIGHT_P */ 220 | tlv320aic3204_write(0x39, (imp << 2)); /* Route IN3L to RIGHT_N */ 221 | tlv320aic3204_write(0x00, 0x00); /* Select Page 0 */ 222 | } 223 | 224 | 225 | void tlv320aic3204_set_gain(int g1, int g2) 226 | { 227 | if (g1 < 0) g1 = 0; 228 | if (g2 < 0) g2 = 0; 229 | if (g1 > 95) g1 = 95; 230 | if (g2 > 95) g2 = 95; 231 | 232 | tlv320aic3204_write(0x00, 0x01); /* Select Page 1 */ 233 | tlv320aic3204_write(0x3b, g1); /* Unmute Left MICPGA, set gain */ 234 | tlv320aic3204_write(0x3c, g2); /* Unmute Right MICPGA, set gain */ 235 | tlv320aic3204_write(0x00, 0x00); /* Select Page 0 */ 236 | } 237 | 238 | void tlv320aic3204_set_digital_gain(int g1, int g2) 239 | { 240 | if (g1 < -24) g1 = -24; 241 | if (g1 > 40) g1 = 40; 242 | if (g2 < -24) g2 = -24; 243 | if (g2 > 40) g2 = 40; 244 | 245 | tlv320aic3204_write(0x00, 0x00); /* Select Page 0 */ 246 | tlv320aic3204_write(0x53, g1 & 0x7f); /* Left ADC Channel Volume */ 247 | tlv320aic3204_write(0x54, g2 & 0x7f); /* Right ADC Channel Volume */ 248 | } 249 | 250 | void tlv320aic3204_set_volume(int gain) 251 | { 252 | if (gain > 29) 253 | gain = 29; 254 | else if (gain < -6) 255 | gain = 0x40; 256 | else 257 | gain &= 0x3f; 258 | 259 | tlv320aic3204_write(0x00, 0x01); /* Select Page 1 */ 260 | tlv320aic3204_write(0x10, gain); /* Unmute Left MICPGA, set gain */ 261 | tlv320aic3204_write(0x11, gain); /* Unmute Right MICPGA, set gain */ 262 | tlv320aic3204_write(0x00, 0x00); /* Select Page 0 */ 263 | } 264 | 265 | void tlv320aic3204_agc_config(tlv320aic3204_agc_config_t *conf) 266 | { 267 | int ctrl = 0; 268 | if (conf == NULL) { 269 | ctrl = 0; 270 | } else { 271 | ctrl = 0x80 272 | | ((conf->target_level & 0x7) << 4) 273 | | (conf->gain_hysteresis & 0x3); 274 | } 275 | tlv320aic3204_write(0x00, 0x00); /* Select Page 0 */ 276 | tlv320aic3204_write(0x56, ctrl); /* Left AGC Control Register */ 277 | tlv320aic3204_write(0x5e, ctrl); /* Right AGC Control Register */ 278 | if (ctrl == 0) 279 | return; 280 | 281 | ctrl = ((conf->attack & 0x1f) << 3) | (conf->attack_scale & 0x7); 282 | tlv320aic3204_write(0x59, ctrl); /* Left AGC Attack Time */ 283 | tlv320aic3204_write(0x61, ctrl); /* Right AGC Attack Time */ 284 | 285 | ctrl = ((conf->decay & 0x1f) << 3) | (conf->decay_scale & 0x7); 286 | tlv320aic3204_write(0x5a, ctrl); /* Left AGC Decay Time */ 287 | tlv320aic3204_write(0x62, ctrl); /* Right AGC Decay Time */ 288 | 289 | ctrl = conf->maximum_gain; 290 | tlv320aic3204_write(0x58, ctrl); /* Left AGC Maximum Gain */ 291 | tlv320aic3204_write(0x60, ctrl); /* Right AGC Maximum Gain */ 292 | } 293 | 294 | // implement HPF of first order IIR 295 | const uint8_t adc_iir_filter_dcreject[] = { 296 | /* len, page, reg, data.... */ 297 | /* left channel C4 - C6 */ 298 | 12, 8, 24, 299 | /* Pg8 Reg24-35 */ 300 | 0x7f, 0xfa, 0xda, 0x00, 301 | 0x80, 0x05, 0x26, 0x00, 302 | 0x7f, 0xf5, 0xb5, 0x00, 303 | 304 | /* right channel C36 - C38 */ 305 | 12, 9, 32, 306 | /* Pg9 Reg 32-43 */ 307 | 0x7f, 0xfa, 0xda, 0x00, 308 | 0x80, 0x05, 0x26, 0x00, 309 | 0x7f, 0xf5, 0xb5, 0x00, 310 | 0 /* sentinel */ 311 | }; 312 | 313 | // implement HPF of first order IIR 314 | const uint8_t adc_iir_filter_dcreject2[] = { 315 | /* len, page, reg, data.... */ 316 | /* left channel C4 - C6 */ 317 | 12, 8, 24, 318 | /* Pg8 Reg24-35 */ 319 | 0x7f, 0xfa, 0xda, 0x00, 320 | 0x80, 0x05, 0x26, 0x00, 321 | 0x7f, 0xf5, 0xb5, 0x00, 322 | 323 | /* right channel C36 - C38 */ 324 | 12, 9, 32, 325 | /* Pg9 Reg 32-43 */ 326 | 0x80, 0x06, 0x37, 0x00, 327 | 0x7f, 0xfa, 0xeb, 0x00, 328 | 0x7f, 0xf5, 0xb5, 0x00, 329 | 0 /* sentinel */ 330 | }; 331 | 332 | const uint8_t adc_iir_filter_default[] = { 333 | /* len, page, reg, data.... */ 334 | /* left channel C4 - C6 */ 335 | 12, 8, 24, 336 | /* Pg8 Reg24-35 */ 337 | 0x7f, 0xff, 0xff, 0x00, 338 | 0x00, 0x00, 0x00, 0x00, 339 | 0x00, 0x00, 0x00, 0x00, 340 | 341 | /* right channel C36 - C38 */ 342 | 12, 9, 32, 343 | /* Pg9 Reg 32-43 */ 344 | 0x7f, 0xff, 0xff, 0x00, 345 | 0x00, 0x00, 0x00, 0x00, 346 | 0x00, 0x00, 0x00, 0x00, 347 | 0 /* sentinel */ 348 | }; 349 | 350 | void tlv320aic3204_config_adc_filter(int enable) 351 | { 352 | const uint8_t *p = adc_iir_filter_default; 353 | if (enable) 354 | p = adc_iir_filter_dcreject2; 355 | 356 | while (*p != 0) { 357 | uint8_t len = *p++; 358 | uint8_t page = *p++; 359 | uint8_t reg = *p++; 360 | tlv320aic3204_write(0x00, page); 361 | while (len-- > 0) 362 | tlv320aic3204_write(reg++, *p++); 363 | } 364 | tlv320aic3204_write(0x00, 0x08); /* Select Page 8 */ 365 | tlv320aic3204_write(0x01, 0x05); /* ADC Coefficient Buffers will be switched at next frame boundary */ 366 | tlv320aic3204_write(0x00, 0x00); /* Back to page 0 */ 367 | } 368 | 369 | void tlv320aic3204_config_adc_filter2(double adj) 370 | { 371 | int reg; 372 | int32_t b0 = 0x7ffada00; 373 | int32_t b1 = 0x80052600; 374 | int32_t a1 = 0x7ff5b500; 375 | 376 | tlv320aic3204_write(0x00, 0x08); 377 | reg = 24; 378 | tlv320aic3204_write(reg++, b0 >> 24); 379 | tlv320aic3204_write(reg++, b0 >> 16); 380 | tlv320aic3204_write(reg++, b0 >> 8); 381 | tlv320aic3204_write(reg++, 0); 382 | tlv320aic3204_write(reg++, b1 >> 24); 383 | tlv320aic3204_write(reg++, b1 >> 16); 384 | tlv320aic3204_write(reg++, b1 >> 8); 385 | tlv320aic3204_write(reg++, 0); 386 | tlv320aic3204_write(reg++, a1 >> 24); 387 | tlv320aic3204_write(reg++, a1 >> 16); 388 | tlv320aic3204_write(reg++, a1 >> 8); 389 | tlv320aic3204_write(reg++, 0); 390 | 391 | b0 = (int32_t)(b0 * adj); 392 | b1 = (int32_t)(b1 * adj); 393 | tlv320aic3204_write(0x00, 0x09); 394 | reg = 32; 395 | tlv320aic3204_write(reg++, b0 >> 24); 396 | tlv320aic3204_write(reg++, b0 >> 16); 397 | tlv320aic3204_write(reg++, b0 >> 8); 398 | tlv320aic3204_write(reg++, 0); 399 | tlv320aic3204_write(reg++, b1 >> 24); 400 | tlv320aic3204_write(reg++, b1 >> 16); 401 | tlv320aic3204_write(reg++, b1 >> 8); 402 | tlv320aic3204_write(reg++, 0); 403 | tlv320aic3204_write(reg++, a1 >> 24); 404 | tlv320aic3204_write(reg++, a1 >> 16); 405 | tlv320aic3204_write(reg++, a1 >> 8); 406 | tlv320aic3204_write(reg++, 0); 407 | 408 | tlv320aic3204_write(0x00, 0x08); /* Select Page 8 */ 409 | tlv320aic3204_write(0x01, 0x05); /* ADC Coefficient Buffers will be switched at next frame boundary */ 410 | tlv320aic3204_write(0x00, 0x00); /* Back to page 0 */ 411 | } 412 | 413 | int tlv320aic3204_get_sticky_flag_register(void) 414 | { 415 | return tlv320aic3204_read(0x2a); /* Sticky Flag Register */ 416 | } 417 | 418 | int8_t tlv320aic3204_get_left_agc_gain(void) 419 | { 420 | return tlv320aic3204_read(0x5d); /* Left Channel AGC Gain Flag */ 421 | } 422 | 423 | int8_t tlv320aic3204_get_right_agc_gain(void) 424 | { 425 | return tlv320aic3204_read(0x65); /* Right Channel AGC Gain Flag */ 426 | } 427 | 428 | void tlv320aic3204_set_adc_phase_adjust(int8_t adjust) 429 | { 430 | tlv320aic3204_write(0x55, adjust); 431 | } 432 | 433 | void tlv320aic3204_set_adc_fine_gain_adjust(int8_t g1, int8_t g2) 434 | { 435 | tlv320aic3204_write(0x52, (g1 & 0x7) << 4 | (g2 & 0x7)); 436 | } 437 | 438 | void tlv320aic3204_beep(void) 439 | { 440 | /* 441 | tlv320aic3204_write(0x25, 00); // power off dac 442 | wait_ms(10); 443 | tlv320aic3204_write(0x3c, 25); // select PRB_P25 to beep 444 | tlv320aic3204_write(0x25, 0xee); // DAC power on 445 | */ 446 | 447 | // set duration 448 | tlv320aic3204_write(0x4a, 0x10); 449 | tlv320aic3204_write(0x4b, 0x00); 450 | // beep 451 | tlv320aic3204_write(0x47, 0x80); 452 | 453 | /* 454 | tlv320aic3204_write(0x3c, 17); // restore to PRB_P17 455 | */ 456 | } 457 | -------------------------------------------------------------------------------- /ui.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com 3 | * All rights reserved. 4 | * 5 | * This is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3, or (at your option) 8 | * any later version. 9 | * 10 | * The software is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with GNU Radio; see the file COPYING. If not, write to 17 | * the Free Software Foundation, Inc., 51 Franklin Street, 18 | * Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #include "ch.h" 22 | #include "hal.h" 23 | #include "nanosdr.h" 24 | #include "si5351.h" 25 | #include 26 | #include 27 | 28 | #define set_volume(gain) tlv320aic3204_set_volume(gain) 29 | 30 | int fetch_encoder_tick(void); 31 | 32 | #define NO_EVENT 0 33 | #define EVT_BUTTON_SINGLE_CLICK 0x01 34 | #define EVT_BUTTON_DOUBLE_CLICK 0x02 35 | #define EVT_BUTTON_DOWN_LONG 0x04 36 | #define EVT_UP 0x10 37 | #define EVT_DOWN 0x20 38 | #define EVT_PUSH_UP 0x30 39 | #define EVT_PUSH_DOWN 0x40 40 | 41 | #define BUTTON_DOWN_LONG_TICKS 16000 42 | #define BUTTON_DOUBLE_TICKS 500 43 | #define BUTTON_DEBOUNCE_TICKS 10 44 | #define BUTTON_NO_ACTION 0 45 | 46 | #define BIT_PUSH 0 47 | #define BIT_ENCODER0 1 48 | #define BIT_ENCODER1 2 49 | 50 | static uint16_t last_button = 0; 51 | static uint16_t button_event_inhibited = 0; 52 | static uint32_t last_button_down_ticks; 53 | //static uint8_t dragged = 0; // encoder changed while button pressed 54 | 55 | 56 | int 57 | read_buttons(void) 58 | { 59 | return (palReadPort(GPIOA) & 0x1) ^ config.button_polarity; 60 | } 61 | 62 | void 63 | inhibit_button_event(void) 64 | { 65 | button_event_inhibited = 1; 66 | } 67 | 68 | int btn_check(void) 69 | { 70 | int cur_button = read_buttons(); 71 | int changed = last_button ^ cur_button; 72 | int status = 0; 73 | uint32_t ticks = chVTGetSystemTime(); 74 | if (changed & (1<= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS) { 76 | if (!(cur_button & (1<= last_button_down_ticks + BUTTON_DOWN_LONG_TICKS) { 97 | status |= EVT_BUTTON_DOWN_LONG; 98 | button_event_inhibited = 1; 99 | } 100 | } 101 | 102 | last_button = cur_button; 103 | 104 | return status; 105 | } 106 | 107 | #define VOLUME_MAX 29 108 | #define VOLUME_MIN -7 109 | #define RFGAIN_MAX 95 110 | 111 | static void 112 | set_gain(int gain) 113 | { 114 | int dgain = 0; 115 | if (gain > RFGAIN_MAX) { 116 | dgain = gain - RFGAIN_MAX; 117 | gain = RFGAIN_MAX; 118 | } 119 | if (gain < 0) { 120 | dgain = gain; 121 | gain = 0; 122 | } 123 | 124 | tlv320aic3204_set_gain(gain, gain); 125 | tlv320aic3204_set_digital_gain(dgain, dgain); 126 | } 127 | 128 | 129 | void 130 | update_frequency(void) 131 | { 132 | set_tune(uistat.freq); 133 | } 134 | 135 | 136 | int enc_status = 0; 137 | int enc_count = 0; 138 | 139 | 140 | int 141 | fetch_encoder_tick(void) 142 | { 143 | int n = enc_count; 144 | enc_count = 0; 145 | return n; 146 | } 147 | 148 | void ext_callback(EXTDriver *extp, expchannel_t channel) 149 | { 150 | (void)extp; 151 | int cur = palReadPort(GPIOB); 152 | const int trans_tbl[4][4] = { 153 | /*falling A */ /*rising A */ /*falling B */ /*rising B */ 154 | { 0, 0, 3, 3 }, { 1, 1, 2, 2 }, { 0, 1, 1, 0 }, { 3, 2, 2, 3 } 155 | }; 156 | int s = (channel - 1) * 2; // A: 0, B: 2 157 | if (cur & (1 << channel)) 158 | s |= 1; // rising 159 | if (enc_status == 0 && s == 3) // rising B 160 | enc_count--; 161 | if (enc_status == 3 && s == 2) // falling B 162 | enc_count++; 163 | enc_status = trans_tbl[s][enc_status]; 164 | #if 0 165 | if (channel == 0) { 166 | enc_count = 0; 167 | } 168 | #endif 169 | } 170 | 171 | static const EXTConfig extconf = { 172 | { 173 | { 0, NULL }, //{ EXT_MODE_GPIOA | EXT_CH_MODE_RISING_EDGE | EXT_CH_MODE_AUTOSTART, ext_callback }, 174 | { EXT_MODE_GPIOB | EXT_CH_MODE_BOTH_EDGES | EXT_CH_MODE_AUTOSTART, ext_callback }, 175 | { EXT_MODE_GPIOB | EXT_CH_MODE_BOTH_EDGES | EXT_CH_MODE_AUTOSTART, ext_callback }, 176 | { 0, NULL }, 177 | { 0, NULL }, 178 | { 0, NULL }, 179 | { 0, NULL }, 180 | { 0, NULL }, 181 | { 0, NULL }, 182 | { 0, NULL }, 183 | { 0, NULL }, 184 | { 0, NULL }, 185 | { 0, NULL }, 186 | { 0, NULL }, 187 | { 0, NULL }, 188 | { 0, NULL }, 189 | { 0, NULL }, 190 | { 0, NULL }, 191 | { 0, NULL }, 192 | { 0, NULL }, 193 | { 0, NULL }, 194 | { 0, NULL }, 195 | { 0, NULL }, 196 | { 0, NULL }, 197 | { 0, NULL }, 198 | { 0, NULL }, 199 | { 0, NULL }, 200 | { 0, NULL }, 201 | { 0, NULL }, 202 | { 0, NULL }, 203 | { 0, NULL }, 204 | { 0, NULL } 205 | } 206 | }; 207 | 208 | void 209 | recall_channel(unsigned int channel) 210 | { 211 | // apply settings at channel 212 | uistat.freq = config.channels[channel].freq; 213 | //uistat.rfgain = config.channels[channel].rfgain; 214 | uistat.modulation = config.channels[channel].modulation; 215 | 216 | //set_gain(uistat.rfgain); 217 | set_modulation(uistat.modulation); 218 | update_frequency(); 219 | } 220 | 221 | void 222 | ui_init(void) 223 | { 224 | #if 1 225 | extStart(&EXTD1, &extconf); 226 | //chCondObjectInit(&condvar_button); 227 | #endif 228 | 229 | set_volume(uistat.volume); 230 | set_gain(uistat.rfgain); 231 | set_agc_mode(uistat.agcmode); 232 | set_modulation(uistat.modulation); 233 | //recall_channel(uistat.channel); 234 | update_frequency(); 235 | } 236 | 237 | static int minmax(int x, int min, int max) 238 | { 239 | if (x >= max) 240 | return max - 1; 241 | if (x < min) 242 | return min; 243 | return x; 244 | } 245 | 246 | void 247 | ui_process(void) 248 | { 249 | int status = btn_check(); 250 | int tick = fetch_encoder_tick(); 251 | int n; 252 | if (status & EVT_BUTTON_SINGLE_CLICK) { 253 | uistat.mode++; 254 | if (uistat.agcmode != 0 && uistat.mode == RFGAIN) 255 | uistat.mode++; 256 | // skip CWTONE, IQBAL on click 257 | if (uistat.mode == AGC_MAXGAIN) 258 | uistat.mode = SPDISP; 259 | uistat.mode %= MODE_MAX; 260 | disp_update(); 261 | } else if (status & EVT_BUTTON_DOWN_LONG) { 262 | tlv320aic3204_beep(); 263 | save_config_current_channel(); 264 | } 265 | if (tick != 0) { 266 | if (read_buttons() != 0) { 267 | // button pressed 268 | 269 | if (uistat.mode == FREQ) { 270 | if (tick < 0) { 271 | if (uistat.digit < 7) 272 | uistat.digit++; 273 | else 274 | uistat.mode--; 275 | } 276 | if (tick > 0) { 277 | if (uistat.digit > 0) 278 | uistat.digit--; 279 | else 280 | uistat.mode++; 281 | } 282 | } else { 283 | if (tick < 0) { 284 | uistat.mode--; 285 | 286 | if (uistat.mode == IQBAL || uistat.mode == RFGAIN) 287 | disp_clear_aux(); 288 | 289 | // skip rfgain if agc is enabled 290 | if (uistat.agcmode != 0 && uistat.mode == RFGAIN) 291 | uistat.mode--; 292 | } 293 | if (tick > 0) { 294 | uistat.mode++; 295 | 296 | // skip rfgain if agc is enabled 297 | if (uistat.agcmode != 0 && uistat.mode == RFGAIN) 298 | uistat.mode++; 299 | 300 | if (uistat.mode == AGC_MAXGAIN || uistat.mode == SPDISP) 301 | disp_clear_aux(); 302 | } 303 | uistat.mode = uistat.mode % MODE_MAX; 304 | } 305 | disp_update(); 306 | inhibit_button_event(); 307 | } else { 308 | if (uistat.mode == CHANNEL) { 309 | uistat.channel = minmax(uistat.channel + tick, 0, CHANNEL_MAX); 310 | recall_channel(uistat.channel); 311 | } else if (uistat.mode == VOLUME) { 312 | uistat.volume = minmax(uistat.volume + tick, VOLUME_MIN, VOLUME_MAX+1); 313 | set_volume(uistat.volume); 314 | } else if (uistat.mode == FREQ) { 315 | int32_t step = 1; 316 | for (n = uistat.digit; n > 0; n--) 317 | step *= 10; 318 | int32_t freq = uistat.freq + step * tick; 319 | if (freq > 0) 320 | uistat.freq = freq; 321 | update_frequency(); 322 | } else if (uistat.mode == RFGAIN) { 323 | uistat.rfgain = minmax((int)uistat.rfgain + tick, -24, RFGAIN_MAX + 40+1); 324 | set_gain(uistat.rfgain); 325 | } else if (uistat.mode == AGC) { 326 | uistat.agcmode = minmax(uistat.agcmode + tick, 0, AGC_MAX); 327 | set_agc_mode(uistat.agcmode); 328 | } else if (uistat.mode == MOD) { 329 | if (tick > 0 && uistat.modulation < MOD_MAX-1) { 330 | uistat.modulation++; 331 | } 332 | if (tick < 0 && uistat.modulation > 0) { 333 | uistat.modulation--; 334 | } 335 | set_modulation(uistat.modulation); 336 | update_frequency(); 337 | } else if (uistat.mode == CWTONE) { 338 | uistat.cw_tone_freq = minmax(uistat.cw_tone_freq + tick, -2000, 2000); 339 | update_cwtone(); 340 | } else if (uistat.mode == IQBAL) { 341 | uistat.iqbal = minmax(uistat.iqbal + tick * 10, -4000, 4000); 342 | update_iqbal(); 343 | } else if (uistat.mode == AGC_MAXGAIN) { 344 | config.agc.maximum_gain = minmax(config.agc.maximum_gain + tick, 0, 128); 345 | update_agc(); 346 | } else if (uistat.mode == SPDISP) { 347 | uistat.spdispmode = minmax(uistat.spdispmode + tick, 0, SPDISP_MODE_MAX); 348 | } else if (uistat.mode == WFDISP) { 349 | uistat.wfdispmode = minmax(uistat.wfdispmode + tick, 0, WFDISP_MODE_MAX); 350 | } 351 | } 352 | 353 | disp_update(); 354 | } 355 | } 356 | 357 | -------------------------------------------------------------------------------- /usbcfg.c: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include "ch.h" 18 | #include "hal.h" 19 | 20 | /* Virtual serial port over USB.*/ 21 | SerialUSBDriver SDU1; 22 | 23 | /* 24 | * Endpoints to be used for USBD1. 25 | */ 26 | #define USBD1_DATA_REQUEST_EP 1 27 | #define USBD1_DATA_AVAILABLE_EP 1 28 | #define USBD1_INTERRUPT_REQUEST_EP 2 29 | 30 | /* 31 | * USB Device Descriptor. 32 | */ 33 | static const uint8_t vcom_device_descriptor_data[18] = { 34 | USB_DESC_DEVICE (0x0110, /* bcdUSB (1.1). */ 35 | 0x02, /* bDeviceClass (CDC). */ 36 | 0x00, /* bDeviceSubClass. */ 37 | 0x00, /* bDeviceProtocol. */ 38 | 0x40, /* bMaxPacketSize. */ 39 | 0x0483, /* idVendor (ST). */ 40 | 0x5740, /* idProduct. */ 41 | 0x0200, /* bcdDevice. */ 42 | 1, /* iManufacturer. */ 43 | 2, /* iProduct. */ 44 | 3, /* iSerialNumber. */ 45 | 1) /* bNumConfigurations. */ 46 | }; 47 | 48 | /* 49 | * Device Descriptor wrapper. 50 | */ 51 | static const USBDescriptor vcom_device_descriptor = { 52 | sizeof vcom_device_descriptor_data, 53 | vcom_device_descriptor_data 54 | }; 55 | 56 | /* Configuration Descriptor tree for a CDC.*/ 57 | static const uint8_t vcom_configuration_descriptor_data[67] = { 58 | /* Configuration Descriptor.*/ 59 | USB_DESC_CONFIGURATION(67, /* wTotalLength. */ 60 | 0x02, /* bNumInterfaces. */ 61 | 0x01, /* bConfigurationValue. */ 62 | 0, /* iConfiguration. */ 63 | 0xC0, /* bmAttributes (self powered). */ 64 | 50), /* bMaxPower (100mA). */ 65 | /* Interface Descriptor.*/ 66 | USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */ 67 | 0x00, /* bAlternateSetting. */ 68 | 0x01, /* bNumEndpoints. */ 69 | 0x02, /* bInterfaceClass (Communications 70 | Interface Class, CDC section 71 | 4.2). */ 72 | 0x02, /* bInterfaceSubClass (Abstract 73 | Control Model, CDC section 4.3). */ 74 | 0x01, /* bInterfaceProtocol (AT commands, 75 | CDC section 4.4). */ 76 | 0), /* iInterface. */ 77 | /* Header Functional Descriptor (CDC section 5.2.3).*/ 78 | USB_DESC_BYTE (5), /* bLength. */ 79 | USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ 80 | USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header 81 | Functional Descriptor. */ 82 | USB_DESC_BCD (0x0110), /* bcdCDC. */ 83 | /* Call Management Functional Descriptor. */ 84 | USB_DESC_BYTE (5), /* bFunctionLength. */ 85 | USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ 86 | USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management 87 | Functional Descriptor). */ 88 | USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */ 89 | USB_DESC_BYTE (0x01), /* bDataInterface. */ 90 | /* ACM Functional Descriptor.*/ 91 | USB_DESC_BYTE (4), /* bFunctionLength. */ 92 | USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ 93 | USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract 94 | Control Management Descriptor). */ 95 | USB_DESC_BYTE (0x02), /* bmCapabilities. */ 96 | /* Union Functional Descriptor.*/ 97 | USB_DESC_BYTE (5), /* bFunctionLength. */ 98 | USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ 99 | USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union 100 | Functional Descriptor). */ 101 | USB_DESC_BYTE (0x00), /* bMasterInterface (Communication 102 | Class Interface). */ 103 | USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class 104 | Interface). */ 105 | /* Endpoint 2 Descriptor.*/ 106 | USB_DESC_ENDPOINT (USBD1_INTERRUPT_REQUEST_EP|0x80, 107 | 0x03, /* bmAttributes (Interrupt). */ 108 | 0x0008, /* wMaxPacketSize. */ 109 | 0xFF), /* bInterval. */ 110 | /* Interface Descriptor.*/ 111 | USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */ 112 | 0x00, /* bAlternateSetting. */ 113 | 0x02, /* bNumEndpoints. */ 114 | 0x0A, /* bInterfaceClass (Data Class 115 | Interface, CDC section 4.5). */ 116 | 0x00, /* bInterfaceSubClass (CDC section 117 | 4.6). */ 118 | 0x00, /* bInterfaceProtocol (CDC section 119 | 4.7). */ 120 | 0x00), /* iInterface. */ 121 | /* Endpoint 3 Descriptor.*/ 122 | USB_DESC_ENDPOINT (USBD1_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ 123 | 0x02, /* bmAttributes (Bulk). */ 124 | 0x0040, /* wMaxPacketSize. */ 125 | 0x00), /* bInterval. */ 126 | /* Endpoint 1 Descriptor.*/ 127 | USB_DESC_ENDPOINT (USBD1_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/ 128 | 0x02, /* bmAttributes (Bulk). */ 129 | 0x0040, /* wMaxPacketSize. */ 130 | 0x00) /* bInterval. */ 131 | }; 132 | 133 | /* 134 | * Configuration Descriptor wrapper. 135 | */ 136 | static const USBDescriptor vcom_configuration_descriptor = { 137 | sizeof vcom_configuration_descriptor_data, 138 | vcom_configuration_descriptor_data 139 | }; 140 | 141 | /* 142 | * U.S. English language identifier. 143 | */ 144 | static const uint8_t vcom_string0[] = { 145 | USB_DESC_BYTE(4), /* bLength. */ 146 | USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ 147 | USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */ 148 | }; 149 | 150 | /* 151 | * Vendor string. 152 | */ 153 | static const uint8_t vcom_string1[] = { 154 | USB_DESC_BYTE(38), /* bLength. */ 155 | USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ 156 | 'S', 0, 'T', 0, 'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'e', 0, 157 | 'l', 0, 'e', 0, 'c', 0, 't', 0, 'r', 0, 'o', 0, 'n', 0, 'i', 0, 158 | 'c', 0, 's', 0 159 | }; 160 | 161 | /* 162 | * Device Description string. 163 | */ 164 | static const uint8_t vcom_string2[] = { 165 | USB_DESC_BYTE(56), /* bLength. */ 166 | USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ 167 | 'C', 0, 'h', 0, 'i', 0, 'b', 0, 'i', 0, 'O', 0, 'S', 0, '/', 0, 168 | 'R', 0, 'T', 0, ' ', 0, 'V', 0, 'i', 0, 'r', 0, 't', 0, 'u', 0, 169 | 'a', 0, 'l', 0, ' ', 0, 'C', 0, 'O', 0, 'M', 0, ' ', 0, 'P', 0, 170 | 'o', 0, 'r', 0, 't', 0 171 | }; 172 | 173 | /* 174 | * Serial Number string. 175 | */ 176 | static const uint8_t vcom_string3[] = { 177 | USB_DESC_BYTE(8), /* bLength. */ 178 | USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ 179 | '0' + CH_KERNEL_MAJOR, 0, 180 | '0' + CH_KERNEL_MINOR, 0, 181 | '0' + CH_KERNEL_PATCH, 0 182 | }; 183 | 184 | /* 185 | * Strings wrappers array. 186 | */ 187 | static const USBDescriptor vcom_strings[] = { 188 | {sizeof vcom_string0, vcom_string0}, 189 | {sizeof vcom_string1, vcom_string1}, 190 | {sizeof vcom_string2, vcom_string2}, 191 | {sizeof vcom_string3, vcom_string3} 192 | }; 193 | 194 | /* 195 | * Handles the GET_DESCRIPTOR callback. All required descriptors must be 196 | * handled here. 197 | */ 198 | static const USBDescriptor *get_descriptor(USBDriver *usbp, 199 | uint8_t dtype, 200 | uint8_t dindex, 201 | uint16_t lang) { 202 | 203 | (void)usbp; 204 | (void)lang; 205 | switch (dtype) { 206 | case USB_DESCRIPTOR_DEVICE: 207 | return &vcom_device_descriptor; 208 | case USB_DESCRIPTOR_CONFIGURATION: 209 | return &vcom_configuration_descriptor; 210 | case USB_DESCRIPTOR_STRING: 211 | if (dindex < 4) 212 | return &vcom_strings[dindex]; 213 | } 214 | return NULL; 215 | } 216 | 217 | /** 218 | * @brief IN EP1 state. 219 | */ 220 | static USBInEndpointState ep1instate; 221 | 222 | /** 223 | * @brief OUT EP1 state. 224 | */ 225 | static USBOutEndpointState ep1outstate; 226 | 227 | /** 228 | * @brief EP1 initialization structure (both IN and OUT). 229 | */ 230 | static const USBEndpointConfig ep1config = { 231 | USB_EP_MODE_TYPE_BULK, 232 | NULL, 233 | sduDataTransmitted, 234 | sduDataReceived, 235 | 0x0040, 236 | 0x0040, 237 | &ep1instate, 238 | &ep1outstate, 239 | 2, 240 | NULL 241 | }; 242 | 243 | /** 244 | * @brief IN EP2 state. 245 | */ 246 | static USBInEndpointState ep2instate; 247 | 248 | /** 249 | * @brief EP2 initialization structure (IN only). 250 | */ 251 | static const USBEndpointConfig ep2config = { 252 | USB_EP_MODE_TYPE_INTR, 253 | NULL, 254 | sduInterruptTransmitted, 255 | NULL, 256 | 0x0010, 257 | 0x0000, 258 | &ep2instate, 259 | NULL, 260 | 1, 261 | NULL 262 | }; 263 | 264 | /* 265 | * Handles the USB driver global events. 266 | */ 267 | static void usb_event(USBDriver *usbp, usbevent_t event) { 268 | extern SerialUSBDriver SDU1; 269 | 270 | switch (event) { 271 | case USB_EVENT_RESET: 272 | return; 273 | case USB_EVENT_ADDRESS: 274 | return; 275 | case USB_EVENT_CONFIGURED: 276 | chSysLockFromISR(); 277 | 278 | /* Enables the endpoints specified into the configuration. 279 | Note, this callback is invoked from an ISR so I-Class functions 280 | must be used.*/ 281 | usbInitEndpointI(usbp, USBD1_DATA_REQUEST_EP, &ep1config); 282 | usbInitEndpointI(usbp, USBD1_INTERRUPT_REQUEST_EP, &ep2config); 283 | 284 | /* Resetting the state of the CDC subsystem.*/ 285 | sduConfigureHookI(&SDU1); 286 | 287 | chSysUnlockFromISR(); 288 | return; 289 | case USB_EVENT_SUSPEND: 290 | chSysLockFromISR(); 291 | 292 | /* Disconnection event on suspend.*/ 293 | sduDisconnectI(&SDU1); 294 | 295 | chSysUnlockFromISR(); 296 | return; 297 | case USB_EVENT_WAKEUP: 298 | return; 299 | case USB_EVENT_STALLED: 300 | return; 301 | } 302 | return; 303 | } 304 | 305 | /* 306 | * Handles the USB driver global events. 307 | */ 308 | static void sof_handler(USBDriver *usbp) { 309 | 310 | (void)usbp; 311 | 312 | osalSysLockFromISR(); 313 | sduSOFHookI(&SDU1); 314 | osalSysUnlockFromISR(); 315 | } 316 | 317 | /* 318 | * USB driver configuration. 319 | */ 320 | const USBConfig usbcfg = { 321 | usb_event, 322 | get_descriptor, 323 | sduRequestsHook, 324 | sof_handler 325 | }; 326 | 327 | /* 328 | * Serial over USB driver configuration. 329 | */ 330 | const SerialUSBConfig serusbcfg = { 331 | &USBD1, 332 | USBD1_DATA_REQUEST_EP, 333 | USBD1_DATA_AVAILABLE_EP, 334 | USBD1_INTERRUPT_REQUEST_EP 335 | }; 336 | -------------------------------------------------------------------------------- /usbcfg.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | #ifndef USBCFG_H 17 | #define USBCFG_H 18 | 19 | extern const USBConfig usbcfg; 20 | extern SerialUSBConfig serusbcfg; 21 | extern SerialUSBDriver SDU1; 22 | 23 | #endif /* USBCFG_H */ 24 | 25 | /** @} */ 26 | --------------------------------------------------------------------------------