diff --git a/examples/vfd16LF01_counter/Makefile b/examples/vfd16LF01_counter/Makefile new file mode 100644 index 0000000..909105c --- /dev/null +++ b/examples/vfd16LF01_counter/Makefile @@ -0,0 +1,3 @@ +PROGRAM=vfd16lf01_counter +EXTRA_COMPONENTS = extras/vfd16lf01 +include ../../common.mk diff --git a/examples/vfd16LF01_counter/vfd16LF01_counter.c b/examples/vfd16LF01_counter/vfd16LF01_counter.c new file mode 100644 index 0000000..5dd106d --- /dev/null +++ b/examples/vfd16LF01_counter/vfd16LF01_counter.c @@ -0,0 +1,44 @@ +/* + * Simple cunter that is displayed on 16lf01 VFD display. + * Author: Grzegorz Hetman - ghetman@gmail.com + */ + +#include "espressif/esp_common.h" +#include "esp/uart.h" +#include "FreeRTOS.h" +#include "task.h" + +// Samsung VFD 16lf01 driver +#include "vfd16lf01/vfd16lf01.h" + +void counter(void *pvParameters) +{ + uint8_t count = 0; + + uint8_t pin_clk = 15; + uint8_t pin_rst = 13; + uint8_t pin_data = 0; + uint8_t digits = 16; + uint8_t brightness = 31; // Range 0-31 + + vfd_16lf01_init(pin_clk, pin_rst, pin_data, digits, brightness); + vfd_16lf01_print("ESP-OPEN-RTOS ;)", pin_clk, pin_data); + + vTaskDelay(5000 / portTICK_RATE_MS); + + while(1) { + char msg[16]; + sprintf(msg, "Counter %d", count++); + printf("%s\n", msg); + vfd_16lf01_print(msg, pin_clk, pin_data); + vTaskDelay(250 / portTICK_RATE_MS); + } +} + +void user_init(void) +{ + uart_set_baud(0, 115200); + printf("SDK version:%s\n", sdk_system_get_sdk_version()); + xTaskCreate(&counter, (signed char *)"counter", 256, NULL, 2, NULL); +} + diff --git a/extras/vfd16lf01/LICENSE b/extras/vfd16lf01/LICENSE new file mode 100644 index 0000000..3004e9b --- /dev/null +++ b/extras/vfd16lf01/LICENSE @@ -0,0 +1,7 @@ +This is a driver for Samsung 16LF01 series VFD. + +Originate written by Daniele Napolitano, distributed under GPL. + +Ported by Grzegorz Hetman : ghetman@gmail.com + +Daniele project site: https://github.com/DnaX/Samsung_16LF01_VFD \ No newline at end of file diff --git a/extras/vfd16lf01/component.mk b/extras/vfd16lf01/component.mk new file mode 100644 index 0000000..12d059d --- /dev/null +++ b/extras/vfd16lf01/component.mk @@ -0,0 +1,9 @@ +# Component makefile for extras/vfd16lf01 + +# expected anyone using bmp driver includes it as 'vfd16lf01/vfd16lf01.h' +INC_DIRS += $(vfd16lf01_ROOT).. + +# args for passing into compile rule generation +vfd16lf01_SRC_DIR = $(vfd16lf01_ROOT) + +$(eval $(call component_compile_rules,vfd16lf01)) diff --git a/extras/vfd16lf01/vfd16lf01.c b/extras/vfd16lf01/vfd16lf01.c new file mode 100644 index 0000000..5945448 --- /dev/null +++ b/extras/vfd16lf01/vfd16lf01.c @@ -0,0 +1,165 @@ +#include "vfd16lf01.h" +#include // sdk_os_delay_us + +#define VFD_CMD_BUFFER_POINTER 0b10100000 +#define VFD_CMD_DIGIT_COUNTER 0b11000000 +#define VFD_CMD_MASK 0b00001111 +#define VFD_CMD_BRIGHTNESS 0b11100000 +#define VFD_CMD_BRIGHTNESS_MASK 0b00011111 + +#define bit_read(value, bit) (((value) >> (bit)) & 0x01) + +static uint8_t _digits_count; + +static void vfd_16lf01_command(uint8_t payload, uint8_t clk, uint8_t data){ + static int8_t i=0; + // If you notice any strange issue with displayed payload + // please increase all delay value to 1~2ms. +#ifdef VIA_INVERTERS + for (i=7; i>=0; i--) { + if (bit_read(payload, i)){ + gpio_write(data, 0); + } else { + gpio_write(data, 1); + } + + gpio_write(clk, 0); + sdk_os_delay_us(500); + gpio_write(clk, 1); + sdk_os_delay_us(500); + gpio_write(clk, 0); + // Internal processing time (50us) + sdk_os_delay_us(50); + } +#else + for (i=7; i>=0; i--) { + if (bit_read(payload, i)){ + gpio_write(data, 1); + } else { + gpio_write(data, 0); + } + + gpio_write(clk, 1); + sdk_os_delay_us(500); + gpio_write(clk, 0); + sdk_os_delay_us(500); + gpio_write(clk, 1); + // Internal processing time (50us) + sdk_os_delay_us(50); + } +#endif +} + +// Set number of digits to control. +static void vfd_16lf01_set_digits_count(uint8_t digits, uint8_t clk, uint8_t data) { + if (digits > 16) { + digits = 16; + } + + _digits_count = digits; + digits &= VFD_CMD_MASK; + vfd_16lf01_command(VFD_CMD_DIGIT_COUNTER | digits, clk, data); +} + +// Write a char on the display +static inline uint8_t vfd_16lf01_write(uint8_t _char, uint8_t clk, uint8_t data) { + // First set of charmap (letters ad some symbols) + if (_char >= 64 && _char <= 95) { + vfd_16lf01_command(_char - 64, clk, data); + } + // Second set of charmap (numbers and some symbols) + else if (_char >= 32 && _char <= 63) { + vfd_16lf01_command(_char, clk, data); + } + // Lower case letters + else if (_char >= 97 && _char <= 122) { + vfd_16lf01_command(_char - 96, clk, data); + } + return 1; +} + +// Reset device. +void vfd_16lf01_reset(uint8_t rst){ +#ifdef VIA_INVERTERS + gpio_write(rst, 1); + sdk_os_delay_us(500); + gpio_write(rst, 0); + sdk_os_delay_us(500); +#else + gpio_write(rst, 0); + sdk_os_delay_us(500); + gpio_write(rst, 1); + sdk_os_delay_us(500); +#endif +} + +// Initialize device. +void vfd_16lf01_init(uint8_t clk, uint8_t rst, uint8_t data, uint8_t digits, uint8_t brightness) { + gpio_enable(clk, GPIO_OUTPUT); + gpio_enable(rst, GPIO_OUTPUT); + gpio_enable(data, GPIO_OUTPUT); + + vfd_16lf01_reset(rst); + vfd_16lf01_set_digits_count(digits, clk, data);//16 + + vfd_16lf01_clear(clk, data); + vfd_16lf01_set_brightness(brightness, clk, data);//31 +} + +// Set buffer pointer position. +void vfd_16lf01_set_cursor(uint8_t pos, uint8_t clk, uint8_t data) { + if (pos > 15) { + pos = 15; + } + + // First digit value is B1111, from second start from 0 + if (pos == 0) { + pos = 0b1111; + } + else { + pos--; + } + + pos &= VFD_CMD_MASK; + vfd_16lf01_command(VFD_CMD_BUFFER_POINTER | pos, clk, data); +} + +// Set display brightness, from 0 to 31. +void vfd_16lf01_set_brightness(uint8_t amount, uint8_t clk, uint8_t data) { + if (amount > 31) { + amount = 31; + } + amount &= VFD_CMD_BRIGHTNESS_MASK; + vfd_16lf01_command(VFD_CMD_BRIGHTNESS | amount, clk, data); +} + + +// Return to position 1 +void vfd_16lf01_home(uint8_t clk, uint8_t data) { + vfd_16lf01_set_cursor(0, clk, data); +} + +// Blank the display by setting up to 16 spaces +void vfd_16lf01_clear(uint8_t clk, uint8_t data) { + static uint8_t i = 0; + vfd_16lf01_set_cursor(0, clk, data); + for (i=0; i<_digits_count; i++) { + vfd_16lf01_write(' ', clk, data); + } +} + +void vfd_16lf01_print(char *chp, uint8_t clk, uint8_t data) { + uint8_t i = 0; + + vfd_16lf01_home(clk, data); + + while (*chp){ + vfd_16lf01_write(*chp++, clk, data); + i++; + } + + // Clear the rest cells that can display old characters. + for (;i < _digits_count; i++) { + vfd_16lf01_write(' ', clk, data); + } +} \ No newline at end of file diff --git a/extras/vfd16lf01/vfd16lf01.h b/extras/vfd16lf01/vfd16lf01.h new file mode 100644 index 0000000..96e1f80 --- /dev/null +++ b/extras/vfd16lf01/vfd16lf01.h @@ -0,0 +1,19 @@ +#ifndef DRIVER_VFD16LF01_H_ +#define DRIVER_VFD16LF01_H_ + +#include "FreeRTOS.h" + +// Comment this out, if your display +// is connected directly to esp module, +// otherwise all signals will be inverted. +#define VIA_INVERTERS + +void vfd_16lf01_init(uint8_t clk, uint8_t rst, uint8_t dat, uint8_t digits, uint8_t brightness); +void vfd_16lf01_set_brightness(uint8_t amount, uint8_t clk, uint8_t data); +void vfd_16lf01_set_cursor(uint8_t pos, uint8_t clk, uint8_t data); +void vfd_16lf01_print(char *chp, uint8_t clk, uint8_t data); +void vfd_16lf01_clear(uint8_t clk, uint8_t data); +void vfd_16lf01_home(uint8_t clk, uint8_t data); +void vfd_16lf01_reset(uint8_t rst); + +#endif