summaryrefslogtreecommitdiff
path: root/firmware/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/main.c')
-rw-r--r--firmware/main.c124
1 files changed, 62 insertions, 62 deletions
diff --git a/firmware/main.c b/firmware/main.c
index 7fc78c3..ec1e576 100644
--- a/firmware/main.c
+++ b/firmware/main.c
@@ -38,15 +38,6 @@
#include "serial.h"
#include "adc.h"
-/* Bit count of this device. Note that to change this you will also have to adapt the per-bit timer period lookup table
- * below.
- */
-#define NBITS 14
-
-/* Maximum bit count supported by serial command protocol. The brightness data is assumed to be of this bit width, but
- * only the uppermost NBITS bits are used. */
-#define MAX_BITS 16
-
void do_transpose(void);
/* Bit-golfed modulation data generated from the above values by the main loop, ready to be sent out to the shift
@@ -58,6 +49,56 @@ volatile uint32_t brightness_by_bit[NBITS] = { 0 };
uint32_t sys_time = 0;
uint32_t sys_time_seconds = 0;
+/* This value sets how long a batch of ADC conversions used for temperature measurement is started before the end of the
+ * longest cycle. Here too the above caveats apply.
+ *
+ * This value is in TIM1/TIM3 timer counts. */
+#define ADC_PRETRIGGER 150 /* trigger with about 12us margin to TIM1 CC IRQ */
+
+/* Bit timing base value. This is the lowes bit interval used */
+#define PERIOD_BASE 4
+
+/* This value is a constant offset added to every bit period to allow for the timer IRQ handler to execute. This is set
+ * empirically using a debugger and a logic analyzer. */
+#define TIMER_CYCLES_FOR_SPI_TRANSMISSIONS 120
+
+/* This is the same as above, but for the reset cycle of the bit period. */
+#define RESET_PERIOD_LENGTH 40
+
+/* Defines for brevity */
+#define A TIMER_CYCLES_FOR_SPI_TRANSMISSIONS
+#define B PERIOD_BASE
+
+/* This is a constant offset containing some empirically determined correction values */
+#define C (1 /* reset pulse comp */ - 3 /* analog snafu comp */)
+
+/* This lookup table maps bit positions to timer period values. This is a lookup table to allow for the compensation for
+ * non-linear effects of ringing at lower bit durations.
+ */
+static uint16_t timer_period_lookup[NBITS] = {
+ /* LSB here */
+ A - C + (B<< 0),
+ A - C + (B<< 1),
+ A - C + (B<< 2),
+ A - C + (B<< 3),
+ A - C + (B<< 4),
+ A - C + (B<< 5),
+ A - C + (B<< 6),
+ A - C + (B<< 7),
+ A - C + (B<< 8),
+ A - C + (B<< 9),
+ A - C + (B<<10),
+ A - C + (B<<11),
+ A - C + (B<<12),
+ A - C + (B<<13),
+ /* MSB here */
+};
+
+/* Don't pollute the global namespace */
+#undef A
+#undef B
+#undef C
+
int main(void) {
/* Get all the good clocks and PLLs on this thing up and running. We're running from an external 25MHz crystal,
* which we're first dividing down by 5 to get 5 MHz, then PLL'ing up by 6 to get 30 MHz as our main system clock.
@@ -90,14 +131,14 @@ int main(void) {
/* Enable all the periphery we need */
- RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN;
+ RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_DMAEN;
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN | RCC_APB2ENR_TIM1EN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_ADCEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
/* Configure all the GPIOs */
GPIOA->MODER |=
(3<<GPIO_MODER_MODER0_Pos) /* PA0 - Current measurement analog input */
- | (1<<GPIO_MODER_MODER1_Pos) /* PA1 - RS485 TX enable */
+ | (2<<GPIO_MODER_MODER1_Pos) /* PA1 - RS485 TX enable */
| (2<<GPIO_MODER_MODER2_Pos) /* PA2 - RS485 TX */
| (2<<GPIO_MODER_MODER3_Pos) /* PA3 - RS485 RX */
/* PA4 reserved because */
@@ -123,7 +164,8 @@ int main(void) {
/* Alternate function settings */
GPIOA->AFR[0] |=
- (1<<GPIO_AFRL_AFRL2_Pos) /* USART1_TX */
+ (1<<GPIO_AFRL_AFRL1_Pos) /* USART1_RTS (RS485 DE) */
+ | (1<<GPIO_AFRL_AFRL2_Pos) /* USART1_TX */
| (1<<GPIO_AFRL_AFRL3_Pos) /* USART1_RX */
| (0<<GPIO_AFRL_AFRL5_Pos) /* SPI1_SCK */
| (0<<GPIO_AFRL_AFRL7_Pos); /* SPI1_MOSI */
@@ -142,12 +184,14 @@ int main(void) {
TIM1->PSC = 1; /* Prescale by 2, resulting in a 16MHz timer frequency and 62.5ns timer step size. */
/* CH2 - clear/!MR, CH3 - strobe/STCP */
- TIM1->CCMR2 = (6<<TIM_CCMR2_OC3M_Pos) | TIM_CCMR2_OC3PE;
- TIM1->CCER |= TIM_CCER_CC3E | TIM_CCER_CC3NE | TIM_CCER_CC3P | TIM_CCER_CC3NP;
+ TIM1->CCMR2 = (6<<TIM_CCMR2_OC3M_Pos) | TIM_CCMR2_OC3PE | (6<<TIM_CCMR2_OC4M_Pos);
+ TIM1->CCER |= TIM_CCER_CC3E | TIM_CCER_CC3NE | TIM_CCER_CC3P | TIM_CCER_CC3NP | TIM_CCER_CC4E;
TIM1->BDTR = TIM_BDTR_MOE | (1<<TIM_BDTR_DTG_Pos); /* really short dead time */
TIM1->DIER = TIM_DIER_UIE; /* Enable update (overrun) interrupt */
TIM1->ARR = 1;
TIM1->CR1 |= TIM_CR1_CEN;
+ /* Trigger at the end of the longest bit cycle. This means this does not trigger in shorter bit cycles. */
+ TIM1->CCR4 = timer_period_lookup[NBITS-1] - ADC_PRETRIGGER;
/* Configure Timer 1 update (overrun) interrupt on NVIC. Used only for update (overrun) for strobe timing. */
NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
@@ -184,7 +228,8 @@ int main(void) {
| USART_CR1_RE;
USART1->CR3 = USART_CR3_DEM; /* RS485 DE enable (output on RTS) */
// USART1->BRR = 30;
- USART1->BRR = 40; // 750000
+ //USART1->BRR = 40; // 750000
+ USART1->BRR = 60; // 500000
USART1->CR1 |= USART_CR1_UE;
/* Configure USART1 interrupt on NVIC. Used only for RX. */
@@ -214,58 +259,13 @@ void do_transpose(void) {
for (uint32_t i=0; i<NBITS; i++) {
uint32_t mask = 1<<i<<(MAX_BITS-NBITS); /* Bit mask for this bit value. */
uint32_t bv = 0; /* accumulator thing */
- for (uint32_t j=0; j<32; j++) {
+ for (uint32_t j=0; j<32; j++)
if (rx_buf.set_fb_rq.framebuf[j] & mask)
- bv |= 1<<j;
- }
+ bv |= 1<<j;
brightness_by_bit[i] = bv;
}
}
-/* Bit timing base value. This is the lowes bit interval used */
-#define PERIOD_BASE 4
-
-/* This value is a constant offset added to every bit period to allow for the timer IRQ handler to execute. This is set
- * empirically using a debugger and a logic analyzer. */
-#define TIMER_CYCLES_FOR_SPI_TRANSMISSIONS 120
-
-/* This is the same as above, but for the reset cycle of the bit period. */
-#define RESET_PERIOD_LENGTH 40
-
-/* Defines for brevity */
-#define A TIMER_CYCLES_FOR_SPI_TRANSMISSIONS
-#define B PERIOD_BASE
-
-/* This is a constant offset containing some empirically determined correction values */
-#define C (1 /* reset pulse comp */ - 3 /* analog snafu comp */)
-
-/* This lookup table maps bit positions to timer period values. This is a lookup table to allow for the compensation for
- * non-linear effects of ringing at lower bit durations.
- */
-static uint16_t timer_period_lookup[NBITS] = {
- /* LSB here */
- A - C + (B<< 0),
- A - C + (B<< 1),
- A - C + (B<< 2),
- A - C + (B<< 3),
- A - C + (B<< 4),
- A - C + (B<< 5),
- A - C + (B<< 6),
- A - C + (B<< 7),
- A - C + (B<< 8),
- A - C + (B<< 9),
- A - C + (B<<10),
- A - C + (B<<11),
- A - C + (B<<12),
- A - C + (B<<13),
- /* MSB here */
-};
-
-/* Don't pollute the global namespace */
-#undef A
-#undef B
-#undef C
-
/* Timer 1 main IRQ handler. This is used only for overflow ("update" or UP event in ST's terminology). */
void TIM1_BRK_UP_TRG_COM_IRQHandler(void) {
/* The index of the currently active bit. On entry of this function, this is the bit index of the upcoming period.