From 37a6ef033a59a672fbe4013f544ac63308c35967 Mon Sep 17 00:00:00 2001 From: patacongo Date: Fri, 20 Feb 2009 00:59:18 +0000 Subject: [PATCH] Add support for M16C buttons and LEDs git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1519 42af7a65-404d-4744-a932-0658087f49c3 --- configs/skp16c26/include/board.h | 47 ++++----- configs/skp16c26/ostest/defconfig | 4 +- configs/skp16c26/src/up_buttons.c | 32 ++++++ configs/skp16c26/src/up_lcd.c | 78 +++++++++++--- configs/skp16c26/src/up_leds.c | 167 +++++++++++++++++++++++++++++- 5 files changed, 283 insertions(+), 45 deletions(-) diff --git a/configs/skp16c26/include/board.h b/configs/skp16c26/include/board.h index 029d5d628e..961e1b0dd1 100644 --- a/configs/skp16c26/include/board.h +++ b/configs/skp16c26/include/board.h @@ -71,25 +71,6 @@ #define M16C_XIN_FREQ 20000000 /* 20MHz */ -/* Switches */ - -#define S1 p8_3 -#define S2 p8_2 -#define S3 p8_1 -#define S1_DDR pd8_3 -#define S2_DDR pd8_2 -#define S3_DDR pd8_1 - -/* LEDs */ - -#define RED_LED p8_0 -#define YLW_LED p7_4 -#define GRN_LED p7_2 - -#define RED_DDR pd8_0 /* LED port direction register */ -#define YLW_DDR pd7_4 -#define GRN_DDR pd7_2 - /* Interrupt Priority Levels ********************************************************/ /* IPL settings */ @@ -126,21 +107,29 @@ #undef M16C_INT0_PRIO /* INT0 interrupt priority */ #undef M16C_INT1_PRIO /* INT1 interrupt priority */ -/********************************************************************************/ -/* Macro Definitions */ -/********************************************************************************/ +/* LED definitions **********************************************************/ -#define LED_ON 0 -#define LED_OFF 1 + /* GREEN YELLOW RED */ +#define LED_STARTED 0 /* OFF OFF OFF */ +#define LED_HEAPALLOCATE 1 /* ON OFF OFF */ +#define LED_IRQSENABLED 2 /* OFF ON OFF */ +#define LED_STACKCREATED 3 /* ON ON OFF */ +#define LED_INIRQ 4 /* ON OFF ON */ +#define LED_SIGNAL 5 /* OFF ON ON */ +#define LED_ASSERTION 6 /* ON ON ON */ +#define LED_PANIC 7 /* NC** NC** ON* */ -/* Use these macros for switch inputs */ +/* *=FLASHING **=if INIRQ, SIGNAL, or ASSERTION will be flashing */ -#define ENABLE_SWITCHES {S1_DDR = 0; S2_DDR = 0; S3_DDR = 0;} +/* BUTTON definitions **************************************************************/ -/* Use these macros to control the LEDs */ +#define SW1_PRESSED 0x01 /* Bit 0: 1=SW1 pressed */ +#define SW2_PRESSED 0x02 /* Bit 1: 1=SW2 pressed */ +#define SW3_PRESSED 0x04 /* Bit 2: 1=SW3 pressed */ -#define LED(led, state) ((led) = !state) -#define ENABLE_LEDS {RED_LED = LED_OFF; YLW_LED = LED_OFF; GRN_LED = LED_OFF; RED_DDR = 1; YLW_DDR = 1; GRN_DDR = 1; } +/************************************************************************************ + * Macro Definitions + ************************************************************************************/ /************************************************************************************ * Inline Functions diff --git a/configs/skp16c26/ostest/defconfig b/configs/skp16c26/ostest/defconfig index 9218c7232e..ff764621f1 100644 --- a/configs/skp16c26/ostest/defconfig +++ b/configs/skp16c26/ostest/defconfig @@ -60,6 +60,7 @@ # used during interrupt handling. # CONFIG_ARCH_STACKDUMP - Do stack dumps after assertions # CONFIG_ARCH_LEDS - Use LEDs to show state. Unique to skp16c26. +# CONFIG_ARCH_BUTTONS - Provide button APIs. Unique to skp16c26. # CONFIG_ARCH_LCD - Configure LCD. Unique to skp16c26. CONFIG_ARCH=sh @@ -76,7 +77,8 @@ CONFIG_DRAM_END=(CONFIG_DRAM_START+CONFIG_DRAM_SIZE) CONFIG_BOARD_LOOPSPERMSEC=16945 CONFIG_ARCH_INTERRUPTSTACK=128 CONFIG_ARCH_STACKDUMP=y -CONFIG_ARCH_LEDS=n +CONFIG_ARCH_LEDS=y +CONFIG_ARCH_BUTTONS=y CONFIG_ARCH_LCD=y # diff --git a/configs/skp16c26/src/up_buttons.c b/configs/skp16c26/src/up_buttons.c index 5785532bce..64d9d7345d 100644 --- a/configs/skp16c26/src/up_buttons.c +++ b/configs/skp16c26/src/up_buttons.c @@ -48,6 +48,14 @@ * Definitions ****************************************************************************/ +/* The SKP62C26 has 3 buttons control by bits 1, 2, and 3 in port 8. */ + +#define SW1_BIT (1 << 3) /* Bit 3, port 8 */ +#define SW2_BIT (1 << 2) /* Bit 2, port 8 */ +#define SW3_BIT (1 << 1) /* Bit 1, port 8 */ + +#define SW_PRESSED(p,b) (((p) & (b)) == 0) + /**************************************************************************** * Private Data ****************************************************************************/ @@ -67,6 +75,11 @@ #ifdef CONFIG_ARCH_BUTTONS void up_buttoninit(void) { + ubyte regval; + + regval = getreg8(M16C_PD8); + regval |= (SW1_BIT | SW2_BIT | SW3_BIT); + putreg8(regval, M16C_PD8); } /**************************************************************************** @@ -75,5 +88,24 @@ void up_buttoninit(void) ubyte up_buttons(void) { + ubyte swset = 0; + ubyte regval = getreg8(M16C_P8); + + if (SW_PRESSED(regval, SW1_BIT)) + { + swset |= SW1_PRESSED; + } + + if (SW_PRESSED(regval, SW2_BIT)) + { + swset |= SW2_PRESSED; + } + + if (SW_PRESSED(regval, SW3_BIT)) + { + swset |= SW3_PRESSED; + } + + return swset; } #endif /* CONFIG_ARCH_BUTTONS */ diff --git a/configs/skp16c26/src/up_lcd.c b/configs/skp16c26/src/up_lcd.c index 81844018d8..4cb08ca25f 100644 --- a/configs/skp16c26/src/up_lcd.c +++ b/configs/skp16c26/src/up_lcd.c @@ -39,6 +39,7 @@ #include #include +#include #include "up_arch.h" #include "up_internal.h" @@ -50,24 +51,35 @@ * Definitions ************************************************************************************/ +/* LCD dimensions *******************************************************************/ + +#define LCD_NLINES 2 /* Two lines */ +#define LCD_NCHARS 8 /* Eight characters per line */ + /* LCD commands *********************************************************************/ -#define LCD_CLEAR 0x01 /* Clear LCD display and home cursor */ -#define LCD_HOME_L1 0x80 /* move cursor to line 1 */ -#define LCD_HOME_L2 0xc0 /* move cursor to line 2 */ -#define CURSOR_MODE_DEC 0x04 /* Cursor auto decrement after R/W */ -#define CURSOR_MODE_INC 0x06 /* Cursor auto increment after R/W */ -#define FUNCTION_SET 0x28 /* Setup, 4 bits,2 lines, 5X7 */ -#define LCD_CURSOR_ON 0x0e /* Display ON with Cursor */ -#define LCD_CURSOR_OFF 0x0c /* Display ON with Cursor off */ -#define LCD_CURSOR_BLINK 0x0d /* Display on with blinking cursor */ -#define LCD_CURSOR_LEFT 0x10 /* Move Cursor Left One Position */ -#define LCD_CURSOR_RIGHT 0x14 /* Move Cursor Right One Position */ +#define LCD_CLEAR 0x01 /* Clear LCD display and home cursor */ +#define CURSOR_MODE_DEC 0x04 /* Cursor auto decrement after R/W */ +#define CURSOR_MODE_INC 0x06 /* Cursor auto increment after R/W */ +#define LCD_CURSOR_ON 0x0e /* Display ON with Cursor */ +#define LCD_CURSOR_OFF 0x0c /* Display ON with Cursor off */ +#define LCD_CURSOR_BLINK 0x0d /* Display on with blinking cursor */ +#define LCD_CURSOR_LEFT 0x10 /* Move Cursor Left One Position */ +#define LCD_CURSOR_RIGHT 0x14 /* Move Cursor Right One Position */ +#define FUNCTION_SET 0x28 /* Setup, 4 bits,2 lines, 5X7 */ +#define LCD_CGRAM 0x40 /* Map characters to CG RAM */ +#define LCD_POS_L1(p) (0x80 | p) /* Move cursor to line 1, character p+1 */ +#define LCD_POS_L2(p) (0xc0 | p) /* Move cursor to line 2, character p+1 */ +#define LCD_HOME_L1 0x80 /* Move cursor to line 1 */ +#define LCD_HOME_L2 0xc0 /* Move cursor to line 2 */ /************************************************************************************ * Private Data ************************************************************************************/ +static ubyte g_nchars; /* Number of characters in lines 2 */ +static ubyte g_line[LCD_NCHARS]; /* The content of lines 2 */ + /************************************************************************************ * Private Functions ************************************************************************************/ @@ -165,6 +177,32 @@ void up_lcdwrite(boolean data, ubyte ch) up_enpulse(data); } +/************************************************************************************ + * Name: up_scroll + ************************************************************************************/ + +static void up_scroll(void) +{ + int i; + + /* Clear the display and position the cursor at the beginning of line 1 */ + + up_lcdwrite(FALSE, LCD_CLEAR); + up_lcdwrite(FALSE, LCD_HOME_L1); + + /* Copy line 2 to line 1 */ + + for (i = 0; i < g_nchars; i++) + { + up_lcdwrite(TRUE, g_line[i]); + } + + /* Position the cursor at the beginning of line 2 */ + + up_lcdwrite(FALSE, LCD_HOME_L2); + g_nchars = 0; +} + /************************************************************************************ * Public Functions ************************************************************************************/ @@ -220,7 +258,23 @@ void up_lcdinit(void) void up_lcdputc(char ch) { - up_lcdwrite(TRUE, ch); + /* Check for new line */ + + if (ch == '\n') + { + up_scroll(); + } + + /* Should we wrap to truncate at the end of line??? Let's truncate. In either + * case, let's ignore all other non-printable characters. + */ + + else if (g_nchars < LCD_NCHARS && isprint(ch)) + { + up_lcdwrite(TRUE, ch); + g_line[g_nchars] = ch; + g_nchars++; + } } #endif /* CONFIG_ARCH_LCD */ diff --git a/configs/skp16c26/src/up_leds.c b/configs/skp16c26/src/up_leds.c index a34b47756f..a65d423a9b 100644 --- a/configs/skp16c26/src/up_leds.c +++ b/configs/skp16c26/src/up_leds.c @@ -39,20 +39,90 @@ #include #include + +#include +#include "up_arch.h" #include "up_internal.h" +#include "chip.h" + +#ifdef CONFIG_ARCH_LEDS /************************************************************************************ - * Definitions + * Preprocessor Definitions + ************************************************************************************/ + +/* The SKP62C26 has 3 LEDs control by bits 0 and 2 in port 7 and bit 0 in port 8. */ + +#define GREEN_LED (1 << 2) /* Bit 2, port 7 */ +#define YELLOW_LED (1 << 4) /* Bit 4, port 7 */ +#define RED_LED (1 << 0) /* Bit 0, port 8 */ + +#define GREEN_LED_ON 0 +#define GREEN_LED_OFF GREEN_LED +#define GREEN_LED_MASK GREEN_LED +#define GREEN_LED_PORT M16C_P7 + +#define YELLOW_LED_ON 0 +#define YELLOW_LED_OFF YELLOW_LED +#define YELLOW_LED_MASK YELLOW_LED +#define YELLOW_LED_PORT M16C_P7 + +#define GREENYELLOW_LED_MASK (GREEN_LED_MASK|YELLOW_LED_MASK) +#define GREENYELLOW_LED_PORT M16C_P7 +#define GREENYELLOW_DIR_PORT M16C_PD7 + +#define RED_LED_ON 0 +#define RED_LED_OFF RED_LED +#define RED_LED_MASK RED_LED +#define RED_LED_PORT M16C_P8 +#define RED_DIR_PORT M16C_PD8 + +/************************************************************************************ + * Private Type Definitions ************************************************************************************/ /************************************************************************************ - * Private Data + * Private Data Definitions ************************************************************************************/ +static const ubyte g_ledstate[7] = +{ + (GREEN_LED_OFF | YELLOW_LED_OFF | RED_LED_OFF), /* LED_STARTED */ + (GREEN_LED_ON | YELLOW_LED_OFF | RED_LED_OFF), /* LED_HEAPALLOCATE */ + (GREEN_LED_OFF | YELLOW_LED_ON | RED_LED_OFF), /* LED_IRQSENABLED */ + (GREEN_LED_ON | YELLOW_LED_ON | RED_LED_OFF), /* LED_STACKCREATED */ + + (GREEN_LED_ON | YELLOW_LED_OFF | RED_LED_ON ), /* LED_INIRQ */ + (GREEN_LED_OFF | YELLOW_LED_ON | RED_LED_ON ), /* LED_SIGNAL */ + (GREEN_LED_ON | YELLOW_LED_ON | RED_LED_ON ) /* LED_ASSERTION */ +}; + +static ubyte g_prevled[3]; +static ubyte g_nestlevel; + /************************************************************************************ * Private Functions ************************************************************************************/ +/************************************************************************************ + * Name: up_ledinit + ************************************************************************************/ + +static void up_setleds(ubyte gybits, ubyte rbit) +{ + ubyte regval; + + regval = getreg8(GREENYELLOW_LED_PORT); + regval &= ~GREENYELLOW_LED_MASK; + regval |= gybits; + putreg8(regval, GREENYELLOW_LED_PORT); + + regval = getreg8(RED_LED_PORT); + regval &= ~RED_LED_MASK; + regval |= rbit; + putreg8(regval, RED_LED_PORT); +} + /************************************************************************************ * Public Functions ************************************************************************************/ @@ -61,9 +131,29 @@ * Name: up_ledinit ************************************************************************************/ -#ifdef CONFIG_ARCH_LEDS void up_ledinit(void) { + register ubyte regval; + + /* Make sure that the LEDs are in the OFF state */ + + regval = getreg8(GREENYELLOW_LED_PORT); + regval |= (GREEN_LED_OFF |YELLOW_LED_OFF); + putreg8(regval, GREENYELLOW_LED_PORT); + + regval = getreg8(RED_LED_PORT); + regval |= RED_LED_OFF; + putreg8(regval, RED_LED_PORT); + + /* Set the direction to output */ + + regval = getreg8(GREENYELLOW_DIR_PORT); + regval |= (GREEN_LED |YELLOW_LED); + putreg8(regval, GREENYELLOW_DIR_PORT); + + regval = getreg8(RED_DIR_PORT); + regval |= RED_LED; + putreg8(regval, RED_DIR_PORT); } /************************************************************************************ @@ -72,6 +162,34 @@ void up_ledinit(void) void up_ledon(int led) { + ubyte ledset; + + /* If this is the ASSERTION led, preserve the Y&G bits from the last setting and + * set the RED LED on. + */ + + if (led == LED_ASSERTION) + { + ledset = g_ledstate[g_prevled[g_nestlevel]]; + up_setleds(ledset & GREENYELLOW_LED_MASK, RED_LED_ON); + } + else if (led < LED_ASSERTION) + { + /* Otherwise, just show the LEDs corresponding to this state */ + + ledset = g_ledstate[led]; + up_setleds(ledset & GREENYELLOW_LED_MASK, ledset & RED_LED_MASK); + + /* If this was a nested states (INIRQ, SIGNAL, or ASSERTION) then + * stack up the previous value. + */ + + if (led > LED_STACKCREATED) + { + g_nestlevel++; + } + g_prevled[g_nestlevel] = led; + } } /************************************************************************************ @@ -80,5 +198,48 @@ void up_ledon(int led) void up_ledoff(int led) { + ubyte ledset; + + /* If this is the ASSERTION led then what we do depends on the previous state */ + + if (led == LED_ASSERTION) + { + /* If the previous state was one of the nested states (INIRQ, SIGNAL, or ASSERTION), + * then turn the green and yellow LEDs all off. That way we can distinguish + * that case from the simple cases. + */ + + if (g_nestlevel > 0) + { + ledset = 0; + } + else + { + ledset = g_ledstate[g_prevled[0]]; + } + up_setleds(ledset & GREENYELLOW_LED_MASK, RED_LED_OFF); + } + else if (led > 0 && led < LED_ASSERTION) + { + /* If this was one of the nested states, then we want to back to the LED setting + * before entering that nested statel. + */ + + if (g_nestlevel > 0) + { + g_nestlevel--; + led = g_prevled[g_nestlevel]; + } + else if (led > LED_STACKCREATED) + { + /* This shouldn't happen */ + + led--; + } + ledset = g_ledstate[led]; + up_setleds(ledset & GREENYELLOW_LED_MASK, ledset & RED_LED_MASK); + g_prevled[g_nestlevel]= led; + } } + #endif /* CONFIG_ARCH_LEDS */