From c6773e1436ba3adda0a6456dbe54ba1320a095be Mon Sep 17 00:00:00 2001 From: Björn Stenberg Date: Tue, 23 Apr 2002 09:13:23 +0000 Subject: Moved driver to 'drivers' subdir git-svn-id: svn://svn.rockbox.org/rockbox/trunk@189 a1c6a512-1295-4272-9138-f99709370657 --- firmware/ata.c | 242 --------- firmware/ata.h | 32 -- firmware/button.c | 197 ------- firmware/button.h | 54 -- firmware/drivers/ata.c | 242 +++++++++ firmware/drivers/ata.h | 32 ++ firmware/drivers/button.c | 197 +++++++ firmware/drivers/button.h | 54 ++ firmware/drivers/fat.c | 1315 +++++++++++++++++++++++++++++++++++++++++++++ firmware/drivers/fat.h | 154 ++++++ firmware/drivers/i2c.c | 212 ++++++++ firmware/drivers/i2c.h | 33 ++ firmware/drivers/lcd.c | 680 +++++++++++++++++++++++ firmware/drivers/lcd.h | 162 ++++++ firmware/drivers/led.c | 70 +++ firmware/drivers/led.h | 50 ++ firmware/drivers/mas.c | 164 ++++++ firmware/drivers/mas.h | 54 ++ firmware/drivers/serial.c | 75 +++ firmware/drivers/serial.h | 31 ++ firmware/fat.c | 1315 --------------------------------------------- firmware/fat.h | 154 ------ firmware/i2c.c | 212 -------- firmware/i2c.h | 33 -- firmware/lcd.c | 680 ----------------------- firmware/lcd.h | 162 ------ firmware/led.c | 70 --- firmware/led.h | 50 -- firmware/mas.c | 164 ------ firmware/mas.h | 54 -- firmware/serial.c | 75 --- firmware/serial.h | 31 -- 32 files changed, 3525 insertions(+), 3525 deletions(-) delete mode 100644 firmware/ata.c delete mode 100644 firmware/ata.h delete mode 100644 firmware/button.c delete mode 100644 firmware/button.h create mode 100644 firmware/drivers/ata.c create mode 100644 firmware/drivers/ata.h create mode 100644 firmware/drivers/button.c create mode 100644 firmware/drivers/button.h create mode 100644 firmware/drivers/fat.c create mode 100644 firmware/drivers/fat.h create mode 100644 firmware/drivers/i2c.c create mode 100644 firmware/drivers/i2c.h create mode 100644 firmware/drivers/lcd.c create mode 100644 firmware/drivers/lcd.h create mode 100644 firmware/drivers/led.c create mode 100644 firmware/drivers/led.h create mode 100644 firmware/drivers/mas.c create mode 100644 firmware/drivers/mas.h create mode 100644 firmware/drivers/serial.c create mode 100644 firmware/drivers/serial.h delete mode 100644 firmware/fat.c delete mode 100644 firmware/fat.h delete mode 100644 firmware/i2c.c delete mode 100644 firmware/i2c.h delete mode 100644 firmware/lcd.c delete mode 100644 firmware/lcd.h delete mode 100644 firmware/led.c delete mode 100644 firmware/led.h delete mode 100644 firmware/mas.c delete mode 100644 firmware/mas.h delete mode 100644 firmware/serial.c delete mode 100644 firmware/serial.h (limited to 'firmware') diff --git a/firmware/ata.c b/firmware/ata.c deleted file mode 100644 index cb4e1e6b90..0000000000 --- a/firmware/ata.c +++ /dev/null @@ -1,242 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Alan Korr - * - * 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 "ata.h" -#include "kernel.h" -#include "led.h" - -#define ATA_DATA (*((volatile unsigned short*)0x06104100)) -#define ATA_ERROR (*((volatile unsigned char*)0x06100101)) -#define ATA_FEATURE ATA_ERROR -#define ATA_NSECTOR (*((volatile unsigned char*)0x06100102)) -#define ATA_SECTOR (*((volatile unsigned char*)0x06100103)) -#define ATA_LCYL (*((volatile unsigned char*)0x06100104)) -#define ATA_HCYL (*((volatile unsigned char*)0x06100105)) -#define ATA_SELECT (*((volatile unsigned char*)0x06100106)) -#define ATA_COMMAND (*((volatile unsigned char*)0x06100107)) -#define ATA_STATUS ATA_COMMAND -#define ATA_CONTROL (*((volatile unsigned char*)0x06100306)) - -#define SELECT_LBA 0x40 - -#define STATUS_BSY 0x80 -#define STATUS_RDY 0x40 -#define STATUS_DRQ 0x08 -#define STATUS_ERR 0x01 - -#define CONTROL_nIEN 0x02 -#define CONTROL_SRST 0x04 - -#define CMD_READ_SECTORS 0x20 -#define CMD_WRITE_SECTORS 0x30 -#define CMD_STANDBY_IMMEDIATE 0xE0 -#define CMD_STANDBY 0xE2 -#define CMD_SLEEP 0xE6 -#define CMD_SECURITY_FREEZE_LOCK 0xF5 - -static int wait_for_bsy(void) -{ - char timeout = current_tick + HZ; - while (TIME_BEFORE(current_tick, timeout) && (ATA_STATUS & STATUS_BSY)) - yield(); - - if (TIME_BEFORE(current_tick, timeout)) - return 1; - else - return 0; /* timeout */ -} - -static int wait_for_rdy(void) -{ - if (!wait_for_bsy()) - return 0; - return ATA_STATUS & STATUS_RDY; -} - -static int wait_for_start_of_transfer(void) -{ - if (!wait_for_bsy()) - return 0; - return (ATA_STATUS & (STATUS_RDY|STATUS_DRQ)) == (STATUS_RDY|STATUS_DRQ); -} - -static int wait_for_end_of_transfer(void) -{ - if (!wait_for_bsy()) - return 0; - return (ATA_STATUS & (STATUS_RDY|STATUS_DRQ)) == STATUS_RDY; -} - -int ata_read_sectors(unsigned long start, - unsigned char count, - void* buf) -{ - int i; - - if (!wait_for_rdy()) - return 0; - - led_turn_on(); - - ATA_NSECTOR = count; - ATA_SECTOR = start & 0xff; - ATA_LCYL = (start >> 8) & 0xff; - ATA_HCYL = (start >> 16) & 0xff; - ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA; - ATA_COMMAND = CMD_READ_SECTORS; - - for (i=0; i> 8) & 0xff; - ATA_HCYL = (start >> 16) & 0xff; - ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA; - ATA_COMMAND = CMD_WRITE_SECTORS; - - for (i=0; i= 5us */ - - ATA_CONTROL = CONTROL_nIEN; - sleep(HZ/400); /* >2ms */ - - return wait_for_rdy(); -} - -int ata_init(void) -{ - led_turn_off(); - - /* activate ATA */ - PADR |= 0x80; - - if (!ata_hard_reset()) - return -1; - - if (!check_registers()) - return -2; - - if (!check_harddisk()) - return -3; - - if (!freeze_lock()) - return -4; - - ATA_SELECT = SELECT_LBA; - ATA_CONTROL = CONTROL_nIEN; - - return 0; -} diff --git a/firmware/ata.h b/firmware/ata.h deleted file mode 100644 index 50cd85d755..0000000000 --- a/firmware/ata.h +++ /dev/null @@ -1,32 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Alan Korr - * - * 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 __ATA_H__ -#define __ATA_H__ - -extern int ata_hard_reset(void); -extern int ata_soft_reset(void); -extern int ata_init(void); -extern int ata_read_sectors(unsigned long start, - unsigned char count, - void* buf); -extern int ata_write_sectors(unsigned long start, - unsigned char count, - void* buf); - -#endif diff --git a/firmware/button.c b/firmware/button.c deleted file mode 100644 index a1abccd32a..0000000000 --- a/firmware/button.c +++ /dev/null @@ -1,197 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Daniel Stenberg - * - * 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. - * - ****************************************************************************/ -/* - * Archos Jukebox Recorder button functions - */ - -#include "config.h" -#include "sh7034.h" -#include "button.h" - -#ifdef HAVE_RECORDER_KEYPAD - -/* AJBR buttons are connected to the CPU as follows: - * - * ON and OFF are connected to separate port B input pins. - * - * F1, F2, F3, and UP are connected to the AN4 analog input, each through - * a separate voltage divider. The voltage on AN4 depends on which button - * (or none, or a combination) is pressed. - * - * DOWN, PLAY, LEFT, and RIGHT are likewise connected to AN5. */ - -/* Button voltage levels on AN4 and AN5 */ -#define LEVEL1 50 -#define LEVEL2 125 -#define LEVEL3 175 -#define LEVEL4 225 - -/* Number of calls to get_button for a button to stop bouncing - * and to be considered held down. - * Should really use a hardware timer for this. - */ -#define BOUNCE_COUNT 200 -#define HOLD_COUNT 10000 - -static int last; /* Last button pressed */ -static int count; /* Number of calls button has been down */ - - -/* - *Initialize buttons - */ -void button_init() -{ -#ifndef SIMULATOR - /* Set PB4 and PB8 as input pins */ - PBCR1 &= 0xfffc; /* PB8MD = 00 */ - PBCR2 &= 0xfcff; /* PB4MD = 00 */ - PBIOR &= ~(PBDR_BTN_ON|PBDR_BTN_OFF); /* Inputs */ - - /* Set A/D to scan AN4 and AN5. - * This needs to be changed to scan other analog pins - * for battery level, etc. */ - ADCSR = 0; - ADCR = 0; - ADCSR = ADCSR_ADST | ADCSR_SCAN | 0x5; -#endif - last = BUTTON_NONE; - count = 0; -} - -/* - * Get button pressed from hardware - */ -static int get_raw_button (void) -{ - /* Check port B pins for ON and OFF */ - int data = PBDR; - if ((data & PBDR_BTN_ON) == 0) - return BUTTON_ON; - else if ((data & PBDR_BTN_OFF) == 0) - return BUTTON_OFF; - - /* Check AN4 pin for F1-3 and UP */ - data = ADDRAH; - if (data >= LEVEL4) - return BUTTON_F3; - else if (data >= LEVEL3) - return BUTTON_UP; - else if (data >= LEVEL2) - return BUTTON_F2; - else if (data >= LEVEL1) - return BUTTON_F1; - - /* Check AN5 pin for DOWN, PLAY, LEFT, RIGHT */ - data = ADDRBH; - if (data >= LEVEL4) - return BUTTON_DOWN; - else if (data >= LEVEL3) - return BUTTON_PLAY; - else if (data >= LEVEL2) - return BUTTON_LEFT; - else if (data >= LEVEL1) - return BUTTON_RIGHT; - - return BUTTON_NONE; -} - -/* - * Get the currently pressed button. - * Returns one of BUTTON_xxx codes, with possibly a modifier bit set. - * No modifier bits are set when the button is first pressed. - * BUTTON_HELD bit is while the button is being held. - * BUTTON_REL bit is set when button has been released. - */ -int button_get(void) -{ - int btn = get_raw_button(); - int ret; - - /* Last button pressed is still down */ - if (btn != BUTTON_NONE && btn == last) { - count++; - if (count == BOUNCE_COUNT) - return btn; - else if (count >= HOLD_COUNT) - return btn | BUTTON_HELD; - else - return BUTTON_NONE; - } - - /* Last button pressed now released */ - if (btn == BUTTON_NONE && last != BUTTON_NONE) - ret = last | BUTTON_REL; - else - ret = BUTTON_NONE; - - last = btn; - count = 0; - return ret; -} - -#elif HAVE_PLAYER_KEYPAD - -/* The player has all buttons on port pins: - - LEFT: PC0 - RIGHT: PC2 - PLAY: PC3 - STOP: PA11 - ON: PA5 - MENU: PC1 -*/ - -void button_init(void) -{ - /* set port pins as input */ - PAIOR &= ~0x820; -} - -int button_get(void) -{ - int porta = PADR; - int portc = PCDR; - int btn = 0; - - if ( portc & 1 ) - btn |= BUTTON_LEFT; - if ( portc & 2 ) - btn |= BUTTON_MENU; - if ( portc & 4 ) - btn |= BUTTON_RIGHT; - if ( portc & 8 ) - btn |= BUTTON_PLAY | BUTTON_UP; - if ( porta & 0x20 ) - btn |= BUTTON_ON; - if ( porta & 0x800 ) - btn |= BUTTON_STOP | BUTTON_DOWN; - - return btn; -} - -#endif - - - -/* ----------------------------------------------------------------- - * local variables: - * eval: (load-file "rockbox-mode.el") - * end: - */ diff --git a/firmware/button.h b/firmware/button.h deleted file mode 100644 index a8cc71b875..0000000000 --- a/firmware/button.h +++ /dev/null @@ -1,54 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Daniel Stenberg - * - * 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 "config.h" - -void button_init (void); -int button_get (void); - -/* Shared button codes */ -#define BUTTON_NONE 0x0000 -#define BUTTON_ON 0x0001 -#define BUTTON_UP 0x0010 -#define BUTTON_DOWN 0x0020 -#define BUTTON_LEFT 0x0040 -#define BUTTON_RIGHT 0x0080 - -/* Button modifiers */ -#define BUTTON_HELD 0x4000 -#define BUTTON_REL 0x8000 - - -#ifdef HAVE_RECORDER_KEYPAD - -/* Recorder specific button codes */ -#define BUTTON_OFF 0x0002 -#define BUTTON_PLAY 0x0004 -#define BUTTON_F1 0x0100 -#define BUTTON_F2 0x0200 -#define BUTTON_F3 0x0400 - -#elif HAVE_PLAYER_KEYPAD - -/* Jukebox 6000 and Studio specific button codes */ -#define BUTTON_MENU 0x0002 -#define BUTTON_PLAY BUTTON_UP -#define BUTTON_STOP BUTTON_DOWN - -#endif diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c new file mode 100644 index 0000000000..cb4e1e6b90 --- /dev/null +++ b/firmware/drivers/ata.c @@ -0,0 +1,242 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Alan Korr + * + * 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 "ata.h" +#include "kernel.h" +#include "led.h" + +#define ATA_DATA (*((volatile unsigned short*)0x06104100)) +#define ATA_ERROR (*((volatile unsigned char*)0x06100101)) +#define ATA_FEATURE ATA_ERROR +#define ATA_NSECTOR (*((volatile unsigned char*)0x06100102)) +#define ATA_SECTOR (*((volatile unsigned char*)0x06100103)) +#define ATA_LCYL (*((volatile unsigned char*)0x06100104)) +#define ATA_HCYL (*((volatile unsigned char*)0x06100105)) +#define ATA_SELECT (*((volatile unsigned char*)0x06100106)) +#define ATA_COMMAND (*((volatile unsigned char*)0x06100107)) +#define ATA_STATUS ATA_COMMAND +#define ATA_CONTROL (*((volatile unsigned char*)0x06100306)) + +#define SELECT_LBA 0x40 + +#define STATUS_BSY 0x80 +#define STATUS_RDY 0x40 +#define STATUS_DRQ 0x08 +#define STATUS_ERR 0x01 + +#define CONTROL_nIEN 0x02 +#define CONTROL_SRST 0x04 + +#define CMD_READ_SECTORS 0x20 +#define CMD_WRITE_SECTORS 0x30 +#define CMD_STANDBY_IMMEDIATE 0xE0 +#define CMD_STANDBY 0xE2 +#define CMD_SLEEP 0xE6 +#define CMD_SECURITY_FREEZE_LOCK 0xF5 + +static int wait_for_bsy(void) +{ + char timeout = current_tick + HZ; + while (TIME_BEFORE(current_tick, timeout) && (ATA_STATUS & STATUS_BSY)) + yield(); + + if (TIME_BEFORE(current_tick, timeout)) + return 1; + else + return 0; /* timeout */ +} + +static int wait_for_rdy(void) +{ + if (!wait_for_bsy()) + return 0; + return ATA_STATUS & STATUS_RDY; +} + +static int wait_for_start_of_transfer(void) +{ + if (!wait_for_bsy()) + return 0; + return (ATA_STATUS & (STATUS_RDY|STATUS_DRQ)) == (STATUS_RDY|STATUS_DRQ); +} + +static int wait_for_end_of_transfer(void) +{ + if (!wait_for_bsy()) + return 0; + return (ATA_STATUS & (STATUS_RDY|STATUS_DRQ)) == STATUS_RDY; +} + +int ata_read_sectors(unsigned long start, + unsigned char count, + void* buf) +{ + int i; + + if (!wait_for_rdy()) + return 0; + + led_turn_on(); + + ATA_NSECTOR = count; + ATA_SECTOR = start & 0xff; + ATA_LCYL = (start >> 8) & 0xff; + ATA_HCYL = (start >> 16) & 0xff; + ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA; + ATA_COMMAND = CMD_READ_SECTORS; + + for (i=0; i> 8) & 0xff; + ATA_HCYL = (start >> 16) & 0xff; + ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA; + ATA_COMMAND = CMD_WRITE_SECTORS; + + for (i=0; i= 5us */ + + ATA_CONTROL = CONTROL_nIEN; + sleep(HZ/400); /* >2ms */ + + return wait_for_rdy(); +} + +int ata_init(void) +{ + led_turn_off(); + + /* activate ATA */ + PADR |= 0x80; + + if (!ata_hard_reset()) + return -1; + + if (!check_registers()) + return -2; + + if (!check_harddisk()) + return -3; + + if (!freeze_lock()) + return -4; + + ATA_SELECT = SELECT_LBA; + ATA_CONTROL = CONTROL_nIEN; + + return 0; +} diff --git a/firmware/drivers/ata.h b/firmware/drivers/ata.h new file mode 100644 index 0000000000..50cd85d755 --- /dev/null +++ b/firmware/drivers/ata.h @@ -0,0 +1,32 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Alan Korr + * + * 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 __ATA_H__ +#define __ATA_H__ + +extern int ata_hard_reset(void); +extern int ata_soft_reset(void); +extern int ata_init(void); +extern int ata_read_sectors(unsigned long start, + unsigned char count, + void* buf); +extern int ata_write_sectors(unsigned long start, + unsigned char count, + void* buf); + +#endif diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c new file mode 100644 index 0000000000..a1abccd32a --- /dev/null +++ b/firmware/drivers/button.c @@ -0,0 +1,197 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Daniel Stenberg + * + * 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. + * + ****************************************************************************/ +/* + * Archos Jukebox Recorder button functions + */ + +#include "config.h" +#include "sh7034.h" +#include "button.h" + +#ifdef HAVE_RECORDER_KEYPAD + +/* AJBR buttons are connected to the CPU as follows: + * + * ON and OFF are connected to separate port B input pins. + * + * F1, F2, F3, and UP are connected to the AN4 analog input, each through + * a separate voltage divider. The voltage on AN4 depends on which button + * (or none, or a combination) is pressed. + * + * DOWN, PLAY, LEFT, and RIGHT are likewise connected to AN5. */ + +/* Button voltage levels on AN4 and AN5 */ +#define LEVEL1 50 +#define LEVEL2 125 +#define LEVEL3 175 +#define LEVEL4 225 + +/* Number of calls to get_button for a button to stop bouncing + * and to be considered held down. + * Should really use a hardware timer for this. + */ +#define BOUNCE_COUNT 200 +#define HOLD_COUNT 10000 + +static int last; /* Last button pressed */ +static int count; /* Number of calls button has been down */ + + +/* + *Initialize buttons + */ +void button_init() +{ +#ifndef SIMULATOR + /* Set PB4 and PB8 as input pins */ + PBCR1 &= 0xfffc; /* PB8MD = 00 */ + PBCR2 &= 0xfcff; /* PB4MD = 00 */ + PBIOR &= ~(PBDR_BTN_ON|PBDR_BTN_OFF); /* Inputs */ + + /* Set A/D to scan AN4 and AN5. + * This needs to be changed to scan other analog pins + * for battery level, etc. */ + ADCSR = 0; + ADCR = 0; + ADCSR = ADCSR_ADST | ADCSR_SCAN | 0x5; +#endif + last = BUTTON_NONE; + count = 0; +} + +/* + * Get button pressed from hardware + */ +static int get_raw_button (void) +{ + /* Check port B pins for ON and OFF */ + int data = PBDR; + if ((data & PBDR_BTN_ON) == 0) + return BUTTON_ON; + else if ((data & PBDR_BTN_OFF) == 0) + return BUTTON_OFF; + + /* Check AN4 pin for F1-3 and UP */ + data = ADDRAH; + if (data >= LEVEL4) + return BUTTON_F3; + else if (data >= LEVEL3) + return BUTTON_UP; + else if (data >= LEVEL2) + return BUTTON_F2; + else if (data >= LEVEL1) + return BUTTON_F1; + + /* Check AN5 pin for DOWN, PLAY, LEFT, RIGHT */ + data = ADDRBH; + if (data >= LEVEL4) + return BUTTON_DOWN; + else if (data >= LEVEL3) + return BUTTON_PLAY; + else if (data >= LEVEL2) + return BUTTON_LEFT; + else if (data >= LEVEL1) + return BUTTON_RIGHT; + + return BUTTON_NONE; +} + +/* + * Get the currently pressed button. + * Returns one of BUTTON_xxx codes, with possibly a modifier bit set. + * No modifier bits are set when the button is first pressed. + * BUTTON_HELD bit is while the button is being held. + * BUTTON_REL bit is set when button has been released. + */ +int button_get(void) +{ + int btn = get_raw_button(); + int ret; + + /* Last button pressed is still down */ + if (btn != BUTTON_NONE && btn == last) { + count++; + if (count == BOUNCE_COUNT) + return btn; + else if (count >= HOLD_COUNT) + return btn | BUTTON_HELD; + else + return BUTTON_NONE; + } + + /* Last button pressed now released */ + if (btn == BUTTON_NONE && last != BUTTON_NONE) + ret = last | BUTTON_REL; + else + ret = BUTTON_NONE; + + last = btn; + count = 0; + return ret; +} + +#elif HAVE_PLAYER_KEYPAD + +/* The player has all buttons on port pins: + + LEFT: PC0 + RIGHT: PC2 + PLAY: PC3 + STOP: PA11 + ON: PA5 + MENU: PC1 +*/ + +void button_init(void) +{ + /* set port pins as input */ + PAIOR &= ~0x820; +} + +int button_get(void) +{ + int porta = PADR; + int portc = PCDR; + int btn = 0; + + if ( portc & 1 ) + btn |= BUTTON_LEFT; + if ( portc & 2 ) + btn |= BUTTON_MENU; + if ( portc & 4 ) + btn |= BUTTON_RIGHT; + if ( portc & 8 ) + btn |= BUTTON_PLAY | BUTTON_UP; + if ( porta & 0x20 ) + btn |= BUTTON_ON; + if ( porta & 0x800 ) + btn |= BUTTON_STOP | BUTTON_DOWN; + + return btn; +} + +#endif + + + +/* ----------------------------------------------------------------- + * local variables: + * eval: (load-file "rockbox-mode.el") + * end: + */ diff --git a/firmware/drivers/button.h b/firmware/drivers/button.h new file mode 100644 index 0000000000..a8cc71b875 --- /dev/null +++ b/firmware/drivers/button.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Daniel Stenberg + * + * 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 "config.h" + +void button_init (void); +int button_get (void); + +/* Shared button codes */ +#define BUTTON_NONE 0x0000 +#define BUTTON_ON 0x0001 +#define BUTTON_UP 0x0010 +#define BUTTON_DOWN 0x0020 +#define BUTTON_LEFT 0x0040 +#define BUTTON_RIGHT 0x0080 + +/* Button modifiers */ +#define BUTTON_HELD 0x4000 +#define BUTTON_REL 0x8000 + + +#ifdef HAVE_RECORDER_KEYPAD + +/* Recorder specific button codes */ +#define BUTTON_OFF 0x0002 +#define BUTTON_PLAY 0x0004 +#define BUTTON_F1 0x0100 +#define BUTTON_F2 0x0200 +#define BUTTON_F3 0x0400 + +#elif HAVE_PLAYER_KEYPAD + +/* Jukebox 6000 and Studio specific button codes */ +#define BUTTON_MENU 0x0002 +#define BUTTON_PLAY BUTTON_UP +#define BUTTON_STOP BUTTON_DOWN + +#endif diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c new file mode 100644 index 0000000000..328428a941 --- /dev/null +++ b/firmware/drivers/fat.c @@ -0,0 +1,1315 @@ +/*************************************************************************** + * __________ __ ___. + * 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 +#include +#include +#include +#include +#include +#include + +#define BLOCK_SIZE 512 + +#include "fat.h" +#include "ata.h" + +#define NUM_ROOT_DIR_ENTRIES 512 +#define NUM_FATS 2 +#define NUM_RESERVED_SECTORS 1 +#define NUM_BLOCKS 10000 + +struct dsksz2secperclus +{ + unsigned int disk_size; + unsigned int sec_per_cluster; +}; + +/* +** This is the table for FAT16 drives. NOTE that this table includes +** entries for disk sizes larger than 512 MB even though typically +** only the entries for disks < 512 MB in size are used. +** The way this table is accessed is to look for the first entry +** in the table for which the disk size is less than or equal +** to the DiskSize field in that table entry. For this table to +** work properly BPB_RsvdSecCnt must be 1, BPB_NumFATs +** must be 2, and BPB_RootEntCnt must be 512. Any of these values +** being different may require the first table entries DiskSize value +** to be changed otherwise the cluster count may be to low for FAT16. +*/ +struct dsksz2secperclus dsk_table_fat16 [] = +{ + { 8400, 0}, /* disks up to 4.1 MB, the 0 value for SecPerClusVal + trips an error */ + { 32680, 2}, /* disks up to 16 MB, 1k cluster */ + { 262144, 4}, /* disks up to 128 MB, 2k cluster */ + { 524288, 8}, /* disks up to 256 MB, 4k cluster */ + { 1048576, 16}, /* disks up to 512 MB, 8k cluster */ +/* The entries after this point are not used unless FAT16 is forced */ + { 2097152, 32}, /* disks up to 1 GB, 16k cluster */ + { 4194304, 64}, /* disks up to 2 GB, 32k cluster */ + { 0xFFFFFFFF, 0} /* any disk greater than 2GB, + 0 value for SecPerClusVal trips an error */ +}; + +int fat_num_rootdir_sectors(struct bpb *bpb); +int fat_first_sector_of_cluster(struct bpb *bpb, unsigned int cluster); +int fat_get_fatsize(struct bpb* bpb); +int fat_get_totsec(struct bpb* bpb); +int fat_get_rootdir_sector(struct bpb *bpb); +int fat_first_data_sector(struct bpb* bpb); +int fat_get_bpb(struct bpb *bpb); +int fat_bpb_is_sane(struct bpb *bpb); +int fat_create_fat(struct bpb* bpb); +int fat_dbg_read_block(char *name, unsigned char *buf); +int fat_flush_fat(struct bpb *bpb); +unsigned char *fat_cache_fat_sector(struct bpb *bpb, int secnum); +int fat_update_entry(struct bpb *bpb, int entry, unsigned int val); +unsigned int fat_getcurrdostime(unsigned short *dosdate, + unsigned short *dostime, + unsigned char *dostenth); +int fat_create_root_dir(struct bpb *bpb); +int fat_create_dos_name(unsigned char *name, unsigned char *newname); +int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name); + +unsigned char *fat_cache[256]; +int fat_cache_dirty[256]; +char current_directory[256] = "\\"; +struct bpb *global_bpb; +struct disk_info di; + +extern int yyparse(void); + + +#ifdef TEST_FAT +void prompt(void) +{ + printf("C:%s>", current_directory); +} + +int main(int argc, char *argv[]) +{ + struct bpb bpb; + + memset(fat_cache, 0, sizeof(fat_cache)); + memset(fat_cache_dirty, 0, sizeof(fat_cache_dirty)); + + disk_init(NUM_BLOCKS); + + di.num_sectors = NUM_BLOCKS; + di.sec_per_track = 40; + di.num_heads = 250; + di.hidden_sectors = 0; + + if(read_disk("diskdump.dmp") < 0) + { + printf("*** Warning! The disk is uninitialized\n"); + } + else + { + fat_get_bpb(&bpb); + } + + global_bpb = &bpb; + prompt(); + yyparse(); + + dump_disk("diskdump.dmp"); + return 0; +} +#endif + +int fat_sec2cluster(struct bpb *bpb, unsigned int sec) +{ + int first_sec = fat_first_data_sector(bpb); + + if(sec < first_sec) + { + fprintf(stderr, "fat_sec2cluster() - Bad sector number (%d)\n", sec); + return -1; + } + + return ((sec - first_sec) / bpb->bpb_secperclus) + 2; +} + +int fat_last_cluster_in_chain(struct bpb *bpb, unsigned int cluster) +{ + int iseof = 0; + + switch(bpb->fat_type) + { + case FATTYPE_FAT12: + if(cluster >= 0x0ff8) + iseof = 1; + break; + case FATTYPE_FAT16: + if(cluster >= 0xfff8) + iseof = 1; + break; + case FATTYPE_FAT32: + if(cluster >= 0x0ffffff8) + iseof = 1; + break; + } + return iseof; +} + +int fat_cluster2sec(struct bpb *bpb, unsigned int cluster) +{ + int max_cluster = (fat_get_totsec(bpb) - fat_first_data_sector(bpb)) / + bpb->bpb_secperclus + 1; + + if(cluster > max_cluster) + { + fprintf(stderr, "fat_cluster2sec() - Bad cluster number (%d)\n", + cluster); + return -1; + } + + return fat_first_sector_of_cluster(bpb, cluster); +} + +int fat_first_sector_of_cluster(struct bpb *bpb, unsigned int cluster) +{ + return (cluster - 2) * bpb->bpb_secperclus + fat_first_data_sector(bpb); +} + +int fat_num_rootdir_sectors(struct bpb *bpb) +{ + return ((bpb->bpb_rootentcnt * 32) + (bpb->bpb_bytspersec - 1)) / + bpb->bpb_bytspersec; +} + +int fat_get_fatsize(struct bpb* bpb) +{ + if(bpb->bpb_fatsz16 != 0) + return bpb->bpb_fatsz16; + else + return bpb->bpb_fatsz32; +} + +int fat_get_totsec(struct bpb* bpb) +{ + if(bpb->bpb_totsec16 != 0) + return bpb->bpb_totsec16; + else + return bpb->bpb_totsec32; +} + +int fat_get_rootdir_sector(struct bpb *bpb) +{ + return bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fat_get_fatsize(bpb); +} + +int fat_first_data_sector(struct bpb* bpb) +{ + int fatsz; + int rootdirsectors; + + fatsz = fat_get_fatsize(bpb); + + rootdirsectors = fat_num_rootdir_sectors(bpb); + + return bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fatsz + rootdirsectors; +} + +int fat_format(struct disk_info *di, char *vol_name) +{ + unsigned char buf[BLOCK_SIZE]; + struct bpb bpb; + unsigned int root_dir_sectors; + unsigned int tmp1, tmp2; + int sec_per_clus = 0; + int fat_size; + int i = 0; + int err; + + while(di->num_sectors > dsk_table_fat16[i].disk_size) + { + i++; + } + + sec_per_clus = dsk_table_fat16[i].sec_per_cluster; + + if(sec_per_clus == 0) + { + fprintf(stderr, "fat_format() - Bad disk size (%u)\n", + di->num_sectors); + return -1; + } + + /* First calculate how many sectors we need for + the root directory */ + root_dir_sectors = ((NUM_ROOT_DIR_ENTRIES * 32) + + (BLOCK_SIZE - 1)) / BLOCK_SIZE; + + /* Now calculate the FAT size */ + tmp1 = di->num_sectors - (NUM_RESERVED_SECTORS + root_dir_sectors); + tmp2 = (256 * sec_per_clus) + NUM_FATS; + + fat_size = (tmp1 + (tmp2 - 1)) / tmp2; + + /* Now create the BPB. We must be careful, so we really make + it little endian. */ + memset(buf, 0xff, BLOCK_SIZE); + + strncpy(&buf[BS_OEMNAME], "MSWIN4.1", 8); + buf[BPB_BYTSPERSEC] = BLOCK_SIZE & 0xff; + buf[BPB_BYTSPERSEC+1] = BLOCK_SIZE >> 8; + buf[BPB_SECPERCLUS] = sec_per_clus; + buf[BPB_RSVDSECCNT] = 1; + buf[BPB_RSVDSECCNT+1] = 0; + buf[BPB_NUMFATS] = 2; + buf[BPB_ROOTENTCNT] = NUM_ROOT_DIR_ENTRIES & 0xff; + buf[BPB_ROOTENTCNT+1] = NUM_ROOT_DIR_ENTRIES >> 8; + buf[BPB_TOTSEC16] = di->num_sectors & 0xff; + buf[BPB_TOTSEC16+1] = di->num_sectors >> 8; + buf[BPB_MEDIA] = 0xf0; + buf[BPB_FATSZ16] = fat_size & 0xff; + buf[BPB_FATSZ16+1] = fat_size >> 8; + buf[BPB_SECPERTRK] = di->sec_per_track & 0xff; + buf[BPB_SECPERTRK+1] = di->sec_per_track >> 8; + buf[BPB_NUMHEADS] = di->num_heads & 0xff; + buf[BPB_NUMHEADS+1] = di->num_heads >> 8; + buf[BPB_HIDDSEC] = di->hidden_sectors & 0xff; + buf[BPB_HIDDSEC+1] = (di->hidden_sectors >> 8) & 0xff; + buf[BPB_HIDDSEC+2] = (di->hidden_sectors >> 16) & 0xff; + buf[BPB_HIDDSEC+3] = (di->hidden_sectors >> 24) & 0xff; + buf[BPB_TOTSEC32] = 0; + buf[BPB_TOTSEC32+1] = 0; + buf[BPB_TOTSEC32+2] = 0; + buf[BPB_TOTSEC32+3] = 0; + + buf[BS_DRVNUM] = 0; + buf[BS_RESERVED1] = 0; + buf[BS_BOOTSIG] = 0x29; + buf[BS_VOLID] = 0x78; + buf[BS_VOLID+1] = 0x56; + buf[BS_VOLID+2] = 0x34; + buf[BS_VOLID+3] = 0x12; + memset(&buf[BS_VOLLAB], ' ', 11); + strncpy(&buf[BS_VOLLAB], vol_name, MIN(11, strlen(vol_name)); + strncpy(&buf[BS_FILSYSTYPE], "FAT16 ", 8); + + /* The final signature */ + buf[BPB_LAST_WORD] = 0x55; + buf[BPB_LAST_WORD+1] = 0xaa; + + /* Now write the sector to disk */ + err = ata_write_sectors(0,1,buf); + if(err) + { + fprintf(stderr, "fat_format() - Couldn't write BSB (error code %i)\n", + err); + return -1; + } + + if(fat_get_bpb(&bpb) < 0) + { + fprintf(stderr, "fat_format() - Couldn't read BPB\n"); + return -1; + } + + if(fat_create_fat(&bpb) < 0) + { + fprintf(stderr, "fat_format() - Couldn't create FAT\n"); + return -1; + } + + if(fat_create_root_dir(&bpb) < 0) + { + fprintf(stderr, "fat_format() - Couldn't write root dir sector\n"); + return -1; + } + + return 0; +} + +int fat_get_bpb(struct bpb *bpb) +{ + unsigned char buf[BLOCK_SIZE]; + int err; + int fatsz; + int rootdirsectors; + int totsec; + int datasec; + int countofclusters; + + /* Read the sector */ + err = ata_read_sectors(0,1,buf); + if(err) + { + fprintf(stderr, "fat_get_bpb() - Couldn't read BPB (error code %i)\n", + err); + return -1; + } + + memset(bpb, 0, sizeof(struct bpb)); + + strncpy(bpb->bs_oemname, &buf[BS_OEMNAME], 8); + bpb->bs_oemname[8] = 0; + + bpb->bpb_bytspersec = buf[BPB_BYTSPERSEC] | (buf[BPB_BYTSPERSEC+1] << 8); + bpb->bpb_secperclus = buf[BPB_SECPERCLUS]; + bpb->bpb_rsvdseccnt = buf[BPB_RSVDSECCNT] | (buf[BPB_RSVDSECCNT+1] << 8); + bpb->bpb_numfats = buf[BPB_NUMFATS]; + bpb->bpb_rootentcnt = buf[BPB_ROOTENTCNT] | (buf[BPB_ROOTENTCNT+1] << 8); + bpb->bpb_totsec16 = buf[BPB_TOTSEC16] | (buf[BPB_TOTSEC16+1] << 8); + bpb->bpb_media = buf[BPB_MEDIA]; + bpb->bpb_fatsz16 = buf[BPB_FATSZ16] | (buf[BPB_FATSZ16+1] << 8); + bpb->bpb_secpertrk = buf[BPB_SECPERTRK] | (buf[BPB_SECPERTRK+1] << 8); + bpb->bpb_numheads = buf[BPB_NUMHEADS] | (buf[BPB_NUMHEADS+1] << 8); + bpb->bpb_hiddsec = buf[BPB_HIDDSEC] | (buf[BPB_HIDDSEC+1] << 8) | + (buf[BPB_HIDDSEC+2] << 16) | (buf[BPB_HIDDSEC+3] << 24); + bpb->bpb_totsec32 = buf[BPB_TOTSEC32] | (buf[BPB_TOTSEC32+1] << 8) | + (buf[BPB_TOTSEC32+2] << 16) | (buf[BPB_TOTSEC32+3] << 24); + + bpb->bs_drvnum = buf[BS_DRVNUM]; + bpb->bs_bootsig = buf[BS_BOOTSIG]; + if(bpb->bs_bootsig == 0x29) + { + bpb->bs_volid = buf[BS_VOLID] | (buf[BS_VOLID+1] << 8) | + (buf[BS_VOLID+2] << 16) | (buf[BS_VOLID+3] << 24); + strncpy(bpb->bs_vollab, &buf[BS_VOLLAB], 11); + strncpy(bpb->bs_filsystype, &buf[BS_FILSYSTYPE], 8); + } + + bpb->bpb_fatsz32 = (buf[BPB_FATSZ32] + (buf[BPB_FATSZ32+1] << 8)) | + (buf[BPB_FATSZ32+2] << 16) | (buf[BPB_FATSZ32+3] << 24); + + bpb->last_word = buf[BPB_LAST_WORD] | (buf[BPB_LAST_WORD+1] << 8); + + /* Determine FAT type */ + fatsz = fat_get_fatsize(bpb); + + if(bpb->bpb_totsec16 != 0) + totsec = bpb->bpb_totsec16; + else + totsec = bpb->bpb_totsec32; + + rootdirsectors = fat_num_rootdir_sectors(bpb); + datasec = totsec - (bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fatsz + + rootdirsectors); + countofclusters = datasec / bpb->bpb_secperclus; + + if(countofclusters < 4085) + { + bpb->fat_type = FATTYPE_FAT12; + } + else + { + if(countofclusters < 65525) + { + bpb->fat_type = FATTYPE_FAT16; + } + else + { + bpb->fat_type = FATTYPE_FAT32; + } + } + + if(fat_bpb_is_sane(bpb) < 0) + { + fprintf(stderr, "fat_get_bpb() - BPB is not sane\n"); + return -1; + } + + return 0; +} + +int fat_bpb_is_sane(struct bpb *bpb) +{ + if(bpb->fat_type == FATTYPE_FAT32) + { + fprintf(stderr, "fat_bpb_is_sane() - Error: FAT32 not supported\n"); + return -1; + } + + if(bpb->bpb_bytspersec != 512) + { + fprintf(stderr, + "fat_bpb_is_sane() - Warning: sector size is not 512 (%i)\n", + bpb->bpb_bytspersec); + } + if(bpb->bpb_secperclus * bpb->bpb_bytspersec > 32768) + { + fprintf(stderr, + "fat_bpb_is_sane() - Warning: cluster size is larger than 32K " + "(%i * %i = %i)\n", + bpb->bpb_bytspersec, bpb->bpb_secperclus, + bpb->bpb_bytspersec * bpb->bpb_secperclus); + } + if(bpb->bpb_rsvdseccnt != 1) + { + fprintf(stderr, + "fat_bpb_is_sane() - Warning: Reserved sectors is not 1 (%i)\n", + bpb->bpb_rsvdseccnt); + } + if(bpb->bpb_numfats != 2) + { + fprintf(stderr, + "fat_bpb_is_sane() - Warning: NumFATS is not 2 (%i)\n", + bpb->bpb_numfats); + } + if(bpb->bpb_rootentcnt != 512) + { + fprintf(stderr, + "fat_bpb_is_sane() - Warning: RootEntCnt is not 512 (%i)\n", + bpb->bpb_rootentcnt); + } + if(bpb->bpb_totsec16 < 200) + { + if(bpb->bpb_totsec16 == 0) + { + fprintf(stderr, "fat_bpb_is_sane() - Error: TotSec16 is 0\n"); + return -1; + } + else + { + fprintf(stderr, + "fat_bpb_is_sane() - Warning: TotSec16 " + "is quite small (%i)\n", + bpb->bpb_totsec16); + } + } + if(bpb->bpb_media != 0xf0 && bpb->bpb_media < 0xf8) + { + fprintf(stderr, + "fat_bpb_is_sane() - Warning: Non-standard " + "media type (0x%02x)\n", + bpb->bpb_media); + } + if(bpb->last_word != 0xaa55) + { + fprintf(stderr, "fat_bpb_is_sane() - Error: Last word is not " + "0xaa55 (0x%04x)\n", bpb->last_word); + return -1; + } + return 0; +} + +int fat_create_fat(struct bpb* bpb) +{ + unsigned char *sec; + int i; + int secnum = 0; + int fatsz; + + if(fat_bpb_is_sane(bpb) < 0) + { + fprintf(stderr, "fat_create_fat() - BPB is not sane\n"); + return -1; + } + + if(bpb->bpb_fatsz16 != 0) + fatsz = bpb->bpb_fatsz16; + else + fatsz = bpb->bpb_fatsz32; + + sec = fat_cache_fat_sector(bpb, secnum); + if(!sec) + { + fprintf(stderr, "fat_create_fat() - Couldn't cache fat sector" + " (%d)\n", secnum); + return -1; + } + + fat_cache_dirty[secnum] = 1; + + /* First entry should have the media type in the + low byte and the rest of the bits set to 1. + The second should be the EOC mark. */ + memset(sec, 0, BLOCK_SIZE); + sec[0] = bpb->bpb_media; + if(bpb->fat_type == FATTYPE_FAT12) + { + sec[1] = 0xff; + sec[2] = 0xff; + } + if(bpb->fat_type == FATTYPE_FAT16) + { + sec[0] = bpb->bpb_media; + sec[1] = 0xff; + sec[2] = 0xff; + sec[3] = 0xff; + } + secnum++; + + for(i = 0; i < fatsz - 1;i++) + { + sec = fat_cache_fat_sector(bpb, secnum); + if(!sec) + { + fprintf(stderr, "fat_create_fat() - Couldn't cache fat sector" + " (%d)\n", i); + return -1; + } + fat_cache_dirty[secnum] = 1; + secnum++; + memset(sec, 0, BLOCK_SIZE); + } + + if(fat_flush_fat(bpb) < 0) + { + fprintf(stderr, "fat_create_fat() - Couldn't flush fat\n"); + return -1; + } + return 0; +} + +int fat_dbg_read_block(char *name, unsigned char *buf) +{ + FILE *f; + + f = fopen(name, "rb"); + if(f) + { + if(fread(buf, 1, 512, f) != 512) + { + fprintf(stderr, "Could not read file \"%s\"\n", name); + fclose(f); + return -1; + } + /* Now write the sector to disk */ + ata_write_sectors(0,1,buf); + fclose(f); + } + else + { + fprintf(stderr, "Could not open file \"%s\"\n", name); + return -1; + } + return 0; +} + +unsigned char *fat_cache_fat_sector(struct bpb *bpb, int secnum) +{ + unsigned char *sec; + + sec = fat_cache[secnum]; + /* Load the sector if it is not cached */ + if(!sec) + { + sec = malloc(bpb->bpb_bytspersec); + if(!sec) + { + fprintf(stderr, "fat_cache_fat_sector() - Out of memory\n"); + return NULL; + } + if(ata_read_sectors(secnum + bpb->bpb_rsvdseccnt,1,sec)) + { + fprintf(stderr, "fat_cache_fat_sector() - Could" + " not read sector %d\n", + secnum); + free(sec); + return NULL; + } + fat_cache[secnum] = sec; + } + return sec; +} + +int fat_update_entry(struct bpb *bpb, int entry, unsigned int val) +{ + unsigned char *sec; + unsigned char *sec2; + int fatsz; + int fatoffset; + int thisfatsecnum; + int thisfatentoffset; + unsigned int tmp; + + fatsz = fat_get_fatsize(bpb); + + if(bpb->fat_type == FATTYPE_FAT12) + { + fatoffset = entry + (entry / 2); + } + else + { + if(bpb->fat_type == FATTYPE_FAT16) + fatoffset = entry * 2; + else + fatoffset = entry * 4; + } + thisfatsecnum = fatoffset / bpb->bpb_bytspersec; + thisfatentoffset = fatoffset % bpb->bpb_bytspersec; + + sec = fat_cache_fat_sector(bpb, thisfatsecnum); + /* Load the sector if it is not cached */ + if(!sec) + { + fprintf(stderr, "fat_update_entry() - Could not cache sector %d\n", + thisfatsecnum); + return -1; + } + + fat_cache_dirty[thisfatsecnum] = 1; + + switch(bpb->fat_type) + { + case FATTYPE_FAT12: + if(thisfatentoffset == bpb->bpb_bytspersec - 1) + { + /* This entry spans a sector boundary. Take care */ + sec2 = fat_cache_fat_sector(bpb, thisfatsecnum + 1); + /* Load the sector if it is not cached */ + if(!sec2) + { + fprintf(stderr, "fat_update_entry() - Could not " + "cache sector %d\n", + thisfatsecnum + 1); + return -1; + } + fat_cache_dirty[thisfatsecnum + 1] = 1; + } + else + { + if(entry & 1) /* Odd entry number? */ + { + tmp = sec[thisfatentoffset] & 0xf0; + sec[thisfatentoffset] = tmp | (val & 0x0f); + sec[thisfatentoffset+1] = (val >> 4) & 0xff; + } + else + { + sec[thisfatentoffset] = val & 0xff; + tmp = sec[thisfatentoffset+1] & 0x0f; + sec[thisfatentoffset+1] = tmp | ((val >> 4) & 0xf0); + } + } + break; + case FATTYPE_FAT16: + *(unsigned short *)(&sec[thisfatentoffset]) = val; + break; + case FATTYPE_FAT32: + tmp = *(unsigned short *)(&sec[thisfatentoffset]) & 0xf000000; + val = tmp | (val & 0x0fffffff); + *(unsigned short *)(&sec[thisfatentoffset]) = val; + break; + } + return 0; +} + +int fat_read_entry(struct bpb *bpb, int entry) +{ + unsigned char *sec; + unsigned char *sec2; + int fatsz; + int fatoffset; + int thisfatsecnum; + int thisfatentoffset; + int val = -1; + + fatsz = fat_get_fatsize(bpb); + + if(bpb->fat_type == FATTYPE_FAT12) + { + fatoffset = entry + (entry / 2); + } + else + { + if(bpb->fat_type == FATTYPE_FAT16) + fatoffset = entry * 2; + else + fatoffset = entry * 4; + } + thisfatsecnum = fatoffset / bpb->bpb_bytspersec; + thisfatentoffset = fatoffset % bpb->bpb_bytspersec; + + sec = fat_cache_fat_sector(bpb, thisfatsecnum); + /* Load the sector if it is not cached */ + if(!sec) + { + fprintf(stderr, "fat_update_entry() - Could not cache sector %d\n", + thisfatsecnum); + return -1; + } + + switch(bpb->fat_type) + { + case FATTYPE_FAT12: + if(thisfatentoffset == bpb->bpb_bytspersec - 1) + { + /* This entry spans a sector boundary. Take care */ + sec2 = fat_cache_fat_sector(bpb, thisfatsecnum + 1); + /* Load the sector if it is not cached */ + if(!sec2) + { + fprintf(stderr, "fat_update_entry() - Could not " + "cache sector %d\n", + thisfatsecnum + 1); + return -1; + } + } + else + { + if(entry & 1) /* Odd entry number? */ + { + val = (sec[thisfatentoffset] & 0x0f) | + (sec[thisfatentoffset+1] << 4); + } + else + { + val = (sec[thisfatentoffset] & 0xff) | + ((sec[thisfatentoffset+1] & 0x0f) << 8); + } + } + break; + case FATTYPE_FAT16: + val = *(unsigned short *)(&sec[thisfatentoffset]); + break; + case FATTYPE_FAT32: + val = *(unsigned int *)(&sec[thisfatentoffset]); + break; + } + return val; +} + +int fat_flush_fat(struct bpb *bpb) +{ + int i; + int err; + unsigned char *sec; + int fatsz; + unsigned short d, t; + char m; + + fatsz = fat_get_fatsize(bpb); + + for(i = 0;i < 256;i++) + { + if(fat_cache[i] && fat_cache_dirty[i]) + { + printf("Flushing FAT sector %d\n", i); + sec = fat_cache[i]; + err = ata_write_sectors(i + bpb->bpb_rsvdseccnt,1,sec); + if(err) + { + fprintf(stderr, "fat_flush_fat() - Couldn't write" + " sector (%d)\n", i + bpb->bpb_rsvdseccnt); + return -1; + } + err = ata_write_sectors(i + bpb->bpb_rsvdseccnt + fatsz,1,sec); + if(err) + { + fprintf(stderr, "fat_flush_fat() - Couldn't write" + " sector (%d)\n", i + bpb->bpb_rsvdseccnt + fatsz); + return -1; + } + fat_cache_dirty[i] = 0; + } + } + + fat_getcurrdostime(&d, &t, &m); + return 0; +} + +unsigned int fat_getcurrdostime(unsigned short *dosdate, + unsigned short *dostime, + unsigned char *dostenth) +{ + struct timeb tb; + struct tm *tm; + + ftime(&tb); + tm = localtime(&tb.time); + + *dosdate = ((tm->tm_year - 80) << 9) | + ((tm->tm_mon + 1) << 5) | + (tm->tm_mday); + + *dostime = (tm->tm_hour << 11) | + (tm->tm_min << 5) | + (tm->tm_sec >> 1); + + *dostenth = (tm->tm_sec & 1) * 100 + tb.millitm / 10; + return 0; +} + +int fat_create_root_dir(struct bpb *bpb) +{ + unsigned char buf[BLOCK_SIZE]; + int fatsz; + int sec; + int res; + int i; + unsigned short dosdate; + unsigned short dostime; + unsigned char dostenth; + int num_root_sectors; + + fatsz = fat_get_fatsize(bpb); + + sec = bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fatsz; + + memset(buf, 0, sizeof(buf)); + + strncpy(&buf[FATDIR_NAME], bpb->bs_vollab, 11); + buf[FATDIR_ATTR] = FAT_ATTR_VOLUME_ID; + buf[FATDIR_NTRES] = 0; + + fat_getcurrdostime(&dosdate, &dostime, &dostenth); + buf[FATDIR_WRTDATE] = dosdate & 0xff; + buf[FATDIR_WRTDATE+1] = dosdate >> 8; + buf[FATDIR_WRTTIME] = dostime & 0xff; + buf[FATDIR_WRTTIME+1] = dostime >> 8; + + printf("Writing rootdir to sector %d...\n", sec); + + res = ata_write_sectors(sec,1,buf); + if(res) + { + fprintf(stderr, "fat_create_root_dir() - Couldn't write sector (%d)\n", + sec); + return -1; + } + + printf("Clearing the rest of the root dir.\n"); + sec++; + num_root_sectors = bpb->bpb_rootentcnt * 32 / bpb->bpb_bytspersec; + memset(buf, 0, BLOCK_SIZE); + + for(i = 1;i < num_root_sectors;i++) + { + if(ata_write_sectors(sec++,1,buf)) + { + fprintf(stderr, "fat_create_root_dir() - " + " Couldn't write sector (%d)\n", sec); + return -1; + } + } + + return 0; +} + +int fat_get_next_cluster(struct bpb *bpb, unsigned int cluster) +{ + int next_cluster = fat_read_entry(bpb, cluster); + + if(fat_last_cluster_in_chain(bpb, next_cluster)) + return 0; + else + return next_cluster; +} + +int fat_add_dir_entry(struct bpb *bpb, unsigned int currdir, + struct fat_direntry *de) +{ + unsigned char buf[BLOCK_SIZE]; + unsigned char *eptr; + int i; + int err; + unsigned int sec; + unsigned int sec_cnt; + int need_to_update_last_empty_marker = 0; + int is_rootdir = (currdir == 0); + int done = 0; + unsigned char firstbyte; + + if(is_rootdir) + { + sec = fat_get_rootdir_sector(bpb); + } + else + { + sec = fat_first_sector_of_cluster(bpb, currdir); + } + + sec_cnt = 0; + + while(!done) + { + /* The root dir has a fixed size */ + if(is_rootdir) + { + if(sec_cnt >= bpb->bpb_rootentcnt * 32 / bpb->bpb_bytspersec) + { + /* We have reached the last sector of the root dir */ + if(need_to_update_last_empty_marker) + { + /* Since the directory is full, there is no room for + a marker, so we just exit */ + return 0; + } + else + { + fprintf(stderr, "fat_add_dir_entry() -" + " Root dir is full\n"); + return -1; + } + } + } + else + { + if(sec_cnt >= bpb->bpb_secperclus) + { + /* We have reached the end of this cluster */ + printf("Moving to the next cluster..."); + currdir = fat_get_next_cluster(bpb, currdir); + printf("new cluster is %d\n", currdir); + + if(!currdir) + { + /* This was the last in the chain, + we have to allocate a new cluster */ + /* TODO */ + } + } + } + + printf("Reading sector %d...\n", sec); + /* Read the next sector in the current dir */ + err = ata_read_sectors(sec,1,buf); + if(err) + { + fprintf(stderr, "fat_add_dir_entry() - Couldn't read dir sector" + " (error code %i)\n", err); + return -1; + } + + if(need_to_update_last_empty_marker) + { + /* All we need to do is to set the first entry to 0 */ + printf("Clearing the first entry in sector %d\n", sec); + buf[0] = 0; + done = 1; + } + else + { + /* Look for a free slot */ + for(i = 0;i < BLOCK_SIZE;i+=32) + { + firstbyte = buf[i]; + if(firstbyte == 0xe5 || firstbyte == 0) + { + printf("Found free slot at entry %d in sector %d\n", + i/32, sec); + eptr = &buf[i]; + memset(eptr, 0, 32); + strncpy(&eptr[FATDIR_NAME], de->name, 11); + eptr[FATDIR_ATTR] = de->attr; + eptr[FATDIR_NTRES] = 0; + + eptr[FATDIR_CRTTIMETENTH] = de->crttimetenth; + eptr[FATDIR_CRTDATE] = de->crtdate & 0xff; + eptr[FATDIR_CRTDATE+1] = de->crtdate >> 8; + eptr[FATDIR_CRTTIME] = de->crttime & 0xff; + eptr[FATDIR_CRTTIME+1] = de->crttime >> 8; + + eptr[FATDIR_WRTDATE] = de->wrtdate & 0xff; + eptr[FATDIR_WRTDATE+1] = de->wrtdate >> 8; + eptr[FATDIR_WRTTIME] = de->wrttime & 0xff; + eptr[FATDIR_WRTTIME+1] = de->wrttime >> 8; + + eptr[FATDIR_FILESIZE] = de->filesize & 0xff; + eptr[FATDIR_FILESIZE+1] = (de->filesize >> 8) & 0xff; + eptr[FATDIR_FILESIZE+2] = (de->filesize >> 16) & 0xff; + eptr[FATDIR_FILESIZE+3] = (de->filesize >> 24) & 0xff; + + /* Advance the last_empty_entry marker */ + if(firstbyte == 0) + { + i += 32; + if(i < BLOCK_SIZE) + { + buf[i] = 0; + /* We are done */ + done = 1; + } + else + { + /* We must fill in the first entry + in the next sector */ + need_to_update_last_empty_marker = 1; + } + } + + err = ata_write_sectors(sec,1,buf); + if(err) + { + fprintf(stderr, "fat_add_dir_entry() - " + " Couldn't write dir" + " sector (error code %i)\n", err); + return -1; + } + break; + } + } + } + sec++; + sec_cnt++; + } + + return 0; +} + +unsigned char fat_char2dos(unsigned char c) +{ + switch(c) + { + case 0xe5: /* Special kanji character */ + c = 0x05; + break; + case 0x22: + case 0x2a: + case 0x2b: + case 0x2c: + case 0x2e: + case 0x3a: + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x7c: + /* Illegal name */ + c = 0; + break; + + default: + if(c < 0x20) + { + /* Illegal name */ + c = 0; + } + break; + } + return c; +} + +int fat_create_dos_name(unsigned char *name, unsigned char *newname) +{ + unsigned char n[12]; + unsigned char c; + int i; + char *ext; + + if(strlen(name) > 12) + { + return -1; + } + + strcpy(n, name); + + ext = strchr(n, '.'); + if(ext) + { + *ext++ = 0; + } + + /* The file name is either empty, or there was only an extension. + In either case it is illegal. */ + if(n[0] == 0) + { + return -1; + } + + /* Name part */ + for(i = 0;n[i] && (i < 8);i++) + { + c = fat_char2dos(n[i]); + if(c) + { + newname[i] = toupper(c); + } + } + while(i < 8) + { + newname[i++] = ' '; + } + + /* Extension part */ + for(i = 0;ext && ext[i] && (i < 3);i++) + { + c = fat_char2dos(ext[i]); + if(c) + { + newname[8+i] = toupper(c); + } + } + while(i < 3) + { + newname[8+i++] = ' '; + } + return 0; +} + +int fat_create_dir(struct bpb *bpb, unsigned int currdir, char *name) +{ + struct fat_direntry de; + int err; + + printf("fat_create_file()\n"); + memset(&de, 0, sizeof(struct fat_direntry)); + if(fat_create_dos_name(name, de.name) < 0) + { + fprintf(stderr, "fat_create_file() - Illegal file name (%s)\n", name); + return -1; + } + + fat_getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth); + de.wrtdate = de.crtdate; + de.wrttime = de.crttime; + de.filesize = 0; + de.attr = FAT_ATTR_DIRECTORY; + + err = fat_add_dir_entry(bpb, currdir, &de); + return 0; +} + +int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name) +{ + struct fat_direntry de; + int err; + + printf("fat_create_file()\n"); + memset(&de, 0, sizeof(struct fat_direntry)); + if(fat_create_dos_name(name, de.name) < 0) + { + fprintf(stderr, "fat_create_file() - Illegal file name (%s)\n", name); + return -1; + } + fat_getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth); + de.wrtdate = de.crtdate; + de.wrttime = de.crttime; + de.filesize = 0; + + err = fat_add_dir_entry(bpb, currdir, &de); + return err; +} + +void fat_fill_direntry(struct fat_direntry *de, char *buf) +{ + memset(de, 0, sizeof(struct fat_direntry)); + + strncpy(de->name, &buf[FATDIR_NAME], 11); + de->attr = buf[FATDIR_ATTR]; + de->crttimetenth = buf[FATDIR_CRTTIMETENTH]; + de->crtdate = buf[FATDIR_CRTDATE] | (buf[FATDIR_CRTDATE+1] << 8); + de->crttime = buf[FATDIR_CRTTIME] | (buf[FATDIR_CRTTIME+1] << 8); + de->wrtdate = buf[FATDIR_WRTDATE] | (buf[FATDIR_WRTDATE+1] << 8); + de->wrttime = buf[FATDIR_WRTTIME] | (buf[FATDIR_WRTTIME+1] << 8); + + de->filesize = buf[FATDIR_FILESIZE] | + (buf[FATDIR_FILESIZE+1] << 8) | + (buf[FATDIR_FILESIZE+2] << 16) | + (buf[FATDIR_FILESIZE+3] << 24); +} + +int fat_opendir(struct bpb *bpb, struct fat_dirent *ent, unsigned int currdir) +{ + int is_rootdir = (currdir == 0); + unsigned int sec; + int err; + + if(is_rootdir) + { + sec = fat_get_rootdir_sector(bpb); + } + else + { + sec = fat_first_sector_of_cluster(bpb, currdir); + } + + /* Read the first sector in the current dir */ + err = ata_read_sectors(sec,1,ent->cached_buf); + if(err) + { + fprintf(stderr, "fat_getfirst() - Couldn't read dir sector" + " (error code %i)\n", err); + return -1; + } + + ent->entry = 0; + ent->cached_sec = sec; + ent->num_sec = 0; + return 0; +} + +int fat_getnext(struct bpb *bpb, struct fat_dirent *ent, + struct fat_direntry *entry) +{ + int done = 0; + int i; + int err; + unsigned char firstbyte; + + while(!done) + { + /* Look for a free slot */ + for(i = ent->entry;i < BLOCK_SIZE/32;i++) + { + firstbyte = ent->cached_buf[i*32]; + if(firstbyte == 0xe5) + { + continue; + } + + if(firstbyte == 0) + { + return -1; + } + + fat_fill_direntry(entry, &ent->cached_buf[i*32]); + done = 1; + break; + } + + /* Next sector? */ + if(i >= BLOCK_SIZE/32) + { + ent->num_sec++; + ent->cached_sec++; + + /* Do we need to advance one cluster? */ + if(ent->num_sec >= bpb->bpb_secperclus) + { + ent->num_sec = 0; + ent->cached_sec = fat_get_next_cluster( + bpb, fat_sec2cluster(bpb, ent->cached_sec)); + if(!ent->cached_sec) + { + printf("End of cluster chain.\n"); + return -1; + } + } + + /* Read the next sector */ + err = ata_read_sectors(ent->cached_sec,1,ent->cached_buf); + if(err) + { + fprintf(stderr, "fat_getnext() - Couldn't read dir sector" + " (error code %i)\n", err); + return -1; + } + + i = 0; + } + else + { + i++; + } + ent->entry = i; + } + return 0; +} diff --git a/firmware/drivers/fat.h b/firmware/drivers/fat.h new file mode 100644 index 0000000000..f1dc8dc5a0 --- /dev/null +++ b/firmware/drivers/fat.h @@ -0,0 +1,154 @@ +/*************************************************************************** + * __________ __ ___. + * 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 FAT_H +#define FAT_H + +#define FATTYPE_FAT12 0 +#define FATTYPE_FAT16 1 +#define FATTYPE_FAT32 2 + +#define BS_JMPBOOT 0 +#define BS_OEMNAME 3 +#define BPB_BYTSPERSEC 11 +#define BPB_SECPERCLUS 13 +#define BPB_RSVDSECCNT 14 +#define BPB_NUMFATS 16 +#define BPB_ROOTENTCNT 17 +#define BPB_TOTSEC16 19 +#define BPB_MEDIA 21 +#define BPB_FATSZ16 22 +#define BPB_SECPERTRK 24 +#define BPB_NUMHEADS 26 +#define BPB_HIDDSEC 28 +#define BPB_TOTSEC32 32 + +#define BS_DRVNUM 36 +#define BS_RESERVED1 37 +#define BS_BOOTSIG 38 +#define BS_VOLID 39 +#define BS_VOLLAB 43 +#define BS_FILSYSTYPE 54 + +#define BPB_FATSZ32 36 + +#define BPB_LAST_WORD 510 + +#define MIN(a,b) (((a) < (b))?(a):(b))) + +struct bpb +{ + char bs_oemname[9]; /* OEM string, ending with \0 */ + int bpb_bytspersec; /* Bytes per sectory, typically 512 */ + int bpb_secperclus; /* Sectors per cluster */ + int bpb_rsvdseccnt; /* Number of reserved sectors */ + int bpb_numfats; /* Number of FAT structures, typically 2 */ + int bpb_rootentcnt; /* Number of dir entries in the root */ + int bpb_totsec16; /* Number of sectors on the volume (old 16-bit) */ + int bpb_media; /* Media type (typically 0xf0 or 0xf8) */ + int bpb_fatsz16; /* Number of used sectors per FAT structure */ + int bpb_secpertrk; /* Number of sectors per track */ + int bpb_numheads; /* Number of heads */ + int bpb_hiddsec; /* Hidden sectors before the volume */ + unsigned int bpb_totsec32; /* Number of sectors on the volume + (new 32-bit) */ + /**** FAT12/16 specific *****/ + int bs_drvnum; /* Drive number */ + int bs_bootsig; /* Is 0x29 if the following 3 fields are valid */ + unsigned int bs_volid; /* Volume ID */ + char bs_vollab[12]; /* Volume label, 11 chars plus \0 */ + char bs_filsystype[9]; /* File system type, 8 chars plus \0 */ + + /**** FAT32 specific *****/ + int bpb_fatsz32; + + int last_word; /* Must be 0xaa55 */ + + int fat_type; /* What type of FAT is this? */ +}; + +#define FAT_ATTR_READ_ONLY 0x01 +#define FAT_ATTR_HIDDEN 0x02 +#define FAT_ATTR_SYSTEM 0x04 +#define FAT_ATTR_VOLUME_ID 0x08 +#define FAT_ATTR_DIRECTORY 0x10 +#define FAT_ATTR_ARCHIVE 0x20 +#define FAT_ATTR_LONG_NAME (FAT_ATTR_READ_ONLY | FAT_ATTR_HIDDEN | \ + FAT_ATTR_SYSTEM | FAT_ATTR_VOLUME_ID) + + +#define FATDIR_NAME 0 +#define FATDIR_ATTR 11 +#define FATDIR_NTRES 12 +#define FATDIR_CRTTIMETENTH 13 +#define FATDIR_CRTTIME 14 +#define FATDIR_CRTDATE 16 +#define FATDIR_LSTACCDATE 18 +#define FATDIR_FSTCLUSHI 20 +#define FATDIR_WRTTIME 22 +#define FATDIR_WRTDATE 24 +#define FATDIR_FSTCLUSLO 26 +#define FATDIR_FILESIZE 28 + +struct fat_direntry +{ + unsigned char name[12]; /* Name plus \0 */ + unsigned short attr; /* Attributes */ + unsigned char crttimetenth; /* Millisecond creation + time stamp (0-199) */ + unsigned short crttime; /* Creation time */ + unsigned short crtdate; /* Creation date */ + unsigned short lstaccdate; /* Last access date */ + unsigned short fstclushi; /* High word of first cluster + (0 for FAT12/16) */ + unsigned short wrttime; /* Last write time */ + unsigned short wrtdate; /* Last write date */ + unsigned short fstcluslo; /* Low word of first cluster */ + unsigned int filesize; /* File size in bytes */ +}; + +struct fat_context +{ + unsigned int curr_dir_sec; /* Current directory sector */ + +}; + +struct disk_info +{ + int num_sectors; + int sec_per_track; + int num_heads; + unsigned int hidden_sectors; +}; + +struct fat_dirent +{ + int entry; + unsigned int cached_sec; + unsigned int num_sec; + char cached_buf[BLOCK_SIZE]; +}; + +int fat_format(struct disk_info *di, char *vol_name); +int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name); +int fat_opendir(struct bpb *bpb, struct fat_dirent *ent, unsigned int currdir); +int fat_getnext(struct bpb *bpb, struct fat_dirent *ent, + struct fat_direntry *entry); + +#endif diff --git a/firmware/drivers/i2c.c b/firmware/drivers/i2c.c new file mode 100644 index 0000000000..3a5603ddd4 --- /dev/null +++ b/firmware/drivers/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 diff --git a/firmware/drivers/lcd.c b/firmware/drivers/lcd.c new file mode 100644 index 0000000000..737bf92a6b --- /dev/null +++ b/firmware/drivers/lcd.c @@ -0,0 +1,680 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Alan Korr + * + * 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 "config.h" +#include "lcd.h" + +#ifndef SIMULATOR +/* + * About /CS,DS,SC,SD + * ------------------ + * + * LCD on JBP and JBR uses a SPI protocol to receive orders (SDA and SCK lines) + * + * - /CS -> Chip Selection line : + * 0 : LCD chipset is activated. + * - DS -> Data Selection line, latched at the rising edge + * of the 8th serial clock (*) : + * 0 : instruction register, + * 1 : data register; + * - SC -> Serial Clock line (SDA). + * - SD -> Serial Data line (SCK), latched at the rising edge + * of each serial clock (*). + * + * _ _ + * /CS \ / + * \______________________________________________________/ + * _____ ____ ____ ____ ____ ____ ____ ____ ____ _____ + * SD \/ D7 \/ D6 \/ D5 \/ D4 \/ D3 \/ D2 \/ D1 \/ D0 \/ + * _____/\____/\____/\____/\____/\____/\____/\____/\____/\_____ + * + * _____ _ _ _ _ _ _ _ ________ + * SC \ * \ * \ * \ * \ * \ * \ * \ * + * \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ + * _ _________________________________________________________ + * DS \/ + * _/\_________________________________________________________ + * + */ + +/* + * The only way to do logical operations in an atomic way + * on SH1 is using : + * + * or.b/and.b/tst.b/xor.b #imm,@(r0,gbr) + * + * but GCC doesn't generate them at all so some assembly + * codes are needed here. + * + * The Global Base Register gbr is expected to be zero + * and r0 is the address of one register in the on-chip + * peripheral module. + * + */ + + /* + * Enter a LCD session : + * + * QI(LCDR) &= ~(LCD_CS|LCD_DS|LCD_SD|LCD_SC); + */ +static void lcd_start (void) +{ + asm + ("and.b\t%0,@(r0,gbr)" + : + : /* %0 */ "I"(~(LCD_CS|LCD_DS|LCD_SD|LCD_SC)), + /* %1 */ "z"(LCDR)); +} + + /* + * Leave a LCD session : + * + * QI(LCDR) |= LCD_CS|LCD_RS|LCD_SD|LCD_SC; + */ +static void lcd_stop (void) +{ + asm + ("or.b\t%0,@(r0,gbr)" + : + : /* %0 */ "I"(LCD_CS|LCD_DS|LCD_SD|LCD_SC), + /* %1 */ "z"(LCDR)); +} + +static void lcd_byte (int byte,int rs) + /* + * char j = 0x80; + * if (rs) + * do + * { + * QI(LCDR) &= ~(LCD_SC|LCD_SD); + * if (j & byte) + * QI(LCDR) |= LCD_SD; + * QI(LCDR) |= LCD_SC|LCD_DS; + * } + * while ((unsigned char)j >>= 1); + * else + * do + * { + * QI(LCDR) &= ~(LCD_SC|LCD_SD|LCD_DS); + * if (j & byte) + * QI(LCDR) |= LCD_SD; + * QI(LCDR) |= LCD_SC; + * } + * while ((unsigned char)j >>= 1); + */ +{ + if (rs > 0) + asm + ("shll8\t%0\n" + "0:\n\t" + "and.b\t%2,@(r0,gbr)\n\t" + "shll\t%0\n\t" + "bf\t1f\n\t" + "or.b\t%3,@(r0,gbr)\n" + "1:\n\t" + "or.b\t%4,@(r0,gbr)\n" + "add\t#-1,%1\n\t" + "cmp/pl\t%1\n\t" + "bt\t0b" + : + : /* %0 */ "r"(((unsigned)byte)<<16), + /* %1 */ "r"(8), + /* %2 */ "I"(~(LCD_SC|LCD_SD)), + /* %3 */ "I"(LCD_SD), + /* %4 */ "I"(LCD_SC|LCD_DS), + /* %5 */ "z"(LCDR)); + else + asm + ("shll8\t%0\n" + "0:\n\t" + "and.b\t%2,@(r0,gbr)\n\t" + "shll\t%0\n\t" + "bf\t1f\n\t" + "or.b\t%3,@(r0,gbr)\n" + "1:\n\t" + "or.b\t%4,@(r0,gbr)\n" + "add\t#-1,%1\n\t" + "cmp/pl\t%1\n\t" + "bt\t0b" + : + : /* %0 */ "r"(((unsigned)byte)<<16), + /* %1 */ "r"(8), + /* %2 */ "I"(~(LCD_SC|LCD_DS|LCD_SD)), + /* %3 */ "I"(LCD_SD), + /* %4 */ "I"(LCD_SC), + /* %5 */ "z"(LCDR)); +} + +void lcd_data (int data) +{ + lcd_byte (data,1); +} + +void lcd_instruction (int instruction) +{ + lcd_byte (instruction,0); +} + +void lcd_zero (int length) +{ + length *= 8; + while (--length >= 0) + lcd_data (0); +} + +void lcd_fill (int data,int length) +{ + length *= 8; + while (--length >= 0) + lcd_data (data); +} + +void lcd_copy (void *data,int count) +{ + while (--count >= 0) + lcd_data (*((char *)data)++); +} + +static void lcd_goto (int x,int y) +{ + lcd_instruction (LCD_CURSOR(x,y)); +} + +/*** BACKLIGHT ***/ + +static void lcd_toggle_backlight (void) +{ + PAIOR ^= LCD_BL; +} + +static void lcd_turn_on_backlight (void) +{ + PAIOR |= LCD_BL; +} + +static void lcd_turn_off_backlight (void) +{ + PAIOR &= ~LCD_BL; +} + +/*** ICONS ***/ +#endif + +#ifdef HAVE_LCD_CHARCELLS +# ifndef JBP_OLD + +static char const lcd_ascii[] = +{ +/*****************************************************************************************/ +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ +/* ************************************************************************************/ +/* 0x */ 0x00,0x01,0x02,0x03,0x00,0x00,0x00,0x00,0x04,0x05,0x00,0x00,0x00,0x00,0x00,0x00, +/* 1x */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* 2x */ 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, +/* 3x */ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, +/* 4x */ 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, +/* 5x */ 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F, +/* 6x */ 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F, +/* 7x */ 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x20,0x20,0x20,0x20,0x20, +/* 8x */ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, +/* 9x */ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, +/* Ax */ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, +/* Bx */ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, +/* Cx */ 0x41,0x41,0x41,0x41,0x41,0x41,0x20,0x43,0x45,0x45,0x45,0x45,0x49,0x49,0x49,0x49, +/* Dx */ 0x44,0x4E,0x4F,0x4F,0x4F,0x4F,0x4F,0x20,0x20,0x55,0x55,0x55,0x55,0x59,0x20,0x20, +/* Ex */ 0x61,0x61,0x61,0x61,0x61,0x61,0x20,0x63,0x65,0x65,0x65,0x65,0x69,0x69,0x69,0x69, +/* Fx */ 0x64,0x6E,0x6F,0x6F,0x6F,0x6F,0x6F,0x20,0x20,0x75,0x75,0x75,0x75,0x79,0x79,0x79 +/******/ + }; + +# else + +static char const lcd_ascii[] = + { +/*****************************************************************************************/ +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ +/* ************************************************************************************/ +/* 0x */ 0x00,0x01,0x02,0x03,0x00,0x00,0x00,0x00,0x85,0x89,0x00,0x00,0x00,0x00,0x00,0x00, +/* 1x */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* 2x */ 0x24,0x25,0x26,0x37,0x06,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33, +/* 3x */ 0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43, +/* 4x */ 0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53, +/* 5x */ 0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0xA9,0x33,0xCE,0x00,0x15, +/* 6x */ 0x00,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73, +/* 7x */ 0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x24,0x24,0x24,0x24,0x24, +/* 8x */ 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, +/* 9x */ 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, +/* Ax */ 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, +/* Bx */ 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, +/* Cx */ 0x45,0x45,0x45,0x45,0x45,0x45,0x24,0x47,0x49,0x49,0x49,0x49,0x4D,0x4D,0x4D,0x4D, +/* Dx */ 0x48,0x52,0x53,0x53,0x53,0x53,0x53,0x24,0x24,0x59,0x59,0x59,0x59,0x5D,0x24,0x24, +/* Ex */ 0x65,0x65,0x65,0x65,0x65,0x65,0x24,0x67,0x69,0x69,0x69,0x69,0x6D,0x6D,0x6D,0x6D, +/* Fx */ 0x73,0x72,0x73,0x73,0x73,0x73,0x73,0x24,0x24,0x79,0x79,0x79,0x79,0x7D,0x24,0x7D +/******/ + }; + +# endif + +void lcd_puts (char const *string) +{ + while (*string) + lcd_data (LCD_ASCII(*string++)); +} + +void lcd_putns (char const *string,int n) +{ + while (n--) + lcd_data (LCD_ASCII(*string++)); +} + +void lcd_putc (int character) +{ + lcd_data (LCD_ASCII(character)); +} + +void lcd_pattern (int which,char const *pattern,int count) +{ + lcd_instruction (LCD_PRAM|which); + lcd_copy ((void *)pattern,count); +} + +void lcd_puthex (unsigned int value,int digits) +{ + switch (digits) { + case 8: + lcd_puthex (value >> 16,4); + case 4: + lcd_puthex (value >> 8,2); + case 2: + lcd_puthex (value >> 4,1); + case 1: + value &= 15; + lcd_putc (value+((value < 10) ? '0' : ('A'-10))); + } +} + + +/* HAVE_LCD_CHARCELLS */ +#elif defined(HAVE_LCD_BITMAP) + +/* + * All bitmaps have this format: + * Bits within a byte are arranged veritcally, LSB at top. + * Bytes are stored in column-major format, with byte 0 at top left, + * byte 1 is 2nd from top, etc. Bytes following left-most column + * starts 2nd left column, etc. + * + * Note: The HW takes bitmap bytes in row-major order. + * + * Memory copy of display bitmap + */ +unsigned char display[DISP_X][DISP_Y/8]; + +/* + * ASCII character generation tables + * + * This contains only the printable characters (0x20-0x7f). + * Each element in this table is a character pattern bitmap. + */ +#define ASCII_MIN 0x20 /* First char in table */ +#define ASCII_MAX 0x7f /* Last char in table */ + +extern const unsigned char char_gen_6x8[][5][1]; +extern const unsigned char char_gen_8x12[][7][2]; +extern const unsigned char char_gen_12x16[][11][2]; + + +/* All zeros and ones bitmaps for area filling */ +static const unsigned char zeros[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 }; +static const unsigned char ones[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff }; + +static int lcd_y; /* Current pixel row */ +static int lcd_x; /* Current pixel column */ +static int lcd_size; /* Current font width */ + +#ifndef SIMULATOR + +/* + * Initialize LCD + */ +void lcd_init (void) +{ + /* Initialize PB0-3 as output pins */ + PBCR2 &= 0xff00; /* MD = 00 */ + PBIOR |= 0x000f; /* IOR = 1 */ + + /* Initialize LCD */ + lcd_write (TRUE, LCD_CNTL_RESET); + lcd_write (TRUE, LCD_CNTL_POWER); + lcd_write (TRUE, LCD_CNTL_SEGREMAP); + lcd_write (TRUE, LCD_CNTL_OUTSCAN); + lcd_write (TRUE, LCD_CNTL_CONTRAST); + lcd_write (TRUE, 0x30); /* Contrast parameter */ + lcd_write (TRUE, LCD_CNTL_DISPON); + + lcd_clear_display(); + lcd_update(); +} + +/* + * Update the display. + * This must be called after all other LCD funtions that change the display. + */ +void lcd_update (void) +{ + int x, y; + + /* Copy display bitmap to hardware */ + for (y = 0; y < DISP_Y/8; y++) + { + lcd_write (TRUE, LCD_CNTL_PAGE | (y & 0xf)); + lcd_write (TRUE, LCD_CNTL_HIGHCOL); + lcd_write (TRUE, LCD_CNTL_LOWCOL); + + for (x = 0; x < DISP_X; x++) + lcd_write (FALSE, display[x][y]); + } +} + +static void lcd_write (bool command, int value) +{ + int bit; + + /* Enable chip select, set DC if data */ + PBDR &= ~(PBDR_LCD_CS1|PBDR_LCD_DC); + if (!command) + PBDR |= PBDR_LCD_DC; + + /* Send each bit, starting with MSB */ + for (bit = 0x80; bit > 0; bit >>= 1) + { + PBDR &= ~(PBDR_LCD_SDA|PBDR_LCD_SCK); + if (value & bit) + PBDR |= PBDR_LCD_SDA; + PBDR |= PBDR_LCD_SCK; + } + + /* Disable chip select */ + PBDR |= PBDR_LCD_CS1; +} + +#endif /* SIMULATOR */ + +/* + * Clear the display + */ +void lcd_clear_display (void) +{ + lcd_position (0, 0, 8); + memset (display, 0, sizeof display); +} + +/* + * Set current x,y position and font size + */ +void lcd_position (int x, int y, int size) +{ + if (x >= 0 && x < DISP_X && y >= 0 && y < DISP_Y) + { + lcd_x = x; + lcd_y = y; + } + + lcd_size = size; +} + +/* + * Display a string at current position and size + */ +void lcd_string (const char *str) +{ + int x = lcd_x; + int nx = lcd_size; + int ny, ch; + const unsigned char *src; + + if (nx == 12) + ny = 16; + else if (nx == 8) + ny = 12; + else + { + nx = 6; + ny = 8; + } + + while ((ch = *str++) != '\0') + { + if (ch == '\n' || lcd_x + nx > DISP_X) + { + /* Wrap to next line */ + lcd_x = x; + lcd_y += ny; + } + + if (lcd_y + ny > DISP_Y) + return; + + /* Limit to char generation table */ + if (ch >= ASCII_MIN && ch <= ASCII_MAX) + { + if (nx == 12) + src = char_gen_12x16[ch-ASCII_MIN][0]; + else if (nx == 8) + src = char_gen_8x12[ch-ASCII_MIN][0]; + else + src = char_gen_6x8[ch-ASCII_MIN][0]; + + lcd_bitmap (src, lcd_x, lcd_y, nx-1, ny, TRUE); + lcd_bitmap (zeros, lcd_x+nx-1, lcd_y, 1, ny, TRUE); + + lcd_x += nx; + } + } +} + +/* + * Display a bitmap at (x, y), size (nx, ny) + * clear is TRUE to clear destination area first + */ +void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny, + bool clear) +{ + unsigned char *dst; + unsigned char *dst2 = &display[x][y/8]; + unsigned int data, mask, mask2, mask3, mask4; + int shift = y & 7; + + ny += shift; + + /* Calculate bit masks */ + mask4 = ~(0xfe << ((ny-1) & 7)); + if (clear) + { + mask = ~(0xff << shift); + mask2 = 0; + mask3 = ~mask4; + if (ny <= 8) + mask3 |= mask; + } + else + mask = mask2 = mask3 = 0xff; + + /* Loop for each column */ + for (x = 0; x < nx; x++) + { + dst = dst2; + dst2 += DISP_Y/8; + data = 0; + y = 0; + + if (ny > 8) + { + /* First partial row */ + data = *src++ << shift; + *dst = (*dst & mask) ^ data; + data >>= 8; + dst++; + + /* Intermediate rows */ + for (y = 8; y < ny-8; y += 8) + { + data |= *src++ << shift; + *dst = (*dst & mask2) ^ data; + data >>= 8; + dst++; + } + } + + /* Last partial row */ + if (y + shift < ny) + data |= *src++ << shift; + *dst = (*dst & mask3) ^ (data & mask4); + } +} + +/* + * Clear a rectangular area at (x, y), size (nx, ny) + */ +void lcd_clearrect (int x, int y, int nx, int ny) +{ + int i; + for (i = 0; i < nx; i++) + lcd_bitmap (zeros, x+i, y, 1, ny, TRUE); +} + +/* + * Fill a rectangular area at (x, y), size (nx, ny) + */ +void lcd_fillrect (int x, int y, int nx, int ny) +{ + int i; + for (i = 0; i < nx; i++) + lcd_bitmap (ones, x+i, y, 1, ny, TRUE); +} + +/* Invert a rectangular area at (x, y), size (nx, ny) */ +void lcd_invertrect (int x, int y, int nx, int ny) +{ + int i; + for (i = 0; i < nx; i++) + lcd_bitmap (ones, x+i, y, 1, ny, FALSE); +} + +#define DRAW_PIXEL(x,y) display[x][y/8] |= (1<<(y&7)) +#define CLEAR_PIXEL(x,y) display[x][y/8] &= ~(1<<(y&7)) + +void lcd_drawline( int x1, int y1, int x2, int y2 ) +{ + int numpixels; + int i; + int deltax, deltay; + int d, dinc1, dinc2; + int x, xinc1, xinc2; + int y, yinc1, yinc2; + + deltax = abs(x2 - x1); + deltay = abs(y2 - y1); + + if(deltax >= deltay) + { + numpixels = deltax; + d = 2 * deltay - deltax; + dinc1 = deltay * 2; + dinc2 = (deltay - deltax) * 2; + xinc1 = 1; + xinc2 = 1; + yinc1 = 0; + yinc2 = 1; + } + else + { + numpixels = deltay; + d = 2 * deltax - deltay; + dinc1 = deltax * 2; + dinc2 = (deltax - deltay) * 2; + xinc1 = 0; + xinc2 = 1; + yinc1 = 1; + yinc2 = 1; + } + numpixels++; /* include endpoints */ + + if(x1 > x2) + { + xinc1 = -xinc1; + xinc2 = -xinc2; + } + + if(y1 > y2) + { + yinc1 = -yinc1; + yinc2 = -yinc2; + } + + x = x1; + y = y1; + + for(i=0; i ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Alan Korr + * + * 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 __LCD_H__ +#define __LCD_H__ + +#include "sh7034.h" +#include "types.h" +#include "config.h" + +#define LCDR (PBDR+1) + +/* PA14 : /LCD-BL --- backlight */ +#define LCD_BL (14-8) + +#ifdef HAVE_LCD_CHARCELLS + /* JukeBox MP3 Player - AJB6K, AJBS20 */ +# define LCD_DS +1 // PB0 = 1 --- 0001 --- LCD-DS +# define LCD_CS +2 // PB1 = 1 --- 0010 --- /LCD-CS +# define LCD_SD +4 // PB2 = 1 --- 0100 --- LCD-SD +# define LCD_SC +8 // PB3 = 1 --- 1000 --- LCD-SC +# ifndef JBP_OLD +# define LCD_CONTRAST_SET ((char)0x50) +# define LCD_CRAM ((char)0x80) /* Characters */ +# define LCD_PRAM ((char)0xC0) /* Patterns */ +# define LCD_IRAM ((char)0x40) /* Icons */ +# else +# define LCD_CONTRAST_SET ((char)0xA8) +# define LCD_CRAM ((char)0xB0) /* Characters */ +# define LCD_PRAM ((char)0x80) /* Patterns */ +# define LCD_IRAM ((char)0xE0) /* Icons */ +# endif +# define LCD_ASCII(c) (lcd_ascii[(c)&255]) +# define LCD_CURSOR(x,y) ((char)(LCD_CRAM+((y)*16+(x)))) +# define LCD_ICON(i) ((char)(LCD_IRAM+i)) +# define LCD_ICON_BATTERY 0 +# define LCD_BATTERY_FRAME 0x02 +# define LCD_BATTERY_BAR1 0x08 +# define LCD_BATTERY_BAR2 0x04 +# define LCD_BATTERY_BAR3 0x10 +# define LCD_ICON_USB 2 +# define LCD_USB_LOGO 0xFF +# define LCD_ICON_PLAY 3 +# define LCD_PLAY_ICON 0xFF +# define LCD_ICON_RECORD 4 +# define LCD_RECORD_ICON 0x10 +# define LCD_ICON_STOP 5 +# define LCD_STOP_ICON 0x0F +# define LCD_ICON_AUDIO 5 +# define LCD_AUDIO_ICON 0xF0 +# define LCD_ICON_REVERSE 6 +# define LCD_REVERSE_ICON 0xFF +# define LCD_ICON_SINGLE 7 +# define LCD_SINGLE_ICON 0xFF +# define LCD_ICON_VOLUME0 9 +# define LCD_VOLUME_ICON 0x04 +# define LCD_VOLUME_BAR1 0x02 +# define LCD_VOLUME_BAR2 0x01 +# define LCD_ICON_VOLUME1 10 +# define LCD_VOLUME_BAR3 0x08 +# define LCD_VOLUME_BAR4 0x04 +# define LCD_VOLUME_BAR5 0x01 +# define LCD_ICON_PARAM 10 +# define LCD_PARAM_SYMBOL 0xF0 +#endif + +#ifdef HAVE_LCD_BITMAP +/* JukeBox MP3 Recorder - AJBR --- FIXME */ + +/* Defines from Alan on IRC, April 11th 2002 */ +#define LCD_SD +1 // PB0 = 1 --- 0001 +#define LCD_SC +2 // PB1 = 1 --- 0010 +#define LCD_RS +4 // PB2 = 1 --- 0100 +#define LCD_CS +8 // PB3 = 1 --- 1000 + +#define LCD_DS LCD_RS + +#define LCD_SET_LOWER_COLUMN_ADDRESS ((char)0x00) +#define LCD_SET_HIGHER_COLUMN_ADDRESS ((char)0x10) +#define LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO ((char)0x20) +#define LCD_SET_POWER_CONTROL_REGISTER ((char)0x28) +#define LCD_SET_DISPLAY_START_LINE ((char)0x40) +#define LCD_SET_CONTRAST_CONTROL_REGISTER ((char)0x81) +#define LCD_SET_SEGMENT_REMAP ((char)0xA0) +#define LCD_SET_LCD_BIAS ((char)0xA2) +#define LCD_SET_ENTIRE_DISPLAY_OFF ((char)0xA4) +#define LCD_SET_ENTIRE_DISPLAY_ON ((char)0xA5) +#define LCD_SET_NORMAL_DISPLAY ((char)0xA6) +#define LCD_SET_REVERSE_DISPLAY ((char)0xA7) +#define LCD_SET_INDICATOR_OFF ((char)0xAC) +#define LCD_SET_INDICATOR_ON ((char)0xAD) +#define LCD_SET_DISPLAY_OFF ((char)0xAE) +#define LCD_SET_DISPLAY_ON ((char)0xAF) +#define LCD_SET_PAGE_ADDRESS ((char)0xB0) +#define LCD_SET_COM_OUTPUT_SCAN_DIRECTION ((char)0xC0) +#define LCD_SET_DISPLAY_OFFSET ((char)0xD3) +#define LCD_SET_READ_MODIFY_WRITE_MODE ((char)0xE0) +#define LCD_SOFTWARE_RESET ((char)0xE2) +#define LCD_NOP ((char)0xE3) +#define LCD_SET_END_OF_READ_MODIFY_WRITE_MODE ((char)0xEE) + + +#define DISP_X 112 +#define DISP_Y 64 + +#define LCD_WIDTH DISP_X /* Display width in pixels */ +#define LCD_HEIGHT DISP_Y /* Display height in pixels */ + +void lcd_init (void); +void lcd_update (void); +void lcd_clear_display (void); +void lcd_position (int x, int y, int size); +void lcd_string (const char *str); +void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny, + bool clear); +void lcd_clearrect (int x, int y, int nx, int ny); +void lcd_fillrect (int x, int y, int nx, int ny); +void lcd_invertrect (int x, int y, int nx, int ny); +void lcd_drawline( int x1, int y1, int x2, int y2 ); +void lcd_drawpixel(int x, int y); +void lcd_clearpixel(int x, int y); +#endif + + +#ifndef SIMULATOR + +extern void lcd_data (int data); +extern void lcd_instruction (int instruction); +extern void lcd_zero (int length); +extern void lcd_fill (int data,int length); +extern void lcd_copy (void *data,int count); + +#ifdef HAVE_LCD_CHARCELLS + +extern void lcd_puts (char const *string); +extern void lcd_putns (char const *string,int n); +extern void lcd_putc (int character); +extern void lcd_puthex (unsigned int value,int digits); + +extern void lcd_pattern (int which,char const *pattern,int count); + +#endif /* HAVE_LCD_CHARCELLS */ + +#endif /* SIMULATOR */ + +#endif /* __LCD_H__ */ diff --git a/firmware/drivers/led.c b/firmware/drivers/led.c new file mode 100644 index 0000000000..d01c9de612 --- /dev/null +++ b/firmware/drivers/led.c @@ -0,0 +1,70 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Alan Korr + * + * 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 "config.h" + +#include + +#define turn_on() \ + set_bit (LEDB,PBDR_ADDR+1) + +#define turn_off() \ + clear_bit (LEDB,PBDR_ADDR+1) + +#define start_timer() \ + set_bit (2,TSTR_ADDR) + +#define stop_timer() \ + clear_bit (2,TSTR_ADDR) + +#define eoi(subinterrupt) \ + clear_bit (subinterrupt,TSR2_ADDR) + +#define set_volume(volume) \ + GRA2 = volume & 0x7FFF + + +void led_set_volume (unsigned short volume) +{ + volume <<= 10; + if (volume == 0) + led_turn_off (); + else if (volume == 0x8000) + led_turn_on (); + else + { + set_volume (volume); + start_timer (); + } +} + +#pragma interrupt +void IMIA2 (void) +{ + turn_off (); + eoi (0); +} + +#pragma interrupt +void OVI2 (void) +{ + turn_on (); + eoi (2); +} + diff --git a/firmware/drivers/led.h b/firmware/drivers/led.h new file mode 100644 index 0000000000..955c59aa81 --- /dev/null +++ b/firmware/drivers/led.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Alan Korr + * + * 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 __LED_H__ +#define __LED_H__ + +#include +#include + +#define LEDB 6 /* PB6 : red LED */ + +static inline void led_turn_off (void) +{ + clear_bit (LEDB,PBDR+1); + clear_bit (2,TSTR_ADDR); +} + +static inline void led_turn_on (void) +{ + set_bit (LEDB,PBDR+1); + set_bit (2,TSTR_ADDR); +} + +static inline void led_toggle (void) +{ + toggle_bit (LEDB,PBDR+1); +} + +extern void led_set_volume (unsigned short volume); +extern void led_setup (void); + +#endif + + diff --git a/firmware/drivers/mas.c b/firmware/drivers/mas.c new file mode 100644 index 0000000000..decfff612b --- /dev/null +++ b/firmware/drivers/mas.c @@ -0,0 +1,164 @@ +/*************************************************************************** + * __________ __ ___. + * 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 "i2c.h" +#include "debug.h" +#include "mas.h" + +/* note: 'len' is number of 32-bit words, not number of bytes! */ +int mas_readmem(int bank, int addr, unsigned long* dest, int len) +{ + int i; + unsigned char buf[16]; + + i=0; + buf[i++] = MAS_DATA_WRITE; + buf[i++] = bank?0xf0:0xe0; + buf[i++] = 0x00; + buf[i++] = (len & 0xff00) >> 8; + buf[i++] = len & 0xff; + buf[i++] = (addr & 0xff00) >> 8; + buf[i++] = addr & 0xff; + + /* send read command */ + if (i2c_write(MAS_DEV_WRITE,buf,i)) + { + return -1; + } + + return mas_devread(dest, len); +} + +/* note: 'len' is number of 32-bit words, not number of bytes! */ +int mas_writemem(int bank, int addr, unsigned long* src, int len) +{ + int i, j; + unsigned char buf[60]; + unsigned char* ptr = (unsigned char*)src; + + i=0; + buf[i++] = MAS_DATA_WRITE; + buf[i++] = bank; + buf[i++] = 0x00; + buf[i++] = (len & 0xff00) >> 8; + buf[i++] = len & 0xff; + buf[i++] = (addr & 0xff00) >> 8; + buf[i++] = addr & 0xff; + + j = 0; + while(len--) { + buf[i++] = ptr[j*4+1]; + buf[i++] = ptr[j*4+0]; + buf[i++] = 0; + buf[i++] = ptr[j*4+2]; + j += 4; + } + + /* send write command */ + if (i2c_write(MAS_DEV_WRITE,buf,i)) + { + return -1; + } + + return 0; +} + +int mas_readreg(int reg) +{ + int i; + unsigned char buf[16]; + + i=0; + buf[i++] = MAS_DATA_WRITE; + buf[i++] = 0xd0 | reg >> 4; + buf[i++] = (reg & 0x0f) << 4; + + /* send read command */ + if (i2c_write(MAS_DEV_WRITE,buf,i)) + { + return -1; + } + + if(mas_devread((unsigned long *)buf, 1)) + { + return -2; + } + + return buf[0] | buf[1] << 8 | buf[3] << 16; +} + +int mas_writereg(int reg, unsigned short val) +{ + int i; + unsigned char buf[16]; + + i=0; + buf[i++] = MAS_DATA_WRITE; + buf[i++] = 0x90 | reg >> 4; + buf[i++] = ((reg & 0x0f) << 4) | (val & 0x0f); + buf[i++] = (val >> 12) & 0xff; + buf[i++] = (val >> 4) & 0xff; + + /* send write command */ + if (i2c_write(MAS_DEV_WRITE,buf,i)) + { + return -1; + } + return 0; +} + +/* note: 'len' is number of 32-bit words, not number of bytes! */ +int mas_devread(unsigned long *dest, int len) +{ + unsigned char* ptr = (unsigned char*)dest; + int ret = 0; + int i; + + /* handle read-back */ + i2c_start(); + i2c_outb(MAS_DEV_WRITE); + if (i2c_getack()) { + i2c_outb(MAS_DATA_READ); + if (i2c_getack()) { + i2c_start(); + i2c_outb(MAS_DEV_READ); + if (i2c_getack()) { + for (i=0;len;i++) { + len--; + ptr[i*4+1] = i2c_inb(0); + ptr[i*4+0] = i2c_inb(0); + ptr[i*4+3] = i2c_inb(0); + if(len) + ptr[i*4+2] = i2c_inb(0); + else + ptr[i*4+2] = i2c_inb(1); /* NAK the last byte */ + } + } + else + ret = -3; + } + else + ret = -2; + } + else + ret = -1; + + i2c_stop(); + + return ret; +} diff --git a/firmware/drivers/mas.h b/firmware/drivers/mas.h new file mode 100644 index 0000000000..65e23f1498 --- /dev/null +++ b/firmware/drivers/mas.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * __________ __ ___. + * 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 _MAS_H_ +#define _MAS_H_ + +#define MAS_BANK_D0 0 +#define MAS_BANK_D1 1 + +/* + MAS I2C defs +*/ +#define MAS_ADR 0x3a +#define MAS_DEV_WRITE (MAS_ADR | 0x00) +#define MAS_DEV_READ (MAS_ADR | 0x01) + +/* registers..*/ +#define MAS_DATA_WRITE 0x68 +#define MAS_DATA_READ 0x69 +#define MAS_CONTROL 0x6a + +/* + * MAS register + */ +#define MAS_REG_DCCF 0x8e +#define MAS_REG_MUTE 0xaa +#define MAS_REG_PIODATA 0xc8 +#define MAS_REG_StartUpConfig 0xe6 +#define MAS_REG_KPRESCALE 0xe7 +#define MAS_REG_KBASS 0x6b +#define MAS_REG_KTREBLE 0x6f + +int mas_readmem(int bank, int addr, unsigned long* dest, int len); +int mas_writemem(int bank, int addr, unsigned long* src, int len); +int mas_devread(unsigned long *buf, int len); +int mas_readreg(int reg); +int mas_writereg(int reg, unsigned short val); + +#endif diff --git a/firmware/drivers/serial.c b/firmware/drivers/serial.c new file mode 100644 index 0000000000..d101ab8095 --- /dev/null +++ b/firmware/drivers/serial.c @@ -0,0 +1,75 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Alan Korr + * + * 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 "serial.h" + +#define TDRE 7 /* transmit data register empty */ +#define RDRF 6 /* receive data register full */ +#define ORER 5 /* overrun error */ +#define FER 4 /* frame error */ +#define PER 3 /* parity error */ + +static int serial_byte,serial_flag; + +void serial_putc (char byte) +{ + while (!(SSR1 & (1< ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Alan Korr + * + * 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 __SERIAL_H__ +#define __SERIAL_H__ + +#include +#include + +extern void serial_putc (char); +extern void serial_puts (char const *); +extern int serial_getc (void); +extern void serial_setup (int); + +#endif diff --git a/firmware/fat.c b/firmware/fat.c deleted file mode 100644 index 328428a941..0000000000 --- a/firmware/fat.c +++ /dev/null @@ -1,1315 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * 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 -#include -#include -#include -#include -#include -#include - -#define BLOCK_SIZE 512 - -#include "fat.h" -#include "ata.h" - -#define NUM_ROOT_DIR_ENTRIES 512 -#define NUM_FATS 2 -#define NUM_RESERVED_SECTORS 1 -#define NUM_BLOCKS 10000 - -struct dsksz2secperclus -{ - unsigned int disk_size; - unsigned int sec_per_cluster; -}; - -/* -** This is the table for FAT16 drives. NOTE that this table includes -** entries for disk sizes larger than 512 MB even though typically -** only the entries for disks < 512 MB in size are used. -** The way this table is accessed is to look for the first entry -** in the table for which the disk size is less than or equal -** to the DiskSize field in that table entry. For this table to -** work properly BPB_RsvdSecCnt must be 1, BPB_NumFATs -** must be 2, and BPB_RootEntCnt must be 512. Any of these values -** being different may require the first table entries DiskSize value -** to be changed otherwise the cluster count may be to low for FAT16. -*/ -struct dsksz2secperclus dsk_table_fat16 [] = -{ - { 8400, 0}, /* disks up to 4.1 MB, the 0 value for SecPerClusVal - trips an error */ - { 32680, 2}, /* disks up to 16 MB, 1k cluster */ - { 262144, 4}, /* disks up to 128 MB, 2k cluster */ - { 524288, 8}, /* disks up to 256 MB, 4k cluster */ - { 1048576, 16}, /* disks up to 512 MB, 8k cluster */ -/* The entries after this point are not used unless FAT16 is forced */ - { 2097152, 32}, /* disks up to 1 GB, 16k cluster */ - { 4194304, 64}, /* disks up to 2 GB, 32k cluster */ - { 0xFFFFFFFF, 0} /* any disk greater than 2GB, - 0 value for SecPerClusVal trips an error */ -}; - -int fat_num_rootdir_sectors(struct bpb *bpb); -int fat_first_sector_of_cluster(struct bpb *bpb, unsigned int cluster); -int fat_get_fatsize(struct bpb* bpb); -int fat_get_totsec(struct bpb* bpb); -int fat_get_rootdir_sector(struct bpb *bpb); -int fat_first_data_sector(struct bpb* bpb); -int fat_get_bpb(struct bpb *bpb); -int fat_bpb_is_sane(struct bpb *bpb); -int fat_create_fat(struct bpb* bpb); -int fat_dbg_read_block(char *name, unsigned char *buf); -int fat_flush_fat(struct bpb *bpb); -unsigned char *fat_cache_fat_sector(struct bpb *bpb, int secnum); -int fat_update_entry(struct bpb *bpb, int entry, unsigned int val); -unsigned int fat_getcurrdostime(unsigned short *dosdate, - unsigned short *dostime, - unsigned char *dostenth); -int fat_create_root_dir(struct bpb *bpb); -int fat_create_dos_name(unsigned char *name, unsigned char *newname); -int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name); - -unsigned char *fat_cache[256]; -int fat_cache_dirty[256]; -char current_directory[256] = "\\"; -struct bpb *global_bpb; -struct disk_info di; - -extern int yyparse(void); - - -#ifdef TEST_FAT -void prompt(void) -{ - printf("C:%s>", current_directory); -} - -int main(int argc, char *argv[]) -{ - struct bpb bpb; - - memset(fat_cache, 0, sizeof(fat_cache)); - memset(fat_cache_dirty, 0, sizeof(fat_cache_dirty)); - - disk_init(NUM_BLOCKS); - - di.num_sectors = NUM_BLOCKS; - di.sec_per_track = 40; - di.num_heads = 250; - di.hidden_sectors = 0; - - if(read_disk("diskdump.dmp") < 0) - { - printf("*** Warning! The disk is uninitialized\n"); - } - else - { - fat_get_bpb(&bpb); - } - - global_bpb = &bpb; - prompt(); - yyparse(); - - dump_disk("diskdump.dmp"); - return 0; -} -#endif - -int fat_sec2cluster(struct bpb *bpb, unsigned int sec) -{ - int first_sec = fat_first_data_sector(bpb); - - if(sec < first_sec) - { - fprintf(stderr, "fat_sec2cluster() - Bad sector number (%d)\n", sec); - return -1; - } - - return ((sec - first_sec) / bpb->bpb_secperclus) + 2; -} - -int fat_last_cluster_in_chain(struct bpb *bpb, unsigned int cluster) -{ - int iseof = 0; - - switch(bpb->fat_type) - { - case FATTYPE_FAT12: - if(cluster >= 0x0ff8) - iseof = 1; - break; - case FATTYPE_FAT16: - if(cluster >= 0xfff8) - iseof = 1; - break; - case FATTYPE_FAT32: - if(cluster >= 0x0ffffff8) - iseof = 1; - break; - } - return iseof; -} - -int fat_cluster2sec(struct bpb *bpb, unsigned int cluster) -{ - int max_cluster = (fat_get_totsec(bpb) - fat_first_data_sector(bpb)) / - bpb->bpb_secperclus + 1; - - if(cluster > max_cluster) - { - fprintf(stderr, "fat_cluster2sec() - Bad cluster number (%d)\n", - cluster); - return -1; - } - - return fat_first_sector_of_cluster(bpb, cluster); -} - -int fat_first_sector_of_cluster(struct bpb *bpb, unsigned int cluster) -{ - return (cluster - 2) * bpb->bpb_secperclus + fat_first_data_sector(bpb); -} - -int fat_num_rootdir_sectors(struct bpb *bpb) -{ - return ((bpb->bpb_rootentcnt * 32) + (bpb->bpb_bytspersec - 1)) / - bpb->bpb_bytspersec; -} - -int fat_get_fatsize(struct bpb* bpb) -{ - if(bpb->bpb_fatsz16 != 0) - return bpb->bpb_fatsz16; - else - return bpb->bpb_fatsz32; -} - -int fat_get_totsec(struct bpb* bpb) -{ - if(bpb->bpb_totsec16 != 0) - return bpb->bpb_totsec16; - else - return bpb->bpb_totsec32; -} - -int fat_get_rootdir_sector(struct bpb *bpb) -{ - return bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fat_get_fatsize(bpb); -} - -int fat_first_data_sector(struct bpb* bpb) -{ - int fatsz; - int rootdirsectors; - - fatsz = fat_get_fatsize(bpb); - - rootdirsectors = fat_num_rootdir_sectors(bpb); - - return bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fatsz + rootdirsectors; -} - -int fat_format(struct disk_info *di, char *vol_name) -{ - unsigned char buf[BLOCK_SIZE]; - struct bpb bpb; - unsigned int root_dir_sectors; - unsigned int tmp1, tmp2; - int sec_per_clus = 0; - int fat_size; - int i = 0; - int err; - - while(di->num_sectors > dsk_table_fat16[i].disk_size) - { - i++; - } - - sec_per_clus = dsk_table_fat16[i].sec_per_cluster; - - if(sec_per_clus == 0) - { - fprintf(stderr, "fat_format() - Bad disk size (%u)\n", - di->num_sectors); - return -1; - } - - /* First calculate how many sectors we need for - the root directory */ - root_dir_sectors = ((NUM_ROOT_DIR_ENTRIES * 32) + - (BLOCK_SIZE - 1)) / BLOCK_SIZE; - - /* Now calculate the FAT size */ - tmp1 = di->num_sectors - (NUM_RESERVED_SECTORS + root_dir_sectors); - tmp2 = (256 * sec_per_clus) + NUM_FATS; - - fat_size = (tmp1 + (tmp2 - 1)) / tmp2; - - /* Now create the BPB. We must be careful, so we really make - it little endian. */ - memset(buf, 0xff, BLOCK_SIZE); - - strncpy(&buf[BS_OEMNAME], "MSWIN4.1", 8); - buf[BPB_BYTSPERSEC] = BLOCK_SIZE & 0xff; - buf[BPB_BYTSPERSEC+1] = BLOCK_SIZE >> 8; - buf[BPB_SECPERCLUS] = sec_per_clus; - buf[BPB_RSVDSECCNT] = 1; - buf[BPB_RSVDSECCNT+1] = 0; - buf[BPB_NUMFATS] = 2; - buf[BPB_ROOTENTCNT] = NUM_ROOT_DIR_ENTRIES & 0xff; - buf[BPB_ROOTENTCNT+1] = NUM_ROOT_DIR_ENTRIES >> 8; - buf[BPB_TOTSEC16] = di->num_sectors & 0xff; - buf[BPB_TOTSEC16+1] = di->num_sectors >> 8; - buf[BPB_MEDIA] = 0xf0; - buf[BPB_FATSZ16] = fat_size & 0xff; - buf[BPB_FATSZ16+1] = fat_size >> 8; - buf[BPB_SECPERTRK] = di->sec_per_track & 0xff; - buf[BPB_SECPERTRK+1] = di->sec_per_track >> 8; - buf[BPB_NUMHEADS] = di->num_heads & 0xff; - buf[BPB_NUMHEADS+1] = di->num_heads >> 8; - buf[BPB_HIDDSEC] = di->hidden_sectors & 0xff; - buf[BPB_HIDDSEC+1] = (di->hidden_sectors >> 8) & 0xff; - buf[BPB_HIDDSEC+2] = (di->hidden_sectors >> 16) & 0xff; - buf[BPB_HIDDSEC+3] = (di->hidden_sectors >> 24) & 0xff; - buf[BPB_TOTSEC32] = 0; - buf[BPB_TOTSEC32+1] = 0; - buf[BPB_TOTSEC32+2] = 0; - buf[BPB_TOTSEC32+3] = 0; - - buf[BS_DRVNUM] = 0; - buf[BS_RESERVED1] = 0; - buf[BS_BOOTSIG] = 0x29; - buf[BS_VOLID] = 0x78; - buf[BS_VOLID+1] = 0x56; - buf[BS_VOLID+2] = 0x34; - buf[BS_VOLID+3] = 0x12; - memset(&buf[BS_VOLLAB], ' ', 11); - strncpy(&buf[BS_VOLLAB], vol_name, MIN(11, strlen(vol_name)); - strncpy(&buf[BS_FILSYSTYPE], "FAT16 ", 8); - - /* The final signature */ - buf[BPB_LAST_WORD] = 0x55; - buf[BPB_LAST_WORD+1] = 0xaa; - - /* Now write the sector to disk */ - err = ata_write_sectors(0,1,buf); - if(err) - { - fprintf(stderr, "fat_format() - Couldn't write BSB (error code %i)\n", - err); - return -1; - } - - if(fat_get_bpb(&bpb) < 0) - { - fprintf(stderr, "fat_format() - Couldn't read BPB\n"); - return -1; - } - - if(fat_create_fat(&bpb) < 0) - { - fprintf(stderr, "fat_format() - Couldn't create FAT\n"); - return -1; - } - - if(fat_create_root_dir(&bpb) < 0) - { - fprintf(stderr, "fat_format() - Couldn't write root dir sector\n"); - return -1; - } - - return 0; -} - -int fat_get_bpb(struct bpb *bpb) -{ - unsigned char buf[BLOCK_SIZE]; - int err; - int fatsz; - int rootdirsectors; - int totsec; - int datasec; - int countofclusters; - - /* Read the sector */ - err = ata_read_sectors(0,1,buf); - if(err) - { - fprintf(stderr, "fat_get_bpb() - Couldn't read BPB (error code %i)\n", - err); - return -1; - } - - memset(bpb, 0, sizeof(struct bpb)); - - strncpy(bpb->bs_oemname, &buf[BS_OEMNAME], 8); - bpb->bs_oemname[8] = 0; - - bpb->bpb_bytspersec = buf[BPB_BYTSPERSEC] | (buf[BPB_BYTSPERSEC+1] << 8); - bpb->bpb_secperclus = buf[BPB_SECPERCLUS]; - bpb->bpb_rsvdseccnt = buf[BPB_RSVDSECCNT] | (buf[BPB_RSVDSECCNT+1] << 8); - bpb->bpb_numfats = buf[BPB_NUMFATS]; - bpb->bpb_rootentcnt = buf[BPB_ROOTENTCNT] | (buf[BPB_ROOTENTCNT+1] << 8); - bpb->bpb_totsec16 = buf[BPB_TOTSEC16] | (buf[BPB_TOTSEC16+1] << 8); - bpb->bpb_media = buf[BPB_MEDIA]; - bpb->bpb_fatsz16 = buf[BPB_FATSZ16] | (buf[BPB_FATSZ16+1] << 8); - bpb->bpb_secpertrk = buf[BPB_SECPERTRK] | (buf[BPB_SECPERTRK+1] << 8); - bpb->bpb_numheads = buf[BPB_NUMHEADS] | (buf[BPB_NUMHEADS+1] << 8); - bpb->bpb_hiddsec = buf[BPB_HIDDSEC] | (buf[BPB_HIDDSEC+1] << 8) | - (buf[BPB_HIDDSEC+2] << 16) | (buf[BPB_HIDDSEC+3] << 24); - bpb->bpb_totsec32 = buf[BPB_TOTSEC32] | (buf[BPB_TOTSEC32+1] << 8) | - (buf[BPB_TOTSEC32+2] << 16) | (buf[BPB_TOTSEC32+3] << 24); - - bpb->bs_drvnum = buf[BS_DRVNUM]; - bpb->bs_bootsig = buf[BS_BOOTSIG]; - if(bpb->bs_bootsig == 0x29) - { - bpb->bs_volid = buf[BS_VOLID] | (buf[BS_VOLID+1] << 8) | - (buf[BS_VOLID+2] << 16) | (buf[BS_VOLID+3] << 24); - strncpy(bpb->bs_vollab, &buf[BS_VOLLAB], 11); - strncpy(bpb->bs_filsystype, &buf[BS_FILSYSTYPE], 8); - } - - bpb->bpb_fatsz32 = (buf[BPB_FATSZ32] + (buf[BPB_FATSZ32+1] << 8)) | - (buf[BPB_FATSZ32+2] << 16) | (buf[BPB_FATSZ32+3] << 24); - - bpb->last_word = buf[BPB_LAST_WORD] | (buf[BPB_LAST_WORD+1] << 8); - - /* Determine FAT type */ - fatsz = fat_get_fatsize(bpb); - - if(bpb->bpb_totsec16 != 0) - totsec = bpb->bpb_totsec16; - else - totsec = bpb->bpb_totsec32; - - rootdirsectors = fat_num_rootdir_sectors(bpb); - datasec = totsec - (bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fatsz + - rootdirsectors); - countofclusters = datasec / bpb->bpb_secperclus; - - if(countofclusters < 4085) - { - bpb->fat_type = FATTYPE_FAT12; - } - else - { - if(countofclusters < 65525) - { - bpb->fat_type = FATTYPE_FAT16; - } - else - { - bpb->fat_type = FATTYPE_FAT32; - } - } - - if(fat_bpb_is_sane(bpb) < 0) - { - fprintf(stderr, "fat_get_bpb() - BPB is not sane\n"); - return -1; - } - - return 0; -} - -int fat_bpb_is_sane(struct bpb *bpb) -{ - if(bpb->fat_type == FATTYPE_FAT32) - { - fprintf(stderr, "fat_bpb_is_sane() - Error: FAT32 not supported\n"); - return -1; - } - - if(bpb->bpb_bytspersec != 512) - { - fprintf(stderr, - "fat_bpb_is_sane() - Warning: sector size is not 512 (%i)\n", - bpb->bpb_bytspersec); - } - if(bpb->bpb_secperclus * bpb->bpb_bytspersec > 32768) - { - fprintf(stderr, - "fat_bpb_is_sane() - Warning: cluster size is larger than 32K " - "(%i * %i = %i)\n", - bpb->bpb_bytspersec, bpb->bpb_secperclus, - bpb->bpb_bytspersec * bpb->bpb_secperclus); - } - if(bpb->bpb_rsvdseccnt != 1) - { - fprintf(stderr, - "fat_bpb_is_sane() - Warning: Reserved sectors is not 1 (%i)\n", - bpb->bpb_rsvdseccnt); - } - if(bpb->bpb_numfats != 2) - { - fprintf(stderr, - "fat_bpb_is_sane() - Warning: NumFATS is not 2 (%i)\n", - bpb->bpb_numfats); - } - if(bpb->bpb_rootentcnt != 512) - { - fprintf(stderr, - "fat_bpb_is_sane() - Warning: RootEntCnt is not 512 (%i)\n", - bpb->bpb_rootentcnt); - } - if(bpb->bpb_totsec16 < 200) - { - if(bpb->bpb_totsec16 == 0) - { - fprintf(stderr, "fat_bpb_is_sane() - Error: TotSec16 is 0\n"); - return -1; - } - else - { - fprintf(stderr, - "fat_bpb_is_sane() - Warning: TotSec16 " - "is quite small (%i)\n", - bpb->bpb_totsec16); - } - } - if(bpb->bpb_media != 0xf0 && bpb->bpb_media < 0xf8) - { - fprintf(stderr, - "fat_bpb_is_sane() - Warning: Non-standard " - "media type (0x%02x)\n", - bpb->bpb_media); - } - if(bpb->last_word != 0xaa55) - { - fprintf(stderr, "fat_bpb_is_sane() - Error: Last word is not " - "0xaa55 (0x%04x)\n", bpb->last_word); - return -1; - } - return 0; -} - -int fat_create_fat(struct bpb* bpb) -{ - unsigned char *sec; - int i; - int secnum = 0; - int fatsz; - - if(fat_bpb_is_sane(bpb) < 0) - { - fprintf(stderr, "fat_create_fat() - BPB is not sane\n"); - return -1; - } - - if(bpb->bpb_fatsz16 != 0) - fatsz = bpb->bpb_fatsz16; - else - fatsz = bpb->bpb_fatsz32; - - sec = fat_cache_fat_sector(bpb, secnum); - if(!sec) - { - fprintf(stderr, "fat_create_fat() - Couldn't cache fat sector" - " (%d)\n", secnum); - return -1; - } - - fat_cache_dirty[secnum] = 1; - - /* First entry should have the media type in the - low byte and the rest of the bits set to 1. - The second should be the EOC mark. */ - memset(sec, 0, BLOCK_SIZE); - sec[0] = bpb->bpb_media; - if(bpb->fat_type == FATTYPE_FAT12) - { - sec[1] = 0xff; - sec[2] = 0xff; - } - if(bpb->fat_type == FATTYPE_FAT16) - { - sec[0] = bpb->bpb_media; - sec[1] = 0xff; - sec[2] = 0xff; - sec[3] = 0xff; - } - secnum++; - - for(i = 0; i < fatsz - 1;i++) - { - sec = fat_cache_fat_sector(bpb, secnum); - if(!sec) - { - fprintf(stderr, "fat_create_fat() - Couldn't cache fat sector" - " (%d)\n", i); - return -1; - } - fat_cache_dirty[secnum] = 1; - secnum++; - memset(sec, 0, BLOCK_SIZE); - } - - if(fat_flush_fat(bpb) < 0) - { - fprintf(stderr, "fat_create_fat() - Couldn't flush fat\n"); - return -1; - } - return 0; -} - -int fat_dbg_read_block(char *name, unsigned char *buf) -{ - FILE *f; - - f = fopen(name, "rb"); - if(f) - { - if(fread(buf, 1, 512, f) != 512) - { - fprintf(stderr, "Could not read file \"%s\"\n", name); - fclose(f); - return -1; - } - /* Now write the sector to disk */ - ata_write_sectors(0,1,buf); - fclose(f); - } - else - { - fprintf(stderr, "Could not open file \"%s\"\n", name); - return -1; - } - return 0; -} - -unsigned char *fat_cache_fat_sector(struct bpb *bpb, int secnum) -{ - unsigned char *sec; - - sec = fat_cache[secnum]; - /* Load the sector if it is not cached */ - if(!sec) - { - sec = malloc(bpb->bpb_bytspersec); - if(!sec) - { - fprintf(stderr, "fat_cache_fat_sector() - Out of memory\n"); - return NULL; - } - if(ata_read_sectors(secnum + bpb->bpb_rsvdseccnt,1,sec)) - { - fprintf(stderr, "fat_cache_fat_sector() - Could" - " not read sector %d\n", - secnum); - free(sec); - return NULL; - } - fat_cache[secnum] = sec; - } - return sec; -} - -int fat_update_entry(struct bpb *bpb, int entry, unsigned int val) -{ - unsigned char *sec; - unsigned char *sec2; - int fatsz; - int fatoffset; - int thisfatsecnum; - int thisfatentoffset; - unsigned int tmp; - - fatsz = fat_get_fatsize(bpb); - - if(bpb->fat_type == FATTYPE_FAT12) - { - fatoffset = entry + (entry / 2); - } - else - { - if(bpb->fat_type == FATTYPE_FAT16) - fatoffset = entry * 2; - else - fatoffset = entry * 4; - } - thisfatsecnum = fatoffset / bpb->bpb_bytspersec; - thisfatentoffset = fatoffset % bpb->bpb_bytspersec; - - sec = fat_cache_fat_sector(bpb, thisfatsecnum); - /* Load the sector if it is not cached */ - if(!sec) - { - fprintf(stderr, "fat_update_entry() - Could not cache sector %d\n", - thisfatsecnum); - return -1; - } - - fat_cache_dirty[thisfatsecnum] = 1; - - switch(bpb->fat_type) - { - case FATTYPE_FAT12: - if(thisfatentoffset == bpb->bpb_bytspersec - 1) - { - /* This entry spans a sector boundary. Take care */ - sec2 = fat_cache_fat_sector(bpb, thisfatsecnum + 1); - /* Load the sector if it is not cached */ - if(!sec2) - { - fprintf(stderr, "fat_update_entry() - Could not " - "cache sector %d\n", - thisfatsecnum + 1); - return -1; - } - fat_cache_dirty[thisfatsecnum + 1] = 1; - } - else - { - if(entry & 1) /* Odd entry number? */ - { - tmp = sec[thisfatentoffset] & 0xf0; - sec[thisfatentoffset] = tmp | (val & 0x0f); - sec[thisfatentoffset+1] = (val >> 4) & 0xff; - } - else - { - sec[thisfatentoffset] = val & 0xff; - tmp = sec[thisfatentoffset+1] & 0x0f; - sec[thisfatentoffset+1] = tmp | ((val >> 4) & 0xf0); - } - } - break; - case FATTYPE_FAT16: - *(unsigned short *)(&sec[thisfatentoffset]) = val; - break; - case FATTYPE_FAT32: - tmp = *(unsigned short *)(&sec[thisfatentoffset]) & 0xf000000; - val = tmp | (val & 0x0fffffff); - *(unsigned short *)(&sec[thisfatentoffset]) = val; - break; - } - return 0; -} - -int fat_read_entry(struct bpb *bpb, int entry) -{ - unsigned char *sec; - unsigned char *sec2; - int fatsz; - int fatoffset; - int thisfatsecnum; - int thisfatentoffset; - int val = -1; - - fatsz = fat_get_fatsize(bpb); - - if(bpb->fat_type == FATTYPE_FAT12) - { - fatoffset = entry + (entry / 2); - } - else - { - if(bpb->fat_type == FATTYPE_FAT16) - fatoffset = entry * 2; - else - fatoffset = entry * 4; - } - thisfatsecnum = fatoffset / bpb->bpb_bytspersec; - thisfatentoffset = fatoffset % bpb->bpb_bytspersec; - - sec = fat_cache_fat_sector(bpb, thisfatsecnum); - /* Load the sector if it is not cached */ - if(!sec) - { - fprintf(stderr, "fat_update_entry() - Could not cache sector %d\n", - thisfatsecnum); - return -1; - } - - switch(bpb->fat_type) - { - case FATTYPE_FAT12: - if(thisfatentoffset == bpb->bpb_bytspersec - 1) - { - /* This entry spans a sector boundary. Take care */ - sec2 = fat_cache_fat_sector(bpb, thisfatsecnum + 1); - /* Load the sector if it is not cached */ - if(!sec2) - { - fprintf(stderr, "fat_update_entry() - Could not " - "cache sector %d\n", - thisfatsecnum + 1); - return -1; - } - } - else - { - if(entry & 1) /* Odd entry number? */ - { - val = (sec[thisfatentoffset] & 0x0f) | - (sec[thisfatentoffset+1] << 4); - } - else - { - val = (sec[thisfatentoffset] & 0xff) | - ((sec[thisfatentoffset+1] & 0x0f) << 8); - } - } - break; - case FATTYPE_FAT16: - val = *(unsigned short *)(&sec[thisfatentoffset]); - break; - case FATTYPE_FAT32: - val = *(unsigned int *)(&sec[thisfatentoffset]); - break; - } - return val; -} - -int fat_flush_fat(struct bpb *bpb) -{ - int i; - int err; - unsigned char *sec; - int fatsz; - unsigned short d, t; - char m; - - fatsz = fat_get_fatsize(bpb); - - for(i = 0;i < 256;i++) - { - if(fat_cache[i] && fat_cache_dirty[i]) - { - printf("Flushing FAT sector %d\n", i); - sec = fat_cache[i]; - err = ata_write_sectors(i + bpb->bpb_rsvdseccnt,1,sec); - if(err) - { - fprintf(stderr, "fat_flush_fat() - Couldn't write" - " sector (%d)\n", i + bpb->bpb_rsvdseccnt); - return -1; - } - err = ata_write_sectors(i + bpb->bpb_rsvdseccnt + fatsz,1,sec); - if(err) - { - fprintf(stderr, "fat_flush_fat() - Couldn't write" - " sector (%d)\n", i + bpb->bpb_rsvdseccnt + fatsz); - return -1; - } - fat_cache_dirty[i] = 0; - } - } - - fat_getcurrdostime(&d, &t, &m); - return 0; -} - -unsigned int fat_getcurrdostime(unsigned short *dosdate, - unsigned short *dostime, - unsigned char *dostenth) -{ - struct timeb tb; - struct tm *tm; - - ftime(&tb); - tm = localtime(&tb.time); - - *dosdate = ((tm->tm_year - 80) << 9) | - ((tm->tm_mon + 1) << 5) | - (tm->tm_mday); - - *dostime = (tm->tm_hour << 11) | - (tm->tm_min << 5) | - (tm->tm_sec >> 1); - - *dostenth = (tm->tm_sec & 1) * 100 + tb.millitm / 10; - return 0; -} - -int fat_create_root_dir(struct bpb *bpb) -{ - unsigned char buf[BLOCK_SIZE]; - int fatsz; - int sec; - int res; - int i; - unsigned short dosdate; - unsigned short dostime; - unsigned char dostenth; - int num_root_sectors; - - fatsz = fat_get_fatsize(bpb); - - sec = bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fatsz; - - memset(buf, 0, sizeof(buf)); - - strncpy(&buf[FATDIR_NAME], bpb->bs_vollab, 11); - buf[FATDIR_ATTR] = FAT_ATTR_VOLUME_ID; - buf[FATDIR_NTRES] = 0; - - fat_getcurrdostime(&dosdate, &dostime, &dostenth); - buf[FATDIR_WRTDATE] = dosdate & 0xff; - buf[FATDIR_WRTDATE+1] = dosdate >> 8; - buf[FATDIR_WRTTIME] = dostime & 0xff; - buf[FATDIR_WRTTIME+1] = dostime >> 8; - - printf("Writing rootdir to sector %d...\n", sec); - - res = ata_write_sectors(sec,1,buf); - if(res) - { - fprintf(stderr, "fat_create_root_dir() - Couldn't write sector (%d)\n", - sec); - return -1; - } - - printf("Clearing the rest of the root dir.\n"); - sec++; - num_root_sectors = bpb->bpb_rootentcnt * 32 / bpb->bpb_bytspersec; - memset(buf, 0, BLOCK_SIZE); - - for(i = 1;i < num_root_sectors;i++) - { - if(ata_write_sectors(sec++,1,buf)) - { - fprintf(stderr, "fat_create_root_dir() - " - " Couldn't write sector (%d)\n", sec); - return -1; - } - } - - return 0; -} - -int fat_get_next_cluster(struct bpb *bpb, unsigned int cluster) -{ - int next_cluster = fat_read_entry(bpb, cluster); - - if(fat_last_cluster_in_chain(bpb, next_cluster)) - return 0; - else - return next_cluster; -} - -int fat_add_dir_entry(struct bpb *bpb, unsigned int currdir, - struct fat_direntry *de) -{ - unsigned char buf[BLOCK_SIZE]; - unsigned char *eptr; - int i; - int err; - unsigned int sec; - unsigned int sec_cnt; - int need_to_update_last_empty_marker = 0; - int is_rootdir = (currdir == 0); - int done = 0; - unsigned char firstbyte; - - if(is_rootdir) - { - sec = fat_get_rootdir_sector(bpb); - } - else - { - sec = fat_first_sector_of_cluster(bpb, currdir); - } - - sec_cnt = 0; - - while(!done) - { - /* The root dir has a fixed size */ - if(is_rootdir) - { - if(sec_cnt >= bpb->bpb_rootentcnt * 32 / bpb->bpb_bytspersec) - { - /* We have reached the last sector of the root dir */ - if(need_to_update_last_empty_marker) - { - /* Since the directory is full, there is no room for - a marker, so we just exit */ - return 0; - } - else - { - fprintf(stderr, "fat_add_dir_entry() -" - " Root dir is full\n"); - return -1; - } - } - } - else - { - if(sec_cnt >= bpb->bpb_secperclus) - { - /* We have reached the end of this cluster */ - printf("Moving to the next cluster..."); - currdir = fat_get_next_cluster(bpb, currdir); - printf("new cluster is %d\n", currdir); - - if(!currdir) - { - /* This was the last in the chain, - we have to allocate a new cluster */ - /* TODO */ - } - } - } - - printf("Reading sector %d...\n", sec); - /* Read the next sector in the current dir */ - err = ata_read_sectors(sec,1,buf); - if(err) - { - fprintf(stderr, "fat_add_dir_entry() - Couldn't read dir sector" - " (error code %i)\n", err); - return -1; - } - - if(need_to_update_last_empty_marker) - { - /* All we need to do is to set the first entry to 0 */ - printf("Clearing the first entry in sector %d\n", sec); - buf[0] = 0; - done = 1; - } - else - { - /* Look for a free slot */ - for(i = 0;i < BLOCK_SIZE;i+=32) - { - firstbyte = buf[i]; - if(firstbyte == 0xe5 || firstbyte == 0) - { - printf("Found free slot at entry %d in sector %d\n", - i/32, sec); - eptr = &buf[i]; - memset(eptr, 0, 32); - strncpy(&eptr[FATDIR_NAME], de->name, 11); - eptr[FATDIR_ATTR] = de->attr; - eptr[FATDIR_NTRES] = 0; - - eptr[FATDIR_CRTTIMETENTH] = de->crttimetenth; - eptr[FATDIR_CRTDATE] = de->crtdate & 0xff; - eptr[FATDIR_CRTDATE+1] = de->crtdate >> 8; - eptr[FATDIR_CRTTIME] = de->crttime & 0xff; - eptr[FATDIR_CRTTIME+1] = de->crttime >> 8; - - eptr[FATDIR_WRTDATE] = de->wrtdate & 0xff; - eptr[FATDIR_WRTDATE+1] = de->wrtdate >> 8; - eptr[FATDIR_WRTTIME] = de->wrttime & 0xff; - eptr[FATDIR_WRTTIME+1] = de->wrttime >> 8; - - eptr[FATDIR_FILESIZE] = de->filesize & 0xff; - eptr[FATDIR_FILESIZE+1] = (de->filesize >> 8) & 0xff; - eptr[FATDIR_FILESIZE+2] = (de->filesize >> 16) & 0xff; - eptr[FATDIR_FILESIZE+3] = (de->filesize >> 24) & 0xff; - - /* Advance the last_empty_entry marker */ - if(firstbyte == 0) - { - i += 32; - if(i < BLOCK_SIZE) - { - buf[i] = 0; - /* We are done */ - done = 1; - } - else - { - /* We must fill in the first entry - in the next sector */ - need_to_update_last_empty_marker = 1; - } - } - - err = ata_write_sectors(sec,1,buf); - if(err) - { - fprintf(stderr, "fat_add_dir_entry() - " - " Couldn't write dir" - " sector (error code %i)\n", err); - return -1; - } - break; - } - } - } - sec++; - sec_cnt++; - } - - return 0; -} - -unsigned char fat_char2dos(unsigned char c) -{ - switch(c) - { - case 0xe5: /* Special kanji character */ - c = 0x05; - break; - case 0x22: - case 0x2a: - case 0x2b: - case 0x2c: - case 0x2e: - case 0x3a: - case 0x3b: - case 0x3c: - case 0x3d: - case 0x3e: - case 0x3f: - case 0x5b: - case 0x5c: - case 0x5d: - case 0x7c: - /* Illegal name */ - c = 0; - break; - - default: - if(c < 0x20) - { - /* Illegal name */ - c = 0; - } - break; - } - return c; -} - -int fat_create_dos_name(unsigned char *name, unsigned char *newname) -{ - unsigned char n[12]; - unsigned char c; - int i; - char *ext; - - if(strlen(name) > 12) - { - return -1; - } - - strcpy(n, name); - - ext = strchr(n, '.'); - if(ext) - { - *ext++ = 0; - } - - /* The file name is either empty, or there was only an extension. - In either case it is illegal. */ - if(n[0] == 0) - { - return -1; - } - - /* Name part */ - for(i = 0;n[i] && (i < 8);i++) - { - c = fat_char2dos(n[i]); - if(c) - { - newname[i] = toupper(c); - } - } - while(i < 8) - { - newname[i++] = ' '; - } - - /* Extension part */ - for(i = 0;ext && ext[i] && (i < 3);i++) - { - c = fat_char2dos(ext[i]); - if(c) - { - newname[8+i] = toupper(c); - } - } - while(i < 3) - { - newname[8+i++] = ' '; - } - return 0; -} - -int fat_create_dir(struct bpb *bpb, unsigned int currdir, char *name) -{ - struct fat_direntry de; - int err; - - printf("fat_create_file()\n"); - memset(&de, 0, sizeof(struct fat_direntry)); - if(fat_create_dos_name(name, de.name) < 0) - { - fprintf(stderr, "fat_create_file() - Illegal file name (%s)\n", name); - return -1; - } - - fat_getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth); - de.wrtdate = de.crtdate; - de.wrttime = de.crttime; - de.filesize = 0; - de.attr = FAT_ATTR_DIRECTORY; - - err = fat_add_dir_entry(bpb, currdir, &de); - return 0; -} - -int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name) -{ - struct fat_direntry de; - int err; - - printf("fat_create_file()\n"); - memset(&de, 0, sizeof(struct fat_direntry)); - if(fat_create_dos_name(name, de.name) < 0) - { - fprintf(stderr, "fat_create_file() - Illegal file name (%s)\n", name); - return -1; - } - fat_getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth); - de.wrtdate = de.crtdate; - de.wrttime = de.crttime; - de.filesize = 0; - - err = fat_add_dir_entry(bpb, currdir, &de); - return err; -} - -void fat_fill_direntry(struct fat_direntry *de, char *buf) -{ - memset(de, 0, sizeof(struct fat_direntry)); - - strncpy(de->name, &buf[FATDIR_NAME], 11); - de->attr = buf[FATDIR_ATTR]; - de->crttimetenth = buf[FATDIR_CRTTIMETENTH]; - de->crtdate = buf[FATDIR_CRTDATE] | (buf[FATDIR_CRTDATE+1] << 8); - de->crttime = buf[FATDIR_CRTTIME] | (buf[FATDIR_CRTTIME+1] << 8); - de->wrtdate = buf[FATDIR_WRTDATE] | (buf[FATDIR_WRTDATE+1] << 8); - de->wrttime = buf[FATDIR_WRTTIME] | (buf[FATDIR_WRTTIME+1] << 8); - - de->filesize = buf[FATDIR_FILESIZE] | - (buf[FATDIR_FILESIZE+1] << 8) | - (buf[FATDIR_FILESIZE+2] << 16) | - (buf[FATDIR_FILESIZE+3] << 24); -} - -int fat_opendir(struct bpb *bpb, struct fat_dirent *ent, unsigned int currdir) -{ - int is_rootdir = (currdir == 0); - unsigned int sec; - int err; - - if(is_rootdir) - { - sec = fat_get_rootdir_sector(bpb); - } - else - { - sec = fat_first_sector_of_cluster(bpb, currdir); - } - - /* Read the first sector in the current dir */ - err = ata_read_sectors(sec,1,ent->cached_buf); - if(err) - { - fprintf(stderr, "fat_getfirst() - Couldn't read dir sector" - " (error code %i)\n", err); - return -1; - } - - ent->entry = 0; - ent->cached_sec = sec; - ent->num_sec = 0; - return 0; -} - -int fat_getnext(struct bpb *bpb, struct fat_dirent *ent, - struct fat_direntry *entry) -{ - int done = 0; - int i; - int err; - unsigned char firstbyte; - - while(!done) - { - /* Look for a free slot */ - for(i = ent->entry;i < BLOCK_SIZE/32;i++) - { - firstbyte = ent->cached_buf[i*32]; - if(firstbyte == 0xe5) - { - continue; - } - - if(firstbyte == 0) - { - return -1; - } - - fat_fill_direntry(entry, &ent->cached_buf[i*32]); - done = 1; - break; - } - - /* Next sector? */ - if(i >= BLOCK_SIZE/32) - { - ent->num_sec++; - ent->cached_sec++; - - /* Do we need to advance one cluster? */ - if(ent->num_sec >= bpb->bpb_secperclus) - { - ent->num_sec = 0; - ent->cached_sec = fat_get_next_cluster( - bpb, fat_sec2cluster(bpb, ent->cached_sec)); - if(!ent->cached_sec) - { - printf("End of cluster chain.\n"); - return -1; - } - } - - /* Read the next sector */ - err = ata_read_sectors(ent->cached_sec,1,ent->cached_buf); - if(err) - { - fprintf(stderr, "fat_getnext() - Couldn't read dir sector" - " (error code %i)\n", err); - return -1; - } - - i = 0; - } - else - { - i++; - } - ent->entry = i; - } - return 0; -} diff --git a/firmware/fat.h b/firmware/fat.h deleted file mode 100644 index f1dc8dc5a0..0000000000 --- a/firmware/fat.h +++ /dev/null @@ -1,154 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * 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 FAT_H -#define FAT_H - -#define FATTYPE_FAT12 0 -#define FATTYPE_FAT16 1 -#define FATTYPE_FAT32 2 - -#define BS_JMPBOOT 0 -#define BS_OEMNAME 3 -#define BPB_BYTSPERSEC 11 -#define BPB_SECPERCLUS 13 -#define BPB_RSVDSECCNT 14 -#define BPB_NUMFATS 16 -#define BPB_ROOTENTCNT 17 -#define BPB_TOTSEC16 19 -#define BPB_MEDIA 21 -#define BPB_FATSZ16 22 -#define BPB_SECPERTRK 24 -#define BPB_NUMHEADS 26 -#define BPB_HIDDSEC 28 -#define BPB_TOTSEC32 32 - -#define BS_DRVNUM 36 -#define BS_RESERVED1 37 -#define BS_BOOTSIG 38 -#define BS_VOLID 39 -#define BS_VOLLAB 43 -#define BS_FILSYSTYPE 54 - -#define BPB_FATSZ32 36 - -#define BPB_LAST_WORD 510 - -#define MIN(a,b) (((a) < (b))?(a):(b))) - -struct bpb -{ - char bs_oemname[9]; /* OEM string, ending with \0 */ - int bpb_bytspersec; /* Bytes per sectory, typically 512 */ - int bpb_secperclus; /* Sectors per cluster */ - int bpb_rsvdseccnt; /* Number of reserved sectors */ - int bpb_numfats; /* Number of FAT structures, typically 2 */ - int bpb_rootentcnt; /* Number of dir entries in the root */ - int bpb_totsec16; /* Number of sectors on the volume (old 16-bit) */ - int bpb_media; /* Media type (typically 0xf0 or 0xf8) */ - int bpb_fatsz16; /* Number of used sectors per FAT structure */ - int bpb_secpertrk; /* Number of sectors per track */ - int bpb_numheads; /* Number of heads */ - int bpb_hiddsec; /* Hidden sectors before the volume */ - unsigned int bpb_totsec32; /* Number of sectors on the volume - (new 32-bit) */ - /**** FAT12/16 specific *****/ - int bs_drvnum; /* Drive number */ - int bs_bootsig; /* Is 0x29 if the following 3 fields are valid */ - unsigned int bs_volid; /* Volume ID */ - char bs_vollab[12]; /* Volume label, 11 chars plus \0 */ - char bs_filsystype[9]; /* File system type, 8 chars plus \0 */ - - /**** FAT32 specific *****/ - int bpb_fatsz32; - - int last_word; /* Must be 0xaa55 */ - - int fat_type; /* What type of FAT is this? */ -}; - -#define FAT_ATTR_READ_ONLY 0x01 -#define FAT_ATTR_HIDDEN 0x02 -#define FAT_ATTR_SYSTEM 0x04 -#define FAT_ATTR_VOLUME_ID 0x08 -#define FAT_ATTR_DIRECTORY 0x10 -#define FAT_ATTR_ARCHIVE 0x20 -#define FAT_ATTR_LONG_NAME (FAT_ATTR_READ_ONLY | FAT_ATTR_HIDDEN | \ - FAT_ATTR_SYSTEM | FAT_ATTR_VOLUME_ID) - - -#define FATDIR_NAME 0 -#define FATDIR_ATTR 11 -#define FATDIR_NTRES 12 -#define FATDIR_CRTTIMETENTH 13 -#define FATDIR_CRTTIME 14 -#define FATDIR_CRTDATE 16 -#define FATDIR_LSTACCDATE 18 -#define FATDIR_FSTCLUSHI 20 -#define FATDIR_WRTTIME 22 -#define FATDIR_WRTDATE 24 -#define FATDIR_FSTCLUSLO 26 -#define FATDIR_FILESIZE 28 - -struct fat_direntry -{ - unsigned char name[12]; /* Name plus \0 */ - unsigned short attr; /* Attributes */ - unsigned char crttimetenth; /* Millisecond creation - time stamp (0-199) */ - unsigned short crttime; /* Creation time */ - unsigned short crtdate; /* Creation date */ - unsigned short lstaccdate; /* Last access date */ - unsigned short fstclushi; /* High word of first cluster - (0 for FAT12/16) */ - unsigned short wrttime; /* Last write time */ - unsigned short wrtdate; /* Last write date */ - unsigned short fstcluslo; /* Low word of first cluster */ - unsigned int filesize; /* File size in bytes */ -}; - -struct fat_context -{ - unsigned int curr_dir_sec; /* Current directory sector */ - -}; - -struct disk_info -{ - int num_sectors; - int sec_per_track; - int num_heads; - unsigned int hidden_sectors; -}; - -struct fat_dirent -{ - int entry; - unsigned int cached_sec; - unsigned int num_sec; - char cached_buf[BLOCK_SIZE]; -}; - -int fat_format(struct disk_info *di, char *vol_name); -int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name); -int fat_opendir(struct bpb *bpb, struct fat_dirent *ent, unsigned int currdir); -int fat_getnext(struct bpb *bpb, struct fat_dirent *ent, - struct fat_direntry *entry); - -#endif diff --git a/firmware/i2c.c b/firmware/i2c.c deleted file mode 100644 index 3a5603ddd4..0000000000 --- a/firmware/i2c.c +++ /dev/null @@ -1,212 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * 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 diff --git a/firmware/lcd.c b/firmware/lcd.c deleted file mode 100644 index 737bf92a6b..0000000000 --- a/firmware/lcd.c +++ /dev/null @@ -1,680 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Alan Korr - * - * 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 "config.h" -#include "lcd.h" - -#ifndef SIMULATOR -/* - * About /CS,DS,SC,SD - * ------------------ - * - * LCD on JBP and JBR uses a SPI protocol to receive orders (SDA and SCK lines) - * - * - /CS -> Chip Selection line : - * 0 : LCD chipset is activated. - * - DS -> Data Selection line, latched at the rising edge - * of the 8th serial clock (*) : - * 0 : instruction register, - * 1 : data register; - * - SC -> Serial Clock line (SDA). - * - SD -> Serial Data line (SCK), latched at the rising edge - * of each serial clock (*). - * - * _ _ - * /CS \ / - * \______________________________________________________/ - * _____ ____ ____ ____ ____ ____ ____ ____ ____ _____ - * SD \/ D7 \/ D6 \/ D5 \/ D4 \/ D3 \/ D2 \/ D1 \/ D0 \/ - * _____/\____/\____/\____/\____/\____/\____/\____/\____/\_____ - * - * _____ _ _ _ _ _ _ _ ________ - * SC \ * \ * \ * \ * \ * \ * \ * \ * - * \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ - * _ _________________________________________________________ - * DS \/ - * _/\_________________________________________________________ - * - */ - -/* - * The only way to do logical operations in an atomic way - * on SH1 is using : - * - * or.b/and.b/tst.b/xor.b #imm,@(r0,gbr) - * - * but GCC doesn't generate them at all so some assembly - * codes are needed here. - * - * The Global Base Register gbr is expected to be zero - * and r0 is the address of one register in the on-chip - * peripheral module. - * - */ - - /* - * Enter a LCD session : - * - * QI(LCDR) &= ~(LCD_CS|LCD_DS|LCD_SD|LCD_SC); - */ -static void lcd_start (void) -{ - asm - ("and.b\t%0,@(r0,gbr)" - : - : /* %0 */ "I"(~(LCD_CS|LCD_DS|LCD_SD|LCD_SC)), - /* %1 */ "z"(LCDR)); -} - - /* - * Leave a LCD session : - * - * QI(LCDR) |= LCD_CS|LCD_RS|LCD_SD|LCD_SC; - */ -static void lcd_stop (void) -{ - asm - ("or.b\t%0,@(r0,gbr)" - : - : /* %0 */ "I"(LCD_CS|LCD_DS|LCD_SD|LCD_SC), - /* %1 */ "z"(LCDR)); -} - -static void lcd_byte (int byte,int rs) - /* - * char j = 0x80; - * if (rs) - * do - * { - * QI(LCDR) &= ~(LCD_SC|LCD_SD); - * if (j & byte) - * QI(LCDR) |= LCD_SD; - * QI(LCDR) |= LCD_SC|LCD_DS; - * } - * while ((unsigned char)j >>= 1); - * else - * do - * { - * QI(LCDR) &= ~(LCD_SC|LCD_SD|LCD_DS); - * if (j & byte) - * QI(LCDR) |= LCD_SD; - * QI(LCDR) |= LCD_SC; - * } - * while ((unsigned char)j >>= 1); - */ -{ - if (rs > 0) - asm - ("shll8\t%0\n" - "0:\n\t" - "and.b\t%2,@(r0,gbr)\n\t" - "shll\t%0\n\t" - "bf\t1f\n\t" - "or.b\t%3,@(r0,gbr)\n" - "1:\n\t" - "or.b\t%4,@(r0,gbr)\n" - "add\t#-1,%1\n\t" - "cmp/pl\t%1\n\t" - "bt\t0b" - : - : /* %0 */ "r"(((unsigned)byte)<<16), - /* %1 */ "r"(8), - /* %2 */ "I"(~(LCD_SC|LCD_SD)), - /* %3 */ "I"(LCD_SD), - /* %4 */ "I"(LCD_SC|LCD_DS), - /* %5 */ "z"(LCDR)); - else - asm - ("shll8\t%0\n" - "0:\n\t" - "and.b\t%2,@(r0,gbr)\n\t" - "shll\t%0\n\t" - "bf\t1f\n\t" - "or.b\t%3,@(r0,gbr)\n" - "1:\n\t" - "or.b\t%4,@(r0,gbr)\n" - "add\t#-1,%1\n\t" - "cmp/pl\t%1\n\t" - "bt\t0b" - : - : /* %0 */ "r"(((unsigned)byte)<<16), - /* %1 */ "r"(8), - /* %2 */ "I"(~(LCD_SC|LCD_DS|LCD_SD)), - /* %3 */ "I"(LCD_SD), - /* %4 */ "I"(LCD_SC), - /* %5 */ "z"(LCDR)); -} - -void lcd_data (int data) -{ - lcd_byte (data,1); -} - -void lcd_instruction (int instruction) -{ - lcd_byte (instruction,0); -} - -void lcd_zero (int length) -{ - length *= 8; - while (--length >= 0) - lcd_data (0); -} - -void lcd_fill (int data,int length) -{ - length *= 8; - while (--length >= 0) - lcd_data (data); -} - -void lcd_copy (void *data,int count) -{ - while (--count >= 0) - lcd_data (*((char *)data)++); -} - -static void lcd_goto (int x,int y) -{ - lcd_instruction (LCD_CURSOR(x,y)); -} - -/*** BACKLIGHT ***/ - -static void lcd_toggle_backlight (void) -{ - PAIOR ^= LCD_BL; -} - -static void lcd_turn_on_backlight (void) -{ - PAIOR |= LCD_BL; -} - -static void lcd_turn_off_backlight (void) -{ - PAIOR &= ~LCD_BL; -} - -/*** ICONS ***/ -#endif - -#ifdef HAVE_LCD_CHARCELLS -# ifndef JBP_OLD - -static char const lcd_ascii[] = -{ -/*****************************************************************************************/ -/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ -/* ************************************************************************************/ -/* 0x */ 0x00,0x01,0x02,0x03,0x00,0x00,0x00,0x00,0x04,0x05,0x00,0x00,0x00,0x00,0x00,0x00, -/* 1x */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -/* 2x */ 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, -/* 3x */ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, -/* 4x */ 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, -/* 5x */ 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F, -/* 6x */ 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F, -/* 7x */ 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x20,0x20,0x20,0x20,0x20, -/* 8x */ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, -/* 9x */ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, -/* Ax */ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, -/* Bx */ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, -/* Cx */ 0x41,0x41,0x41,0x41,0x41,0x41,0x20,0x43,0x45,0x45,0x45,0x45,0x49,0x49,0x49,0x49, -/* Dx */ 0x44,0x4E,0x4F,0x4F,0x4F,0x4F,0x4F,0x20,0x20,0x55,0x55,0x55,0x55,0x59,0x20,0x20, -/* Ex */ 0x61,0x61,0x61,0x61,0x61,0x61,0x20,0x63,0x65,0x65,0x65,0x65,0x69,0x69,0x69,0x69, -/* Fx */ 0x64,0x6E,0x6F,0x6F,0x6F,0x6F,0x6F,0x20,0x20,0x75,0x75,0x75,0x75,0x79,0x79,0x79 -/******/ - }; - -# else - -static char const lcd_ascii[] = - { -/*****************************************************************************************/ -/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ -/* ************************************************************************************/ -/* 0x */ 0x00,0x01,0x02,0x03,0x00,0x00,0x00,0x00,0x85,0x89,0x00,0x00,0x00,0x00,0x00,0x00, -/* 1x */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -/* 2x */ 0x24,0x25,0x26,0x37,0x06,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33, -/* 3x */ 0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43, -/* 4x */ 0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53, -/* 5x */ 0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0xA9,0x33,0xCE,0x00,0x15, -/* 6x */ 0x00,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73, -/* 7x */ 0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x24,0x24,0x24,0x24,0x24, -/* 8x */ 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, -/* 9x */ 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, -/* Ax */ 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, -/* Bx */ 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, -/* Cx */ 0x45,0x45,0x45,0x45,0x45,0x45,0x24,0x47,0x49,0x49,0x49,0x49,0x4D,0x4D,0x4D,0x4D, -/* Dx */ 0x48,0x52,0x53,0x53,0x53,0x53,0x53,0x24,0x24,0x59,0x59,0x59,0x59,0x5D,0x24,0x24, -/* Ex */ 0x65,0x65,0x65,0x65,0x65,0x65,0x24,0x67,0x69,0x69,0x69,0x69,0x6D,0x6D,0x6D,0x6D, -/* Fx */ 0x73,0x72,0x73,0x73,0x73,0x73,0x73,0x24,0x24,0x79,0x79,0x79,0x79,0x7D,0x24,0x7D -/******/ - }; - -# endif - -void lcd_puts (char const *string) -{ - while (*string) - lcd_data (LCD_ASCII(*string++)); -} - -void lcd_putns (char const *string,int n) -{ - while (n--) - lcd_data (LCD_ASCII(*string++)); -} - -void lcd_putc (int character) -{ - lcd_data (LCD_ASCII(character)); -} - -void lcd_pattern (int which,char const *pattern,int count) -{ - lcd_instruction (LCD_PRAM|which); - lcd_copy ((void *)pattern,count); -} - -void lcd_puthex (unsigned int value,int digits) -{ - switch (digits) { - case 8: - lcd_puthex (value >> 16,4); - case 4: - lcd_puthex (value >> 8,2); - case 2: - lcd_puthex (value >> 4,1); - case 1: - value &= 15; - lcd_putc (value+((value < 10) ? '0' : ('A'-10))); - } -} - - -/* HAVE_LCD_CHARCELLS */ -#elif defined(HAVE_LCD_BITMAP) - -/* - * All bitmaps have this format: - * Bits within a byte are arranged veritcally, LSB at top. - * Bytes are stored in column-major format, with byte 0 at top left, - * byte 1 is 2nd from top, etc. Bytes following left-most column - * starts 2nd left column, etc. - * - * Note: The HW takes bitmap bytes in row-major order. - * - * Memory copy of display bitmap - */ -unsigned char display[DISP_X][DISP_Y/8]; - -/* - * ASCII character generation tables - * - * This contains only the printable characters (0x20-0x7f). - * Each element in this table is a character pattern bitmap. - */ -#define ASCII_MIN 0x20 /* First char in table */ -#define ASCII_MAX 0x7f /* Last char in table */ - -extern const unsigned char char_gen_6x8[][5][1]; -extern const unsigned char char_gen_8x12[][7][2]; -extern const unsigned char char_gen_12x16[][11][2]; - - -/* All zeros and ones bitmaps for area filling */ -static const unsigned char zeros[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 }; -static const unsigned char ones[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff }; - -static int lcd_y; /* Current pixel row */ -static int lcd_x; /* Current pixel column */ -static int lcd_size; /* Current font width */ - -#ifndef SIMULATOR - -/* - * Initialize LCD - */ -void lcd_init (void) -{ - /* Initialize PB0-3 as output pins */ - PBCR2 &= 0xff00; /* MD = 00 */ - PBIOR |= 0x000f; /* IOR = 1 */ - - /* Initialize LCD */ - lcd_write (TRUE, LCD_CNTL_RESET); - lcd_write (TRUE, LCD_CNTL_POWER); - lcd_write (TRUE, LCD_CNTL_SEGREMAP); - lcd_write (TRUE, LCD_CNTL_OUTSCAN); - lcd_write (TRUE, LCD_CNTL_CONTRAST); - lcd_write (TRUE, 0x30); /* Contrast parameter */ - lcd_write (TRUE, LCD_CNTL_DISPON); - - lcd_clear_display(); - lcd_update(); -} - -/* - * Update the display. - * This must be called after all other LCD funtions that change the display. - */ -void lcd_update (void) -{ - int x, y; - - /* Copy display bitmap to hardware */ - for (y = 0; y < DISP_Y/8; y++) - { - lcd_write (TRUE, LCD_CNTL_PAGE | (y & 0xf)); - lcd_write (TRUE, LCD_CNTL_HIGHCOL); - lcd_write (TRUE, LCD_CNTL_LOWCOL); - - for (x = 0; x < DISP_X; x++) - lcd_write (FALSE, display[x][y]); - } -} - -static void lcd_write (bool command, int value) -{ - int bit; - - /* Enable chip select, set DC if data */ - PBDR &= ~(PBDR_LCD_CS1|PBDR_LCD_DC); - if (!command) - PBDR |= PBDR_LCD_DC; - - /* Send each bit, starting with MSB */ - for (bit = 0x80; bit > 0; bit >>= 1) - { - PBDR &= ~(PBDR_LCD_SDA|PBDR_LCD_SCK); - if (value & bit) - PBDR |= PBDR_LCD_SDA; - PBDR |= PBDR_LCD_SCK; - } - - /* Disable chip select */ - PBDR |= PBDR_LCD_CS1; -} - -#endif /* SIMULATOR */ - -/* - * Clear the display - */ -void lcd_clear_display (void) -{ - lcd_position (0, 0, 8); - memset (display, 0, sizeof display); -} - -/* - * Set current x,y position and font size - */ -void lcd_position (int x, int y, int size) -{ - if (x >= 0 && x < DISP_X && y >= 0 && y < DISP_Y) - { - lcd_x = x; - lcd_y = y; - } - - lcd_size = size; -} - -/* - * Display a string at current position and size - */ -void lcd_string (const char *str) -{ - int x = lcd_x; - int nx = lcd_size; - int ny, ch; - const unsigned char *src; - - if (nx == 12) - ny = 16; - else if (nx == 8) - ny = 12; - else - { - nx = 6; - ny = 8; - } - - while ((ch = *str++) != '\0') - { - if (ch == '\n' || lcd_x + nx > DISP_X) - { - /* Wrap to next line */ - lcd_x = x; - lcd_y += ny; - } - - if (lcd_y + ny > DISP_Y) - return; - - /* Limit to char generation table */ - if (ch >= ASCII_MIN && ch <= ASCII_MAX) - { - if (nx == 12) - src = char_gen_12x16[ch-ASCII_MIN][0]; - else if (nx == 8) - src = char_gen_8x12[ch-ASCII_MIN][0]; - else - src = char_gen_6x8[ch-ASCII_MIN][0]; - - lcd_bitmap (src, lcd_x, lcd_y, nx-1, ny, TRUE); - lcd_bitmap (zeros, lcd_x+nx-1, lcd_y, 1, ny, TRUE); - - lcd_x += nx; - } - } -} - -/* - * Display a bitmap at (x, y), size (nx, ny) - * clear is TRUE to clear destination area first - */ -void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny, - bool clear) -{ - unsigned char *dst; - unsigned char *dst2 = &display[x][y/8]; - unsigned int data, mask, mask2, mask3, mask4; - int shift = y & 7; - - ny += shift; - - /* Calculate bit masks */ - mask4 = ~(0xfe << ((ny-1) & 7)); - if (clear) - { - mask = ~(0xff << shift); - mask2 = 0; - mask3 = ~mask4; - if (ny <= 8) - mask3 |= mask; - } - else - mask = mask2 = mask3 = 0xff; - - /* Loop for each column */ - for (x = 0; x < nx; x++) - { - dst = dst2; - dst2 += DISP_Y/8; - data = 0; - y = 0; - - if (ny > 8) - { - /* First partial row */ - data = *src++ << shift; - *dst = (*dst & mask) ^ data; - data >>= 8; - dst++; - - /* Intermediate rows */ - for (y = 8; y < ny-8; y += 8) - { - data |= *src++ << shift; - *dst = (*dst & mask2) ^ data; - data >>= 8; - dst++; - } - } - - /* Last partial row */ - if (y + shift < ny) - data |= *src++ << shift; - *dst = (*dst & mask3) ^ (data & mask4); - } -} - -/* - * Clear a rectangular area at (x, y), size (nx, ny) - */ -void lcd_clearrect (int x, int y, int nx, int ny) -{ - int i; - for (i = 0; i < nx; i++) - lcd_bitmap (zeros, x+i, y, 1, ny, TRUE); -} - -/* - * Fill a rectangular area at (x, y), size (nx, ny) - */ -void lcd_fillrect (int x, int y, int nx, int ny) -{ - int i; - for (i = 0; i < nx; i++) - lcd_bitmap (ones, x+i, y, 1, ny, TRUE); -} - -/* Invert a rectangular area at (x, y), size (nx, ny) */ -void lcd_invertrect (int x, int y, int nx, int ny) -{ - int i; - for (i = 0; i < nx; i++) - lcd_bitmap (ones, x+i, y, 1, ny, FALSE); -} - -#define DRAW_PIXEL(x,y) display[x][y/8] |= (1<<(y&7)) -#define CLEAR_PIXEL(x,y) display[x][y/8] &= ~(1<<(y&7)) - -void lcd_drawline( int x1, int y1, int x2, int y2 ) -{ - int numpixels; - int i; - int deltax, deltay; - int d, dinc1, dinc2; - int x, xinc1, xinc2; - int y, yinc1, yinc2; - - deltax = abs(x2 - x1); - deltay = abs(y2 - y1); - - if(deltax >= deltay) - { - numpixels = deltax; - d = 2 * deltay - deltax; - dinc1 = deltay * 2; - dinc2 = (deltay - deltax) * 2; - xinc1 = 1; - xinc2 = 1; - yinc1 = 0; - yinc2 = 1; - } - else - { - numpixels = deltay; - d = 2 * deltax - deltay; - dinc1 = deltax * 2; - dinc2 = (deltax - deltay) * 2; - xinc1 = 0; - xinc2 = 1; - yinc1 = 1; - yinc2 = 1; - } - numpixels++; /* include endpoints */ - - if(x1 > x2) - { - xinc1 = -xinc1; - xinc2 = -xinc2; - } - - if(y1 > y2) - { - yinc1 = -yinc1; - yinc2 = -yinc2; - } - - x = x1; - y = y1; - - for(i=0; i ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Alan Korr - * - * 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 __LCD_H__ -#define __LCD_H__ - -#include "sh7034.h" -#include "types.h" -#include "config.h" - -#define LCDR (PBDR+1) - -/* PA14 : /LCD-BL --- backlight */ -#define LCD_BL (14-8) - -#ifdef HAVE_LCD_CHARCELLS - /* JukeBox MP3 Player - AJB6K, AJBS20 */ -# define LCD_DS +1 // PB0 = 1 --- 0001 --- LCD-DS -# define LCD_CS +2 // PB1 = 1 --- 0010 --- /LCD-CS -# define LCD_SD +4 // PB2 = 1 --- 0100 --- LCD-SD -# define LCD_SC +8 // PB3 = 1 --- 1000 --- LCD-SC -# ifndef JBP_OLD -# define LCD_CONTRAST_SET ((char)0x50) -# define LCD_CRAM ((char)0x80) /* Characters */ -# define LCD_PRAM ((char)0xC0) /* Patterns */ -# define LCD_IRAM ((char)0x40) /* Icons */ -# else -# define LCD_CONTRAST_SET ((char)0xA8) -# define LCD_CRAM ((char)0xB0) /* Characters */ -# define LCD_PRAM ((char)0x80) /* Patterns */ -# define LCD_IRAM ((char)0xE0) /* Icons */ -# endif -# define LCD_ASCII(c) (lcd_ascii[(c)&255]) -# define LCD_CURSOR(x,y) ((char)(LCD_CRAM+((y)*16+(x)))) -# define LCD_ICON(i) ((char)(LCD_IRAM+i)) -# define LCD_ICON_BATTERY 0 -# define LCD_BATTERY_FRAME 0x02 -# define LCD_BATTERY_BAR1 0x08 -# define LCD_BATTERY_BAR2 0x04 -# define LCD_BATTERY_BAR3 0x10 -# define LCD_ICON_USB 2 -# define LCD_USB_LOGO 0xFF -# define LCD_ICON_PLAY 3 -# define LCD_PLAY_ICON 0xFF -# define LCD_ICON_RECORD 4 -# define LCD_RECORD_ICON 0x10 -# define LCD_ICON_STOP 5 -# define LCD_STOP_ICON 0x0F -# define LCD_ICON_AUDIO 5 -# define LCD_AUDIO_ICON 0xF0 -# define LCD_ICON_REVERSE 6 -# define LCD_REVERSE_ICON 0xFF -# define LCD_ICON_SINGLE 7 -# define LCD_SINGLE_ICON 0xFF -# define LCD_ICON_VOLUME0 9 -# define LCD_VOLUME_ICON 0x04 -# define LCD_VOLUME_BAR1 0x02 -# define LCD_VOLUME_BAR2 0x01 -# define LCD_ICON_VOLUME1 10 -# define LCD_VOLUME_BAR3 0x08 -# define LCD_VOLUME_BAR4 0x04 -# define LCD_VOLUME_BAR5 0x01 -# define LCD_ICON_PARAM 10 -# define LCD_PARAM_SYMBOL 0xF0 -#endif - -#ifdef HAVE_LCD_BITMAP -/* JukeBox MP3 Recorder - AJBR --- FIXME */ - -/* Defines from Alan on IRC, April 11th 2002 */ -#define LCD_SD +1 // PB0 = 1 --- 0001 -#define LCD_SC +2 // PB1 = 1 --- 0010 -#define LCD_RS +4 // PB2 = 1 --- 0100 -#define LCD_CS +8 // PB3 = 1 --- 1000 - -#define LCD_DS LCD_RS - -#define LCD_SET_LOWER_COLUMN_ADDRESS ((char)0x00) -#define LCD_SET_HIGHER_COLUMN_ADDRESS ((char)0x10) -#define LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO ((char)0x20) -#define LCD_SET_POWER_CONTROL_REGISTER ((char)0x28) -#define LCD_SET_DISPLAY_START_LINE ((char)0x40) -#define LCD_SET_CONTRAST_CONTROL_REGISTER ((char)0x81) -#define LCD_SET_SEGMENT_REMAP ((char)0xA0) -#define LCD_SET_LCD_BIAS ((char)0xA2) -#define LCD_SET_ENTIRE_DISPLAY_OFF ((char)0xA4) -#define LCD_SET_ENTIRE_DISPLAY_ON ((char)0xA5) -#define LCD_SET_NORMAL_DISPLAY ((char)0xA6) -#define LCD_SET_REVERSE_DISPLAY ((char)0xA7) -#define LCD_SET_INDICATOR_OFF ((char)0xAC) -#define LCD_SET_INDICATOR_ON ((char)0xAD) -#define LCD_SET_DISPLAY_OFF ((char)0xAE) -#define LCD_SET_DISPLAY_ON ((char)0xAF) -#define LCD_SET_PAGE_ADDRESS ((char)0xB0) -#define LCD_SET_COM_OUTPUT_SCAN_DIRECTION ((char)0xC0) -#define LCD_SET_DISPLAY_OFFSET ((char)0xD3) -#define LCD_SET_READ_MODIFY_WRITE_MODE ((char)0xE0) -#define LCD_SOFTWARE_RESET ((char)0xE2) -#define LCD_NOP ((char)0xE3) -#define LCD_SET_END_OF_READ_MODIFY_WRITE_MODE ((char)0xEE) - - -#define DISP_X 112 -#define DISP_Y 64 - -#define LCD_WIDTH DISP_X /* Display width in pixels */ -#define LCD_HEIGHT DISP_Y /* Display height in pixels */ - -void lcd_init (void); -void lcd_update (void); -void lcd_clear_display (void); -void lcd_position (int x, int y, int size); -void lcd_string (const char *str); -void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny, - bool clear); -void lcd_clearrect (int x, int y, int nx, int ny); -void lcd_fillrect (int x, int y, int nx, int ny); -void lcd_invertrect (int x, int y, int nx, int ny); -void lcd_drawline( int x1, int y1, int x2, int y2 ); -void lcd_drawpixel(int x, int y); -void lcd_clearpixel(int x, int y); -#endif - - -#ifndef SIMULATOR - -extern void lcd_data (int data); -extern void lcd_instruction (int instruction); -extern void lcd_zero (int length); -extern void lcd_fill (int data,int length); -extern void lcd_copy (void *data,int count); - -#ifdef HAVE_LCD_CHARCELLS - -extern void lcd_puts (char const *string); -extern void lcd_putns (char const *string,int n); -extern void lcd_putc (int character); -extern void lcd_puthex (unsigned int value,int digits); - -extern void lcd_pattern (int which,char const *pattern,int count); - -#endif /* HAVE_LCD_CHARCELLS */ - -#endif /* SIMULATOR */ - -#endif /* __LCD_H__ */ diff --git a/firmware/led.c b/firmware/led.c deleted file mode 100644 index d01c9de612..0000000000 --- a/firmware/led.c +++ /dev/null @@ -1,70 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Alan Korr - * - * 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 "config.h" - -#include - -#define turn_on() \ - set_bit (LEDB,PBDR_ADDR+1) - -#define turn_off() \ - clear_bit (LEDB,PBDR_ADDR+1) - -#define start_timer() \ - set_bit (2,TSTR_ADDR) - -#define stop_timer() \ - clear_bit (2,TSTR_ADDR) - -#define eoi(subinterrupt) \ - clear_bit (subinterrupt,TSR2_ADDR) - -#define set_volume(volume) \ - GRA2 = volume & 0x7FFF - - -void led_set_volume (unsigned short volume) -{ - volume <<= 10; - if (volume == 0) - led_turn_off (); - else if (volume == 0x8000) - led_turn_on (); - else - { - set_volume (volume); - start_timer (); - } -} - -#pragma interrupt -void IMIA2 (void) -{ - turn_off (); - eoi (0); -} - -#pragma interrupt -void OVI2 (void) -{ - turn_on (); - eoi (2); -} - diff --git a/firmware/led.h b/firmware/led.h deleted file mode 100644 index 955c59aa81..0000000000 --- a/firmware/led.h +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Alan Korr - * - * 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 __LED_H__ -#define __LED_H__ - -#include -#include - -#define LEDB 6 /* PB6 : red LED */ - -static inline void led_turn_off (void) -{ - clear_bit (LEDB,PBDR+1); - clear_bit (2,TSTR_ADDR); -} - -static inline void led_turn_on (void) -{ - set_bit (LEDB,PBDR+1); - set_bit (2,TSTR_ADDR); -} - -static inline void led_toggle (void) -{ - toggle_bit (LEDB,PBDR+1); -} - -extern void led_set_volume (unsigned short volume); -extern void led_setup (void); - -#endif - - diff --git a/firmware/mas.c b/firmware/mas.c deleted file mode 100644 index decfff612b..0000000000 --- a/firmware/mas.c +++ /dev/null @@ -1,164 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * 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 "i2c.h" -#include "debug.h" -#include "mas.h" - -/* note: 'len' is number of 32-bit words, not number of bytes! */ -int mas_readmem(int bank, int addr, unsigned long* dest, int len) -{ - int i; - unsigned char buf[16]; - - i=0; - buf[i++] = MAS_DATA_WRITE; - buf[i++] = bank?0xf0:0xe0; - buf[i++] = 0x00; - buf[i++] = (len & 0xff00) >> 8; - buf[i++] = len & 0xff; - buf[i++] = (addr & 0xff00) >> 8; - buf[i++] = addr & 0xff; - - /* send read command */ - if (i2c_write(MAS_DEV_WRITE,buf,i)) - { - return -1; - } - - return mas_devread(dest, len); -} - -/* note: 'len' is number of 32-bit words, not number of bytes! */ -int mas_writemem(int bank, int addr, unsigned long* src, int len) -{ - int i, j; - unsigned char buf[60]; - unsigned char* ptr = (unsigned char*)src; - - i=0; - buf[i++] = MAS_DATA_WRITE; - buf[i++] = bank; - buf[i++] = 0x00; - buf[i++] = (len & 0xff00) >> 8; - buf[i++] = len & 0xff; - buf[i++] = (addr & 0xff00) >> 8; - buf[i++] = addr & 0xff; - - j = 0; - while(len--) { - buf[i++] = ptr[j*4+1]; - buf[i++] = ptr[j*4+0]; - buf[i++] = 0; - buf[i++] = ptr[j*4+2]; - j += 4; - } - - /* send write command */ - if (i2c_write(MAS_DEV_WRITE,buf,i)) - { - return -1; - } - - return 0; -} - -int mas_readreg(int reg) -{ - int i; - unsigned char buf[16]; - - i=0; - buf[i++] = MAS_DATA_WRITE; - buf[i++] = 0xd0 | reg >> 4; - buf[i++] = (reg & 0x0f) << 4; - - /* send read command */ - if (i2c_write(MAS_DEV_WRITE,buf,i)) - { - return -1; - } - - if(mas_devread((unsigned long *)buf, 1)) - { - return -2; - } - - return buf[0] | buf[1] << 8 | buf[3] << 16; -} - -int mas_writereg(int reg, unsigned short val) -{ - int i; - unsigned char buf[16]; - - i=0; - buf[i++] = MAS_DATA_WRITE; - buf[i++] = 0x90 | reg >> 4; - buf[i++] = ((reg & 0x0f) << 4) | (val & 0x0f); - buf[i++] = (val >> 12) & 0xff; - buf[i++] = (val >> 4) & 0xff; - - /* send write command */ - if (i2c_write(MAS_DEV_WRITE,buf,i)) - { - return -1; - } - return 0; -} - -/* note: 'len' is number of 32-bit words, not number of bytes! */ -int mas_devread(unsigned long *dest, int len) -{ - unsigned char* ptr = (unsigned char*)dest; - int ret = 0; - int i; - - /* handle read-back */ - i2c_start(); - i2c_outb(MAS_DEV_WRITE); - if (i2c_getack()) { - i2c_outb(MAS_DATA_READ); - if (i2c_getack()) { - i2c_start(); - i2c_outb(MAS_DEV_READ); - if (i2c_getack()) { - for (i=0;len;i++) { - len--; - ptr[i*4+1] = i2c_inb(0); - ptr[i*4+0] = i2c_inb(0); - ptr[i*4+3] = i2c_inb(0); - if(len) - ptr[i*4+2] = i2c_inb(0); - else - ptr[i*4+2] = i2c_inb(1); /* NAK the last byte */ - } - } - else - ret = -3; - } - else - ret = -2; - } - else - ret = -1; - - i2c_stop(); - - return ret; -} diff --git a/firmware/mas.h b/firmware/mas.h deleted file mode 100644 index 65e23f1498..0000000000 --- a/firmware/mas.h +++ /dev/null @@ -1,54 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * 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 _MAS_H_ -#define _MAS_H_ - -#define MAS_BANK_D0 0 -#define MAS_BANK_D1 1 - -/* - MAS I2C defs -*/ -#define MAS_ADR 0x3a -#define MAS_DEV_WRITE (MAS_ADR | 0x00) -#define MAS_DEV_READ (MAS_ADR | 0x01) - -/* registers..*/ -#define MAS_DATA_WRITE 0x68 -#define MAS_DATA_READ 0x69 -#define MAS_CONTROL 0x6a - -/* - * MAS register - */ -#define MAS_REG_DCCF 0x8e -#define MAS_REG_MUTE 0xaa -#define MAS_REG_PIODATA 0xc8 -#define MAS_REG_StartUpConfig 0xe6 -#define MAS_REG_KPRESCALE 0xe7 -#define MAS_REG_KBASS 0x6b -#define MAS_REG_KTREBLE 0x6f - -int mas_readmem(int bank, int addr, unsigned long* dest, int len); -int mas_writemem(int bank, int addr, unsigned long* src, int len); -int mas_devread(unsigned long *buf, int len); -int mas_readreg(int reg); -int mas_writereg(int reg, unsigned short val); - -#endif diff --git a/firmware/serial.c b/firmware/serial.c deleted file mode 100644 index d101ab8095..0000000000 --- a/firmware/serial.c +++ /dev/null @@ -1,75 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Alan Korr - * - * 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 "serial.h" - -#define TDRE 7 /* transmit data register empty */ -#define RDRF 6 /* receive data register full */ -#define ORER 5 /* overrun error */ -#define FER 4 /* frame error */ -#define PER 3 /* parity error */ - -static int serial_byte,serial_flag; - -void serial_putc (char byte) -{ - while (!(SSR1 & (1< ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Alan Korr - * - * 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 __SERIAL_H__ -#define __SERIAL_H__ - -#include -#include - -extern void serial_putc (char); -extern void serial_puts (char const *); -extern int serial_getc (void); -extern void serial_setup (int); - -#endif -- cgit v1.2.3