precalculate all spi data

This commit is contained in:
King Kévin 2016-01-24 21:54:42 +01:00
parent 486d80f00d
commit 94664bafad
3 changed files with 47 additions and 100 deletions

124
lib/vfd.c
View File

@ -305,12 +305,9 @@ static const uint8_t pict5x7[][5] = {
/* the 32 bits values to be shifted out to the VFD driver /* the 32 bits values to be shifted out to the VFD driver
* split into 16 bit for SPI transfer */ * split into 16 bit for SPI transfer */
static uint32_t vfd_data[VFD_DRIVERS] = {0}; static uint16_t vfd_spi[VFD_DIGITS+VFD_MATRIX][VFD_DRIVERS*2] = {0};
static uint16_t vfd_spi[VFD_DRIVERS*2] = {0}; static volatile uint8_t vfd_spi_i = 0; // which driver data is being transmitted
static volatile uint8_t vfd_spi_i = 0; static volatile uint8_t vfd_mux = 0; // which part to output
char vfd_digits[VFD_DIGITS] = {0};
char vfd_matrixs[VFD_MATRIX] = {0};
/* set digit <nb> to ASCII character <c> /* set digit <nb> to ASCII character <c>
* use the MSB of <c> to enable the dot */ * use the MSB of <c> to enable the dot */
@ -319,11 +316,8 @@ void vfd_digit(uint8_t nb, char c)
if (!(nb<VFD_DIGITS)) { // check the digit exists if (!(nb<VFD_DIGITS)) { // check the digit exists
return; return;
} }
// clear data uint32_t vfd_data[VFD_DRIVERS] = {0}; // the data to be shifted out for the driver
for (uint8_t i=0; i<LENGTH(vfd_data); i++) {
vfd_data[i] = 0;
}
vfd_data[1] = 1<<(4+(9-nb)); // select digit vfd_data[1] = 1<<(4+(9-nb)); // select digit
/* encode segment /* encode segment
@ -350,6 +344,12 @@ void vfd_digit(uint8_t nb, char c)
vfd_data[1] |= (ascii_7segments[i]<<(17)); // add encoded segments to memory vfd_data[1] |= (ascii_7segments[i]<<(17)); // add encoded segments to memory
} }
} }
// prepare the data for SPI to shift it out
for (uint8_t i=0; i<LENGTH(vfd_data); i++) {
vfd_spi[nb][i*2] = vfd_data[i];
vfd_spi[nb][i*2+1] = vfd_data[i]>>16;
}
} }
/* set dot matrix <nb> to ASCII character <c> /* set dot matrix <nb> to ASCII character <c>
@ -361,10 +361,7 @@ void vfd_matrix(uint8_t nb, char c)
return; return;
} }
// clear data uint32_t vfd_data[VFD_DRIVERS] = {0}; // the data to be shifted out for the driver
for (uint8_t i=0; i<LENGTH(vfd_data); i++) {
vfd_data[i] = 0;
}
// select matrix // select matrix
if (nb<4) { if (nb<4) {
@ -392,46 +389,11 @@ void vfd_matrix(uint8_t nb, char c)
vfd_data[2] |= pict5x7[i][4]<<24; vfd_data[2] |= pict5x7[i][4]<<24;
} }
} }
}
/* shift out the VFD data */ // prepare the data for SPI to shift it out
void vfd_shift(void) for (uint8_t i=0; i<LENGTH(vfd_data); i++) {
{ vfd_spi[nb+VFD_DIGITS][i*2] = vfd_data[i];
// prepare SPI data vfd_spi[nb+VFD_DIGITS][i*2+1] = vfd_data[i]>>16;
for (uint8_t i=0; i<LENGTH(vfd_data) && (uint8_t)(i*2+1)<LENGTH(vfd_spi); i++) {
vfd_spi[i*2] = vfd_data[i];
vfd_spi[i*2+1] = vfd_data[i]>>16;
}
vfd_spi_i = 0;
// enable SPI (the tx empty interrupt will trigger)
spi_enable(VFD_SPI);
}
/* transmit every digit and matrix */
void vfd_transmit(void)
{
for (uint8_t i=0; i<LENGTH(vfd_digits); i++) {
if (vfd_digits[i]==0) {
continue; // skip unused digits
}
vfd_digit(i,vfd_digits[i]); // set digit
vfd_shift(); // shift out data
// let the fluorescence glow up a bit
for (uint32_t j = 0; j < 0x2000; j++) {
__asm__("nop");
}
}
for (uint8_t i=0; i<LENGTH(vfd_matrixs); i++) {
if (vfd_matrixs[i]==0) {
continue; // skip unused matrix
}
vfd_matrix(i,vfd_matrixs[i]); // set matrix
vfd_shift(); // shift out data
// let the fluorescence glow up a bit
for (uint32_t j = 0; j < 0x2000; j++) {
__asm__("nop");
}
} }
} }
@ -439,14 +401,10 @@ void vfd_transmit(void)
* the data has to be transmitted separately */ * the data has to be transmitted separately */
void vfd_clear(void) void vfd_clear(void)
{ {
for (uint8_t i=0; i<LENGTH(vfd_digits); i++) { for (uint8_t i=0; i<LENGTH(vfd_spi); i++) {
vfd_digits[i] = 0; for (uint8_t j=0; j<LENGTH(vfd_spi[0]); j++) {
} vfd_spi[i][j] = 0;
for (uint8_t i=0; i<LENGTH(vfd_matrixs); i++) { }
vfd_matrixs[i] = 0;
}
for (uint8_t i=0; i<LENGTH(vfd_data); i++) {
vfd_data[i] = 0;
} }
} }
@ -454,14 +412,10 @@ void vfd_clear(void)
* the data has to be transmitted separately */ * the data has to be transmitted separately */
void vfd_test(void) void vfd_test(void)
{ {
for (uint8_t i=0; i<LENGTH(vfd_digits); i++) { for (uint8_t i=0; i<LENGTH(vfd_spi); i++) {
vfd_digits[i] = '8'; for (uint8_t j=0; j<LENGTH(vfd_spi[0]); j++) {
} vfd_spi[i][j] = ~0;
for (uint8_t i=0; i<LENGTH(vfd_matrixs); i++) { }
vfd_matrixs[i] = 0x80+LENGTH(pict5x7)-1;
}
for (uint8_t i=0; i<LENGTH(vfd_data); i++) {
vfd_data[i] = ~0;
} }
} }
@ -526,8 +480,8 @@ void vfd_setup(void)
spi_enable_software_slave_management(VFD_SPI); spi_enable_software_slave_management(VFD_SPI);
spi_set_nss_high(VFD_SPI); // set NSS high spi_set_nss_high(VFD_SPI); // set NSS high
spi_enable_tx_buffer_empty_interrupt(VFD_SPI); // enable TX empty interrupt
nvic_enable_irq(VFD_SPI_IRQ); // enable SPI interrupt nvic_enable_irq(VFD_SPI_IRQ); // enable SPI interrupt
spi_enable(VFD_SPI); // enable SPI (the tx empty interrupt will trigger)
/* setup timer to refresh display */ /* setup timer to refresh display */
rcc_periph_clock_enable(VFD_TIMER_RCC); // enable clock for timer block rcc_periph_clock_enable(VFD_TIMER_RCC); // enable clock for timer block
@ -548,11 +502,14 @@ void spi2_isr(void)
#endif #endif
{ {
if (SPI_SR(VFD_SPI) & SPI_SR_TXE) { // transmission buffer empty if (SPI_SR(VFD_SPI) & SPI_SR_TXE) { // transmission buffer empty
if (vfd_spi_i<LENGTH(vfd_spi)) { // check if data is available if (vfd_spi_i<LENGTH(vfd_spi[0])) { // check if data is available
gpio_clear(VFD_PORT, VFD_NLE); // slave select to latch data gpio_clear(VFD_PORT, VFD_NLE); // slave select to latch data
spi_send(VFD_SPI, vfd_spi[vfd_spi_i++]); // send next data spi_send(VFD_SPI, vfd_spi[vfd_mux][vfd_spi_i++]); // send next data
} else { // all data transmitted } else { // all data transmitted
spi_clean_disable(VFD_SPI); // wait for transmission to complete spi_disable_tx_buffer_empty_interrupt(VFD_SPI); // no need to wait for new data
while (SPI_SR(VFD_SPI) & SPI_SR_BSY); // wait for data to be shifted out
spi_disable_tx_buffer_empty_interrupt(VFD_SPI); // no need to wait for new data
gpio_set(VFD_PORT, VFD_NLE); // output latched data
} }
} }
} }
@ -567,21 +524,12 @@ void tim4_isr(void)
void tim5_isr(void) void tim5_isr(void)
#endif #endif
{ {
static uint8_t vfd_mux = 0; // which part to output //gpio_toggle(LED_PORT, LED_PIN);
if (timer_get_flag(VFD_TIMER, TIM_SR_UIF)) { // overflow even happened if (timer_get_flag(VFD_TIMER, TIM_SR_UIF)) { // overflow even happened
gpio_toggle(LED_PORT, LED_PIN);
timer_clear_flag(VFD_TIMER, TIM_SR_UIF); // clear flag timer_clear_flag(VFD_TIMER, TIM_SR_UIF); // clear flag
if (vfd_mux<LENGTH(vfd_digits)) { vfd_spi_i = 0; // set the register to shift out
if (vfd_digits[vfd_mux]!=0) { // skip unused digits spi_enable_tx_buffer_empty_interrupt(VFD_SPI); // enable TX empty interrupt
vfd_digit(vfd_mux,vfd_digits[vfd_mux]); // set digit vfd_mux = (vfd_mux+1)%LENGTH(vfd_spi); // got to next segment
vfd_shift(); // shift out data
}
} else if (vfd_mux<LENGTH(vfd_digits)+LENGTH(vfd_matrixs)) {
if (vfd_matrixs[vfd_mux-LENGTH(vfd_digits)]!=0) { // skip unused matrix
vfd_matrix(vfd_mux-LENGTH(vfd_digits),vfd_matrixs[vfd_mux-LENGTH(vfd_digits)]); // set matrix
vfd_shift(); // shift out data
}
}
vfd_mux = (vfd_mux+1)%(LENGTH(vfd_digits)+LENGTH(vfd_matrixs)); // got to next segment
} }
} }

