summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/debug.c181
-rw-r--r--firmware/debug.h25
-rw-r--r--firmware/i2c.c212
-rw-r--r--firmware/i2c.h33
4 files changed, 451 insertions, 0 deletions
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 <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+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<count; i++)
+ {
+ i2c_outb(buf[i]);
+ if (!i2c_getack())
+ {
+ x=-2;
+ break;
+ }
+ }
+ }
+ else
+ {
+ debugf("i2c_write() - no ack\n");
+ x=-1;
+ }
+ i2c_stop();
+ return x;
+}
+
+int i2c_read(int address, unsigned char* buf, int count )
+{
+ int i,x=0;
+
+ i2c_start();
+ i2c_outb(address | 1);
+ if (i2c_getack()) {
+ for (i=0; i<count; i++) {
+ buf[i] = i2c_inb(0);
+ }
+ }
+ else
+ x=-1;
+ i2c_stop();
+ return x;
+}
diff --git a/firmware/i2c.h b/firmware/i2c.h
new file mode 100644
index 0000000000..a16077428c
--- /dev/null
+++ b/firmware/i2c.h
@@ -0,0 +1,33 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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 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