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
This commit is contained in:
patacongo 2009-02-20 00:59:18 +00:00
parent 1c7918916c
commit 37a6ef033a
5 changed files with 283 additions and 45 deletions

View File

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

View File

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

View File

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

View File

@ -39,6 +39,7 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <ctype.h>
#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 */

View File

@ -39,20 +39,90 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <arch/board/board.h>
#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 */