mirror of
https://github.com/elua/elua.git
synced 2025-01-25 01:02:54 +08:00
XMC4300: eLua LCD module for the DFRobot shield: Initial working commit
This commit is contained in:
parent
9e8d6b2583
commit
60173fea14
@ -28,6 +28,8 @@ return {
|
||||
linenoise = { shell_lines = 10, lua_lines = 50 },
|
||||
xmodem = false,
|
||||
niffs = false,
|
||||
xmc43_dac = true,
|
||||
xmc43_lcd = true,
|
||||
},
|
||||
config = {
|
||||
egc = { mode = "alloc" },
|
||||
|
@ -29,6 +29,10 @@ function add_platform_components( t, board, cpu )
|
||||
if board == 'XMC4700-RELAX' then
|
||||
t.xmc47_dac = { macro = 'ENABLE_DAC' }
|
||||
end
|
||||
if board == 'XMC4300-RELAX-ETHERCAT' then
|
||||
t.xmc43_dac = { macro = 'ENABLE_DAC' }
|
||||
t.xmc43_lcd = { macro = 'ENABLE_LCD' }
|
||||
end
|
||||
end
|
||||
|
||||
-- Add specific configuration to the 'configs' table
|
||||
@ -48,8 +52,9 @@ function get_platform_modules( board, cpu )
|
||||
m.pot = { guards = { 'ENABLE_POTENTIOMETER' }, lib = '"pot"', open = false }
|
||||
m.disp = { guards = { 'ENABLE_OLED_DISPLAY' }, lib = '"disp"', open = false }
|
||||
end
|
||||
if board == 'XMC4700-RELAX' then
|
||||
if board == 'XMC4700-RELAX' or board == 'XMC4300-RELAX-ETHERCAT' then
|
||||
m.dac = { guards = { 'ENABLE_DAC' }, lib = '"dac"', open = false }
|
||||
m.lcd = { guards = { 'ENABLE_LCD' }, lib = '"lcd"', open = false }
|
||||
end
|
||||
return m
|
||||
end
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
-- eLua configuration file for the XMC4000 series of microcontrollers
|
||||
|
||||
specific_files = "platform.c xmclib/src/xmc4_eru.c xmclib/src/xmc4_flash.c xmclib/src/xmc4_gpio.c xmclib/src/xmc4_rtc.c xmclib/src/xmc4_scu.c xmclib/src/xmc_can.c xmclib/src/xmc_ccu4.c xmclib/src/xmc_ccu8.c xmclib/src/xmc_common.c xmclib/src/xmc_dac.c xmclib/src/xmc_dma.c xmclib/src/xmc_dsd.c xmclib/src/xmc_ebu.c xmclib/src/xmc_ecat.c xmclib/src/xmc_eru.c xmclib/src/xmc_eth_mac.c xmclib/src/xmc_fce.c xmclib/src/xmc_gpio.c xmclib/src/xmc_hrpwm.c xmclib/src/xmc_i2c.c xmclib/src/xmc_i2s.c xmclib/src/xmc_ledts.c xmclib/src/xmc_posif.c xmclib/src/xmc_rtc.c xmclib/src/xmc_sdmmc.c xmclib/src/xmc_spi.c xmclib/src/xmc_uart.c xmclib/src/xmc_usbd.c xmclib/src/xmc_usic.c xmclib/src/xmc_vadc.c xmclib/src/xmc_wdt.c xmclib/gen/CLOCK_XMC4/clock_xmc4.c xmclib/gen/CLOCK_XMC4/clock_xmc4_conf.c xmclib/gen/UART/uart.c xmclib/gen/UART/uart_conf.c xmclib/gen/CPU_CTRL_XMC4/cpu_ctrl_xmc4.c xmclib/gen/CPU_CTRL_XMC4/cpu_ctrl_xmc4_conf.c xmclib/gen/FATFS/fatfs.c xmclib/gen/FATFS/fatfs_conf.c xmclib/gen/FATFS/sltha.c xmclib/gen/RTC/rtc.c xmclib/gen/RTC/rtc_conf.c xmclib/gen/SDMMC_BLOCK/sdmmc_block_private_sd.c xmclib/gen/SDMMC_BLOCK/sdmmc_block_private_spi.c xmclib/gen/SDMMC_BLOCK/sdmmc_block.c xmclib/gen/SDMMC_BLOCK/sdmmc_block_conf.c xmclib/gen/SYSTIMER/systimer.c xmclib/gen/SYSTIMER/systimer_conf.c xmclib/gen/DAVE.c pot.c dts.c rtc.c disp.c xmclib/gen/SPI_MASTER/spi_master.c xmclib/gen/SPI_MASTER/spi_master_conf.c xmclib/gen/GUI_SEGGERLIBRARY/gui_seggerlibrary.c xmclib/gen/GUI_SEGGERLIBRARY/gui_seggerlibrary_conf.c xmclib/gen/GUI_SEGGERLIBRARY/LCDConf.c xmclib/gen/GUI_SEGGERLIBRARY/Config/GUIConf.c xmclib/gen/GUI_SEGGERLIBRARY/Config/GUI_X.c ebu.c xmclib/gen/GLOBAL_DMA/global_dma.c xmclib/gen/GLOBAL_DMA/global_dma_conf.c dac.c"
|
||||
specific_files = "platform.c xmclib/src/xmc4_eru.c xmclib/src/xmc4_flash.c xmclib/src/xmc4_gpio.c xmclib/src/xmc4_rtc.c xmclib/src/xmc4_scu.c xmclib/src/xmc_can.c xmclib/src/xmc_ccu4.c xmclib/src/xmc_ccu8.c xmclib/src/xmc_common.c xmclib/src/xmc_dac.c xmclib/src/xmc_dma.c xmclib/src/xmc_dsd.c xmclib/src/xmc_ebu.c xmclib/src/xmc_ecat.c xmclib/src/xmc_eru.c xmclib/src/xmc_eth_mac.c xmclib/src/xmc_fce.c xmclib/src/xmc_gpio.c xmclib/src/xmc_hrpwm.c xmclib/src/xmc_i2c.c xmclib/src/xmc_i2s.c xmclib/src/xmc_ledts.c xmclib/src/xmc_posif.c xmclib/src/xmc_rtc.c xmclib/src/xmc_sdmmc.c xmclib/src/xmc_spi.c xmclib/src/xmc_uart.c xmclib/src/xmc_usbd.c xmclib/src/xmc_usic.c xmclib/src/xmc_vadc.c xmclib/src/xmc_wdt.c xmclib/gen/CLOCK_XMC4/clock_xmc4.c xmclib/gen/CLOCK_XMC4/clock_xmc4_conf.c xmclib/gen/UART/uart.c xmclib/gen/UART/uart_conf.c xmclib/gen/CPU_CTRL_XMC4/cpu_ctrl_xmc4.c xmclib/gen/CPU_CTRL_XMC4/cpu_ctrl_xmc4_conf.c xmclib/gen/FATFS/fatfs.c xmclib/gen/FATFS/fatfs_conf.c xmclib/gen/FATFS/sltha.c xmclib/gen/RTC/rtc.c xmclib/gen/RTC/rtc_conf.c xmclib/gen/SDMMC_BLOCK/sdmmc_block_private_sd.c xmclib/gen/SDMMC_BLOCK/sdmmc_block_private_spi.c xmclib/gen/SDMMC_BLOCK/sdmmc_block.c xmclib/gen/SDMMC_BLOCK/sdmmc_block_conf.c xmclib/gen/SYSTIMER/systimer.c xmclib/gen/SYSTIMER/systimer_conf.c xmclib/gen/DAVE.c pot.c dts.c rtc.c disp.c xmclib/gen/SPI_MASTER/spi_master.c xmclib/gen/SPI_MASTER/spi_master_conf.c xmclib/gen/GUI_SEGGERLIBRARY/gui_seggerlibrary.c xmclib/gen/GUI_SEGGERLIBRARY/gui_seggerlibrary_conf.c xmclib/gen/GUI_SEGGERLIBRARY/LCDConf.c xmclib/gen/GUI_SEGGERLIBRARY/Config/GUIConf.c xmclib/gen/GUI_SEGGERLIBRARY/Config/GUI_X.c ebu.c xmclib/gen/GLOBAL_DMA/global_dma.c xmclib/gen/GLOBAL_DMA/global_dma_conf.c dac.c lcd.c dwt.c"
|
||||
|
||||
local ldscript = ""
|
||||
local target_files = ""
|
||||
|
22
src/platform/xmc4000/dwt.c
Normal file
22
src/platform/xmc4000/dwt.c
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
/*
|
||||
* Taken from the "Microseconds delay lib for STM32 (or whatever ARM)
|
||||
* based on DWT". See https://github.com/keatis/dwt_delay/
|
||||
*/
|
||||
|
||||
#include "dwt.h"
|
||||
|
||||
/* Initialize DWT for micros delay */
|
||||
void dwt_init (void) {
|
||||
if (!(CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk)) {
|
||||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||
DWT->CYCCNT = 0;
|
||||
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
|
||||
}
|
||||
}
|
||||
|
||||
/* DWT delay routine */
|
||||
void dwt_delay (uint32_t us) {
|
||||
int32_t target_tick = DWT->CYCCNT + us * (SystemCoreClock / 1000000);
|
||||
while (DWT->CYCCNT <= target_tick);
|
||||
}
|
15
src/platform/xmc4000/dwt.h
Normal file
15
src/platform/xmc4000/dwt.h
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
/*
|
||||
* Taken from the "Microseconds delay lib for STM32 (or whatever ARM)
|
||||
* based on DWT". See https://github.com/keatis/dwt_delay/
|
||||
*/
|
||||
|
||||
#ifndef DWT_H_
|
||||
#define DWT_H_
|
||||
|
||||
#include <DAVE.h>
|
||||
|
||||
void dwt_init (void);
|
||||
void dwt_delay (uint32_t us);
|
||||
|
||||
#endif /* DWT_H_ */
|
612
src/platform/xmc4000/lcd.c
Normal file
612
src/platform/xmc4000/lcd.c
Normal file
@ -0,0 +1,612 @@
|
||||
|
||||
/*
|
||||
* Arduino's LiquidCrystal interface: Adapted for XMC4300 (and
|
||||
* friends) by Raman Gopalan <ramangopalan@gmail.com>
|
||||
* See https://github.com/arduino-libraries/LiquidCrystal
|
||||
*
|
||||
* LCD Lua module structure adapted from Mizar32's I2C LCD interface.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
#include "platform.h"
|
||||
#include "lrotable.h"
|
||||
#include "platform_conf.h"
|
||||
#include "lcd.h"
|
||||
#include "dwt.h"
|
||||
|
||||
/********************************************************************************
|
||||
Globals
|
||||
*******************************************************************************/
|
||||
|
||||
lcd_t xmc_lcd;
|
||||
|
||||
// When the display powers up, it is configured as follows:
|
||||
//
|
||||
// 1. Display clear
|
||||
// 2. Function set:
|
||||
// DL = 1; 8-bit interface data
|
||||
// N = 0; 1-line display
|
||||
// F = 0; 5x8 dot character font
|
||||
// 3. Display on/off control:
|
||||
// D = 0; Display off
|
||||
// C = 0; Cursor off
|
||||
// B = 0; Blinking off
|
||||
// 4. Entry mode set:
|
||||
// I/D = 1; Increment by 1
|
||||
// S = 0; No shift
|
||||
//
|
||||
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
|
||||
// can't assume that its in that state when a sketch starts (and the
|
||||
// LiquidCrystal constructor is called).
|
||||
|
||||
/********************************************************************************
|
||||
INITIALIZATION FUNCTIONS
|
||||
*******************************************************************************/
|
||||
|
||||
void lcd_init_4bits_mode (lcd_t *l) {
|
||||
lcd_init(l,
|
||||
1,
|
||||
LCD_RS_PIN,
|
||||
NULL,
|
||||
255,
|
||||
LCD_ENABLE_PIN,
|
||||
LCD_DATA4_PIN,
|
||||
LCD_DATA5_PIN,
|
||||
LCD_DATA6_PIN,
|
||||
LCD_DATA7_PIN,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
NULL, 0);
|
||||
}
|
||||
|
||||
void lcd_init (lcd_t *l,
|
||||
uint8_t four_bit_mode,
|
||||
XMC_GPIO_PORT_t *const rs_port,
|
||||
uint8_t rs_pin,
|
||||
XMC_GPIO_PORT_t *const rw_port,
|
||||
uint8_t rw_pin,
|
||||
XMC_GPIO_PORT_t *const enable_port,
|
||||
uint8_t enable_pin,
|
||||
XMC_GPIO_PORT_t *const d0_port,
|
||||
uint8_t d0_pin,
|
||||
XMC_GPIO_PORT_t *const d1_port,
|
||||
uint8_t d1_pin,
|
||||
XMC_GPIO_PORT_t *const d2_port,
|
||||
uint8_t d2_pin,
|
||||
XMC_GPIO_PORT_t *const d3_port,
|
||||
uint8_t d3_pin,
|
||||
XMC_GPIO_PORT_t *const d4_port,
|
||||
uint8_t d4_pin,
|
||||
XMC_GPIO_PORT_t *const d5_port,
|
||||
uint8_t d5_pin,
|
||||
XMC_GPIO_PORT_t *const d6_port,
|
||||
uint8_t d6_pin,
|
||||
XMC_GPIO_PORT_t *const d7_port,
|
||||
uint8_t d7_pin) {
|
||||
l->rs_port = rs_port;
|
||||
l->rs_pin = rs_pin;
|
||||
l->rw_port = rw_port;
|
||||
l->rw_pin = rw_pin;
|
||||
l->enable_port = enable_port;
|
||||
l->enable_pin = enable_pin;
|
||||
l->data_pins[0] = d0_pin;
|
||||
l->data_pins[1] = d1_pin;
|
||||
l->data_pins[2] = d2_pin;
|
||||
l->data_pins[3] = d3_pin;
|
||||
l->data_pins[4] = d4_pin;
|
||||
l->data_pins[5] = d5_pin;
|
||||
l->data_pins[6] = d6_pin;
|
||||
l->data_pins[7] = d7_pin;
|
||||
l->data_ports[0] = d0_port;
|
||||
l->data_ports[1] = d1_port;
|
||||
l->data_ports[2] = d2_port;
|
||||
l->data_ports[3] = d3_port;
|
||||
l->data_ports[4] = d4_port;
|
||||
l->data_ports[5] = d5_port;
|
||||
l->data_ports[6] = d6_port;
|
||||
l->data_ports[7] = d7_port;
|
||||
|
||||
if (four_bit_mode)
|
||||
l->display_function = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
|
||||
else
|
||||
l->display_function = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS;
|
||||
|
||||
lcd_begin(l, LCD_COLS, LCD_ROWS, LCD_5x8DOTS);
|
||||
}
|
||||
|
||||
void lcd_begin (lcd_t *l, uint8_t cols, uint8_t lines, uint8_t dotsize) {
|
||||
int i;
|
||||
|
||||
if (lines > 1) {
|
||||
l->display_function |= LCD_2LINE;
|
||||
}
|
||||
l->num_lines = lines;
|
||||
|
||||
lcd_set_row_offsets(l, 0x00, 0x40, 0x00 + cols, 0x40 + cols);
|
||||
|
||||
/* For some 1 line displays you can select a 10 pixel high font */
|
||||
if ((dotsize != LCD_5x8DOTS) && (lines == 1)) {
|
||||
l->display_function |= LCD_5x10DOTS;
|
||||
}
|
||||
|
||||
XMC_GPIO_SetMode(l->rs_port, l->rs_pin, XMC_GPIO_MODE_OUTPUT_PUSH_PULL);
|
||||
// we can save 1 pin by not using RW. Indicate by passing 255 instead of pin#
|
||||
if (l->rw_pin != 255) {
|
||||
XMC_GPIO_SetMode(l->rw_port, l->rw_pin, XMC_GPIO_MODE_OUTPUT_PUSH_PULL);
|
||||
}
|
||||
XMC_GPIO_SetMode(l->enable_port, l->enable_pin, XMC_GPIO_MODE_OUTPUT_PUSH_PULL);
|
||||
|
||||
/* Do these once, instead of every time a character is drawn for speed reasons. */
|
||||
for (i = 0; i < ((l->display_function & LCD_8BITMODE) ? 8U : 4U); ++i) {
|
||||
XMC_GPIO_SetMode(l->data_ports[i], l->data_pins[i], XMC_GPIO_MODE_OUTPUT_PUSH_PULL);
|
||||
}
|
||||
|
||||
// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
|
||||
// according to datasheet, we need at least 40ms after power rises above 2.7V
|
||||
// before sending commands. Arduino can turn on way before 4.5V so we'll wait 50
|
||||
dwt_delay(50000);
|
||||
// Now we pull both RS and R/W low to begin commands
|
||||
XMC_GPIO_SetOutputLow(l->rs_port, l->rs_pin);
|
||||
XMC_GPIO_SetOutputLow(l->enable_port, l->enable_pin);
|
||||
if (l->rw_pin != 255) {
|
||||
XMC_GPIO_SetOutputLow(l->rw_port, l->rw_pin);
|
||||
}
|
||||
|
||||
//put the LCD into 4 bit or 8 bit mode
|
||||
if (!(l->display_function & LCD_8BITMODE)) {
|
||||
// this is according to the hitachi HD44780 datasheet
|
||||
// figure 24, pg 46
|
||||
|
||||
// we start in 8bit mode, try to set 4 bit mode
|
||||
lcd_write4bits(l, 0x03);
|
||||
dwt_delay(4500); // wait min 4.1ms
|
||||
|
||||
// second try
|
||||
lcd_write4bits(l, 0x03);
|
||||
dwt_delay(4500); // wait min 4.1ms
|
||||
|
||||
// third go!
|
||||
lcd_write4bits(l, 0x03);
|
||||
dwt_delay(150);
|
||||
|
||||
// finally, set to 4-bit interface
|
||||
lcd_write4bits(l, 0x02);
|
||||
} else {
|
||||
// this is according to the hitachi HD44780 datasheet
|
||||
// page 45 figure 23
|
||||
|
||||
// Send function set command sequence
|
||||
lcd_command(l, LCD_FUNCTIONSET | l->display_function);
|
||||
dwt_delay(4500); // wait more than 4.1ms
|
||||
|
||||
// second try
|
||||
lcd_command(l, LCD_FUNCTIONSET | l->display_function);
|
||||
dwt_delay(150);
|
||||
|
||||
// third go
|
||||
lcd_command(l, LCD_FUNCTIONSET | l->display_function);
|
||||
}
|
||||
|
||||
// finally, set # lines, font size, etc.
|
||||
lcd_command(l, LCD_FUNCTIONSET | l->display_function);
|
||||
|
||||
// turn the display on with no cursor or blinking default
|
||||
l->display_control = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
|
||||
lcd_display(l);
|
||||
|
||||
// clear it off
|
||||
lcd_clear(l);
|
||||
|
||||
// Initialize to default text direction (for romance languages)
|
||||
l->display_mode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
|
||||
// set the entry mode
|
||||
lcd_command(l, LCD_ENTRYMODESET | l->display_mode);
|
||||
|
||||
}
|
||||
|
||||
void lcd_set_row_offsets (lcd_t *l, int row0, int row1, int row2, int row3) {
|
||||
l->row_offsets[0] = row0;
|
||||
l->row_offsets[1] = row1;
|
||||
l->row_offsets[2] = row2;
|
||||
l->row_offsets[3] = row3;
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
USER FUNCTIONS
|
||||
*******************************************************************************/
|
||||
|
||||
void lcd_clear (lcd_t *l) {
|
||||
lcd_command(l, LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
||||
dwt_delay(2000); // this command takes a long time!
|
||||
}
|
||||
|
||||
void lcd_home (lcd_t *l) {
|
||||
lcd_command(l, LCD_RETURNHOME); // set cursor position to zero
|
||||
dwt_delay(2000); // this command takes a long time!
|
||||
}
|
||||
|
||||
void lcd_set_cursor (lcd_t *l, uint8_t col, uint8_t row) {
|
||||
const size_t max_lines = sizeof(l->row_offsets) / sizeof(*l->row_offsets);
|
||||
if (row >= max_lines) {
|
||||
row = max_lines - 1; // we count rows starting w/0
|
||||
}
|
||||
if (row >= l->num_lines) {
|
||||
row = l->num_lines - 1; // we count rows starting w/0
|
||||
}
|
||||
|
||||
lcd_command(l, LCD_SETDDRAMADDR | (col + l->row_offsets[row]));
|
||||
}
|
||||
|
||||
// Turn the display on/off (quickly)
|
||||
void lcd_no_display (lcd_t *l) {
|
||||
l->display_control &= ~LCD_DISPLAYON;
|
||||
lcd_command(l, LCD_DISPLAYCONTROL | l->display_control);
|
||||
}
|
||||
|
||||
void lcd_display (lcd_t *l) {
|
||||
l->display_control |= LCD_DISPLAYON;
|
||||
lcd_command(l, LCD_DISPLAYCONTROL | l->display_control);
|
||||
}
|
||||
|
||||
// Turns the underline cursor on/off
|
||||
void lcd_no_cursor (lcd_t *l) {
|
||||
l->display_control &= ~LCD_CURSORON;
|
||||
lcd_command(l, LCD_DISPLAYCONTROL | l->display_control);
|
||||
}
|
||||
|
||||
void lcd_cursor (lcd_t *l) {
|
||||
l->display_control |= LCD_CURSORON;
|
||||
lcd_command(l, LCD_DISPLAYCONTROL | l->display_control);
|
||||
}
|
||||
|
||||
// Turn on and off the blinking cursor
|
||||
void lcd_no_blink (lcd_t *l) {
|
||||
l->display_control &= ~LCD_BLINKON;
|
||||
lcd_command(l, LCD_DISPLAYCONTROL | l->display_control);
|
||||
}
|
||||
|
||||
void lcd_blink (lcd_t *l) {
|
||||
l->display_control |= LCD_BLINKON;
|
||||
lcd_command(l, LCD_DISPLAYCONTROL | l->display_control);
|
||||
}
|
||||
|
||||
// These commands scroll the display without changing the RAM
|
||||
void lcd_scroll_display_left (lcd_t *l) {
|
||||
lcd_command(l, LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
|
||||
}
|
||||
|
||||
void lcd_scroll_display_right (lcd_t *l) {
|
||||
lcd_command(l, LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
|
||||
}
|
||||
|
||||
// This is for text that flows Left to Right
|
||||
void lcd_left_to_right (lcd_t *l) {
|
||||
l->display_mode |= LCD_ENTRYLEFT;
|
||||
lcd_command(l, LCD_ENTRYMODESET | l->display_mode);
|
||||
}
|
||||
|
||||
// This is for text that flows Right to Left
|
||||
void lcd_right_to_left (lcd_t *l) {
|
||||
l->display_mode &= ~LCD_ENTRYLEFT;
|
||||
lcd_command(l, LCD_ENTRYMODESET | l->display_mode);
|
||||
}
|
||||
|
||||
// This will 'right justify' text from the cursor
|
||||
void lcd_autoscroll (lcd_t *l) {
|
||||
l->display_mode |= LCD_ENTRYSHIFTINCREMENT;
|
||||
lcd_command(l, LCD_ENTRYMODESET | l->display_mode);
|
||||
}
|
||||
|
||||
// This will 'left justify' text from the cursor
|
||||
void lcd_no_autoscroll (lcd_t *l) {
|
||||
l->display_mode &= ~LCD_ENTRYSHIFTINCREMENT;
|
||||
lcd_command(l, LCD_ENTRYMODESET | l->display_mode);
|
||||
}
|
||||
|
||||
// Allows us to fill the first 8 CGRAM locations
|
||||
// with custom characters
|
||||
void lcd_create_char (lcd_t *l, uint8_t location, uint8_t charmap[]) {
|
||||
uint32_t i;
|
||||
location &= 0x7; // we only have 8 locations 0-7
|
||||
lcd_command(l, LCD_SETCGRAMADDR | (location << 3));
|
||||
for (i = 0; i < 8; i++) {
|
||||
lcd_write(l, charmap[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_echo (lcd_t *l, uint8_t *s, uint32_t len) {
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
lcd_write(l, s[i]);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
MID LEVEL FUNCTIONS (FOR SENDING DATA/COMMANDS)
|
||||
*******************************************************************************/
|
||||
|
||||
inline void lcd_command (lcd_t *l, uint8_t value) {
|
||||
lcd_send(l, value, 0U);
|
||||
}
|
||||
|
||||
inline size_t lcd_write (lcd_t *l, uint8_t value) {
|
||||
lcd_send(l, value, 1U);
|
||||
return 1; // assume success
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
LOW LEVEL DATA PUSHING FUNCTIONS
|
||||
*******************************************************************************/
|
||||
|
||||
/* Write either command or data, with automatic 4/8-bit selection */
|
||||
void lcd_send (lcd_t *l, uint8_t value, uint8_t mode) {
|
||||
if (mode)
|
||||
XMC_GPIO_SetOutputHigh(l->rs_port, l->rs_pin);
|
||||
else
|
||||
XMC_GPIO_SetOutputLow(l->rs_port, l->rs_pin);
|
||||
|
||||
// If there is a RW pin indicated, set it low to write
|
||||
if (l->rw_pin != 255) {
|
||||
XMC_GPIO_SetOutputLow(l->rw_port, l->rw_pin);
|
||||
}
|
||||
|
||||
if (l->display_function & LCD_8BITMODE) {
|
||||
lcd_write8bits(l, value);
|
||||
} else {
|
||||
lcd_write4bits(l, value >> 4);
|
||||
lcd_write4bits(l, value);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_pulse_enable (lcd_t *l) {
|
||||
XMC_GPIO_SetOutputLow(l->enable_port, l->enable_pin);
|
||||
dwt_delay(1);
|
||||
XMC_GPIO_SetOutputHigh(l->enable_port, l->enable_pin);
|
||||
dwt_delay(1); // enable pulse must be >450ns
|
||||
XMC_GPIO_SetOutputLow(l->enable_port, l->enable_pin);
|
||||
dwt_delay(100); // commands need > 37us to settle
|
||||
}
|
||||
|
||||
void lcd_write4bits (lcd_t *l, uint8_t value) {
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if ((value >> i) & 0x01)
|
||||
XMC_GPIO_SetOutputHigh(l->data_ports[i], l->data_pins[i]);
|
||||
else
|
||||
XMC_GPIO_SetOutputLow(l->data_ports[i], l->data_pins[i]);
|
||||
}
|
||||
|
||||
lcd_pulse_enable(l);
|
||||
}
|
||||
|
||||
void lcd_write8bits (lcd_t *l, uint8_t value) {
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if ((value >> i) & 0x01)
|
||||
XMC_GPIO_SetOutputHigh(l->data_ports[i], l->data_pins[i]);
|
||||
else
|
||||
XMC_GPIO_SetOutputLow(l->data_ports[i], l->data_pins[i]);
|
||||
}
|
||||
|
||||
lcd_pulse_enable(l);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
Lua module functions begin...
|
||||
*******************************************************************************/
|
||||
|
||||
// Lua: xmc4000.lcd.setup( right-to-left )
|
||||
// Set right-to-left mode,
|
||||
static int xmc_lcd_setup( lua_State *L )
|
||||
{
|
||||
// lua_toboolean returns 0 or 1, and returns 0 if the parameter is absent
|
||||
unsigned right_to_left = lua_toboolean( L, 1 ); // Default: print left-to-right
|
||||
|
||||
lcd_init_4bits_mode( &xmc_lcd );
|
||||
if ( right_to_left )
|
||||
lcd_right_to_left( &xmc_lcd );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Lua: xmc4000.lcd.clear()
|
||||
// Clear the display, reset its shiftedness and put the cursor at 1,1
|
||||
static int xmc_lcd_clear( lua_State *L )
|
||||
{
|
||||
lcd_clear( &xmc_lcd );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Lua: xmc4000.lcd.home()
|
||||
// Reset the display's shiftedness and put the cursor at 1,1
|
||||
static int xmc_lcd_home( lua_State *L )
|
||||
{
|
||||
lcd_home( &xmc_lcd );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Lua: xmc4000.lcd.goto( row, col )
|
||||
// Move the cursor to the specified row (1 or 2) and column (1-16)
|
||||
// in the character memory.
|
||||
static int xmc_lcd_goto( lua_State *L )
|
||||
{
|
||||
int row = luaL_checkinteger( L, 1 );
|
||||
int col = luaL_checkinteger( L, 2 );
|
||||
|
||||
if ( row < 1 || row > LCD_ROWS || col < 1 || col > LCD_COLS )
|
||||
return luaL_error( L, "row/column must be 1-%d and 1-%d", LCD_ROWS, LCD_COLS );
|
||||
|
||||
lcd_set_cursor( &xmc_lcd, col - 1, row );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Lua: xmc4000.lcd.print( string )
|
||||
// Send data bytes to the LCD module.
|
||||
// Usually this will be a string of text or a list of character codes.
|
||||
// If they pass us integer values <0 or >255, we just use the bottom 8 bits.
|
||||
static int xmc_lcd_print( lua_State *L )
|
||||
{
|
||||
unsigned argc = lua_gettop( L ); // Number of parameters supplied
|
||||
int argn;
|
||||
|
||||
for ( argn = 1; argn <= argc; argn ++ )
|
||||
{
|
||||
switch ( lua_type( L, argn ) )
|
||||
{
|
||||
case LUA_TNUMBER:
|
||||
{
|
||||
u8 byte = luaL_checkint( L, argn );
|
||||
lcd_write( &xmc_lcd, byte );
|
||||
}
|
||||
break;
|
||||
|
||||
case LUA_TSTRING:
|
||||
{
|
||||
size_t len; // Number of chars in string
|
||||
const char *str = luaL_checklstring( L, argn, &len );
|
||||
lcd_echo( &xmc_lcd, (u8 *) str, len );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return luaL_typerror( L, argn, "integer or string" );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: For later, when we initialize the ADCs.
|
||||
//
|
||||
// Return the current state of the pressed buttons as a string containing
|
||||
// a selection of the letters S, L, R, U, D or an empty string if none are
|
||||
// currently held down.
|
||||
/* static int lcd_buttons( lua_State *L ) */
|
||||
/* { */
|
||||
/* u8 code; // bit code for buttons held */
|
||||
/* char string[6]; // Up to 5 buttons and a \0 */
|
||||
/* char *stringp = string; // Where to write the next character; */
|
||||
|
||||
/* code = recv_buttons(); */
|
||||
/* if( code & LCD_BUTTON_SELECT ) *stringp++ = 'S'; */
|
||||
/* if( code & LCD_BUTTON_LEFT ) *stringp++ = 'L'; */
|
||||
/* if( code & LCD_BUTTON_RIGHT ) *stringp++ = 'R'; */
|
||||
/* if( code & LCD_BUTTON_UP ) *stringp++ = 'U'; */
|
||||
/* if( code & LCD_BUTTON_DOWN ) *stringp++ = 'D'; */
|
||||
/* *stringp = '\0'; */
|
||||
|
||||
/* lua_pushstring( L, string ); */
|
||||
|
||||
/* return 1; */
|
||||
/* } */
|
||||
|
||||
// Perform cursor operations, selected by a string parameter,
|
||||
// as recommended in the Lua Reference Manual, p.58: "luaL_checkoption()"
|
||||
static int xmc_lcd_cursor( lua_State *L )
|
||||
{
|
||||
static const char const *args[] =
|
||||
{ "off", "on", "noblink", "blink", NULL };
|
||||
|
||||
switch ( luaL_checkoption( L, 1, NULL, args ) )
|
||||
{
|
||||
case 0:
|
||||
lcd_no_cursor( &xmc_lcd );
|
||||
break;
|
||||
case 1:
|
||||
lcd_cursor( &xmc_lcd );
|
||||
break;
|
||||
case 2:
|
||||
lcd_no_blink( &xmc_lcd );
|
||||
break;
|
||||
case 3:
|
||||
lcd_blink( &xmc_lcd );
|
||||
break;
|
||||
default:
|
||||
return luaL_argerror( L, 1, NULL );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* // Perform display operations, selected by a string parameter. */
|
||||
/* static int lcd_display( lua_State *L ) */
|
||||
/* { */
|
||||
/* static const char const *args[] = */
|
||||
/* { "off", "on", "left", "right", NULL }; */
|
||||
|
||||
/* switch ( luaL_checkoption( L, 1, NULL, args ) ) */
|
||||
/* { */
|
||||
/* case 0: display_is_off = 1; */
|
||||
/* send_command( LCD_CMD_DISPLAY_OFF ); */
|
||||
/* break; */
|
||||
/* case 1: display_is_off = 0; */
|
||||
/* send_command( cursor_type ); // Turns display on */
|
||||
/* break; */
|
||||
/* case 2: send_command( LCD_CMD_SHIFT_DISPLAY_LEFT ); */
|
||||
/* break; */
|
||||
/* case 3: send_command( LCD_CMD_SHIFT_DISPLAY_RIGHT ); */
|
||||
/* break; */
|
||||
/* default: return luaL_argerror( L, 1, NULL ); */
|
||||
/* } */
|
||||
/* return 0; */
|
||||
/* } */
|
||||
|
||||
// Lua: xmc4000.lcd.definechar( code, glyph )
|
||||
// code: 0-7
|
||||
// glyph: a table of up to 8 numbers with values 0-31.
|
||||
// If less than 8 are supplied, the bottom rows are blanked.
|
||||
// If more than 8 are supplied, the extra are ignored.
|
||||
|
||||
static int xmc_lcd_definechar( lua_State *L ) {
|
||||
int code; // The character code we are defining, 0-7
|
||||
size_t datalen; // The number of elements in the glyph table
|
||||
size_t line; // Which line of the char are we defining?
|
||||
u8 data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
int old_address; // The coded value for the current cursor position
|
||||
|
||||
// First parameter: glyph code to define
|
||||
code = luaL_checkint( L, 1 );
|
||||
if( code < 0 || code > 7 )
|
||||
return luaL_error( L, "user-defined characters have codes 0-7" );
|
||||
|
||||
// Second parameter: table of integer values to define the glyph
|
||||
luaL_checktype( L, 2, LUA_TTABLE );
|
||||
datalen = lua_objlen( L, 2 );
|
||||
// Check all parameters before starting the I2C command.
|
||||
if( datalen >= 8 ) datalen = 8; // Ignore extra parameters
|
||||
for( line = 0; line < datalen; line ++ )
|
||||
{
|
||||
int value;
|
||||
lua_rawgeti( L, 2, line + 1 );
|
||||
value = luaL_checkint( L, -1 );
|
||||
lua_pop( L, 1 );
|
||||
data[line] = value;
|
||||
}
|
||||
|
||||
lcd_create_char( &xmc_lcd, code, data );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MIN_OPT_LEVEL 2
|
||||
#include "lrodefs.h"
|
||||
|
||||
// mizar32.disp.*() module function map
|
||||
const LUA_REG_TYPE lcd_map[] =
|
||||
{
|
||||
{ LSTRKEY( "setup" ), LFUNCVAL( xmc_lcd_setup ) },
|
||||
{ LSTRKEY( "clear" ), LFUNCVAL( xmc_lcd_clear ) },
|
||||
{ LSTRKEY( "home" ), LFUNCVAL( xmc_lcd_home ) },
|
||||
{ LSTRKEY( "goto" ), LFUNCVAL( xmc_lcd_goto ) },
|
||||
{ LSTRKEY( "print" ), LFUNCVAL( xmc_lcd_print ) },
|
||||
{ LSTRKEY( "cursor" ), LFUNCVAL( xmc_lcd_cursor ) },
|
||||
{ LSTRKEY( "definechar" ), LFUNCVAL( xmc_lcd_definechar ) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
140
src/platform/xmc4000/lcd.h
Normal file
140
src/platform/xmc4000/lcd.h
Normal file
@ -0,0 +1,140 @@
|
||||
#ifndef LCD_H_
|
||||
#define LCD_H_
|
||||
|
||||
/*
|
||||
* Arduino's LiquidCrystal interface: Adapted for XMC4300 (and
|
||||
* friends) by Raman Gopalan <ramangopalan@gmail.com>
|
||||
* See https://github.com/arduino-libraries/LiquidCrystal
|
||||
*
|
||||
* LCD Lua module structure adapted from Mizar32's I2C LCD interface.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <DAVE.h>
|
||||
|
||||
/* Number of rows and columns */
|
||||
#define LCD_COLS (16U)
|
||||
#define LCD_ROWS (2U)
|
||||
|
||||
/* Commands */
|
||||
#define LCD_CLEARDISPLAY (0x01)
|
||||
#define LCD_RETURNHOME (0x02)
|
||||
#define LCD_ENTRYMODESET (0x04)
|
||||
#define LCD_DISPLAYCONTROL (0x08)
|
||||
#define LCD_CURSORSHIFT (0x10)
|
||||
#define LCD_FUNCTIONSET (0x20)
|
||||
#define LCD_SETCGRAMADDR (0x40)
|
||||
#define LCD_SETDDRAMADDR (0x80)
|
||||
|
||||
/* Flags for display entry mode */
|
||||
#define LCD_ENTRYRIGHT (0x00)
|
||||
#define LCD_ENTRYLEFT (0x02)
|
||||
#define LCD_ENTRYSHIFTINCREMENT (0x01)
|
||||
#define LCD_ENTRYSHIFTDECREMENT (0x00)
|
||||
|
||||
/* Flags for display on/off control */
|
||||
#define LCD_DISPLAYON (0x04)
|
||||
#define LCD_DISPLAYOFF (0x00)
|
||||
#define LCD_CURSORON (0x02)
|
||||
#define LCD_CURSOROFF (0x00)
|
||||
#define LCD_BLINKON (0x01)
|
||||
#define LCD_BLINKOFF (0x00)
|
||||
|
||||
/* Flags for display/cursor shift */
|
||||
#define LCD_DISPLAYMOVE (0x08)
|
||||
#define LCD_CURSORMOVE (0x00)
|
||||
#define LCD_MOVERIGHT (0x04)
|
||||
#define LCD_MOVELEFT (0x00)
|
||||
|
||||
/* Flags for function set */
|
||||
#define LCD_8BITMODE (0x10)
|
||||
#define LCD_4BITMODE (0x00)
|
||||
#define LCD_2LINE (0x08)
|
||||
#define LCD_1LINE (0x00)
|
||||
#define LCD_5x10DOTS (0x04)
|
||||
#define LCD_5x8DOTS (0x00)
|
||||
|
||||
/* HW pins */
|
||||
#define LCD_RS_PIN P3_6
|
||||
#define LCD_ENABLE_PIN P0_6
|
||||
#define LCD_DATA4_PIN P5_0
|
||||
#define LCD_DATA5_PIN P2_7
|
||||
#define LCD_DATA6_PIN P2_9
|
||||
#define LCD_DATA7_PIN P2_4 //P15_9
|
||||
|
||||
/********************************************************************************
|
||||
STRUCTURES
|
||||
*******************************************************************************/
|
||||
|
||||
typedef struct lcd_t {
|
||||
uint8_t rs_pin; XMC_GPIO_PORT_t *rs_port;
|
||||
uint8_t rw_pin; XMC_GPIO_PORT_t *rw_port;
|
||||
uint8_t enable_pin; XMC_GPIO_PORT_t *enable_port;
|
||||
uint8_t data_pins[8]; XMC_GPIO_PORT_t *data_ports[8];
|
||||
uint8_t display_function;
|
||||
uint8_t display_control;
|
||||
uint8_t display_mode;
|
||||
uint8_t initialized;
|
||||
uint8_t num_lines;
|
||||
uint8_t row_offsets[4];
|
||||
} lcd_t;
|
||||
|
||||
/********************************************************************************
|
||||
FUNCTION PROTOTYPES
|
||||
*******************************************************************************/
|
||||
|
||||
/* LCD system commands */
|
||||
void lcd_set_row_offsets (lcd_t *l, int row0, int row1, int row2, int row3);
|
||||
void lcd_set_cursor (lcd_t *l, uint8_t col, uint8_t row);
|
||||
size_t lcd_write (lcd_t *l, uint8_t value);
|
||||
void lcd_command (lcd_t *l, uint8_t value);
|
||||
void lcd_send (lcd_t *l, uint8_t value, uint8_t mode);
|
||||
void lcd_write4bits (lcd_t *l, uint8_t value);
|
||||
void lcd_write8bits (lcd_t *l, uint8_t value);
|
||||
void lcd_pulse_enable (lcd_t *l);
|
||||
void lcd_begin (lcd_t *l, uint8_t cols, uint8_t lines, uint8_t dotsize);
|
||||
|
||||
/* LCD user commands */
|
||||
void lcd_create_char (lcd_t *l, uint8_t location, uint8_t charmap[]);
|
||||
void lcd_init_4bits_mode (lcd_t *l);
|
||||
void lcd_echo (lcd_t *l, uint8_t *s, uint32_t len);
|
||||
void lcd_clear (lcd_t *l);
|
||||
void lcd_home (lcd_t *l);
|
||||
void lcd_no_display (lcd_t *l);
|
||||
void lcd_display (lcd_t *l);
|
||||
void lcd_no_blink (lcd_t *l);
|
||||
void lcd_blink (lcd_t *l);
|
||||
void lcd_no_cursor (lcd_t *l);
|
||||
void lcd_cursor (lcd_t *l);
|
||||
void lcd_scroll_display_left (lcd_t *l);
|
||||
void lcd_scroll_display_right (lcd_t *l);
|
||||
void lcd_left_to_right (lcd_t *l);
|
||||
void lcd_right_to_left (lcd_t *l);
|
||||
void lcd_autoscroll (lcd_t *l);
|
||||
void lcd_no_autoscroll (lcd_t *l);
|
||||
void lcd_init (lcd_t *l,
|
||||
uint8_t four_bit_mode,
|
||||
XMC_GPIO_PORT_t *const rs_port,
|
||||
uint8_t rs_pin,
|
||||
XMC_GPIO_PORT_t *const rw_port,
|
||||
uint8_t rw_pin,
|
||||
XMC_GPIO_PORT_t *const enable_port,
|
||||
uint8_t enable_pin,
|
||||
XMC_GPIO_PORT_t *const d0_port,
|
||||
uint8_t d0_pin,
|
||||
XMC_GPIO_PORT_t *const d1_port,
|
||||
uint8_t d1_pin,
|
||||
XMC_GPIO_PORT_t *const d2_port,
|
||||
uint8_t d2_pin,
|
||||
XMC_GPIO_PORT_t *const d3_port,
|
||||
uint8_t d3_pin,
|
||||
XMC_GPIO_PORT_t *const d4_port,
|
||||
uint8_t d4_pin,
|
||||
XMC_GPIO_PORT_t *const d5_port,
|
||||
uint8_t d5_pin,
|
||||
XMC_GPIO_PORT_t *const d6_port,
|
||||
uint8_t d6_pin,
|
||||
XMC_GPIO_PORT_t *const d7_port,
|
||||
uint8_t d7_pin);
|
||||
|
||||
#endif /* #ifndef LCD_H_ */
|
@ -13,6 +13,7 @@
|
||||
#include "utils.h"
|
||||
#include "common.h"
|
||||
#include "platform_conf.h"
|
||||
#include "dwt.h"
|
||||
|
||||
// Platform includes
|
||||
#include "DAVE.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user