Trim down peak calculation a bit.
[kugel-rb.git] / firmware / drivers / serial.c
blobeb2df9890b46a175e8fc257c8c452f10804ab280
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 (MODEL_NUMBER == 3) || (MODEL_NUMBER == 8)
257 /* Route the Tx/Rx pins. 4G Ipod??? */
258 outl(0x70000018, inl(0x70000018) & ~0xc00);
259 #elif (MODEL_NUMBER == 4) || (MODEL_NUMBER == 5)
261 /* Route the Tx/Rx pins. 5G Ipod */
262 (*(volatile unsigned long *)(0x7000008C)) &= ~0x0C;
263 GPO32_ENABLE &= ~0x0C;
264 #endif
266 DEV_EN = DEV_EN | DEV_SER0;
267 CPU_HI_INT_DIS = SER0_MASK;
269 DEV_RS |= DEV_SER0;
270 sleep(1);
271 DEV_RS &= ~DEV_SER0;
273 SER0_LCR = 0x80; /* Divisor latch enable */
274 SER0_DLM = 0x00;
275 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
276 SER0_IER = 0x01;
278 SER0_FCR = 0x07; /* Tx+Rx FIFO reset and FIFO enable */
280 CPU_INT_EN |= HI_MASK;
281 CPU_HI_INT_EN |= SER0_MASK;
282 tmp = SER0_RBR;
284 serial_bitrate(0);
287 void serial_bitrate(int rate)
289 if(rate == 0)
291 autobaud = 2;
292 SER0_LCR = 0x80; /* Divisor latch enable */
293 SER0_DLL = 0x0D; /* 24000000/13/16 = 115384 baud */
294 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
295 return;
298 autobaud = 0;
299 SER0_LCR = 0x80; /* Divisor latch enable */
300 SER0_DLL = 24000000L / rate / 16;
301 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
304 int tx_rdy(void)
306 if((SER0_LSR & 0x20))
307 return 1;
308 else
309 return 0;
312 int rx_rdy(void)
314 if((SER0_LSR & 0x1))
315 return 1;
316 else
317 return 0;
320 void tx_writec(unsigned char c)
322 SER0_THR =(int) c;
325 unsigned char rx_readc(void)
327 return (SER0_RBR & 0xFF);
330 void SERIAL0(void)
332 static int badbaud = 0;
333 static bool newpkt = true;
334 char temp;
336 while(rx_rdy())
338 temp = rx_readc();
339 if (newpkt && autobaud > 0)
341 if (autobaud == 1)
343 switch (temp)
345 case 0xFF:
346 case 0x55:
347 break;
348 case 0xFC:
349 SER0_LCR = 0x80; /* Divisor latch enable */
350 SER0_DLL = 0x4E; /* 24000000/78/16 = 19230 baud */
351 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
352 temp = 0xFF;
353 break;
354 case 0xE0:
355 SER0_LCR = 0x80; /* Divisor latch enable */
356 SER0_DLL = 0x9C; /* 24000000/156/16 = 9615 baud */
357 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
358 temp = 0xFF;
359 break;
360 default:
361 badbaud++;
362 if (badbaud >= 6) /* Switch baud detection mode */
364 autobaud = 2;
365 SER0_LCR = 0x80; /* Divisor latch enable */
366 SER0_DLL = 0x0D; /* 24000000/13/16 = 115384 baud */
367 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
368 badbaud = 0;
369 } else {
370 SER0_LCR = 0x80; /* Divisor latch enable */
371 SER0_DLL = 0x1A; /* 24000000/26/16 = 57692 baud */
372 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
374 continue;
376 } else {
377 switch (temp)
379 case 0xFF:
380 case 0x55:
381 break;
382 case 0xFE:
383 SER0_LCR = 0x80; /* Divisor latch enable */
384 SER0_DLL = 0x1A; /* 24000000/26/16 = 57692 baud */
385 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
386 temp = 0xFF;
387 break;
388 case 0xFC:
389 SER0_LCR = 0x80; /* Divisor latch enable */
390 SER0_DLL = 0x27; /* 24000000/39/16 = 38461 baud */
391 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
392 temp = 0xFF;
393 break;
394 case 0xE0:
395 SER0_LCR = 0x80; /* Divisor latch enable */
396 SER0_DLL = 0x4E; /* 24000000/78/16 = 19230 baud */
397 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
398 temp = 0xFF;
399 break;
400 default:
401 badbaud++;
402 if (badbaud >= 6) /* Switch baud detection */
404 autobaud = 1;
405 SER0_LCR = 0x80; /* Divisor latch enable */
406 SER0_DLL = 0x1A; /* 24000000/26/16 = 57692 baud */
407 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
408 badbaud = 0;
409 } else {
410 SER0_LCR = 0x80; /* Divisor latch enable */
411 SER0_DLL = 0x0D; /* 24000000/13/16 = 115384 baud */
412 SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
414 continue;
418 bool pkt = iap_getc(temp);
419 if(newpkt && !pkt)
420 autobaud = 0; /* Found good baud */
421 newpkt = pkt;
425 #endif
427 void dprintf(const char * str, ... )
429 char dprintfbuff[256];
430 char * ptr;
432 va_list ap;
433 va_start(ap, str);
435 ptr = dprintfbuff;
436 vsnprintf(ptr,sizeof(dprintfbuff),str,ap);
437 va_end(ap);
439 serial_tx((unsigned char *)ptr);
442 void serial_tx(const unsigned char * buf)
444 /*Tx*/
445 for(;;) {
446 if(tx_rdy()) {
447 if(*buf == '\0')
448 return;
449 if(*buf == '\n')
450 tx_writec('\r');
451 tx_writec(*buf);
452 buf++;