diff --git a/Makefile b/Makefile index 2f07600..d451e18 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ # be silent per default, but 'make V=1' will show all compiler calls. ifneq ($(V),1) Q := @ -NULL := 2> /dev/null +NULL := 1> /dev/null 2> /dev/null endif # the final binary name (without extension) @@ -94,6 +94,9 @@ OOCD ?= openocd OOCD_INTERFACE ?= stlink-v2 OOCD_TARGET ?= stm32f1x +# which USB CDC ACM port is used bu the device, so we can reset it +ACMPORT = /dev/ttyACM0 + # board specific USB DFU bootloader BOOTLOADERS = STM32duino-bootloader BOOTLOADER = $(BOOTLOADERS)/STM32F1/binaries/generic_boot20_pa1.bin @@ -129,12 +132,12 @@ list: $(BINARY).list %.map: %.elf @# it's generated along with the elf -%.elf: $(OBJ) $(LDSCRIPT) $(LIB_DIR)/lib$(LIBNAME).a +%.elf: $(LDSCRIPT) $(LIB_DIR)/lib$(LIBNAME).a $(OBJ) $(info compiling $(@)) $(Q)$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJ) $(LDLIBS) -o $(@) + $(Q)size $(@) %.o: %.c - @#printf " CC $(*).c\n" $(Q)$(CC) $(CFLAGS) $(ARCH_FLAGS) -o $(@) -c $(<) clean: @@ -155,9 +158,14 @@ flash-swd: $(BINARY).hex $(info flashing $(<) using SWD) $(Q)$(OOCD) --file interface/$(OOCD_INTERFACE).cfg --file target/$(OOCD_TARGET).cfg --command "init" --command "reset init" --command "flash write_image erase $(<)" --command "reset" --command "shutdown" $(NULL) -flash-dfu: $(BINARY).bin +# reset device by setting the data width to 5 bis on the USB CDC ACM port +reset: + $(Q)stty --file /dev/ttyACM0 115200 raw cs5 + $(Q)sleep 0.5 + +flash-dfu: $(BINARY).bin reset $(info flashing $(<) using DFU) - $(Q)dfu-util --device 1eaf:0003 --cfg 1 --intf 0 --alt 2 --reset --download $(<) + $(Q)dfu-util --device 1eaf:0003 --cfg 1 --intf 0 --alt 2 --reset --download $(<) $(NULL) .PHONY: clean elf bin hex srec list bootloader flash flash-swd flash-dfu .SECONDARY: diff --git a/main.h b/global.h similarity index 85% rename from main.h rename to global.h index 6d2e1eb..559ae06 100644 --- a/main.h +++ b/global.h @@ -14,6 +14,12 @@ */ /* Copyright (c) 2016 King Kévin */ +/* get the length of an array */ +#define LENGTH(x) (sizeof(x) / sizeof((x)[0])) + +/* system clock frequency in Hz */ +#define SYSTEM_CLOCK_FREQ 72000000 + /* LED is on pin 11/PA1 */ #define LED_RCC RCC_GPIOA #define LED_PORT GPIOA @@ -21,3 +27,4 @@ /* default output (i.e. for printf) */ int _write(int file, char *ptr, int len); + diff --git a/lib/usb_cdcacm.c b/lib/usb_cdcacm.c index 27f3859..9f3d01e 100644 --- a/lib/usb_cdcacm.c +++ b/lib/usb_cdcacm.c @@ -24,20 +24,23 @@ #include // real-time control clock library #include // general purpose input output library #include // interrupt handler +#include // reset utilities #include // Cortex M3 utilities #include // USB library #include // USB CDC library #include "usb_cdcacm.h" // USB CDC ACM header and definitions -/* USB descriptor */ +/* USB devices descriptor + * as defined in USB CDC specification section 5 + */ static const struct usb_device_descriptor device_descriptor = { .bLength = USB_DT_DEVICE_SIZE, // the size of this header in bytes, 18 .bDescriptorType = USB_DT_DEVICE, // a value of 1 indicates that this is a device descriptor .bcdUSB = 0x0200, // this device supports USB 2.0 .bDeviceClass = USB_CLASS_CDC, // use the CDC device class - .bDeviceSubClass = USB_CDC_SUBCLASS_ACM, // use the ACM sub-class - .bDeviceProtocol = USB_CDC_PROTOCOL_NONE, // use no specific protocol + .bDeviceSubClass = 0, // unused + .bDeviceProtocol = 0, // unused .bMaxPacketSize0 = 64, // packet size for endpoint zero in bytes .idVendor = 0xc440, // Vendor ID (CuVo...) .idProduct = 0x0d00, // product ID within the Vendor ID space (...odoo) @@ -77,6 +80,9 @@ static const struct usb_endpoint_descriptor communication_endpoints[] = {{ .bInterval = 255, // the frequency, in number of frames, that we're going to be sending data }}; +/* functional descriptor + * as defined in USB CDC specification section 5.2.3 + */ static const struct { struct usb_cdc_header_descriptor header; struct usb_cdc_call_management_descriptor call_mgmt; @@ -90,8 +96,7 @@ static const struct { .bcdCDC = 0x0110, }, .call_mgmt = { - .bFunctionLength = - sizeof(struct usb_cdc_call_management_descriptor), + .bFunctionLength = sizeof(struct usb_cdc_call_management_descriptor), .bDescriptorType = CS_INTERFACE, .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, .bmCapabilities = 0, @@ -112,6 +117,9 @@ static const struct { }, }; +/* communication class interface descriptor + * as defined in USB CDC specification section 5.1.3 + */ static const struct usb_interface_descriptor communication_interface[] = {{ .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, @@ -129,6 +137,9 @@ static const struct usb_interface_descriptor communication_interface[] = {{ .extralen = sizeof(cdcacm_functional_descriptors), }}; +/* data class interface descriptor + * as defined in USB CDC specification section 5.1.3 + */ static const struct usb_interface_descriptor data_interface[] = {{ .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, @@ -158,7 +169,7 @@ static const struct usb_config_descriptor config = { .bNumInterfaces = 2, // the number of interfaces in this configuration .bConfigurationValue = 1, // the index of this configuration .iConfiguration = 0, // a string index describing this configuration (zero means not provided) - .bmAttributes = 0x80, // self powered (0<<6), supports remote wakeup (5<<0) + .bmAttributes = 0x80, // self powered (0<<6), supports remote wakeup (0<<5) .bMaxPower = 0x32, // the maximum amount of current that this device will draw in 2mA units // end of header .interface = interfaces, // pointer to an array of interfaces @@ -181,6 +192,9 @@ static usbd_device *usb_device; static uint8_t rx_buffer[CDCACM_BUFFER] = {0}; static volatile uint8_t rx_i = 0; static volatile uint8_t rx_used = 0; +static uint8_t tx_buffer[CDCACM_BUFFER] = {0}; +static volatile uint8_t tx_i = 0; +static volatile uint8_t tx_used = 0; /* show the user how much data received over USB is ready */ volatile uint8_t cdcacm_received = 0; // same as rx_used, but since the user can write this variable we don't rely on it @@ -191,30 +205,35 @@ static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data * (void)usbd_dev; switch (req->bRequest) { - case USB_CDC_REQ_SET_CONTROL_LINE_STATE: { - /* - * This Linux cdc_acm driver requires this to be implemented - * even though it's optional in the CDC spec, and we don't - * advertise it in the ACM functional descriptor. - */ - char local_buf[10]; - struct usb_cdc_notification *notif = (void *)local_buf; - - /* We echo signals back to host as notification. */ - notif->bmRequestType = 0xA1; - notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; - notif->wValue = 0; - notif->wIndex = 0; - notif->wLength = 2; - local_buf[8] = req->wValue & 3; - local_buf[9] = 0; - // usbd_ep_write_packet(0x83, buf, 10); - return 1; + case USB_CDC_REQ_SET_CONTROL_LINE_STATE: { + /* + bool dtr = (req->wValue & (1 << 0)) ? true : false; + bool rts = (req->wValue & (1 << 1)) ? true : false; + */ + /* this Linux cdc_acm driver requires this to be implemented + * even though it's optional in the CDC spec, and we don't + * advertise it in the ACM functional descriptor. + */ + return 1; } - case USB_CDC_REQ_SET_LINE_CODING: - if (*len < sizeof(struct usb_cdc_line_coding)) + case USB_CDC_REQ_SET_LINE_CODING: + // ignore if length is wrong + if (*len < sizeof(struct usb_cdc_line_coding)) { + return 0; + } + // get the line coding + struct usb_cdc_line_coding *coding = (struct usb_cdc_line_coding *)*buf; + /* reset device is the data bits is set to 5 + * this is used to allowing rebooting the device in DFU mode for reflashing + * to reset the device from the host you can use stty --file /dev/ttyACM0 115200 raw cs5 + */ + if (coding->bDataBits==5) { + scb_reset_system(); // reset device + while (true); // wait for the reset to happen + } + return 1; + default: return 0; - return 1; } return 0; } @@ -238,13 +257,35 @@ static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep) } } +static void cdcacm_data_tx_cb(usbd_device *usbd_dev, uint8_t ep) +{ + (void)ep; + (void)usbd_dev; + + char usb_data[64] = {0}; // buffer to send data + uint16_t usb_length = 0; // length of transmitted data + + /* transmit data */ + if (tx_used) { // copy received data + for (usb_length=0; usb_length. + * + */ +/* Copyright (c) 2016 King Kévin */ +/* this library is used to drive the vacuum fluorescent display extracted from a Samsung SER-6500 cash register + * it uses three chained supertex HV518 shift register VFD drivers */ + +/* standard libraries */ +#include // standard integer types +#include // general utilities + +/* STM32 (including CM3) libraries */ +#include // real-time control clock library +#include // general purpose input output library +#include // SPI library +#include // timer library +#include // interrupt handler + +#include "global.h" // global definitions +#include "vfd_hv518.h" // VFD library API + +/* supertex HV518 VFD driver pins */ +/* 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_RCC RCC_GPIOA +/* SPI port to use */ +#define VFD_SPI SPI1 +#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 + * starts with space + */ +static const uint8_t ascii_7segments[] = { + 0b00000000, // space + 0b00110000, // ! (I) + 0b00100010, // " + 0b01011100, // # (o) + 0b01101101, // $ (s) + 0b01010010, // % (/) + 0b01111101, // & (6) + 0b00100000, // ' + 0b00111001, // ( ([) + 0b00001111, // ) + 0b01110000, // * + 0b01000110, // + + 0b00010000, // , + 0b01000000, // - + 0b00010000, // . (,) + 0b01010010, // / + 0b00111111, // 0 + 0b00000110, // 1 + 0b01011011, // 2 + 0b01001111, // 3 + 0b01100110, // 4 + 0b01101101, // 5 + 0b01111101, // 6 + 0b00000111, // 7 + 0b01111111, // 8 + 0b01101111, // 9 + 0b01001000, // : (=) + 0b01001000, // ; (=) + 0b01011000, // < + 0b01001000, // = + 0b01001100, // > + 0b01010011, // ? + 0b01111011, // @ + 0b01110111, // A + 0b01111111, // B + 0b00111001, // C + 0b01011110, // D + 0b01111001, // E + 0b01110001, // F + 0b00111101, // G + 0b01110110, // H + 0b00110000, // I + 0b00011110, // J + 0b01110110, // K + 0b00111000, // L + 0b00110111, // M + 0b00110111, // N + 0b00111111, // O + 0b01110011, // P + 0b01101011, // Q + 0b00110011, // R + 0b01101101, // S + 0b01111000, // T + 0b00111110, // U + 0b00111110, // V (U) + 0b00111110, // W (U) + 0b01110110, // X (H) + 0b01101110, // Y + 0b01011011, // Z + 0b00111001, // [ + 0b01100100, // '\' + 0b00001111, // / + 0b00100011, // ^ + 0b00001000, // _ + 0b00000010, // ` + 0b01011111, // a + 0b01111100, // b + 0b01011000, // c + 0b01011110, // d + 0b01111011, // e + 0b01110001, // f + 0b01101111, // g + 0b01110100, // h + 0b00010000, // i + 0b00001100, // j + 0b01110110, // k + 0b00110000, // l + 0b01010100, // m + 0b01010100, // n + 0b01011100, // o + 0b01110011, // p + 0b01100111, // q + 0b01010000, // r + 0b01101101, // s + 0b01111000, // t + 0b00011100, // u + 0b00011100, // v (u) + 0b00011100, // w (u) + 0b01110110, // x + 0b01101110, // y + 0b01011011, // z + 0b00111001, // { ([) + 0b00110000, // | + 0b00001111, // } ([) + 0b01000000, // ~ +}; + +/* font for the 5x7 dot matrix display + * from http://sunge.awardspace.com/glcd-sd/node4.html + * first value is left-most line + * LSB is top dot, MSB is not used + */ +static const uint8_t font5x7[][5] = { + {0x00, 0x00, 0x00, 0x00, 0x00}, // (space) + {0x00, 0x00, 0x5F, 0x00, 0x00}, // ! + {0x00, 0x07, 0x00, 0x07, 0x00}, // " + {0x14, 0x7F, 0x14, 0x7F, 0x14}, // # + {0x24, 0x2A, 0x7F, 0x2A, 0x12}, // $ + {0x23, 0x13, 0x08, 0x64, 0x62}, // % + {0x36, 0x49, 0x55, 0x22, 0x50}, // & + {0x00, 0x05, 0x03, 0x00, 0x00}, // ' + {0x00, 0x1C, 0x22, 0x41, 0x00}, // ( + {0x00, 0x41, 0x22, 0x1C, 0x00}, // ) + {0x08, 0x2A, 0x1C, 0x2A, 0x08}, // * + {0x08, 0x08, 0x3E, 0x08, 0x08}, // + + {0x00, 0x50, 0x30, 0x00, 0x00}, // , + {0x08, 0x08, 0x08, 0x08, 0x08}, // - + {0x00, 0x60, 0x60, 0x00, 0x00}, // . + {0x20, 0x10, 0x08, 0x04, 0x02}, // / + {0x3E, 0x51, 0x49, 0x45, 0x3E}, // 0 + {0x00, 0x42, 0x7F, 0x40, 0x00}, // 1 + {0x42, 0x61, 0x51, 0x49, 0x46}, // 2 + {0x21, 0x41, 0x45, 0x4B, 0x31}, // 3 + {0x18, 0x14, 0x12, 0x7F, 0x10}, // 4 + {0x27, 0x45, 0x45, 0x45, 0x39}, // 5 + {0x3C, 0x4A, 0x49, 0x49, 0x30}, // 6 + {0x01, 0x71, 0x09, 0x05, 0x03}, // 7 + {0x36, 0x49, 0x49, 0x49, 0x36}, // 8 + {0x06, 0x49, 0x49, 0x29, 0x1E}, // 9 + {0x00, 0x36, 0x36, 0x00, 0x00}, // : + {0x00, 0x56, 0x36, 0x00, 0x00}, // ; + {0x00, 0x08, 0x14, 0x22, 0x41}, // < + {0x14, 0x14, 0x14, 0x14, 0x14}, // = + {0x41, 0x22, 0x14, 0x08, 0x00}, // > + {0x02, 0x01, 0x51, 0x09, 0x06}, // ? + {0x32, 0x49, 0x79, 0x41, 0x3E}, // @ + {0x7E, 0x11, 0x11, 0x11, 0x7E}, // A + {0x7F, 0x49, 0x49, 0x49, 0x36}, // B + {0x3E, 0x41, 0x41, 0x41, 0x22}, // C + {0x7F, 0x41, 0x41, 0x22, 0x1C}, // D + {0x7F, 0x49, 0x49, 0x49, 0x41}, // E + {0x7F, 0x09, 0x09, 0x01, 0x01}, // F + {0x3E, 0x41, 0x41, 0x51, 0x32}, // G + {0x7F, 0x08, 0x08, 0x08, 0x7F}, // H + {0x00, 0x41, 0x7F, 0x41, 0x00}, // I + {0x20, 0x40, 0x41, 0x3F, 0x01}, // J + {0x7F, 0x08, 0x14, 0x22, 0x41}, // K + {0x7F, 0x40, 0x40, 0x40, 0x40}, // L + {0x7F, 0x02, 0x04, 0x02, 0x7F}, // M + {0x7F, 0x04, 0x08, 0x10, 0x7F}, // N + {0x3E, 0x41, 0x41, 0x41, 0x3E}, // O + {0x7F, 0x09, 0x09, 0x09, 0x06}, // P + {0x3E, 0x41, 0x51, 0x21, 0x5E}, // Q + {0x7F, 0x09, 0x19, 0x29, 0x46}, // R + {0x46, 0x49, 0x49, 0x49, 0x31}, // S + {0x01, 0x01, 0x7F, 0x01, 0x01}, // T + {0x3F, 0x40, 0x40, 0x40, 0x3F}, // U + {0x1F, 0x20, 0x40, 0x20, 0x1F}, // V + {0x7F, 0x20, 0x18, 0x20, 0x7F}, // W + {0x63, 0x14, 0x08, 0x14, 0x63}, // X + {0x03, 0x04, 0x78, 0x04, 0x03}, // Y + {0x61, 0x51, 0x49, 0x45, 0x43}, // Z + {0x00, 0x00, 0x7F, 0x41, 0x41}, // [ + {0x02, 0x04, 0x08, 0x10, 0x20}, // '\' + {0x41, 0x41, 0x7F, 0x00, 0x00}, // ] + {0x04, 0x02, 0x01, 0x02, 0x04}, // ^ + {0x40, 0x40, 0x40, 0x40, 0x40}, // _ + {0x00, 0x01, 0x02, 0x04, 0x00}, // ` + {0x20, 0x54, 0x54, 0x54, 0x78}, // a + {0x7F, 0x48, 0x44, 0x44, 0x38}, // b + {0x38, 0x44, 0x44, 0x44, 0x20}, // c + {0x38, 0x44, 0x44, 0x48, 0x7F}, // d + {0x38, 0x54, 0x54, 0x54, 0x18}, // e + {0x08, 0x7E, 0x09, 0x01, 0x02}, // f + {0x08, 0x14, 0x54, 0x54, 0x3C}, // g + {0x7F, 0x08, 0x04, 0x04, 0x78}, // h + {0x00, 0x44, 0x7D, 0x40, 0x00}, // i + {0x20, 0x40, 0x44, 0x3D, 0x00}, // j + {0x00, 0x7F, 0x10, 0x28, 0x44}, // k + {0x00, 0x41, 0x7F, 0x40, 0x00}, // l + {0x7C, 0x04, 0x18, 0x04, 0x78}, // m + {0x7C, 0x08, 0x04, 0x04, 0x78}, // n + {0x38, 0x44, 0x44, 0x44, 0x38}, // o + {0x7C, 0x14, 0x14, 0x14, 0x08}, // p + {0x08, 0x14, 0x14, 0x18, 0x7C}, // q + {0x7C, 0x08, 0x04, 0x04, 0x08}, // r + {0x48, 0x54, 0x54, 0x54, 0x20}, // s + {0x04, 0x3F, 0x44, 0x40, 0x20}, // t + {0x3C, 0x40, 0x40, 0x20, 0x7C}, // u + {0x1C, 0x20, 0x40, 0x20, 0x1C}, // v + {0x3C, 0x40, 0x30, 0x40, 0x3C}, // w + {0x44, 0x28, 0x10, 0x28, 0x44}, // x + {0x0C, 0x50, 0x50, 0x50, 0x3C}, // y + {0x44, 0x64, 0x54, 0x4C, 0x44}, // z + {0x00, 0x08, 0x36, 0x41, 0x00}, // { + {0x00, 0x00, 0x7F, 0x00, 0x00}, // | + {0x00, 0x41, 0x36, 0x08, 0x00}, // } + {0b00001000, 0b00000100, 0b00001100, 0b00001000, 0b00000100} // ~ +}; + +/* pictures for the 5x7 dot matrix display + * first value is left-most line + * LSB is top dot, MSB is not used + */ +static const uint8_t pict5x7[][5] = { + {0x08, 0x08, 0x2A, 0x1C, 0x08}, // -> + {0x08, 0x1C, 0x2A, 0x08, 0x08}, // <- + {0b01110000, 0b01110000, 0b01111010, 0b01111100, 0b01011000}, // bunny side 1 + {0b00100000, 0b01110000, 0b01110010, 0b01111100, 0b01011000}, // bunny side 2 + {0b00111110, 0b01001001, 0b01010110, 0b01001001, 0b00111110}, // bunny face 1 + {0b00111110, 0b01010001, 0b01100110, 0b01010001, 0b00111110}, // bunny face 2 + {0b00111000, 0b01010111, 0b01100100, 0b01010111, 0b00111000}, // bunny face 3 + {0b00111000, 0b01001111, 0b01010100, 0b01001111, 0b00111000}, // bunny face 4 + {0b00111000, 0b01011110, 0b01101000, 0b01011110, 0b00111000}, // bunny face 5 + {0b01000001, 0b00110110, 0b00001000, 0b00110110, 0b01000001}, // cross 1 + {~0b01000001, ~0b00110110, ~0b00001000, ~0b00110110, ~0b01000001}, // cross 1 negated + {0b00100010, 0b00010100, 0b00001000, 0b00010100, 0b00100010}, // cross 2 + {~0b00100010, ~0b00010100, ~0b00001000, ~0b00010100, ~0b00100010}, // cross 2 negated + {0x00, 0x00, 0x00, 0x00, 0x00} // nothing +}; + +/* the 32 bits values to be shifted out to the VFD driver + * split into 16 bit for SPI transfer + * since the bits for digits and matrix are independent, they can be combined + * we have more matrix (12) than digits (10) + */ +static uint16_t driver_data[VFD_MATRIX][VFD_DRIVERS*2] = {0}; +static volatile uint8_t spi_i = 0; // 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 const uint32_t digit_mask = 0x00fffff0; // the bits used for selecting then digit and 7 segment anodes (for the second driver) + +/* set digit to ASCII character + * use the MSB of to enable the dot */ +void vfd_digit(uint8_t nb, char c) +{ + if (!(nb=' ') { // only take printable characters + uint8_t i = c-' '; // get index for character + if (i>16); // write back data (most significant half) +} + +/* set dot matrix to ASCII character + * non ASCII characters are used for pictures */ +void vfd_matrix(uint8_t nb, char c) +{ + // check the matrix exists + if (!(nb=' ')) { // only take printable characters + uint8_t i = c-' '; // get index for character + if (i0x7f) { // the non ASCII character are used for pictures + uint8_t i = c-0x80; // get index for character + if (i>16; + } +} + +/* clear VFD display */ +void vfd_clear(void) +{ + for (uint8_t i=0; i. + * + */ +/* Copyright (c) 2016 King Kévin */ +/* this library is used to drive the vacuum fluorescent display extracted from a Samsung SER-6500 cash register + * it uses three chained supertex HV518 shift register VFD drivers */ + +/* the number of blocks available on the VFD */ +#define VFD_DRIVERS 3 +#define VFD_DIGITS 10 +#define VFD_MATRIX 12 + +/* set digit to ASCII character + * use the MSB of to enable the dot */ +void vfd_digit(uint8_t nb, char c); +/* set dot matrix to ASCII character + * non ASCII characters are used for pictures */ +void vfd_matrix(uint8_t nb, char c); +/* clear VFD display */ +void vfd_clear(void); +/* test VFD display (light up all anodes) */ +void vfd_test(void); +/* transmit every digit and matrix */ +void vfd_on(void); +/* switch VFD display off */ +void vfd_off(void); +/* setup VFD */ +void vfd_setup(void); diff --git a/main.c b/main.c index f8ecd15..1e957a2 100644 --- a/main.c +++ b/main.c @@ -28,7 +28,7 @@ #include // Cortex M3 utilities /* own libraries */ -#include "main.h" // board definitions +#include "global.h" // board definitions #include "usart.h" // USART utilities #include "usb_cdcacm.h" // USB CDC ACM utilities