The first video game for the mbed video game console. The code utilizes the SimpleLib package developed by thomas@soete.org. For more information about the project and if you'd like to download the schematics and PCB design visit http://www.mbedgc.com/
serial.h@0:31cd577d85a4, 2011-07-09 (annotated)
- Committer:
- jp
- Date:
- Sat Jul 09 15:47:27 2011 +0000
- Revision:
- 0:31cd577d85a4
Initial release of Snake for the mbed Game Console.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jp | 0:31cd577d85a4 | 1 | /* |
jp | 0:31cd577d85a4 | 2 | * Copyright or � or Copr. 2010, Thomas SOETE |
jp | 0:31cd577d85a4 | 3 | * |
jp | 0:31cd577d85a4 | 4 | * Author e-mail: thomas@soete.org |
jp | 0:31cd577d85a4 | 5 | * Library website : http://mbed.org/users/Alkorin/libraries/SimpleLib/ |
jp | 0:31cd577d85a4 | 6 | * |
jp | 0:31cd577d85a4 | 7 | * This software is governed by the CeCILL license under French law and |
jp | 0:31cd577d85a4 | 8 | * abiding by the rules of distribution of free software. You can use, |
jp | 0:31cd577d85a4 | 9 | * modify and/ or redistribute the software under the terms of the CeCILL |
jp | 0:31cd577d85a4 | 10 | * license as circulated by CEA, CNRS and INRIA at the following URL |
jp | 0:31cd577d85a4 | 11 | * "http://www.cecill.info". |
jp | 0:31cd577d85a4 | 12 | * |
jp | 0:31cd577d85a4 | 13 | * As a counterpart to the access to the source code and rights to copy, |
jp | 0:31cd577d85a4 | 14 | * modify and redistribute granted by the license, users are provided only |
jp | 0:31cd577d85a4 | 15 | * with a limited warranty and the software's author, the holder of the |
jp | 0:31cd577d85a4 | 16 | * economic rights, and the successive licensors have only limited |
jp | 0:31cd577d85a4 | 17 | * liability. |
jp | 0:31cd577d85a4 | 18 | * |
jp | 0:31cd577d85a4 | 19 | * In this respect, the user's attention is drawn to the risks associated |
jp | 0:31cd577d85a4 | 20 | * with loading, using, modifying and/or developing or reproducing the |
jp | 0:31cd577d85a4 | 21 | * software by the user in light of its specific status of free software, |
jp | 0:31cd577d85a4 | 22 | * that may mean that it is complicated to manipulate, and that also |
jp | 0:31cd577d85a4 | 23 | * therefore means that it is reserved for developers and experienced |
jp | 0:31cd577d85a4 | 24 | * professionals having in-depth computer knowledge. Users are therefore |
jp | 0:31cd577d85a4 | 25 | * encouraged to load and test the software's suitability as regards their |
jp | 0:31cd577d85a4 | 26 | * requirements in conditions enabling the security of their systems and/or |
jp | 0:31cd577d85a4 | 27 | * data to be ensured and, more generally, to use and operate it in the |
jp | 0:31cd577d85a4 | 28 | * same conditions as regards security. |
jp | 0:31cd577d85a4 | 29 | * |
jp | 0:31cd577d85a4 | 30 | * The fact that you are presently reading this means that you have had |
jp | 0:31cd577d85a4 | 31 | * knowledge of the CeCILL license and that you accept its terms. |
jp | 0:31cd577d85a4 | 32 | */ |
jp | 0:31cd577d85a4 | 33 | |
jp | 0:31cd577d85a4 | 34 | #ifndef __SIMPLELIB_SERIAL_H__ |
jp | 0:31cd577d85a4 | 35 | #define __SIMPLELIB_SERIAL_H__ |
jp | 0:31cd577d85a4 | 36 | |
jp | 0:31cd577d85a4 | 37 | #include "mbed_globals.h" |
jp | 0:31cd577d85a4 | 38 | #include "interrupts.h" |
jp | 0:31cd577d85a4 | 39 | |
jp | 0:31cd577d85a4 | 40 | /********************************** |
jp | 0:31cd577d85a4 | 41 | * Simple Serial Managment * |
jp | 0:31cd577d85a4 | 42 | ********************************** |
jp | 0:31cd577d85a4 | 43 | * The interrupt handler is : * |
jp | 0:31cd577d85a4 | 44 | * SERIAL_INTERRUPT_HANDLER(void) * |
jp | 0:31cd577d85a4 | 45 | * UART0 : Serial over USB * |
jp | 0:31cd577d85a4 | 46 | * UART1 : TX p13, RX p14 * |
jp | 0:31cd577d85a4 | 47 | * UART2 : TX p28, RX p27 * |
jp | 0:31cd577d85a4 | 48 | * UART3 : TX p9, RX p10 * |
jp | 0:31cd577d85a4 | 49 | **********************************/ |
jp | 0:31cd577d85a4 | 50 | |
jp | 0:31cd577d85a4 | 51 | /** Registers **/ |
jp | 0:31cd577d85a4 | 52 | // Serial port (Choose UARTn (0,1,2,3)) |
jp | 0:31cd577d85a4 | 53 | #define UART_NUMBER UART0 |
jp | 0:31cd577d85a4 | 54 | #define UART_BASE TOKENPASTE2(LPC_,UART_NUMBER) |
jp | 0:31cd577d85a4 | 55 | |
jp | 0:31cd577d85a4 | 56 | // Peripheral Clock Selection registers (See 4.7.3 p56) |
jp | 0:31cd577d85a4 | 57 | #define UART0_PCLK_REG (LPC_SC->PCLKSEL0) |
jp | 0:31cd577d85a4 | 58 | #define UART1_PCLK_REG (LPC_SC->PCLKSEL0) |
jp | 0:31cd577d85a4 | 59 | #define UART2_PCLK_REG (LPC_SC->PCLKSEL1) |
jp | 0:31cd577d85a4 | 60 | #define UART3_PCLK_REG (LPC_SC->PCLKSEL1) |
jp | 0:31cd577d85a4 | 61 | #define UART_PCLK_REG TOKENPASTE2(UART_NUMBER,_PCLK_REG) |
jp | 0:31cd577d85a4 | 62 | |
jp | 0:31cd577d85a4 | 63 | #define UART0_PCLK_OFFSET 6 |
jp | 0:31cd577d85a4 | 64 | #define UART1_PCLK_OFFSET 8 |
jp | 0:31cd577d85a4 | 65 | #define UART2_PCLK_OFFSET 16 |
jp | 0:31cd577d85a4 | 66 | #define UART3_PCLK_OFFSET 18 |
jp | 0:31cd577d85a4 | 67 | #define UART_PCLK_OFFSET TOKENPASTE2(UART_NUMBER,_PCLK_OFFSET) |
jp | 0:31cd577d85a4 | 68 | |
jp | 0:31cd577d85a4 | 69 | #define UART0_PCLK ((LPC_SC->PCLKSEL0 >> 6) & 0x03) |
jp | 0:31cd577d85a4 | 70 | #define UART1_PCLK ((LPC_SC->PCLKSEL0 >> 8) & 0x03) |
jp | 0:31cd577d85a4 | 71 | #define UART2_PCLK ((LPC_SC->PCLKSEL1 >> 16) & 0x03) |
jp | 0:31cd577d85a4 | 72 | #define UART3_PCLK ((LPC_SC->PCLKSEL1 >> 18) & 0x03) |
jp | 0:31cd577d85a4 | 73 | #define UART_PCLK TOKENPASTE2(UART_NUMBER,_PCLK) |
jp | 0:31cd577d85a4 | 74 | |
jp | 0:31cd577d85a4 | 75 | // Pin Function Select register (See 8.5.1-8 p108) |
jp | 0:31cd577d85a4 | 76 | #define UART0RX_PINSEL_REG (LPC_PINCON->PINSEL0) |
jp | 0:31cd577d85a4 | 77 | #define UART1RX_PINSEL_REG (LPC_PINCON->PINSEL1) |
jp | 0:31cd577d85a4 | 78 | #define UART2RX_PINSEL_REG (LPC_PINCON->PINSEL0) |
jp | 0:31cd577d85a4 | 79 | #define UART3RX_PINSEL_REG (LPC_PINCON->PINSEL0) |
jp | 0:31cd577d85a4 | 80 | #define UARTRX_PINSEL_REG TOKENPASTE2(UART_NUMBER,RX_PINSEL_REG) |
jp | 0:31cd577d85a4 | 81 | |
jp | 0:31cd577d85a4 | 82 | #define UART0TX_PINSEL_REG (LPC_PINCON->PINSEL0) |
jp | 0:31cd577d85a4 | 83 | #define UART1TX_PINSEL_REG (LPC_PINCON->PINSEL0) |
jp | 0:31cd577d85a4 | 84 | #define UART2TX_PINSEL_REG (LPC_PINCON->PINSEL0) |
jp | 0:31cd577d85a4 | 85 | #define UART3TX_PINSEL_REG (LPC_PINCON->PINSEL0) |
jp | 0:31cd577d85a4 | 86 | #define UARTTX_PINSEL_REG TOKENPASTE2(UART_NUMBER,TX_PINSEL_REG) |
jp | 0:31cd577d85a4 | 87 | |
jp | 0:31cd577d85a4 | 88 | #define UART0RX_PINSEL_OFFSET 6 |
jp | 0:31cd577d85a4 | 89 | #define UART1RX_PINSEL_OFFSET 0 |
jp | 0:31cd577d85a4 | 90 | #define UART2RX_PINSEL_OFFSET 22 |
jp | 0:31cd577d85a4 | 91 | #define UART3RX_PINSEL_OFFSET 2 |
jp | 0:31cd577d85a4 | 92 | #define UARTRX_PINSEL_OFFSET TOKENPASTE2(UART_NUMBER,RX_PINSEL_OFFSET) |
jp | 0:31cd577d85a4 | 93 | |
jp | 0:31cd577d85a4 | 94 | #define UART0TX_PINSEL_OFFSET 4 |
jp | 0:31cd577d85a4 | 95 | #define UART1TX_PINSEL_OFFSET 30 |
jp | 0:31cd577d85a4 | 96 | #define UART2TX_PINSEL_OFFSET 20 |
jp | 0:31cd577d85a4 | 97 | #define UART3TX_PINSEL_OFFSET 0 |
jp | 0:31cd577d85a4 | 98 | #define UARTTX_PINSEL_OFFSET TOKENPASTE2(UART_NUMBER,TX_PINSEL_OFFSET) |
jp | 0:31cd577d85a4 | 99 | |
jp | 0:31cd577d85a4 | 100 | #define UART0_PINSEL_VALUE 1U |
jp | 0:31cd577d85a4 | 101 | #define UART1_PINSEL_VALUE 1U |
jp | 0:31cd577d85a4 | 102 | #define UART2_PINSEL_VALUE 1U |
jp | 0:31cd577d85a4 | 103 | #define UART3_PINSEL_VALUE 2U |
jp | 0:31cd577d85a4 | 104 | #define UART_PINSEL_VALUE TOKENPASTE2(UART_NUMBER,_PINSEL_VALUE) |
jp | 0:31cd577d85a4 | 105 | |
jp | 0:31cd577d85a4 | 106 | /** Interrupt handlers **/ |
jp | 0:31cd577d85a4 | 107 | #define SERIAL_INTERRUPT_HANDLER EXTERN_C void __IRQ TOKENPASTE2(UART_NUMBER,_IRQHandler) |
jp | 0:31cd577d85a4 | 108 | |
jp | 0:31cd577d85a4 | 109 | /** Bits **/ |
jp | 0:31cd577d85a4 | 110 | // RBR Interrupt Enable (UnIER, 14.4.4 p302) |
jp | 0:31cd577d85a4 | 111 | #define RBR_INT_BIT 0 |
jp | 0:31cd577d85a4 | 112 | // Receiver Data Ready (UnLSR, 14.4.8 p306) |
jp | 0:31cd577d85a4 | 113 | #define RDR_BIT 0 |
jp | 0:31cd577d85a4 | 114 | // Transmitter Holding Register Empty (UnLSR, 14.4.8 p306) |
jp | 0:31cd577d85a4 | 115 | #define THRE_BIT 5 |
jp | 0:31cd577d85a4 | 116 | // RBR Interrupt Enable (UnIER, 14.4.4 p302) |
jp | 0:31cd577d85a4 | 117 | #define SERIAL_INT_RX 1 |
jp | 0:31cd577d85a4 | 118 | // THRE Interrupt Enable (UnIER, 14.4.4 p302) |
jp | 0:31cd577d85a4 | 119 | #define SERIAL_INT_TX 2 |
jp | 0:31cd577d85a4 | 120 | // Divisor Latch Access Bit (UnLCR, 14.4.7 p306) |
jp | 0:31cd577d85a4 | 121 | #define DLA_BIT 7 |
jp | 0:31cd577d85a4 | 122 | // Power Control for Peripherals (PCONP, 4.8.7.1 p63) |
jp | 0:31cd577d85a4 | 123 | #define UART0_PCONP_BIT 3 |
jp | 0:31cd577d85a4 | 124 | #define UART1_PCONP_BIT 4 |
jp | 0:31cd577d85a4 | 125 | #define UART2_PCONP_BIT 24 |
jp | 0:31cd577d85a4 | 126 | #define UART3_PCONP_BIT 25 |
jp | 0:31cd577d85a4 | 127 | |
jp | 0:31cd577d85a4 | 128 | /** Macros **/ |
jp | 0:31cd577d85a4 | 129 | #define SERIAL_PUTCHAR(c) do { \ |
jp | 0:31cd577d85a4 | 130 | while (GET_BIT_VALUE(UART_BASE->LSR, THRE_BIT) == 0); \ |
jp | 0:31cd577d85a4 | 131 | UART_BASE->THR = c; \ |
jp | 0:31cd577d85a4 | 132 | } while(0) |
jp | 0:31cd577d85a4 | 133 | |
jp | 0:31cd577d85a4 | 134 | #define SERIAL_DATA_TO_READ() (GET_BIT_VALUE(UART_BASE->LSR, RDR_BIT) == 1) |
jp | 0:31cd577d85a4 | 135 | |
jp | 0:31cd577d85a4 | 136 | #define SERIAL_GETCHAR() (UART_BASE->RBR) |
jp | 0:31cd577d85a4 | 137 | |
jp | 0:31cd577d85a4 | 138 | // Enable interrupt for RX or TX (SERIAL_INT_RX and SERIAL_INT_TX) |
jp | 0:31cd577d85a4 | 139 | #define SERIAL_ENABLE_INTERRUPT(value) do { \ |
jp | 0:31cd577d85a4 | 140 | UART_BASE->IER = value; \ |
jp | 0:31cd577d85a4 | 141 | ENABLE_INTERRUPT(TOKENPASTE2(UART_NUMBER,_IRQn)); \ |
jp | 0:31cd577d85a4 | 142 | } while(0) |
jp | 0:31cd577d85a4 | 143 | |
jp | 0:31cd577d85a4 | 144 | extern __INLINE void SERIAL_INIT() |
jp | 0:31cd577d85a4 | 145 | { |
jp | 0:31cd577d85a4 | 146 | // Enable UARTn |
jp | 0:31cd577d85a4 | 147 | SET_BIT_VALUE(LPC_SC->PCONP, TOKENPASTE2(UART_NUMBER,_PCONP_BIT) , 1); |
jp | 0:31cd577d85a4 | 148 | // Enable FIFO and reset RX/TX FIFO (See 14.4.6 p305) |
jp | 0:31cd577d85a4 | 149 | UART_BASE->FCR = 0x07; |
jp | 0:31cd577d85a4 | 150 | // 8-bits, No Parity, 1 stop bit (See 14.4.7 p306) |
jp | 0:31cd577d85a4 | 151 | UART_BASE->LCR = 0x03; |
jp | 0:31cd577d85a4 | 152 | // Set CCLK as Peripheral Clock for UART (96MHz with mbed library) |
jp | 0:31cd577d85a4 | 153 | UART_PCLK_REG = (UART_PCLK_REG & (~(3UL << UART_PCLK_OFFSET))) | (1U << UART_PCLK_OFFSET); |
jp | 0:31cd577d85a4 | 154 | // Define Pin's functions as UART |
jp | 0:31cd577d85a4 | 155 | UARTRX_PINSEL_REG = (UARTRX_PINSEL_REG & (~(3U << UARTRX_PINSEL_OFFSET))) | (UART_PINSEL_VALUE << UARTRX_PINSEL_OFFSET); |
jp | 0:31cd577d85a4 | 156 | UARTTX_PINSEL_REG = (UARTTX_PINSEL_REG & (~(3U << UARTTX_PINSEL_OFFSET))) | (UART_PINSEL_VALUE << UARTTX_PINSEL_OFFSET); |
jp | 0:31cd577d85a4 | 157 | } |
jp | 0:31cd577d85a4 | 158 | |
jp | 0:31cd577d85a4 | 159 | // See 14.4.5 p303 |
jp | 0:31cd577d85a4 | 160 | extern __INLINE int SERIAL_CHECK_INTERRUPT(void) { |
jp | 0:31cd577d85a4 | 161 | uint32_t serialStatus = UART_BASE->IIR; |
jp | 0:31cd577d85a4 | 162 | |
jp | 0:31cd577d85a4 | 163 | if (serialStatus & 1) // IntStatus, 1 = No Interrupt is pending. |
jp | 0:31cd577d85a4 | 164 | return 0; |
jp | 0:31cd577d85a4 | 165 | |
jp | 0:31cd577d85a4 | 166 | serialStatus = (serialStatus >> 1) & 0x3; // IntId, 2 = More than threshold data to read, 6 = Some caracters to read |
jp | 0:31cd577d85a4 | 167 | if (serialStatus != 2 && serialStatus != 6) |
jp | 0:31cd577d85a4 | 168 | return 0; |
jp | 0:31cd577d85a4 | 169 | |
jp | 0:31cd577d85a4 | 170 | return 1; |
jp | 0:31cd577d85a4 | 171 | } |
jp | 0:31cd577d85a4 | 172 | |
jp | 0:31cd577d85a4 | 173 | extern __INLINE void SERIAL_SETBAUD(unsigned int baud) { |
jp | 0:31cd577d85a4 | 174 | // Peripheral Clock Selection register bit values (See Table 42, p57) |
jp | 0:31cd577d85a4 | 175 | uint16_t divisorValue = (SystemCoreClock / 16 / baud); |
jp | 0:31cd577d85a4 | 176 | #if 0 |
jp | 0:31cd577d85a4 | 177 | // Peripheral Clock for UART is set to CCLK in SERIAL_INIT. Divisor is then 1. |
jp | 0:31cd577d85a4 | 178 | // Else, use code below |
jp | 0:31cd577d85a4 | 179 | static int divisors[4] = { 4, 1, 2, 8 }; |
jp | 0:31cd577d85a4 | 180 | uint16_t divisorValue = ((SystemCoreClock / 16 / baud) / divisors[UART_PCLK]); |
jp | 0:31cd577d85a4 | 181 | #endif |
jp | 0:31cd577d85a4 | 182 | |
jp | 0:31cd577d85a4 | 183 | UART_BASE->LCR |= (1 << DLA_BIT); |
jp | 0:31cd577d85a4 | 184 | UART_BASE->DLM = (uint8_t) (divisorValue >> 8); |
jp | 0:31cd577d85a4 | 185 | UART_BASE->DLL = (uint8_t) divisorValue; |
jp | 0:31cd577d85a4 | 186 | UART_BASE->LCR &= ~(1 << DLA_BIT); |
jp | 0:31cd577d85a4 | 187 | } |
jp | 0:31cd577d85a4 | 188 | |
jp | 0:31cd577d85a4 | 189 | #endif |