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);