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
* split into 16 bit for SPI transfer */
static uint32_t vfd_data[VFD_DRIVERS] = {0};
static uint16_t vfd_spi[VFD_DRIVERS*2] = {0};
static volatile uint8_t vfd_spi_i = 0;
char vfd_digits[VFD_DIGITS] = {0};
char vfd_matrixs[VFD_MATRIX] = {0};
static uint16_t vfd_spi[VFD_DIGITS+VFD_MATRIX][VFD_DRIVERS*2] = {0};
static volatile uint8_t vfd_spi_i = 0; // which driver data is being transmitted
static volatile uint8_t vfd_mux = 0; // which part to output
/* set digit <nb> to ASCII character <c>
* 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
return;
}
// clear data
for (uint8_t i=0; i<LENGTH(vfd_data); i++) {
vfd_data[i] = 0;
}
uint32_t vfd_data[VFD_DRIVERS] = {0}; // the data to be shifted out for the driver
vfd_data[1] = 1<<(4+(9-nb)); // select digit
/* 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
}
}
// 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>
@ -361,10 +361,7 @@ void vfd_matrix(uint8_t nb, char c)
return;
}
// clear data
for (uint8_t i=0; i<LENGTH(vfd_data); i++) {
vfd_data[i] = 0;
}
uint32_t vfd_data[VFD_DRIVERS] = {0}; // the data to be shifted out for the driver
// select matrix
if (nb<4) {
@ -392,46 +389,11 @@ void vfd_matrix(uint8_t nb, char c)
vfd_data[2] |= pict5x7[i][4]<<24;
}
}
}
/* shift out the VFD data */
void vfd_shift(void)
{
// prepare SPI data
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");
}
// prepare the data for SPI to shift it out
for (uint8_t i=0; i<LENGTH(vfd_data); i++) {
vfd_spi[nb+VFD_DIGITS][i*2] = vfd_data[i];
vfd_spi[nb+VFD_DIGITS][i*2+1] = vfd_data[i]>>16;
}
}
@ -439,14 +401,10 @@ void vfd_transmit(void)
* the data has to be transmitted separately */
void vfd_clear(void)
{
for (uint8_t i=0; i<LENGTH(vfd_digits); i++) {
vfd_digits[i] = 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;
for (uint8_t i=0; i<LENGTH(vfd_spi); i++) {
for (uint8_t j=0; j<LENGTH(vfd_spi[0]); j++) {
vfd_spi[i][j] = 0;
}
}
}
@ -454,14 +412,10 @@ void vfd_clear(void)
* the data has to be transmitted separately */
void vfd_test(void)
{
for (uint8_t i=0; i<LENGTH(vfd_digits); i++) {
vfd_digits[i] = '8';
}
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;
for (uint8_t i=0; i<LENGTH(vfd_spi); i++) {
for (uint8_t j=0; j<LENGTH(vfd_spi[0]); j++) {
vfd_spi[i][j] = ~0;
}
}
}
@ -526,8 +480,8 @@ void vfd_setup(void)
spi_enable_software_slave_management(VFD_SPI);
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
spi_enable(VFD_SPI); // enable SPI (the tx empty interrupt will trigger)
/* setup timer to refresh display */
rcc_periph_clock_enable(VFD_TIMER_RCC); // enable clock for timer block
@ -548,11 +502,14 @@ void spi2_isr(void)
#endif
{
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
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
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)
#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
gpio_toggle(LED_PORT, LED_PIN);
timer_clear_flag(VFD_TIMER, TIM_SR_UIF); // clear flag
if (vfd_mux<LENGTH(vfd_digits)) {
if (vfd_digits[vfd_mux]!=0) { // skip unused digits
vfd_digit(vfd_mux,vfd_digits[vfd_mux]); // set digit
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
vfd_spi_i = 0; // set the register to shift out
spi_enable_tx_buffer_empty_interrupt(VFD_SPI); // enable TX empty interrupt
vfd_mux = (vfd_mux+1)%LENGTH(vfd_spi); // 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>
* non ASCII characters are used for pictures */
void vfd_matrix(uint8_t nb, char c);
/* shift out the VFD data */
void vfd_shift(void);
/* clear VFD display
* the data has to be transmitted separately */
void vfd_clear(void);
@ -40,8 +38,6 @@ void vfd_clear(void);
* the data has to be transmitted separately */
void vfd_test(void);
/* transmit every digit and matrix */
void vfd_transmit(void);
/* switch VFD display on */
void vfd_on(void);
/* switch VFD display off */
void vfd_off(void);

19
main.c
View File

@ -82,23 +82,20 @@ int main(void)
vfd_on(); // switch on VFD
vfd_refresh_on();
vfd_test();
vfd_shift();
for (uint32_t i = 0; i < 0x800000; i++) {
__asm__("nop");
}
vfd_clear();
vfd_shift();
vfd_digit(0,'0');
vfd_shift();
bool vfd_flag = false;
bool refresh = true;
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++) {
vfd_matrixs[i] = 'A'+i;
vfd_matrix(i,'A'+i);
}
while (true) {
while (usart_received) { // echo every received character
@ -112,7 +109,13 @@ int main(void)
while (vfd_flag) {
vfd_flag = false;
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;
}
__WFI(); // go to sleep