View File

@ -31,8 +31,6 @@ void vfd_digit(uint8_t nb, char c);
/* set dot matrix <nb> to ASCII character <c> /* set dot matrix <nb> to ASCII character <c>
* non ASCII characters are used for pictures */ * non ASCII characters are used for pictures */
void vfd_matrix(uint8_t nb, char c); void vfd_matrix(uint8_t nb, char c);
/* shift out the VFD data */
void vfd_shift(void);
/* clear VFD display /* clear VFD display
* the data has to be transmitted separately */ * the data has to be transmitted separately */
void vfd_clear(void); void vfd_clear(void);
@ -40,8 +38,6 @@ void vfd_clear(void);
* the data has to be transmitted separately */ * the data has to be transmitted separately */
void vfd_test(void); void vfd_test(void);
/* transmit every digit and matrix */ /* transmit every digit and matrix */
void vfd_transmit(void);
/* switch VFD display on */
void vfd_on(void); void vfd_on(void);
/* switch VFD display off */ /* switch VFD display off */
void vfd_off(void); void vfd_off(void);

19
main.c
View File

@ -82,23 +82,20 @@ int main(void)
vfd_on(); // switch on VFD vfd_on(); // switch on VFD
vfd_refresh_on();
vfd_test(); vfd_test();
vfd_shift();
for (uint32_t i = 0; i < 0x800000; i++) { for (uint32_t i = 0; i < 0x800000; i++) {
__asm__("nop"); __asm__("nop");
} }
vfd_clear(); vfd_clear();
vfd_shift();
vfd_digit(0,'0');
vfd_shift();
bool vfd_flag = false; bool vfd_flag = false;
bool refresh = true; bool refresh = true;
for (uint8_t i=0; i<LENGTH(vfd_digits); i++) { for (uint8_t i=0; i<LENGTH(vfd_digits); i++) {
vfd_digits[i] = '0'+i; vfd_digit(i,'0'+i);
} }
for (uint8_t i=0; i<LENGTH(vfd_matrixs); i++) { for (uint8_t i=0; i<LENGTH(vfd_matrixs); i++) {
vfd_matrixs[i] = 'A'+i; vfd_matrix(i,'A'+i);
} }
while (true) { while (true) {
while (usart_received) { // echo every received character while (usart_received) { // echo every received character
@ -112,7 +109,13 @@ int main(void)
while (vfd_flag) { while (vfd_flag) {
vfd_flag = false; vfd_flag = false;
gpio_toggle(LED_PORT, LED_PIN); // toggle LED gpio_toggle(LED_PORT, LED_PIN); // toggle LED
refresh ? vfd_refresh_on() : vfd_refresh_off(); if (refresh) {
printf("on\n");
vfd_refresh_on();
} else {
printf("off\n");
vfd_refresh_off();
}
refresh = !refresh; refresh = !refresh;
} }
__WFI(); // go to sleep __WFI(); // go to sleep