Android: no need to keep RockboxPCM_class around
[maemo-rb.git] / firmware / drivers / serial.c
blob26637f140c957b50f030299bdd2b9fdf5ddeb3be
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Alan Korr & Nick Robinson
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include "button.h"
25 #include "config.h"
26 #include "cpu.h"
27 #include "system.h"
28 #include "kernel.h"
29 #include "lcd.h"
30 #include "serial.h"
31 #include "iap.h"
33 #if CONFIG_CPU == IMX31L
34 #include "serial-imx31.h"
35 #endif
37 #if CONFIG_CPU == SH7034
39 /* FIX: this doesn't work on iRiver or iPod yet */
40 /* iFP7xx has no remote */
42 /* Received byte identifiers */
43 #define PLAY 0xC1
44 #define STOP 0xC2
45 #define PREV 0xC4
46 #define NEXT 0xC8
47 #define VOLUP 0xD0
48 #define VOLDN 0xE0
50 void serial_setup (void)
52 /* Set PB10 function to serial Rx */
53 PBCR1 = (PBCR1 & 0xffcf) | 0x0020;
55 SMR1 = 0x00;
56 SCR1 = 0;
57 BRR1 = (FREQ/(32*9600))-1;
58 and_b(0, &SSR1); /* The status bits must be read before they are cleared,
59 so we do an AND operation */
61 /* Let the hardware settle. The serial port needs to wait "at least
62 the interval required to transmit or receive one bit" before it
63 can be used. */
64 sleep(1);
66 SCR1 = 0x10; /* Enable the receiver, no interrupt */
69 int tx_rdy(void)
71 /* a dummy */
72 return 1;
75 int rx_rdy(void)
77 if(SSR1 & SCI_RDRF)
78 return 1;
79 else
80 return 0;
83 void tx_writec(unsigned char c)
85 /* a dummy */
86 (void)c;
89 unsigned char rx_readc(void)
91 char tmp;
92 /* Read byte and clear the Rx Full bit */
93 tmp = RDR1;
94 and_b(~SCI_RDRF, &SSR1);
95 return tmp;
99 /* This function returns the received remote control code only if it is
100 received without errors before or after the reception.
101 It therefore returns the received code on the second call after the
102 code has been received. */
103 int remote_control_rx(void)
105 static int last_valid_button = BUTTON_NONE;
106 static int last_was_error = false;
107 int btn;
108 int ret = BUTTON_NONE;
110 /* Errors? Just clear'em. The receiver stops if we don't */
111 if(SSR1 & (SCI_ORER | SCI_FER | SCI_PER)) {
112 and_b(~(SCI_ORER | SCI_FER | SCI_PER), &SSR1);
113 last_valid_button = BUTTON_NONE;
114 last_was_error = true;
115 return BUTTON_NONE;
118 if(rx_rdy()) {
119 btn = rx_readc();
121 if(last_was_error)
123 last_valid_button = BUTTON_NONE;
124 ret = BUTTON_NONE;
126 else
128 switch (btn)
130 case STOP:
131 last_valid_button = BUTTON_RC_STOP;
132 break;
134 case PLAY:
135 last_valid_button = BUTTON_RC_PLAY;
136 break;
138 case VOLUP:
139 last_valid_button = BUTTON_RC_VOL_UP;
140 break;
142 case VOLDN:
143 last_valid_button = BUTTON_RC_VOL_DOWN;
144 break;
146 case PREV:
147 last_valid_button = BUTTON_RC_LEFT;
148 break;
150 case NEXT:
151 last_valid_button = BUTTON_RC_RIGHT;
152 break;
154 default:
155 last_valid_button = BUTTON_NONE;
156 break;
160 else
162 /* This means that a valid remote control character was received
163 the last time we were called, with no receiver errors either before
164 or after. Then we can assume that there really is a remote control
165 attached, and return the button code. */
166 ret = last_valid_button;
167 last_valid_button = BUTTON_NONE;
170 last_was_error = false;
172 return ret;
175 #elif defined(CPU_COLDFIRE)
177 void serial_setup (void)
179 UCR0 = 0x30; /* Reset transmitter */
180 UCSR0 = 0xdd; /* Timer mode */
182 UCR0 = 0x10; /* Reset pointer */
183 UMR0 = 0x13; /* No parity, 8 bits */
184 UMR0 = 0x07; /* 1 stop bit */
186 UCR0 = 0x04; /* Tx enable */
189 int tx_rdy(void)
191 if(USR0 & 0x04)
192 return 1;
193 else
194 return 0;
197 int rx_rdy(void)
199 /* a dummy */
200 return 0;
203 void tx_writec(unsigned char c)
205 UTB0 = c;
208 #elif (CONFIG_CPU == IMX31L)
210 void serial_setup(void)
212 #ifdef UART_INT /*enable UART Interrupts */
213 UCR1_1 |= (EUARTUCR1_TRDYEN | EUARTUCR1_RRDYEN | EUARTUCR1_TXMPTYEN);
214 UCR4_1 |= (EUARTUCR4_TCEN);
215 #else /*disable UART Interrupts*/
216 UCR1_1 &= ~(EUARTUCR1_TRDYEN | EUARTUCR1_RRDYEN | EUARTUCR1_TXMPTYEN);
217 UCR4_1 &= ~(EUARTUCR4_TCEN);
218 #endif
219 UCR1_1 |= EUARTUCR1_UARTEN;
220 UCR2_1 |= (EUARTUCR2_TXEN | EUARTUCR2_RXEN | EUARTUCR2_IRTS);
222 /* Tx,Rx Interrupt Trigger levels, Disable for now*/
223 /*UFCR1 |= (UFCR1_TXTL_32 | UFCR1_RXTL_32);*/
226 int tx_rdy(void)
228 if((UTS1 & EUARTUTS_TXEMPTY))
229 return 1;
230 else
231 return 0;
234 /*Not ready...After first Rx, UTS1 & UTS1_RXEMPTY
235 keeps returning true*/
236 int rx_rdy(void)
238 if(!(UTS1 & EUARTUTS_RXEMPTY))
239 return 1;
240 else
241 return 0;
244 void tx_writec(unsigned char c)
246 UTXD1=(int) c;
249 #elif defined(IPOD_ACCESSORY_PROTOCOL)
250 static int autobaud = 0;
251 void serial_setup (void)
253 int tmp;
255 #if defined(IPOD_COLOR) || defined(IPOD_4G)
256 /* Route the Tx/Rx pins. 4G Ipod??? */
257 outl(0x70000018, inl(0x70000018) & ~0xc00);
258 #elif defined(IPOD_NANO) || defined(IPOD_VIDEO)
259 /* Route the Tx/Rx pins. 5G Ipod */
260 (*(volatile unsigned long *)(0x7000008C)) &= ~0x0C;
261 GPO32_ENABLE &= ~0x0C;
262 #endif
264 DEV_EN = DEV_EN | DEV_SER0;
265 CPU_HI_INT_DIS = SER0_MASK;
267 DEV_RS |= DEV_SER0;
268 sleep(1);
269 DEV_RS &= ~DEV_SER0;
271 SER0_LCR = 0x80; /* Divisor latch enable */
272 SER0_DLM = 0x00;
273 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
274 SER0_IER = 0x01;
276 SER0_FCR = 0x07; /* Tx+Rx FIFO reset and FIFO enable */
278 CPU_INT_EN |= HI_MASK;
279 CPU_HI_INT_EN |= SER0_MASK;
280 tmp = SER0_RBR;
282 serial_bitrate(0);
285 void serial_bitrate(int rate)
287 if(rate == 0)
289 autobaud = 2;
290 SER0_LCR = 0x80; /* Divisor latch enable */
291 SER0_DLL = 0x0D; /* 24000000/13/16 = 115384 baud */
292 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
293 return;
296 autobaud = 0;
297 SER0_LCR = 0x80; /* Divisor latch enable */
298 SER0_DLL = 24000000L / rate / 16;
299 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
302 int tx_rdy(void)
304 if((SER0_LSR & 0x20))
305 return 1;
306 else
307 return 0;
310 int rx_rdy(void)
312 if((SER0_LSR & 0x1))
313 return 1;
314 else
315 return 0;
318 void tx_writec(unsigned char c)
320 SER0_THR =(int) c;
323 unsigned char rx_readc(void)
325 return (SER0_RBR & 0xFF);
328 void SERIAL0(void)
330 static int badbaud = 0;
331 static bool newpkt = true;
332 char temp;
334 while(rx_rdy())
336 temp = rx_readc();
337 if (newpkt && autobaud > 0)
339 if (autobaud == 1)
341 switch (temp)
343 case 0xFF:
344 case 0x55:
345 break;
346 case 0xFC:
347 SER0_LCR = 0x80; /* Divisor latch enable */
348 SER0_DLL = 0x4E; /* 24000000/78/16 = 19230 baud */
349 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
350 temp = 0xFF;
351 break;
352 case 0xE0:
353 SER0_LCR = 0x80; /* Divisor latch enable */
354 SER0_DLL = 0x9C; /* 24000000/156/16 = 9615 baud */
355 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
356 temp = 0xFF;
357 break;
358 default:
359 badbaud++;
360 if (badbaud >= 6) /* Switch baud detection mode */
362 autobaud = 2;
363 SER0_LCR = 0x80; /* Divisor latch enable */
364 SER0_DLL = 0x0D; /* 24000000/13/16 = 115384 baud */
365 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
366 badbaud = 0;
367 } else {
368 SER0_LCR = 0x80; /* Divisor latch enable */
369 SER0_DLL = 0x1A; /* 24000000/26/16 = 57692 baud */
370 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
372 continue;
374 } else {
375 switch (temp)
377 case 0xFF:
378 case 0x55:
379 break;
380 case 0xFE:
381 SER0_LCR = 0x80; /* Divisor latch enable */
382 SER0_DLL = 0x1A; /* 24000000/26/16 = 57692 baud */
383 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
384 temp = 0xFF;
385 break;
386 case 0xFC:
387 SER0_LCR = 0x80; /* Divisor latch enable */
388 SER0_DLL = 0x27; /* 24000000/39/16 = 38461 baud */
389 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
390 temp = 0xFF;
391 break;
392 case 0xE0:
393 SER0_LCR = 0x80; /* Divisor latch enable */
394 SER0_DLL = 0x4E; /* 24000000/78/16 = 19230 baud */
395 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
396 temp = 0xFF;
397 break;
398 default:
399 badbaud++;
400 if (badbaud >= 6) /* Switch baud detection */
402 autobaud = 1;
403 SER0_LCR = 0x80; /* Divisor latch enable */
404 SER0_DLL = 0x1A; /* 24000000/26/16 = 57692 baud */
405 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
406 badbaud = 0;
407 } else {
408 SER0_LCR = 0x80; /* Divisor latch enable */
409 SER0_DLL = 0x0D; /* 24000000/13/16 = 115384 baud */
410 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
412 continue;
416 bool pkt = iap_getc(temp);
417 if(newpkt && !pkt)
418 autobaud = 0; /* Found good baud */
419 newpkt = pkt;
423 #endif
425 void dprintf(const char * str, ... )
427 char dprintfbuff[256];
428 char * ptr;
430 va_list ap;
431 va_start(ap, str);
433 ptr = dprintfbuff;
434 vsnprintf(ptr,sizeof(dprintfbuff),str,ap);
435 va_end(ap);
437 serial_tx((unsigned char *)ptr);
440 void serial_tx(const unsigned char * buf)
442 /*Tx*/
443 for(;;) {
444 if(tx_rdy()) {
445 if(*buf == '\0')
446 return;
447 if(*buf == '\n')
448 tx_writec('\r');
449 tx_writec(*buf);
450 buf++;