diff --git a/bootloader/e200.c b/bootloader/e200.c index 91217f5c70..27b1118a1c 100644 --- a/bootloader/e200.c +++ b/bootloader/e200.c @@ -36,31 +36,59 @@ #include "power.h" #include "file.h" -void main(void) +static inline void blink(void) { volatile unsigned int* ptr; int i; + ptr = (volatile unsigned int*)0x70000020; - while(1) + *ptr &= ~(1 << 13); + for(i = 0; i < 0xfffff; i++) { - // blink wheel backlight - ptr = (volatile unsigned int*)0x70000020; - if((*ptr) & (1 << 13)) - { - *ptr = (*ptr) & ~(1 << 13); - - } - else - { - *ptr = (*ptr) | (1 << 13); - } - - // wait a while - for(i = 0; i < 0xfffff; i++) - { - } - } + *ptr |= (1 << 13); + for(i = 0; i < 0xfffff; i++) + { + } +} + +static inline void slow_blink(void) +{ + volatile unsigned int* ptr; + int i; + ptr = (volatile unsigned int*)0x70000020; + + *ptr &= ~(1 << 13); + for(i = 0; i < (0xfffff); i++) + { + } + for(i = 0; i < (0xfffff); i++) + { + } + for(i = 0; i < (0xfffff); i++) + { + } + + *ptr |= (1 << 13); + for(i = 0; i < (0xfffff); i++) + { + } + for(i = 0; i < (0xfffff); i++) + { + } + for(i = 0; i < (0xfffff); i++) + { + } +} + +static inline unsigned long get_pc(void) +{ + unsigned long pc; + asm volatile ( + "mov %0, pc\n" + : "=r"(pc) + ); + return pc; } /* These functions are present in the firmware library, but we reimplement @@ -72,7 +100,62 @@ void reset_poweroff_timer(void) int dbg_ports(void) { - return 0; + unsigned int gpio_a, gpio_b, gpio_c, gpio_d; + unsigned int gpio_e, gpio_f, gpio_g, gpio_h; + unsigned int gpio_i, gpio_j, gpio_k, gpio_l; + + char buf[128]; + int line; + + lcd_setmargins(0, 0); + lcd_clear_display(); + lcd_setfont(FONT_SYSFIXED); + + while(1) + { + gpio_a = GPIOA_INPUT_VAL; + gpio_b = GPIOB_INPUT_VAL; + gpio_c = GPIOC_INPUT_VAL; + + gpio_g = GPIOG_INPUT_VAL; + gpio_h = GPIOH_INPUT_VAL; + gpio_i = GPIOI_INPUT_VAL; + + line = 0; + snprintf(buf, sizeof(buf), "GPIO_A: %02x GPIO_G: %02x", gpio_a, gpio_g); + lcd_puts(0, line++, buf); + snprintf(buf, sizeof(buf), "GPIO_B: %02x GPIO_H: %02x", gpio_b, gpio_h); + lcd_puts(0, line++, buf); + snprintf(buf, sizeof(buf), "GPIO_C: %02x GPIO_I: %02x", gpio_c, gpio_i); + lcd_puts(0, line++, buf); + line++; + + gpio_d = GPIOD_INPUT_VAL; + gpio_e = GPIOE_INPUT_VAL; + gpio_f = GPIOF_INPUT_VAL; + + gpio_j = GPIOJ_INPUT_VAL; + gpio_k = GPIOK_INPUT_VAL; + gpio_l = GPIOL_INPUT_VAL; + + snprintf(buf, sizeof(buf), "GPIO_D: %02x GPIO_J: %02x", gpio_d, gpio_j); + lcd_puts(0, line++, buf); + snprintf(buf, sizeof(buf), "GPIO_E: %02x GPIO_K: %02x", gpio_e, gpio_k); + lcd_puts(0, line++, buf); + snprintf(buf, sizeof(buf), "GPIO_F: %02x GPIO_L: %02x", gpio_f, gpio_l); + lcd_puts(0, line++, buf); + line++; + snprintf(buf, sizeof(buf), "ADC_1: %02x", adc_read(ADC_0)); + lcd_puts(0, line++, buf); + snprintf(buf, sizeof(buf), "ADC_2: %02x", adc_read(ADC_1)); + lcd_puts(0, line++, buf); + snprintf(buf, sizeof(buf), "ADC_3: %02x", adc_read(ADC_2)); + lcd_puts(0, line++, buf); + snprintf(buf, sizeof(buf), "ADC_4: %02x", adc_read(ADC_3)); + lcd_puts(0, line++, buf); + lcd_update(); + } + return 0; } void mpeg_stop(void) @@ -95,3 +178,13 @@ void system_reboot(void) { } + +void main(void) +{ + kernel_init(); + adc_init(); + lcd_init_device(); + + dbg_ports(); +} + diff --git a/firmware/SOURCES b/firmware/SOURCES index c95b37d660..62e1fd0853 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -169,11 +169,7 @@ rolo.c thread.c timer.c #ifdef CPU_PP -#if (CONFIG_CPU == PP5024) -target/arm/crt0-pp5024.S -#else target/arm/crt0-pp.S -#endif #elif defined(CPU_ARM) target/arm/crt0.S #elif defined(CPU_COLDFIRE) @@ -236,6 +232,7 @@ drivers/m5636.c #ifdef SANSA_E200 target/arm/sandisk/sansa-e200/ata-e200.c target/arm/sandisk/sansa-e200/lcd-e200.c +target/arm/sandisk/sansa-e200/adc-e200.c #endif #ifdef IAUDIO_X5 diff --git a/firmware/boot.lds b/firmware/boot.lds index 0337b816f2..f361e45e9e 100644 --- a/firmware/boot.lds +++ b/firmware/boot.lds @@ -11,11 +11,7 @@ OUTPUT_ARCH(arm) /* the ipods can't have the crt0.o mentioned here, but the others can't do without it! */ #ifdef CPU_PP -#if (CONFIG_CPU == PP5024) -INPUT(target/arm/crt0-pp5024.o) -#else INPUT(target/arm/crt0-pp.o) -#endif #else INPUT(target/arm/crt0.o) #endif diff --git a/firmware/target/arm/crt0-pp5024.S b/firmware/target/arm/crt0-pp5024.S deleted file mode 100644 index 72edf37052..0000000000 --- a/firmware/target/arm/crt0-pp5024.S +++ /dev/null @@ -1,92 +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 "config.h" -#include "cpu.h" - -#define THUMB_MODE(_r_, _l_) \ - ldr _r_,=_l_ ## f+1 ;\ - bx _r_ ;\ - .pool ;\ - .code 16 ;\ - .thumb_func ;\ - _l_: - -// Switch to ARM mode -#define ARM_MODE(_r_, _l_) \ - ldr _r_,=_l_ ## f ;\ - bx _r_ ;\ - .pool ;\ - .code 32 ;\ - _l_: - - -.equ MODE_MASK, 0x1f -.equ T_BIT, 0x20 -.equ F_BIT, 0x40 -.equ I_BIT, 0x80 -.equ MODE_IRQ, 0x12 -.equ MODE_SVC, 0x13 -.equ MODE_SYS, 0x1f - - - - .section .init.text,"ax",%progbits - - .global start -start: - - .equ PROC_ID, 0x60000000 - .equ COP_CTRL, 0x60007004 - .equ COP_STATUS, 0x60007004 - .equ IIS_CONFIG, 0x70002800 - .equ SLEEP, 0x80000000 - .equ WAKE, 0x0 - .equ SLEEPING, 0x80000000 - - - /* Find out which processor we are */ - mov r0, #PROC_ID - ldr r0, [r0] - and r0, r0, #0xff - cmp r0, #0x55 - beq 1f - - /* put us (co-processor) to sleep */ - ldr r4, =COP_CTRL - mov r3, #SLEEP - str r3, [r4] - ldr pc, =cop_wake_start - -cop_wake_start: - /* jump the COP to startup */ - ldr r0, =startup_loc - ldr pc, [r0] - -1: - msr cpsr_c, #0xd3 - - ldr sp, =0x40017f00 /* set stack */ - - - /* execute the loader - this will load an image to 0x10000000 */ - bl main - -startup_loc: - .word 0x0 - diff --git a/firmware/target/arm/sandisk/sansa-e200/adc-e200.c b/firmware/target/arm/sandisk/sansa-e200/adc-e200.c new file mode 100644 index 0000000000..fbfa7d698a --- /dev/null +++ b/firmware/target/arm/sandisk/sansa-e200/adc-e200.c @@ -0,0 +1,92 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 by Barry Wardell + * + * 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 "cpu.h" +#include "system.h" +#include "kernel.h" +#include "thread.h" +#include "adc.h" + +static unsigned short adcdata[NUM_ADC_CHANNELS]; + +/* Scan ADC so that adcdata[channel] gets updated */ +unsigned short adc_scan(int channel) +{ + unsigned int adc_data_1; + unsigned int adc_data_2; + + /* Initialise */ + ADC_ADDR=0x130; + ADC_STATUS=0; /* 4 bytes, 1 per channel. Each byte is 0 if the channel is + off, 0x40 if the channel is on */ + + /* Enable Channel */ + ADC_ADDR |= (0x1000000<> (8*channel)) & 0xff); + adc_data_2 = ((ADC_DATA_2 >> (8*channel+6)) & 0x3); + + adcdata[channel] = (adc_data_1<<2 | adc_data_2); + + return adcdata[channel]; +} + +/* Read 10-bit channel data */ +unsigned short adc_read(int channel) +{ + return adcdata[channel]; +} + +static int adc_counter; + +static void adc_tick(void) +{ + if(++adc_counter == HZ) + { + adc_counter = 0; + adc_scan(ADC_0); + adc_scan(ADC_1); + adc_scan(ADC_2); + adc_scan(ADC_3); + } +} + +void adc_init(void) +{ + /* Enable ADC */ + ADC_ENABLE_ADDR |= ADC_ENABLE; + + /* Initialise */ + ADC_INIT=0; + + /* Force a scan of all channels to get initial values */ + adc_scan(ADC_0); + adc_scan(ADC_1); + adc_scan(ADC_2); + adc_scan(ADC_3); + + tick_add_task(adc_tick); +} diff --git a/firmware/target/arm/sandisk/sansa-e200/adc-target.h b/firmware/target/arm/sandisk/sansa-e200/adc-target.h index a7b884767c..526f99e43b 100644 --- a/firmware/target/arm/sandisk/sansa-e200/adc-target.h +++ b/firmware/target/arm/sandisk/sansa-e200/adc-target.h @@ -1,4 +1,42 @@ -/* blank */ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 by Barry Wardell + * + * 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 _ADC_TARGET_H_ +#define _ADC_TARGET_H_ -#define ADC_UNREG_POWER 0 /* made up to let powermgmt.c compile */ +#define ADC_ENABLE_ADDR (*(volatile unsigned long*)(0x70000010)) +#define ADC_ENABLE 0x1100 +#define ADC_ADDR (*(volatile unsigned long*)(0x7000ad00)) +#define ADC_STATUS (*(volatile unsigned long*)(0x7000ad04)) +#define ADC_DATA_1 (*(volatile unsigned long*)(0x7000ad20)) +#define ADC_DATA_2 (*(volatile unsigned long*)(0x7000ad24)) +#define ADC_INIT (*(volatile unsigned long*)(0x7000ad2c)) + +#define NUM_ADC_CHANNELS 4 + +#define ADC_0 0 +#define ADC_1 1 +#define ADC_2 2 +#define ADC_3 3 +#define ADC_UNREG_POWER ADC_0 /* For compatibility */ + +/* Force a scan now */ +unsigned short adc_scan(int channel); + +#endif diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c index dedb196c70..2ee191faa5 100644 --- a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c +++ b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c @@ -1,15 +1,264 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Rockbox driver for Sansa e200 LCDs + * + * Based on reverse engineering done my MrH + * + * Copyright (c) 2006 Daniel Ankers + * + * 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 "cpu.h" +#include "lcd.h" +#include "kernel.h" +#include "system.h" -void lcd_update(void) +#define LCD_DATA_IN_GPIO GPIOB_INPUT_VAL +#define LCD_DATA_IN_PIN 6 + +#define LCD_DATA_OUT_GPIO GPIOB_OUTPUT_VAL +#define LCD_DATA_OUT_PIN 7 + +#define LCD_CLOCK_GPIO GPIOB_OUTPUT_VAL +#define LCD_CLOCK_PIN 5 + +#define LCD_CS_GPIO GPIOD_OUTPUT_VAL +#define LCD_CS_PIN 6 + +#define LCD_REG_0 (*(volatile unsigned long *)(0xc2000000)) +#define LCD_REG_1 (*(volatile unsigned long *)(0xc2000004)) +#define LCD_REG_2 (*(volatile unsigned long *)(0xc2000008)) +#define LCD_REG_3 (*(volatile unsigned long *)(0xc200000c)) +#define LCD_REG_4 (*(volatile unsigned long *)(0xc2000010)) +#define LCD_REG_5 (*(volatile unsigned long *)(0xc2000014)) +#define LCD_REG_6 (*(volatile unsigned long *)(0xc2000018)) +#define LCD_REG_7 (*(volatile unsigned long *)(0xc200001c)) +#define LCD_REG_8 (*(volatile unsigned long *)(0xc2000020)) +#define LCD_REG_9 (*(volatile unsigned long *)(0xc2000024)) +#define LCD_FB_BASE_REG (*(volatile unsigned long *)(0xc2000028)) + +static inline void lcd_init_gpio(void) { - + GPIOB_ENABLE |= (1<<7); + GPIOB_ENABLE |= (1<<5); + GPIOB_OUTPUT_EN |= (1<<7); + GPIOB_OUTPUT_EN |= (1<<5); + GPIOD_ENABLE |= (1<<6); + GPIOD_OUTPUT_EN |= (1<<6); } -void lcd_update_rect(int x, int y, int width, int height) +static inline void lcd_bus_idle(void) { - + LCD_CLOCK_GPIO |= (1 << LCD_CLOCK_PIN); + LCD_DATA_OUT_GPIO |= (1 << LCD_DATA_OUT_PIN); } -void lcd_init_device(void) +static inline void lcd_send_byte(unsigned char byte) { + int i; + + for (i = 7; i >=0 ; i--) + { + LCD_CLOCK_GPIO &= ~(1 << LCD_CLOCK_PIN); + if ((byte >> i) & 1) + { + LCD_DATA_OUT_GPIO |= (1 << LCD_DATA_OUT_PIN); + } else { + LCD_DATA_OUT_GPIO &= ~(1 << LCD_DATA_OUT_PIN); + } + udelay(1); + LCD_CLOCK_GPIO |= (1 << LCD_CLOCK_PIN); + udelay(1); + lcd_bus_idle(); + udelay(3); + } +} + +static inline void lcd_send_msg(unsigned char cmd, unsigned int data) +{ + lcd_bus_idle(); + udelay(1); + LCD_CS_GPIO &= ~(1 << LCD_CS_PIN); + udelay(10); + lcd_send_byte(cmd); + lcd_send_byte((unsigned char)(data >> 8)); + lcd_send_byte((unsigned char)(data & 0xff)); + LCD_CS_GPIO |= (1 << LCD_CS_PIN); + udelay(1); + lcd_bus_idle(); +} + +static inline void lcd_write_reg(unsigned int reg, unsigned int data) +{ + lcd_send_msg(0x70, reg); + lcd_send_msg(0x72, data); +} + +inline void lcd_init_device(void) +{ +/* All this is magic worked out by MrH */ + +/* Init GPIO ports */ + lcd_init_gpio(); +/* Controller init */ + outl((inl(0x70000084) | (1 << 28)), 0x70000084); + outl((inl(0x70000080) & ~(1 << 28)), 0x70000080); + outl(((inl(0x70000010) & (0x03ffffff)) | (0x15 << 26)), 0x70000010); + outl(((inl(0x70000014) & (0x0fffffff)) | (0x5 << 28)), 0x70000014); + outl((inl(0x70000020) & ~(0x3 << 10)), 0x70000020); + outl((inl(0x6000600c) | (1 << 26)), 0x6000600c); /* Enable controller */ + outl(0x6, 0x600060d0); + outl((inl(0x60006004) | (1 << 26)), 0x60006004); /* Reset controller? */ + outl((inl(0x70000020) & ~(1 << 14)), 0x70000020); + lcd_bus_idle(); + outl((inl(0x60006004) & ~(1 << 26)), 0x60006004); /* Clear reset? */ + udelay(1000); + + LCD_REG_0 = (LCD_REG_0 & (0x00ffffff)) | (0x22 << 24); + LCD_REG_0 = (LCD_REG_0 & (0xff00ffff)) | (0x14 << 16); + LCD_REG_0 = (LCD_REG_0 & (0xffffc0ff)) | (0x3 << 8); + LCD_REG_0 = (LCD_REG_0 & (0xffffffc0)) | (0xa); + + LCD_REG_1 &= 0x00ffffff; + LCD_REG_1 &= 0xff00ffff; + LCD_REG_1 = (LCD_REG_1 & 0xffff03ff) | (0x2 << 10); + LCD_REG_1 = (LCD_REG_1 & 0xfffffc00) | (0xdd); + + LCD_REG_2 |= (1 << 5); + LCD_REG_2 |= (1 << 6); + LCD_REG_2 = (LCD_REG_2 & 0xfffffcff) | (0x2 << 8); + + LCD_REG_7 &= (0xf800ffff); + LCD_REG_7 &= (0xfffff800); + + LCD_REG_8 = (LCD_REG_8 & (0xf800ffff)) | (0xb0 << 16); + LCD_REG_8 = (LCD_REG_8 & (0xfffff800)) | (0xde); /* X-Y Geometry? */ + + LCD_REG_5 |= 0xc; + LCD_REG_5 = (LCD_REG_5 & ~(0x70)) | (0x3 << 4); + LCD_REG_5 |= 2; + + LCD_REG_6 &= ~(1 << 15); + LCD_REG_6 |= (0xe00); + LCD_REG_6 = (LCD_REG_6 & (0xffffff1f)) | (0x4 << 5); + LCD_REG_6 |= (1 << 4); + + LCD_REG_5 &= ~(1 << 7); + LCD_FB_BASE_REG = (unsigned long)lcd_framebuffer; + + udelay(100000); + +/* LCD init */ + outl((inl(0x70000080) & ~(1 << 28)), 0x70000080); + udelay(10000); + outl((inl(0x70000080) | (1 << 28)), 0x70000080); + udelay(10000); + + lcd_write_reg(16, 0x4444); + lcd_write_reg(17, 0x0001); + lcd_write_reg(18, 0x0003); + lcd_write_reg(19, 0x1119); + lcd_write_reg(18, 0x0013); + udelay(50000); + + lcd_write_reg(16, 0x4440); + lcd_write_reg(19, 0x3119); + udelay(150000); + + lcd_write_reg(1, 0x101b); + lcd_write_reg(2, 0x0700); + lcd_write_reg(3, 0x6020); + lcd_write_reg(4, 0x0000); + lcd_write_reg(5, 0x0000); + lcd_write_reg(8, 0x0102); + lcd_write_reg(9, 0x0000); + lcd_write_reg(11, 0x4400); + lcd_write_reg(12, 0x0110); + + lcd_write_reg(64, 0x0000); + lcd_write_reg(65, 0x0000); + lcd_write_reg(66, (219 << 8)); /* Screen resolution? */ + lcd_write_reg(67, 0x0000); + lcd_write_reg(68, (175 << 8)); + lcd_write_reg(69, (219 << 8)); + + lcd_write_reg(48, 0x0000); + lcd_write_reg(49, 0x0704); + lcd_write_reg(50, 0x0107); + lcd_write_reg(51, 0x0704); + lcd_write_reg(52, 0x0107); + lcd_write_reg(53, 0x0002); + lcd_write_reg(54, 0x0707); + lcd_write_reg(55, 0x0503); + lcd_write_reg(56, 0x0000); + lcd_write_reg(57, 0x0000); + + lcd_write_reg(33, 175); + + lcd_write_reg(12, 0x0110); + + lcd_write_reg(16, 0x4740); + + lcd_write_reg(7, 0x0045); + + udelay(50000); + + lcd_write_reg(7, 0x0065); + lcd_write_reg(7, 0x0067); + + udelay(50000); + + lcd_write_reg(7, 0x0077); + lcd_send_msg(0x70, 34); +} + +inline void lcd_update(void) +{ + if(!(LCD_REG_6 & 1)) + LCD_REG_6 |= 1; +} + +inline void lcd_update_rect(int x, int y, int width, int height) +{ + (void) x; + (void) y; + (void) width; + (void) height; + lcd_update(); +} + + +/*** hardware configuration ***/ + +void lcd_set_contrast(int val) +{ + /* TODO: Implement lcd_set_contrast() */ + (void)val; +} + +void lcd_set_invert_display(bool yesno) +{ + /* TODO: Implement lcd_set_invert_display() */ + (void)yesno; +} + +/* turn the display upside down (call lcd_update() afterwards) */ +void lcd_set_flip(bool yesno) +{ + /* TODO: Implement lcd_set_flip() */ + (void)yesno; }