diff options
Diffstat (limited to 'firmware/main.c')
-rw-r--r-- | firmware/main.c | 124 |
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. |