1
0
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:
Raman 2019-02-26 19:36:43 +05:30
parent 9e8d6b2583
commit 60173fea14
8 changed files with 799 additions and 2 deletions

View File

@ -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" },

View File

@ -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

View File

@ -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 = ""

View 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);
}

View 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
View 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
View 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_ */

View File

@ -13,6 +13,7 @@
#include "utils.h"
#include "common.h"
#include "platform_conf.h"
#include "dwt.h"
// Platform includes
#include "DAVE.h"