diff --git a/firmware/debug.c b/firmware/debug.c new file mode 100644 index 0000000000..d78fa17528 --- /dev/null +++ b/firmware/debug.c @@ -0,0 +1,181 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Linus Nielsen Feltzing + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "sh7034.h" +#include +#include +#include + +char debugmembuf[100]; +char debugbuf[200]; + +static int debug_tx_ready(void) +{ + return (SSR1 & SCI_TDRE); +} + +static void debug_tx_char(char ch) +{ + while (!debug_tx_ready()) + { + ; + } + + /* + * Write data into TDR and clear TDRE + */ + TDR1 = ch; + SSR1 &= ~SCI_TDRE; +} + +static void debug_handle_error(char ssr) +{ + SSR1 &= ~(SCI_ORER | SCI_PER | SCI_FER); +} + +static int debug_rx_ready(void) +{ + char ssr; + + ssr = SSR1 & ( SCI_PER | SCI_FER | SCI_ORER ); + if ( ssr ) + debug_handle_error ( ssr ); + return SSR1 & SCI_RDRF; +} + +static char debug_rx_char(void) +{ + char ch; + char ssr; + + /* Special debug hack. Shut off the IRQ while polling, to prevent the debug + stub from catching the IRQ */ + SCR1 &= ~0x40; + + while (!debug_rx_ready()) + { + ; + } + + ch = RDR1; + SSR1 &= ~SCI_RDRF; + + ssr = SSR1 & (SCI_PER | SCI_FER | SCI_ORER); + + if (ssr) + debug_handle_error (ssr); + + /* Special debug hack. Enable the IRQ again */ + SCR1 |= 0x40; + return ch; +} + +static const char hexchars[] = "0123456789abcdef"; + +static char highhex(int x) +{ + return hexchars[(x >> 4) & 0xf]; +} + +static char lowhex(int x) +{ + return hexchars[x & 0xf]; +} + +static void putpacket (char *buffer) +{ + register int checksum; + + char *src = buffer; + debug_tx_char ('$'); + checksum = 0; + + while (*src) + { + int runlen; + + /* Do run length encoding */ + for (runlen = 0; runlen < 100; runlen ++) + { + if (src[0] != src[runlen]) + { + if (runlen > 3) + { + int encode; + /* Got a useful amount */ + debug_tx_char (*src); + checksum += *src; + debug_tx_char ('*'); + checksum += '*'; + checksum += (encode = runlen + ' ' - 4); + debug_tx_char (encode); + src += runlen; + } + else + { + debug_tx_char (*src); + checksum += *src; + src++; + } + break; + } + } + } + + + debug_tx_char ('#'); + debug_tx_char (highhex(checksum)); + debug_tx_char (lowhex(checksum)); + + /* Wait for the '+' */ + debug_rx_char(); +} + +/* convert the memory, pointed to by mem into hex, placing result in buf */ +/* return a pointer to the last char put in buf (null) */ +static char *mem2hex (char *mem, char *buf, int count) +{ + int i; + int ch; + for (i = 0; i < count; i++) + { + ch = *mem++; + *buf++ = highhex (ch); + *buf++ = lowhex (ch); + } + *buf = 0; + return (buf); +} + +void debug(char *msg) +{ + debugbuf[0] = 'O'; + + mem2hex(msg, &debugbuf[1], strlen(msg)); + putpacket(debugbuf); +} + +void debugf(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsprintf(debugmembuf, fmt, ap); + va_end(ap); + debug(debugmembuf); +} diff --git a/firmware/debug.h b/firmware/debug.h new file mode 100644 index 0000000000..dc3053cb32 --- /dev/null +++ b/firmware/debug.h @@ -0,0 +1,25 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Linus Nielsen Feltzing + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef DEBUG_H +#define DEBUG_H + +void debug(char *msg); +void debugf(char *fmt, ...); + +#endif diff --git a/firmware/i2c.c b/firmware/i2c.c new file mode 100644 index 0000000000..3a5603ddd4 --- /dev/null +++ b/firmware/i2c.c @@ -0,0 +1,212 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Linus Nielsen Feltzing + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "lcd.h" +#include "sh7034.h" +#include "debug.h" + +#define PB13 0x2000 +#define PB7 0x0080 +#define PB5 0x0020 + +/* cute little functions */ +#define SDA_LO (PBDR &= ~PB7) +#define SDA_HI (PBDR |= PB7) +#define SDA_INPUT (PBIOR &= ~PB7) +#define SDA_OUTPUT (PBIOR |= PB7) +#define SDA (PBDR & PB7) + +#define SCL_INPUT (PBIOR &= ~PB13) +#define SCL_OUTPUT (PBIOR |= PB13) +#define SCL_LO (PBDR &= ~PB13) +#define SCL_HI (PBDR |= PB13) +#define SCL (PBDR & PB13) + +/* arbitrary delay loop */ +#define DELAY do { int _x; for(_x=0;_x<20;_x++);} while (0) + +void i2c_start(void) +{ + SDA_OUTPUT; + SDA_HI; + SCL_HI; + SDA_LO; + DELAY; + SCL_LO; +} + +void i2c_stop(void) +{ + SDA_LO; + SCL_HI; + DELAY; + SDA_HI; +} + +void i2c_init(void) +{ + int i; + + /* make PB5, PB7 & PB13 general I/O */ + PBCR1 &= ~0x0c00; /* PB13 */ + PBCR2 &= ~0xcc00; /* PB5 abd PB7 */ + + /* PB5 is "MAS enable". make it output and high */ + PBIOR |= PB5; + PBDR |= PB5; + + /* Set the clock line to an output */ + PBIOR |= PB13; + + SDA_OUTPUT; + SDA_HI; + SCL_LO; + for (i=0;i<3;i++) + i2c_stop(); +} + +void i2c_ack(int bit) +{ + /* Here's the deal. The MAS is slow, and sometimes needs to wait + before it can receive the acknowledge. Therefore it forces the clock + low until it is ready. We need to poll the clock line until it goes + high before we release the ack. */ + + SCL_LO; /* Set the clock low */ + if ( bit ) + SDA_HI; + else + SDA_LO; + + SCL_INPUT; /* Set the clock to input */ + while(!SCL); /* and wait for the MAS to release it */ + + DELAY; + SCL_OUTPUT; + SCL_LO; +} + +int i2c_getack(void) +{ + unsigned short x; + + /* Here's the deal. The MAS is slow, and sometimes needs to wait + before it can send the acknowledge. Therefore it forces the clock + low until it is ready. We need to poll the clock line until it goes + high before we read the ack. */ + + SDA_LO; /* First, discharge the data line */ + SDA_INPUT; /* And set to input */ + SCL_LO; /* Set the clock low */ + SCL_INPUT; /* Set the clock to input */ + while(!SCL); /* and wait for the MAS to release it */ + + x = SDA; + if (x) + /* ack failed */ + return 0; + SCL_OUTPUT; + SCL_LO; + SDA_HI; + SDA_OUTPUT; + return 1; +} + +void i2c_outb(unsigned char byte) +{ + int i; + + /* clock out each bit, MSB first */ + for ( i=0x80; i; i>>=1 ) { + if ( i & byte ) + SDA_HI; + else + SDA_LO; + SCL_HI; + SCL_LO; + } + + SDA_HI; +} + +unsigned char i2c_inb(int ack) +{ + int i; + unsigned char byte = 0; + + /* clock in each bit, MSB first */ + for ( i=0x80; i; i>>=1 ) { + /* Tricky business. Here we discharge the data line by driving it low + and then set it to input to see if it stays low or goes high */ + SDA_LO; /* First, discharge the data line */ + SDA_INPUT; /* And set to input */ + SCL_HI; + if ( SDA ) + byte |= i; + SCL_LO; + SDA_OUTPUT; + } + + i2c_ack(ack); + + return byte; +} + +int i2c_write(int address, unsigned char* buf, int count ) +{ + int i,x=0; + + i2c_start(); + i2c_outb(address & 0xfe); + if (i2c_getack()) + { + for (i=0; i ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Linus Nielsen Feltzing + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef I2C_H +#define I2C_H + +extern void i2c_init(void); +extern int i2c_write(int device, unsigned char* buf, int count ); +extern int i2c_read(int device, unsigned char* buf, int count ); +extern int i2c_readmem(int device, int address, unsigned char* buf, int count ); +extern void i2c_outb(unsigned char byte); +extern unsigned char i2c_inb(int ack); +extern void i2c_start(void); +extern void i2c_stop(void); +extern void i2c_ack(int bit); +extern int i2c_getack(void); + +#endif