diff --git a/code/.project b/code/.project index a3326e8..3e3eff0 100644 --- a/code/.project +++ b/code/.project @@ -86,10 +86,5 @@ 2 CHIBIOS/os - - test - 2 - CHIBIOS/test - diff --git a/code/Makefile b/code/Makefile index a668269..6b91768 100644 --- a/code/Makefile +++ b/code/Makefile @@ -121,7 +121,9 @@ CSRC = $(ALLCSRC) \ radio/ssb.c \ drivers/si5351.c \ drivers/speaker.c \ - trig.c + trig.c \ + test.c \ + num2string.c # C++ sources that can be compiled in ARM or THUMB mode depending on the global # setting. diff --git a/code/main.c b/code/main.c index 3bb8e68..54e8e51 100644 --- a/code/main.c +++ b/code/main.c @@ -16,122 +16,18 @@ #include "hal.h" #include "ch.h" -#include "drivers/si5351.h" - -static void adcerrorcallback(ADCDriver *adcp, adcerror_t err) { - - (void)adcp; - (void)err; - chnWrite(&SD1, (const uint8_t *)"ADC Error\r\n", 11); -} +#include "test.h" /* - * ADC conversion group. - * Mode: Linear buffer, 8 samples of 1 channel, SW triggered. - * Channels: IN10. + * Example Thread */ -static const ADCConversionGroup mic_in = { - FALSE, // single-shot - 1, // 1 channel - NULL, // No callback - adcerrorcallback, - ADC_CFGR1_RES_12BIT, /* CFGR1 */ - ADC_TR(0, 0), /* TR */ - ADC_SMPR_SMP_1P5, /* SMPR */ - ADC_CHSELR_CHSEL5 /* CHSELR */ -}; - -static PWMConfig spkr = { - 4096000, /* 4MHz PWM clock frequency. */ - 4096, /* Initial PWM period 1ms. */ - NULL, - { - {PWM_OUTPUT_ACTIVE_HIGH, NULL}, - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_DISABLED, NULL} - }, - 0, - 0 -}; -/* - * Thread 1. - */ -THD_WORKING_AREA(waThread1, 128); +THD_WORKING_AREA(waThread1, 256); THD_FUNCTION(Thread1, arg) { (void)arg; - /* Audio test: copy audio in to audio out */ - adcStart(&ADCD1, NULL); - pwmStart(&PWMD3, &spkr); - while (true) { - /* Read MIC analog input, output to SPKR (pwm ch1 on tim3) */ - uint16_t sample; - adcConvert(&ADCD1, &mic_in, &sample, 1); - pwmEnableChannel(&PWMD3, 0, sample); // No scaling for now - chThdSleepMilliseconds(1); - } -} - - -static const DACConfig dac1cfg1 = { - .init = 2047U, - .datamode = DAC_DHRM_12BIT_RIGHT, - .cr = 0 -}; - -struct synth tx_clk; - -const QEIConfig encoder = { - .mode = QEI_COUNT_CH1, - .channels = {{QEI_INPUT_NONINVERTED},{QEI_INPUT_NONINVERTED}}, - .range = 30 -}; - -/* - * Thread 2. - */ -THD_WORKING_AREA(waThread2, 128); -THD_FUNCTION(Thread2, arg) { - (void)arg; - /* Power amplifier test: Demonstrate DAC and si5351 */ - /* Starting DAC1 driver.*/ - dacStart(&DACD1, &dac1cfg1); - uint16_t val = 0xFFF/3.3; // 1V desired, 3.3V max. - dacPutChannelX(&DACD1, 1, val); // Output to DAC - i2cStart(&I2CD1, NULL); - synthInit(&tx_clk, 2, 0); //Channel 2, PLLB - /* Starting the si5351 */ - chThdSleepMilliseconds(100); // Make sure the si5351 has time to start up - synthSetCarrier(&tx_clk, 7e6); - synthStart(&tx_clk); - /* Enabling the encoder */ - qeiStart(&QEID1, &encoder); - qeiEnable(&QEID1); - while (true) { - chThdSleepMilliseconds(100); - int32_t f = qeiGetPositionI(&QEID1); - f *= 100<16; // 100Hz per step - synthSetBaseband(&tx_clk, f); - } -} -/* - * Thread 3. - */ -THD_WORKING_AREA(waThread3, 256); -THD_FUNCTION(Thread3, arg) { - - (void)arg; - - /* - * Activates the serial driver 1 using the driver default configuration. - * PA9 and PA10 are routed to USART1. - */ - sdStart(&SD1, NULL); - /* Welcome message.*/ - chnWrite(&SD1, (const uint8_t *)"Hello World!\r\n", 14); while (true) { + serial_test("Hurray! Serial works\r\n"); chThdSleepMilliseconds(500); } } @@ -140,9 +36,7 @@ THD_FUNCTION(Thread3, arg) { * Threads creation table, one entry per thread. */ THD_TABLE_BEGIN - THD_TABLE_THREAD(3, "mic test", waThread1, Thread1, NULL) - THD_TABLE_THREAD(3, "tx test", waThread2, Thread2, NULL) - THD_TABLE_THREAD(4, "lib test", waThread3, Thread3, NULL) + THD_TABLE_THREAD(3, "demo", waThread1, Thread1, NULL) THD_TABLE_END /* diff --git a/code/num2string.c b/code/num2string.c new file mode 100644 index 0000000..6d2e5c5 --- /dev/null +++ b/code/num2string.c @@ -0,0 +1,49 @@ +#include "num2string.h" + +char * memcpy2(char * dest, char * src, unsigned int n){ + while(n--){ + *dest++ = *src++; + } + return dest; +} + +unsigned int strlen2(char * str){ + unsigned int i = 0; + while(*str++ && (i>i)&0xF]; + }while(i); + return 2+8; //2 character prefix, 8 hex nibbles +} diff --git a/code/num2string.h b/code/num2string.h new file mode 100644 index 0000000..1672021 --- /dev/null +++ b/code/num2string.h @@ -0,0 +1,8 @@ +char * memcpy2(char * dest, char * src, unsigned int n); + +static const unsigned int max_strlen = 128; // to prevent infinite loop +unsigned int strlen2(char * src); + +short format_int(char * dest, long val); + +short format_hex(char * dest, long val); diff --git a/code/test.c b/code/test.c new file mode 100644 index 0000000..b89522a --- /dev/null +++ b/code/test.c @@ -0,0 +1,146 @@ +#include "test.h" +#include "hal.h" +#include "drivers/speaker.h" +#include // for sin() +#include "num2string.h" // for format_int() + + +const SerialConfig scfg = { + .speed = 115200, +}; + +void serial_test(char * msg){ + sdStart(&SD1, &scfg); + chnWrite(&SD1, (const uint8_t *)msg, strlen2(msg)); +} + +void speaker_simple_test(float freq){ + PWMConfig spkr = { + .frequency = 32e6, // Run at full processor speed + .period = (1<<10), // 11 bits of data to give a 16 kHz update rate + .callback = NULL, + .channels = { + {PWM_OUTPUT_ACTIVE_HIGH, NULL}, + {PWM_OUTPUT_DISABLED, NULL}, + {PWM_OUTPUT_DISABLED, NULL}, + {PWM_OUTPUT_DISABLED, NULL} + }, + .cr2 = 0, + .dier = 0, + }; + pwmStart(&PWMD3, &spkr); + const float tau = 6.2832; + float step = freq * tau / 10e3; + float x = 0; + while(1){ + x += step; + if(x > tau) + x -= tau; + int16_t val = (1<<9)*(sin(x)+1); + pwmEnableChannel(&PWMD3, 0, val); + chThdSleepMicroseconds(100); + } +} + +void speaker_streaming_test(float freq){ + const float tau = 6.2832; + float step = freq * tau / 10e3; + float x = 0; + const int len = 32; + int16_t audio_buf[len]; + speakerStart(10e3); + while(1){ + for(int i = 0; i < len; ++i){ + x += step; + if(x > tau) + x -= tau; + audio_buf[i] = (1<<9)*(sin(x)+1); + } + speakerUpdate(audio_buf, len); + } +} + +void adc_simple_test(void){ + const ADCConversionGroup mic_in = { + FALSE, // single-shot + 1, // 1 channel + NULL, // No callback + NULL, + ADC_CFGR1_RES_12BIT, /* CFGR1 */ + ADC_TR(0, 0), /* TR */ + ADC_SMPR_SMP_1P5, /* SMPR */ + ADC_CHSELR_CHSEL5 /* CHSELR */ + }; + sdStart(&SD1, &scfg); + chnWrite(&SD1, (const uint8_t *)"Reading ADC channel 5:\r\n", 24); + adcStart(&ADCD1, NULL); + uint16_t sample; + while(1){ + adcConvert(&ADCD1, &mic_in, &sample, 1); + char msg[20]; + int digits = format_int(msg, sample); + memcpy2(msg+digits, "\r\n", 2); + chnWrite(&SD1, (const uint8_t *)msg, digits+2); + chThdSleepMilliseconds(100); + } + +} + +void encoder_test(void){ + const QEIConfig encoder = { + .mode = QEI_COUNT_BOTH, + .channels = {{QEI_INPUT_NONINVERTED},{QEI_INPUT_NONINVERTED}}, + .range = 1000 + }; + sdStart(&SD1, &scfg); + qeiStart(&QEID1, &encoder); + qeiEnable(&QEID1); + while(1){ + int position = qeiGetPositionI(&QEID1); + char msg[20]; + int digits = format_int(msg, position); + memcpy2(msg+digits, "\r\n", 2); + chnWrite(&SD1, (const uint8_t *)msg, digits+2); + chThdSleepMilliseconds(100); + } +} +void dac_simple_test(float freq){ + const DACConfig dac1cfg1 = { + .init = 2047U, + .datamode = DAC_DHRM_12BIT_RIGHT, + .cr = 0 + }; + dacStart(&DACD1, &dac1cfg1); + const float tau = 6.2832; + float step = freq * tau / 10e3; + float x = 0; + while(1){ + x += step; + if(x > tau) + x -= tau; + int16_t val = (1<<9)*(sin(x)+1); + dacPutChannelX(&DACD1, 1, val); + chThdSleepMicroseconds(100); + } +} +void dac_streaming_test(float freq){ + (void)freq; + //TODO: Make callback function to handle half-buffer fill +} +void i2c_simple_test(void){ + const I2CConfig i2c_cfg; // No configuration? + i2cStart(&I2CD1, &i2c_cfg); + sdStart(&SD1, &scfg); + chnWrite(&SD1, (const uint8_t *)"Starting I2C address scan...", 28); + /* Check all valid i2c addresses */ + for(short i = 0b1000; i <0b1111000; ++i ){ + msg_t result = i2cMasterTransmitTimeout(&I2CD1, i, NULL, 0, NULL, 0, TIME_MS2I(10)); + if(I2C_NO_ERROR == result){ // ACK received + char buf[32]; + char * tmp = memcpy2(buf, "\r\nACK ", 6); + tmp += format_hex(tmp, i); + chnWrite(&SD1, (const uint8_t *)buf, tmp-buf); + } + } + chnWrite(&SD1, (const uint8_t *)"\r\nDone.\r\n", 9); +} diff --git a/code/test.h b/code/test.h new file mode 100644 index 0000000..c4536e3 --- /dev/null +++ b/code/test.h @@ -0,0 +1,9 @@ + +void serial_test(char * msg); +void speaker_simple_test(float freq); +void speaker_streaming_test(float freq); +void adc_simple_test(void); +void encoder_test(void); +void dac_simple_test(float freq); +void dac_streaming_test(float freq); +void i2c_simple_test(void);