123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- /*
- * serial port handler
- *
- * Copyright (c) 2009 Openmoko Inc.
- *
- * Authors Daniel Mack <daniel@caiaq.de>
- * Christopher Hall <hsw@openmoko.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <guilib.h>
- #include <wikilib.h>
- #include <input.h>
- #include <msg.h>
- #include <regs.h>
- #include <interrupt.h>
- #include "serial.h"
- static u8 console_buffer[16];
- static unsigned int console_read;
- static unsigned int console_write;
- serial_buffer_type *send_queue_head;
- serial_buffer_type *send_queue_tail;
- const char *transmit;
- volatile bool linefeed;
- #define BUFFER_FULL(w, r, b) ((((w) + 1) % ARRAY_SIZE(b)) == (r))
- #define BUFFER_EMPTY(w, r, b) ((w) == (r))
- #define BUFFER_NEXT(p, b) (p) = (((p) + 1) % ARRAY_SIZE(b))
- void serial_init(void)
- {
- static bool initialised = false;
- if (!initialised) {
- InterruptType s = Interrupt_disable();
- REG_INT_ESIF01 = ESRX0;
- REG_INT_PLCDC_PSIO0 = 0x70;
- console_read = 0;
- console_write = 0;
- send_queue_head = NULL;
- send_queue_tail = NULL;
- linefeed = false;
- initialised = true;
- Interrupt_enable(s);
- }
- }
- void serial_put(serial_buffer_type *buffer)
- {
- if (NULL != buffer) {
- // critical code - disable uart tx interrupts
- InterruptType s = Interrupt_disable();
- REG_INT_ESIF01 &= ~ESTX0;
- Interrupt_enable(s);
- buffer->link = NULL;
- if (NULL != send_queue_tail) {
- send_queue_tail->link = buffer;
- }
- send_queue_tail = buffer;
- if (NULL == send_queue_head) {
- send_queue_head = send_queue_tail;
- transmit = send_queue_head->text;
- s = Interrupt_disable();
- REG_INT_FSIF01 = FSTX0;
- Interrupt_enable(s);
- {
- u8 c = *transmit++;
- if ('\n' == c) {
- c = '\r';
- linefeed = true;
- }
- REG_EFSIF0_TXD = c;
- }
- }
- s = Interrupt_disable();
- REG_INT_ESIF01 |= ESTX0;
- Interrupt_enable(s);
- }
- }
- // in interrupt state
- void serial_drained_0(void)
- {
- if (!linefeed && '\0' == *transmit) {
- serial_buffer_type *p = send_queue_head;
- send_queue_head = send_queue_head->link;
- if (NULL != p->callback) {
- p->callback(p);
- }
- if (NULL == send_queue_head) {
- transmit = NULL;
- send_queue_tail = NULL;
- }
- else {
- transmit = send_queue_head->text;
- }
- }
- if (NULL == transmit) {
- REG_INT_ESIF01 &= ~ESTX0;
- }
- else {
- REG_INT_FSIF01 |= FSTX0;
- if (linefeed) {
- linefeed = false;
- REG_EFSIF0_TXD = '\n';
- }
- else {
- u8 c = *transmit++;
- if ('\n' == c) {
- c = '\r';
- linefeed = true;
- }
- REG_EFSIF0_TXD = c;
- }
- }
- }
- // in interrupt state
- void serial_filled_0(void)
- {
- while (REG_EFSIF0_STATUS & RDBFx) {
- u8 c = REG_EFSIF0_RXD;
- if (c == 0)
- continue;
- console_buffer[console_write] = c;
- BUFFER_NEXT(console_write, console_buffer);
- }
- }
- void serial_out(int port, char c)
- {
- if (port != 0)
- return;
- InterruptType s = Interrupt_disable();
- REG_EFSIF0_TXD = c;
- Interrupt_enable(s);
- }
- bool serial_event_pending(void)
- {
- return !BUFFER_EMPTY(console_write, console_read, console_buffer);
- }
- int serial_get_event(struct wl_input_event *ev)
- {
- if (BUFFER_EMPTY(console_write, console_read, console_buffer))
- return 0;
- // msg(MSG_INFO, " OUT. %d %d %p %p\n", console_read, console_write,
- // ev, &ev->type);
- ev->type = WL_INPUT_EV_TYPE_KEYBOARD;
- if (0x7f == console_buffer[console_read]) {
- console_buffer[console_read] = 0x08;
- }
- ev->key_event.keycode = console_buffer[console_read];
- ev->key_event.value = 1;
- BUFFER_NEXT(console_read, console_buffer);
- /* Override for scrolling... */
- if ((ev->key_event.keycode == WL_KEY_PLUS) || (ev->key_event.keycode == WL_KEY_DOWN)) {
- ev->type = WL_INPUT_EV_TYPE_CURSOR;
- ev->key_event.keycode = WL_INPUT_KEY_CURSOR_DOWN;
- }
- else if ((ev->key_event.keycode == WL_KEY_MINUS) || (ev->key_event.keycode == WL_KEY_UP)) {
- ev->type = WL_INPUT_EV_TYPE_CURSOR;
- ev->key_event.keycode = WL_INPUT_KEY_CURSOR_UP;
- }
- return 1;
- }
|