Skip to content
Browse files

[grifo] add an interrupt driven serial input

the code to decode a few escape sequences is included
to all simulated button presses via the serial port

This probably should not be at interrupt state
and maybe there should be a mechanism to turn this on or off

Signed-off-by: Christopher Hall <hsw@openmoko.com>
  • Loading branch information...
1 parent b28e527 commit 59da482a9813098f12897e53a98c619eb8bc5c04 @hxw hxw committed Dec 28, 2010
Showing with 149 additions and 10 deletions.
  1. +128 −0 samo-lib/grifo/src/serial.c
  2. +21 −10 samo-lib/include/regs.h
View
128 samo-lib/grifo/src/serial.c
@@ -29,16 +29,43 @@
#include <regs.h>
#include "watchdog.h"
+#include "vector.h"
+#include "interrupt.h"
+#include "event.h"
#include "serial.h"
+void receive_interrupt(void) __attribute__((interrupt_handler));
+
+
void Serial_initialise(void)
{
static bool initialised = false;
if (!initialised) {
initialised = true;
+ Vector_initialise();
+ Event_initialise();
Watchdog_initialise();
+
+ Interrupt_type state = Interrupt_disable();
+
SET_BRTRD(0, CALC_BAUD(PLL_CLK, 1, SERIAL_DIVMD, CONSOLE_BPS));
+
+ REG_INT_ESIF01 |= ESRX0 | ESERR0;
+
+ REG_INT_PLCDC_PSI00 |= SERIAL_CH0_INT_PRI_7;
+ int i;
+ for (i = 0; i < 6; ++i) {
+ // flush FIFO
+ register uint32_t c = REG_EFSIF0_RXD;
+ (void)c;
+ }
+
+ REG_INT_FSIF01 = FSTX0 | FSRX0 | FSERR0; // clear the interrupt
+
+ Vector_set(VECTOR_Serial_interface_Ch_0_Receive_error, receive_interrupt);
+ Vector_set(VECTOR_Serial_interface_Ch_0_Receive_buffer_full, receive_interrupt);
+ Interrupt_enable(state);
}
}
@@ -180,3 +207,104 @@ void Serial_HexDump(const void *buffer, size_t size)
Serial_print("|\n");
}
}
+
+
+static int numeric_prefix;
+static enum {
+ state_normal = 0,
+ state_escape,
+ state_escape_parameter,
+} state;
+
+void receive_interrupt(void)
+{
+ Interrupt_SaveR15(); // must be first
+
+ REG_INT_FSIF01 = FSRX0 | FSERR0; // clear the interrupt
+ REG_EFSIF0_STATUS = 0; // clear errors
+
+ while (0 != (REG_EFSIF0_STATUS & RDBFx)) {
+ register uint32_t keycode = REG_EFSIF0_RXD;
+
+ event_t e;
+
+ // switch must perform one of the following actions:
+ // 1. continue
+ // 2. setup e.*
+ switch (state) {
+ case state_normal:
+ // escape sequence: <esc> ('[' | 'O') <digits> <letter-or-tilde>
+ if (27 == keycode) {
+ state = state_escape;
+ numeric_prefix = 0;
+ } else {
+ e.item_type = EVENT_KEY;
+ e.key.code = keycode;
+ Event_put(&e);
+ }
+ break;
+
+ case state_escape: // skip initial '[' or 'O'
+ state = state_escape_parameter;
+ break;
+
+ case state_escape_parameter: // sequence of digits ending with letter or '~'
+ if (isdigit(keycode)) {
+ numeric_prefix *= 10;
+ numeric_prefix += keycode - '0';
+ break;
+ } else {
+ state = state_normal;
+ }
+ e.item_type = EVENT_NONE;
+#if 0
+ // cursor up <esc>[A
+ if ('A' == keycode) {
+ //CURSOR_UP
+ }
+ // cursor down <esc>[B
+ else if ('B' == keycode) {
+ //CURSOR_DOWN
+ }
+ // cursor right <esc>[C
+ else if ('C' == keycode) {
+ //CURSOR_RIGHT
+ }
+ // cursor left <esc>[D
+ else if ('D' == keycode) {
+ //CURSOR_LEFT
+ }
+ // home <esc>OH
+ else
+#endif
+ if ('H' == keycode) {
+ e.item_type = EVENT_BUTTON_DOWN;
+ e.button.code = BUTTON_SEARCH;
+ }
+ // end <esc>OF
+ else if ('F' == keycode) {
+ e.item_type = EVENT_BUTTON_DOWN;
+ e.button.code = BUTTON_HISTORY;
+ }
+ // page up <esc>[5~
+ else if ('~' == keycode && 5 == numeric_prefix) {
+ e.item_type = EVENT_BUTTON_DOWN;
+ e.button.code = BUTTON_RANDOM;
+ }
+ // send button down/up
+ if (EVENT_BUTTON_DOWN == e.item_type) {
+ Event_put(&e);
+ e.item_type = EVENT_BUTTON_UP;
+ Event_put(&e);
+ }
+ break;
+
+ default:
+ state = state_normal;
+ break;
+ }
+ }
+ REG_EFSIF0_STATUS = 0; // clear errors
+
+ Interrupt_RestoreR15(); // must be last
+}
View
31 samo-lib/include/regs.h
@@ -55,7 +55,7 @@
#define REG_INT_P16T01 *((REG_TYPE_8 *) (REG_BASE + 0x266))
#define REG_INT_P16T23 *((REG_TYPE_8 *) (REG_BASE + 0x267))
#define REG_INT_P16T45 *((REG_TYPE_8 *) (REG_BASE + 0x268))
-#define REG_INT_PLCDC_PSIO0 *((REG_TYPE_8 *) (REG_BASE + 0x269))
+#define REG_INT_PLCDC_PSI00 *((REG_TYPE_8 *) (REG_BASE + 0x269))
#define REG_INT_PSI01_PAD *((REG_TYPE_8 *) (REG_BASE + 0x26a))
#define REG_INT_PRTC *((REG_TYPE_8 *) (REG_BASE + 0x26b))
#define REG_INT_PP45L *((REG_TYPE_8 *) (REG_BASE + 0x26c))
@@ -909,15 +909,26 @@
#define APPON (1 << 1)
#define IQB (1 << 0)
-// Bits for: REG_CH1_INT_PRIORITY
-#define SERIAL_CH1_INT_PRI_7 0x7
-#define SERIAL_CH1_INT_PRI_6 0x6
-#define SERIAL_CH1_INT_PRI_5 0x5
-#define SERIAL_CH1_INT_PRI_4 0x4
-#define SERIAL_CH1_INT_PRI_3 0x3
-#define SERIAL_CH1_INT_PRI_2 0x2
-#define SERIAL_CH1_INT_PRI_1 0x1
-#define SERIAL_CH1_INT_PRI_0 0x0
+
+// Bits for: REG_INT_PLCDC_PSI00
+#define SERIAL_CH0_INT_PRI_7 0x70
+#define SERIAL_CH0_INT_PRI_6 0x60
+#define SERIAL_CH0_INT_PRI_5 0x50
+#define SERIAL_CH0_INT_PRI_4 0x40
+#define SERIAL_CH0_INT_PRI_3 0x30
+#define SERIAL_CH0_INT_PRI_2 0x20
+#define SERIAL_CH0_INT_PRI_1 0x10
+#define SERIAL_CH0_INT_PRI_0 0x00
+
+// Bits for: REG_INT_PSI01_PAD
+#define SERIAL_CH1_INT_PRI_7 0x07
+#define SERIAL_CH1_INT_PRI_6 0x06
+#define SERIAL_CH1_INT_PRI_5 0x05
+#define SERIAL_CH1_INT_PRI_4 0x04
+#define SERIAL_CH1_INT_PRI_3 0x03
+#define SERIAL_CH1_INT_PRI_2 0x02
+#define SERIAL_CH1_INT_PRI_1 0x01
+#define SERIAL_CH1_INT_PRI_0 0x00
/*

0 comments on commit 59da482

Please sign in to comment.
Something went wrong with that request. Please try again.