document and correct VFD library

This commit is contained in:
King Kévin 2016-08-14 20:18:10 +02:00
parent c68ab36d97
commit 8002255525
2 changed files with 88 additions and 102 deletions

View File

@ -12,10 +12,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */ /** library to drive vacuum fluorescent display using supertex HV518 shift register VFD drivers (code)
/* this library is used to drive the vacuum fluorescent display extracted from a Samsung SER-6500 cash register * @details the current configuration is for a VFD extracted from a Samsung SER-6500 cash register
* it uses three chained supertex HV518 shift register VFD drivers */ * @file vfd_hv518.c
* @author King Kévin <kingkevin@cuvoodoo.info>
* @date 2016
* @note peripherals used: SPI @ref vfd_hv518_spi , GPIO @ref vfd_hv518_gpio , timer @ref vfd_hv518_timer
*/
/* standard libraries */ /* standard libraries */
#include <stdint.h> // standard integer types #include <stdint.h> // standard integer types
#include <stdlib.h> // general utilities #include <stdlib.h> // general utilities
@ -30,53 +33,37 @@
#include "global.h" // global definitions #include "global.h" // global definitions
#include "vfd_hv518.h" // VFD library API #include "vfd_hv518.h" // VFD library API
/* supertex HV518 VFD driver pins */ /** @defgroup vfd_hv518_gpio GPIO to control supertex HV518 VFD drivers
/* port on which the pins to control the supertex HV518 VFD driver are * @{
* we use port A because of the SPI interface */ */
#define VFD_PORT GPIOA #define VFD_PORT GPIOA /**< GPIO port */
#define VFD_PORT_RCC RCC_GPIOA #define VFD_PORT_RCC RCC_GPIOA /**< GPIO port peripheral clock */
/* SPI port to use */ #define VFD_STR GPIO6 /**< strobe pin to enable high voltage output, high voltage is output on low */
#define VFD_SPI SPI1 #define VFD_NLE GPIO4 /**< latch enable pin, stores the shifted data on low, output the parallel data on high */
#if (VFD_SPI==SPI1) /** @} */
#define VFD_SPI_RCC RCC_SPI1
#define VFD_SPI_IRQ NVIC_SPI1_IRQ
#elif (VFD_SPI==SPI2)
#define VFD_SPI_RCC RCC_SPI2
#define VFD_SPI_IRQ NVIC_SPI2_IRQ
#endif
/* strobe pin to enable high voltage output
* high voltage is output on low
* drive using a GPIO PA6 (normally MISO) */
#define VFD_STR GPIO6
/* latch enable pin
* store the shifted data on low
* output the parallel data on high
* use GPIO (PA4) (NSS does not work as SS) */
#define VFD_NLE GPIO4
/* clock signal
* drive using SPI SCK (PA5) */
#define VFD_CLK GPIO_SPI1_SCK
/* data input, where the data is shifted to
* drive using SPI MOSI (PA7) */
#define VFD_DIN GPIO_SPI1_MOSI
/* timer for automatic refresh */
#define VFD_TIMER TIM2
#if (VFD_TIMER==TIM2)
#define VFD_TIMER_RCC RCC_TIM2
#define VFD_TIMER_IRQ NVIC_TIM2_IRQ
#elif (VFD_TIMER==TIM3)
#define VFD_TIMER_RCC RCC_TIM3
#define VFD_TIMER_IRQ NVIC_TIM3_IRQ
#elif (VFD_TIMER==TIM4)
#define VFD_TIMER_RCC RCC_TIM4
#define VFD_TIMER_IRQ NVIC_TIM4_IRQ
#elif (VFD_TIMER==TIM5)
#define VFD_TIMER_RCC RCC_TIM5
#define VFD_TIMER_IRQ NVIC_TIM5_IRQ
#endif
/* ASCII characters encoded for 7 segments display /** @defgroup vfd_hv518_spi SPI to send data to supertex HV518 VFD drivers
* starts with space * @{
*/
#define VFD_SPI_RCC RCC_SPI1 /**< SPI peripheral */
#define VFD_SPI_PORT GPIOA /**< GPIO port */
#define VFD_SPI_PORT_RCC RCC_GPIOA /**< GPIO port peripheral clock */
#define VFD_SPI_IRQ NVIC_SPI1_IRQ /**< SPI peripheral interrupt signal */
#define VFD_SPI_ISR spi1_isr /**< SPI interrupt service routine */
#define VFD_CLK GPIO_SPI1_SCK /**< clock signal */
#define VFD_DIN GPIO_SPI1_MOSI /**< data input, where the data is shifted to */
/** @} */
/** @defgroup vfd_hv518_timer timer for automatic display blocks refresh
* @{
*/
#define VFD_TIMER_RCC RCC_TIM2 /**< timer peripheral clock */
#define VFD_TIMER_IRQ NVIC_TIM2_IRQ /**< timer interrupt signal */
#define VFD_TIMER_ISR tim2_isr /**< timer interrupt service routine */
/** @} */
/** ASCII characters encoded for the 7 segments digit block
* @note starts with space
*/ */
static const uint8_t ascii_7segments[] = { static const uint8_t ascii_7segments[] = {
0b00000000, // space 0b00000000, // space
@ -176,10 +163,9 @@ static const uint8_t ascii_7segments[] = {
0b01000000, // ~ 0b01000000, // ~
}; };
/* font for the 5x7 dot matrix display /** font for the 5x7 dot matrix block
* from http://sunge.awardspace.com/glcd-sd/node4.html * @details first value is left-most line, LSB is top dot, MSB is not used
* first value is left-most line * @note from http://sunge.awardspace.com/glcd-sd/node4.html
* LSB is top dot, MSB is not used
*/ */
static const uint8_t font5x7[][5] = { static const uint8_t font5x7[][5] = {
{0x00, 0x00, 0x00, 0x00, 0x00}, // (space) {0x00, 0x00, 0x00, 0x00, 0x00}, // (space)
@ -279,9 +265,8 @@ static const uint8_t font5x7[][5] = {
{0b00001000, 0b00000100, 0b00001100, 0b00001000, 0b00000100} // ~ {0b00001000, 0b00000100, 0b00001100, 0b00001000, 0b00000100} // ~
}; };
/* pictures for the 5x7 dot matrix display /** pictures for the 5x7 dot matrix block
* first value is left-most line * @details first value is left-most line, LSB is top dot, MSB is not used
* LSB is top dot, MSB is not used
*/ */
static const uint8_t pict5x7[][5] = { static const uint8_t pict5x7[][5] = {
{0x08, 0x08, 0x2A, 0x1C, 0x08}, // -> {0x08, 0x08, 0x2A, 0x1C, 0x08}, // ->
@ -300,18 +285,23 @@ static const uint8_t pict5x7[][5] = {
{0x00, 0x00, 0x00, 0x00, 0x00} // nothing {0x00, 0x00, 0x00, 0x00, 0x00} // nothing
}; };
/* 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 * @note split into 16 bit for SPI transfer
* since the bits for digits and matrix are independent, they can be combined * @note since the bits for digits and matrix are independent, they can be combined
* we have more matrix (12) than digits (10) * @note we have more matrix (12) than digits (10)
*/ */
static uint16_t driver_data[VFD_MATRIX][VFD_DRIVERS*2] = {0}; static uint16_t driver_data[VFD_MATRIX][VFD_DRIVERS*2] = {0};
static volatile uint8_t spi_i = 0; // which driver data is being transmitted /** which driver data is being transmitted */
static volatile uint8_t vfd_grid = 0; // which grid/part to activate (single digits and matrix can be combined) static volatile uint8_t spi_i = 0;
static const uint32_t digit_mask = 0x00fffff0; // the bits used for selecting then digit and 7 segment anodes (for the second driver) /** which grid/part to activate
* @note digits and matrix can be combined
*/
static volatile uint8_t vfd_grid = 0;
/** the bits used for selecting then digit and 7 segment anodes
* @note for the second driver
*/
static const uint32_t digit_mask = 0x00fffff0;
/* set digit <nb> to ASCII character <c>
* use the MSB of <c> to enable the dot */
void vfd_digit(uint8_t nb, char c) void vfd_digit(uint8_t nb, char c)
{ {
if (!(nb<VFD_DIGITS)) { // check the digit exists if (!(nb<VFD_DIGITS)) { // check the digit exists
@ -352,8 +342,6 @@ void vfd_digit(uint8_t nb, char c)
driver_data[nb][3] = (digit_data>>16); // write back data (most significant half) driver_data[nb][3] = (digit_data>>16); // write back data (most significant half)
} }
/* set dot matrix <nb> to ASCII character <c>
* non ASCII characters are used for pictures */
void vfd_matrix(uint8_t nb, char c) void vfd_matrix(uint8_t nb, char c)
{ {
// check the matrix exists // check the matrix exists
@ -399,7 +387,6 @@ void vfd_matrix(uint8_t nb, char c)
} }
} }
/* clear VFD display */
void vfd_clear(void) void vfd_clear(void)
{ {
for (uint8_t i=0; i<LENGTH(driver_data); i++) { for (uint8_t i=0; i<LENGTH(driver_data); i++) {
@ -409,7 +396,6 @@ void vfd_clear(void)
} }
} }
/* test VFD display (light up all anodes) */
void vfd_test(void) void vfd_test(void)
{ {
for (uint8_t i=0; i<LENGTH(driver_data); i++) { for (uint8_t i=0; i<LENGTH(driver_data); i++) {
@ -419,21 +405,18 @@ void vfd_test(void)
} }
} }
/* switch VFD display on */
void vfd_on(void) void vfd_on(void)
{ {
gpio_clear(VFD_PORT, VFD_STR); // enable HV output gpio_clear(VFD_PORT, VFD_STR); // enable HV output
timer_enable_counter(VFD_TIMER); // start timer to periodically output that to the parts timer_enable_counter(VFD_TIMER); // start timer to periodically output that to the parts
} }
/* switch VFD display off */
void vfd_off(void) void vfd_off(void)
{ {
gpio_set(VFD_PORT, VFD_STR); // disable HV output gpio_set(VFD_PORT, VFD_STR); // disable HV output
timer_disable_counter(VFD_TIMER); // stop timer to periodically output that to the parts timer_disable_counter(VFD_TIMER); // stop timer to periodically output that to the parts
} }
/* setup VFD */
void vfd_setup(void) void vfd_setup(void)
{ {
/* setup GPIO to control the VFD */ /* setup GPIO to control the VFD */
@ -446,8 +429,9 @@ void vfd_setup(void)
/* setup SPI to transmit data */ /* setup SPI to transmit data */
rcc_periph_clock_enable(VFD_SPI_RCC); // enable SPI clock rcc_periph_clock_enable(VFD_SPI_RCC); // enable SPI clock
gpio_set_mode(VFD_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, VFD_CLK); // set VFD pin to alternative function push-pull rcc_periph_clock_enable(VFD_SPI_PORT_RCC); // enable clock for VFD SPI GPIO
gpio_set_mode(VFD_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, VFD_DIN); // set VFD pin to alternative function push-pull gpio_set_mode(VFD_SPI_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, VFD_CLK); // set VFD pin to alternative function push-pull
gpio_set_mode(VFD_SPI_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, VFD_DIN); // set VFD pin to alternative function push-pull
spi_reset(VFD_SPI); // clear SPI values spi_reset(VFD_SPI); // clear SPI values
/* set SPI: /* set SPI:
@ -485,11 +469,8 @@ void vfd_setup(void)
vfd_clear(); // initialize values vfd_clear(); // initialize values
} }
#if (VFD_SPI==SPI1) /** SPI interrupt service routine called when data has been transmitted */
void spi1_isr(void) void VFD_SPI_ISR(void)
#elif (VFD_SPI==SPI2)
void spi2_isr(void)
#endif
{ {
if (SPI_SR(VFD_SPI) & SPI_SR_TXE) { // transmission buffer empty if (SPI_SR(VFD_SPI) & SPI_SR_TXE) { // transmission buffer empty
if (spi_i<LENGTH(driver_data[0])) { // check if data is available if (spi_i<LENGTH(driver_data[0])) { // check if data is available
@ -504,15 +485,8 @@ void spi2_isr(void)
} }
} }
#if (VFD_TIMER==TIM2) /** timer interrupt service routine called time passed */
void tim2_isr(void) void VFD_TIMER_ISR(void)
#elif (VFD_TIMER==TIM3)
void tim3_isr(void)
#elif (VFD_TIMER==TIM4)
void tim4_isr(void)
#elif (VFD_TIMER==TIM5)
void tim5_isr(void)
#endif
{ {
if (timer_get_flag(VFD_TIMER, TIM_SR_UIF)) { // overflow even happened if (timer_get_flag(VFD_TIMER, TIM_SR_UIF)) { // overflow even happened
timer_clear_flag(VFD_TIMER, TIM_SR_UIF); // clear flag timer_clear_flag(VFD_TIMER, TIM_SR_UIF); // clear flag

View File

@ -12,28 +12,40 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */ /** library to drive vacuum fluorescent display using supertex HV518 shift register VFD drivers (API)
/* this library is used to drive the vacuum fluorescent display extracted from a Samsung SER-6500 cash register * @details the current configuration is for a VFD extracted from a Samsung SER-6500 cash register
* it uses three chained supertex HV518 shift register VFD drivers */ * @file vfd_hv518.h
* @author King Kévin <kingkevin@cuvoodoo.info>
* @date 2016
* @note peripherals used: USART @ref usart
*/
/* the number of blocks available on the VFD */ /** number HV518 VFD drivers */
#define VFD_DRIVERS 3 #define VFD_DRIVERS 3
/** number of digits blocks on SER-6500 VFD */
#define VFD_DIGITS 10 #define VFD_DIGITS 10
/** number of dot matrix blocks on SER-6500 VFD */
#define VFD_MATRIX 12 #define VFD_MATRIX 12
/* set digit <nb> to ASCII character <c> /** set character to digit block
* use the MSB of <c> to enable the dot */ * @param[in] nb digit block to set
* @param[in] c ASCII character to set
* @note use the MSB of @p nb to enable the dot
*/
void vfd_digit(uint8_t nb, char c); void vfd_digit(uint8_t nb, char c);
/* set dot matrix <nb> to ASCII character <c> /** set character to matrix block
* non ASCII characters are used for pictures */ * @param[in] nb matrix block to set
* @param[in] c ASCII character to set
* @note on ASCII characters are used for pictures
*/
void vfd_matrix(uint8_t nb, char c); void vfd_matrix(uint8_t nb, char c);
/* clear VFD display */ /** clear VFD display */
void vfd_clear(void); void vfd_clear(void);
/* test VFD display (light up all anodes) */ /** test VFD display (light up all segments) */
void vfd_test(void); void vfd_test(void);
/* transmit every digit and matrix */ /** switch VFD 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);
/* setup VFD */ /** setup VFD */
void vfd_setup(void); void vfd_setup(void);