mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-13 18:17:39 -04:00
merge a big part of the unofficial gigabeat cvs back. Includes working bootloader and rockbox with audio.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11850 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
995a804def
commit
295367686e
31 changed files with 1506 additions and 196 deletions
|
@ -36,6 +36,11 @@ OUTPUT_FORMAT(elf32-sh)
|
|||
#define DRAMORIG 0xc00000 + STUBOFFSET
|
||||
#define IRAMORIG 0x407000
|
||||
#define IRAMSIZE 0x9000
|
||||
#elif CONFIG_CPU == S3C2440
|
||||
#define DRAMORIG 0x100 + STUBOFFSET
|
||||
#define IRAMORIG DRAMORIG
|
||||
#define IRAMSIZE 4K
|
||||
#define IRAM DRAM
|
||||
#else
|
||||
#define DRAMORIG 0x09000000 + STUBOFFSET
|
||||
#endif
|
||||
|
@ -73,7 +78,7 @@ SECTIONS
|
|||
.text :
|
||||
{
|
||||
*(.text*)
|
||||
#if defined(CPU_PP) || (CONFIG_CPU==PNX0101)
|
||||
#ifdef CPU_ARM
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
#endif
|
||||
|
|
|
@ -17,12 +17,133 @@
|
|||
#include "panic.h"
|
||||
#include "power.h"
|
||||
#include "file.h"
|
||||
#include "button-target.h"
|
||||
|
||||
void map_memory(void);
|
||||
|
||||
int line = 0;
|
||||
|
||||
char version[] = APPSVERSION;
|
||||
|
||||
void go_usb_mode(void) {
|
||||
/* This section allows you to toggle bits of any memory location */
|
||||
/* Touchpad to move around the bits. Select to toggle the red bit */
|
||||
typedef struct {
|
||||
unsigned int address;
|
||||
char *desc;
|
||||
} memlocation_struct;
|
||||
|
||||
/* Just add any address and descriptions here */
|
||||
/* Must finish with 0xFFFFFFFF */
|
||||
const memlocation_struct memlocations[] = {
|
||||
/* Address Description */
|
||||
{ 0x56000000, "GPACON" },
|
||||
{ 0x56000004, "GPADAT" },
|
||||
{ 0x56000010, "GPBCON" },
|
||||
{ 0x56000014, "GPBDAT" },
|
||||
{ 0x56000020, "GPCCON" },
|
||||
{ 0x56000024, "GPCDAT" },
|
||||
{ 0x56000030, "GPDCON" },
|
||||
{ 0x56000034, "GPDDAT" },
|
||||
{ 0x56000040, "GPECON" },
|
||||
{ 0x56000044, "GPEDAT" },
|
||||
{ 0x56000050, "GPFCON" },
|
||||
{ 0x56000054, "GPFDAT" },
|
||||
{ 0x56000060, "GPGCON" },
|
||||
{ 0x56000064, "GPGDAT" },
|
||||
{ 0x56000070, "GPHCON" },
|
||||
{ 0x56000074, "GPHDAT" },
|
||||
{ 0xFFFFFFFF, 0 }
|
||||
};
|
||||
|
||||
void memdump(void)
|
||||
{
|
||||
int i, j;
|
||||
int current=0, bit=0;
|
||||
char * bitval;
|
||||
int data;
|
||||
char tmp[40];
|
||||
|
||||
while(1) {
|
||||
i = 0;
|
||||
|
||||
while(memlocations[i].address != 0xFFFFFFFF) {
|
||||
|
||||
data = *(volatile int *)memlocations[i].address;
|
||||
|
||||
snprintf(tmp, sizeof(tmp), "%s %s 0x%08X",
|
||||
(i==current) ? "*" : " ",
|
||||
memlocations[i].desc,
|
||||
data);
|
||||
lcd_puts(0, i*2+5, tmp);
|
||||
|
||||
/* print out in binary, current bit in red */
|
||||
for (j=31; j>=0; j--) {
|
||||
if ((bit == j) && (current == i))
|
||||
lcd_set_foreground(LCD_RGBPACK(255,0,0));
|
||||
lcd_puts((31-j) + ((31-j) / 8), i*2+6, (data & (1 << j)) ? "1" : "0" );
|
||||
lcd_set_foreground(LCD_RGBPACK(0,0,0));
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
data = *(volatile int *)memlocations[current].address;
|
||||
bitval = (data & (1 << bit)) ? "1" : "0";
|
||||
snprintf(tmp, sizeof(tmp), "%s bit %ld = %s", memlocations[current].desc, bit, bitval);
|
||||
lcd_puts(0, (i*2)+7, tmp);
|
||||
|
||||
lcd_update();
|
||||
|
||||
/* touchpad controls */
|
||||
|
||||
/* Up */
|
||||
if (GPJDAT & 0x01) {
|
||||
if (current > 0)
|
||||
current--;
|
||||
while(GPJDAT & 0x01);
|
||||
}
|
||||
|
||||
/* Down */
|
||||
if (GPJDAT & 0x40) {
|
||||
if (current < (i-1))
|
||||
current++;
|
||||
while(GPJDAT & 0x40);
|
||||
}
|
||||
|
||||
/* Left */
|
||||
if (GPJDAT & 0x80) {
|
||||
if (bit < 31)
|
||||
bit++;
|
||||
while(GPJDAT & 0x80);
|
||||
}
|
||||
|
||||
/* Right */
|
||||
if (GPJDAT & 0x1000) {
|
||||
if (bit > 0)
|
||||
bit--;
|
||||
while(GPJDAT & 0x1000);
|
||||
}
|
||||
|
||||
/* Centre - Toggle Bit */
|
||||
if (GPJDAT & 0x08) {
|
||||
data = *(volatile int *)memlocations[current].address;
|
||||
data = data ^ (1 << bit);
|
||||
*(volatile int *)memlocations[current].address = data;
|
||||
while(GPJDAT & 0x08);
|
||||
}
|
||||
|
||||
/* Bail out if the power button is pressed */
|
||||
if (GPGDAT & 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void go_usb_mode(void) {
|
||||
/* Drop into USB mode. This does not check for disconnection. */
|
||||
|
||||
|
||||
int i;
|
||||
|
||||
GPBDAT &= 0x7EF;
|
||||
|
@ -34,17 +155,160 @@ void go_usb_mode(void) {
|
|||
for (i = 0; i < 10000000; i++) {continue;}
|
||||
|
||||
GPBCON &= 0x2FFCFF;
|
||||
GPBDAT |= 1<<5;
|
||||
GPBDAT |= 1<<5;
|
||||
GPBDAT |= 1<<6;
|
||||
}
|
||||
|
||||
|
||||
/* Restores a factory kernel/bootloader from a known location */
|
||||
/* Restores the FWIMG01.DAT file back in the case of a bootloader failure */
|
||||
/* The factory or "good" bootloader must be in /GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG */
|
||||
/* Returns non-zero on failure */
|
||||
int restore_fwimg01dat(void)
|
||||
{
|
||||
int orig_file = 0, dest_file = 0;
|
||||
int size = 0, size_read;
|
||||
char buf[256];
|
||||
char lcd_buf[64];
|
||||
|
||||
orig_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG", O_RDONLY);
|
||||
if (orig_file < 0) {
|
||||
/* Couldn't open source file */
|
||||
lcd_puts(0, line++, "Couldn't open FWIMG01.DAT.ORIG for reading");
|
||||
lcd_update();
|
||||
return(1);
|
||||
}
|
||||
|
||||
lcd_puts(0, line++, "FWIMG01.DAT.ORIG opened for reading");
|
||||
lcd_update();
|
||||
|
||||
dest_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT", O_RDWR);
|
||||
if (dest_file < 0) {
|
||||
/* Couldn't open destination file */
|
||||
lcd_puts(0, line++, "Couldn't open FWIMG01.DAT.ORIG for writing");
|
||||
lcd_update();
|
||||
close(orig_file);
|
||||
return(2);
|
||||
}
|
||||
|
||||
lcd_puts(0, line++, "FWIMG01.DAT opened for writing");
|
||||
lcd_update();
|
||||
|
||||
do {
|
||||
/* Copy in chunks */
|
||||
size_read = read(orig_file, buf, sizeof(buf));
|
||||
if (size_read != write(dest_file, buf, size_read)) {
|
||||
close(orig_file);
|
||||
close(dest_file);
|
||||
return(3);
|
||||
}
|
||||
size += size_read;
|
||||
|
||||
} while (size_read > 0);
|
||||
|
||||
close(orig_file);
|
||||
close(dest_file);
|
||||
|
||||
snprintf(lcd_buf, sizeof(lcd_buf), "Finished copying %ld bytes from", size);
|
||||
lcd_puts(0, line++, lcd_buf);
|
||||
lcd_puts(0, line++, "FWIMG01.DAT.ORIG to FWIMG01.DAT");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int load_rockbox(const char* file_name, unsigned char* buf, int buffer_size)
|
||||
{
|
||||
int fd;
|
||||
int rc;
|
||||
int len;
|
||||
char str[256];
|
||||
//unsigned long chksum;
|
||||
//char model[5];
|
||||
//unsigned long sum;
|
||||
//int i;
|
||||
//char str[80];
|
||||
|
||||
fd = open("/.rockbox/" BOOTFILE, O_RDONLY);
|
||||
if(fd < 0)
|
||||
{
|
||||
fd = open("/" BOOTFILE, O_RDONLY);
|
||||
if(fd < 0)
|
||||
return -1;
|
||||
}
|
||||
fd = open(file_name, O_RDONLY);
|
||||
if(fd < 0)
|
||||
return -2;
|
||||
|
||||
len = filesize(fd);
|
||||
|
||||
if (len > buffer_size) {
|
||||
snprintf(str, sizeof(str), "len: %d buf: %d", len, buffer_size);
|
||||
lcd_puts(0, line++, str);
|
||||
lcd_update();
|
||||
return -6;
|
||||
}
|
||||
|
||||
/*lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
|
||||
|
||||
rc = read(fd, &chksum, 4);
|
||||
chksum=betoh32(chksum);*/ /* Rockbox checksums are big-endian */
|
||||
/*if(rc < 4)
|
||||
return -2;
|
||||
|
||||
rc = read(fd, model, 4);
|
||||
if(rc < 4)
|
||||
return -3;
|
||||
|
||||
model[4] = 0;
|
||||
|
||||
snprintf(str, 80, "Model: %s", model);
|
||||
lcd_puts(0, line++, str);
|
||||
snprintf(str, 80, "Checksum: %x", chksum);
|
||||
lcd_puts(0, line++, str);
|
||||
lcd_update();
|
||||
|
||||
lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
|
||||
*/
|
||||
|
||||
rc = read(fd, buf, len);
|
||||
if(rc < len) {
|
||||
snprintf(str, sizeof(str), "len: %d rc: %d", len, rc);
|
||||
lcd_puts(0, line++, str);
|
||||
lcd_update();
|
||||
return -4;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
/*sum = MODEL_NUMBER;
|
||||
|
||||
for(i = 0;i < len;i++) {
|
||||
sum += buf[i];
|
||||
}
|
||||
|
||||
snprintf(str, 80, "Sum: %x", sum);
|
||||
lcd_puts(0, line++, str);
|
||||
lcd_update();
|
||||
|
||||
if(sum != chksum)
|
||||
return -5;*/
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void * main(void)
|
||||
{
|
||||
int line = 0, i;
|
||||
int i;
|
||||
char buf[256];
|
||||
struct partinfo* pinfo;
|
||||
unsigned short* identify_info;
|
||||
int testfile;
|
||||
//int testfile;
|
||||
unsigned char* loadbuffer;
|
||||
int buffer_size;
|
||||
bool load_original = false;
|
||||
int rc;
|
||||
int(*kernel_entry)(void);
|
||||
|
||||
lcd_init();
|
||||
lcd_setfont(FONT_SYSFIXED);
|
||||
|
@ -57,7 +321,10 @@ void * main(void)
|
|||
*/
|
||||
|
||||
lcd_puts(0, line++, "Hold MENU when booting for rescue mode.");
|
||||
lcd_puts(0, line++, " \"VOL+\" button to restore original kernel");
|
||||
lcd_puts(0, line++, " \"A\" button to load original firmware");
|
||||
lcd_update();
|
||||
sleep(1*HZ);
|
||||
|
||||
/* hold MENU to enter rescue mode */
|
||||
if (GPGDAT & 2) {
|
||||
|
@ -67,12 +334,44 @@ void * main(void)
|
|||
while(1);
|
||||
}
|
||||
|
||||
sleep(5*HZ);
|
||||
|
||||
if(GPGDAT & 0x10) {
|
||||
load_original = true;
|
||||
lcd_puts(0, line++, "Loading original firmware...");
|
||||
lcd_update();
|
||||
}
|
||||
|
||||
i = ata_init();
|
||||
i = disk_mount_all();
|
||||
|
||||
snprintf(buf, sizeof(buf), "disk_mount_all: %d", i);
|
||||
lcd_puts(0, line++, buf);
|
||||
|
||||
/* hold VOL+ to enter rescue mode to copy old image */
|
||||
/* needs to be after ata_init and disk_mount_all */
|
||||
if (GPGDAT & 4) {
|
||||
|
||||
/* Try to restore the original kernel/bootloader if a copy is found */
|
||||
lcd_puts(0, line++, "Restoring FWIMG01.DAT...");
|
||||
lcd_update();
|
||||
|
||||
if (!restore_fwimg01dat()) {
|
||||
lcd_puts(0, line++, "Restoring FWIMG01.DAT successful.");
|
||||
} else {
|
||||
lcd_puts(0, line++, "Restoring FWIMG01.DAT failed.");
|
||||
}
|
||||
|
||||
lcd_puts(0, line++, "Now power cycle to boot original");
|
||||
lcd_update();
|
||||
while(1);
|
||||
}
|
||||
|
||||
/* Memory dump mode if Vol- pressed */
|
||||
if (GPGDAT & 8) {
|
||||
memdump();
|
||||
}
|
||||
|
||||
identify_info = ata_get_identify();
|
||||
|
||||
for (i=0; i < 20; i++)
|
||||
|
@ -96,16 +395,68 @@ void * main(void)
|
|||
lcd_puts(0, line++, buf);
|
||||
|
||||
pinfo = disk_partinfo(0);
|
||||
snprintf(buf, sizeof(buf), "Partition 0: 0x%02x %ld MB",
|
||||
snprintf(buf, sizeof(buf), "Partition 0: 0x%02x %ld MB",
|
||||
pinfo->type, pinfo->size / 2048);
|
||||
lcd_puts(0, line++, buf);
|
||||
|
||||
testfile = open("/boottest.txt", O_WRONLY|O_CREAT|O_TRUNC);
|
||||
write(testfile, "It works!", 9);
|
||||
close(testfile);
|
||||
|
||||
lcd_update();
|
||||
|
||||
/* Load original firmware */
|
||||
if(load_original) {
|
||||
loadbuffer = (unsigned char*)0x30008000;
|
||||
buffer_size =(unsigned char*)0x31000000 - loadbuffer;
|
||||
rc = load_rockbox("/rockbox.gigabeat", loadbuffer, buffer_size);
|
||||
if (rc < 0) {
|
||||
lcd_puts(0, line++, "failed to load original firmware. Loading rockbox");
|
||||
lcd_update();
|
||||
sleep(2*HZ);
|
||||
goto load_rockbox;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "Loaded: %d", rc);
|
||||
lcd_puts(0, line++, buf);
|
||||
lcd_update();
|
||||
sleep(2*HZ);
|
||||
|
||||
|
||||
(*((int*)0x7000000)) = 333;
|
||||
rc = *((int*)0x7000000+0x8000000);
|
||||
snprintf(buf, sizeof(buf), "Bank0 mem test: %d", rc);
|
||||
lcd_puts(0, line++, buf);
|
||||
lcd_update();
|
||||
sleep(3*HZ);
|
||||
|
||||
lcd_puts(0, line++, "Woops, should not return from firmware!");
|
||||
lcd_update();
|
||||
goto usb;
|
||||
}
|
||||
|
||||
load_rockbox:
|
||||
map_memory();
|
||||
lcd_puts(0, line, "Loading Rockbox...");
|
||||
lcd_update();
|
||||
sleep(HZ*4);
|
||||
|
||||
// TODO: read those values from somwhere
|
||||
loadbuffer = (unsigned char*) 0x100;
|
||||
buffer_size = (unsigned char*)0x400000 - loadbuffer;
|
||||
rc=load_rockbox("/rockbox.gigabeat", loadbuffer, buffer_size);
|
||||
if (rc < 0) {
|
||||
snprintf(buf, sizeof(buf), "Rockbox error: %d",rc);
|
||||
lcd_puts(0, line++, buf);
|
||||
lcd_update();
|
||||
} else {
|
||||
lcd_puts(0, line++, "Rockbox loaded.");
|
||||
lcd_update();
|
||||
kernel_entry = (void*)0x100;
|
||||
rc = kernel_entry();
|
||||
snprintf(buf, sizeof(buf), "Woops, should not return from firmware: %d", rc);
|
||||
lcd_puts(0, line++, buf);
|
||||
lcd_update();
|
||||
goto usb;
|
||||
}
|
||||
|
||||
|
||||
usb:
|
||||
/* now wait in USB mode so the bootloader can be updated */
|
||||
go_usb_mode();
|
||||
while(1);
|
||||
|
|
|
@ -136,6 +136,8 @@ drivers/rtc/rtc_pcf50606.c
|
|||
drivers/rtc/rtc_pcf50605.c
|
||||
#elif (CONFIG_RTC == RTC_E8564)
|
||||
drivers/rtc/rtc_e8564.c
|
||||
#elif (CONFIG_RTC == RTC_S3C2440)
|
||||
drivers/rtc/rtc_s3c2440.c
|
||||
#endif /* (CONFIG_RTC == RTC_) */
|
||||
#endif /* SIMULATOR */
|
||||
|
||||
|
@ -447,6 +449,12 @@ target/arm/gigabeat/meg-fx/power-meg-fx.c
|
|||
target/arm/gigabeat/meg-fx/sc606-meg-fx.c
|
||||
target/arm/gigabeat/meg-fx/usb-meg-fx.c
|
||||
target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c
|
||||
target/arm/gigabeat/meg-fx/dma_start.c
|
||||
target/arm/gigabeat/meg-fx/system-meg-fx.c
|
||||
target/arm/gigabeat/meg-fx/mmu-meg-fx.c
|
||||
#ifndef BOOTLOADER
|
||||
target/arm/gigabeat/meg-fx/pcm-meg-fx.c
|
||||
#endif
|
||||
#endif /* SIMULATOR */
|
||||
#endif /* GIGABEAT_F */
|
||||
|
||||
|
|
|
@ -45,9 +45,10 @@ INPUT(target/sh/crt0.o)
|
|||
#define IRAMORIG 0x400000
|
||||
#define IRAMSIZE 0x7000
|
||||
#elif CONFIG_CPU==S3C2440
|
||||
#define DRAMORIG 0x30000000 + STUBOFFSET
|
||||
#define IRAMORIG 0x40000000
|
||||
#define DRAMORIG 0x100 + STUBOFFSET
|
||||
#define IRAMORIG DRAMORIG
|
||||
#define IRAMSIZE 4K
|
||||
#define IRAM DRAM
|
||||
#else
|
||||
#define DRAMORIG 0x09000000 + STUBOFFSET
|
||||
#define IRAMORIG 0x0f000000
|
||||
|
@ -63,7 +64,9 @@ INPUT(target/sh/crt0.o)
|
|||
MEMORY
|
||||
{
|
||||
DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
|
||||
#if CONFIG_CPU != S3C2440
|
||||
IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
|
||||
#endif
|
||||
#if CONFIG_CPU==PNX0101
|
||||
IRAM0 : ORIGIN = 0x0, LENGTH = IRAMSIZE
|
||||
#endif
|
||||
|
@ -146,6 +149,8 @@ SECTIONS
|
|||
|
||||
#if CONFIG_CPU==PNX0101
|
||||
.iram IRAMORIG + SIZEOF(.vectors) :
|
||||
#elif CONFIG_CPU==S3C2440
|
||||
.iram :
|
||||
#else
|
||||
.iram IRAMORIG :
|
||||
#endif
|
||||
|
@ -200,7 +205,7 @@ SECTIONS
|
|||
|
||||
#if defined(CPU_COLDFIRE)
|
||||
.bss ADDR(.data) + SIZEOF(.data) + SIZEOF(.iram):
|
||||
#elif defined(CPU_ARM)
|
||||
#elif defined(CPU_ARM) && CONFIG_CPU != S3C2440
|
||||
.bss ADDR(.data) + SIZEOF(.data) + SIZEOF(.iram) + SIZEOF(.vectors):
|
||||
#else
|
||||
.bss :
|
||||
|
|
|
@ -119,7 +119,7 @@ SECTIONS
|
|||
}
|
||||
#elif (CONFIG_CPU==S3C2440)
|
||||
{
|
||||
. = DRAMORIG + 0x8000;
|
||||
. = DRAMORIG + 0x1000000;
|
||||
.text : {
|
||||
*(.init.text)
|
||||
*(.text)
|
||||
|
|
|
@ -14,6 +14,12 @@
|
|||
/* define this if you have a colour LCD */
|
||||
#define HAVE_LCD_COLOR 1
|
||||
|
||||
/* define this if you have access to the quickscreen */
|
||||
#define HAVE_QUICKSCREEN
|
||||
|
||||
/* define this if you have access to the pitchscreen */
|
||||
#define HAVE_PITCHSCREEN
|
||||
|
||||
/* define this if you would like tagcache to build on this target */
|
||||
#define HAVE_TAGCACHE
|
||||
|
||||
|
@ -30,14 +36,24 @@
|
|||
#define CONFIG_CODEC SWCODEC
|
||||
|
||||
/* define this if you have a real-time clock */
|
||||
|
||||
#if 0 /* TODO */
|
||||
#define CONFIG_RTC RTC_S3C2440
|
||||
#endif
|
||||
|
||||
/* define this if the unit can be powered or charged via USB */
|
||||
#define HAVE_USB_POWER
|
||||
|
||||
/* Define this for LCD backlight available */
|
||||
#define CONFIG_BACKLIGHT BL_GIGABEAT /* port controlled PWM */
|
||||
|
||||
#define HAVE_BACKLIGHT_BRIGHTNESS
|
||||
|
||||
/* Main LCD backlight brightness range and defaults */
|
||||
#define MIN_BRIGHTNESS_SETTING 0 /* 0.5 mA */
|
||||
#define MIN_ACTIVE_BRIGHTNESS_SETTING 16 /* lowest active brightness */
|
||||
#define MAX_DIM_BRIGHTNESS_SETTING 15 /* highest 'dimness' */
|
||||
#define MAX_BRIGHTNESS_SETTING 63 /* 32 mA */
|
||||
#define DEFAULT_BRIGHTNESS_SETTING 39 /* 20 mA */
|
||||
#define DEFAULT_DIMNESS_SETTING 9 /* 5 mA */
|
||||
|
||||
/* Define this if you have a software controlled poweroff */
|
||||
#define HAVE_SW_POWEROFF
|
||||
|
||||
|
@ -54,23 +70,27 @@
|
|||
|
||||
#ifndef SIMULATOR
|
||||
|
||||
/* The LCD on a Gigabeat is 240x320 - it is portrait */
|
||||
#define HAVE_PORTRAIT_LCD
|
||||
|
||||
/* Define this if you have a Motorola SCF5249 */
|
||||
#define CONFIG_CPU S3C2440
|
||||
|
||||
/* Define this if you want to use coldfire's i2c interface */
|
||||
#define CONFIG_I2C I2C_S3C2440
|
||||
|
||||
/* Type of mobile power */
|
||||
#define CONFIG_BATTERY BATT_LIPOL1300
|
||||
#define BATTERY_CAPACITY_MIN 1300 /* min. capacity selectable */
|
||||
#define BATTERY_CAPACITY_MAX 3200 /* max. capacity selectable */
|
||||
#define BATTERY_CAPACITY_INC 50 /* capacity increment */
|
||||
#define BATTERY_TYPES_COUNT 1 /* only one type */
|
||||
/* Type of mobile power - check this out */
|
||||
#define CONFIG_BATTERY BATT_LIION830 /* could change this later */
|
||||
#define BATTERY_CAPACITY_MIN 750 /* min. capacity selectable */
|
||||
#define BATTERY_CAPACITY_MAX 850 /* max. capacity selectable */
|
||||
#define BATTERY_CAPACITY_INC 25 /* capacity increment */
|
||||
#define BATTERY_TYPES_COUNT 1 /* only one type */
|
||||
|
||||
#define BATTERY_SCALE_FACTOR 6852 /* FIX: this value is picked at random */
|
||||
/* ADC[0] is (530) at discharge and 625 at full charge */
|
||||
#define BATTERY_SCALE_FACTOR 6450
|
||||
|
||||
/* Hardware controlled charging? FIXME */
|
||||
#define CONFIG_CHARGING CHARGING_SIMPLE
|
||||
/* Hardware controlled charging with monitoring */
|
||||
#define CONFIG_CHARGING CHARGING_MONITOR
|
||||
|
||||
/* define this if the hardware can be powered off while charging */
|
||||
#define HAVE_POWEROFF_WHILE_CHARGING
|
||||
|
@ -82,9 +102,7 @@
|
|||
#define CPU_FREQ 16934400
|
||||
|
||||
/* Define this if you have ATA power-off control */
|
||||
#if 0 /* TODO */
|
||||
#define HAVE_ATA_POWER_OFF
|
||||
#endif
|
||||
|
||||
/* Virtual LED (icon) */
|
||||
#define CONFIG_LED LED_VIRTUAL
|
||||
|
@ -99,6 +117,7 @@
|
|||
|
||||
#define USB_GIGABEAT_STYLE
|
||||
|
||||
#define HAVE_HEADPHONE_DETECTION
|
||||
/* Define this if you have adjustable CPU frequency */
|
||||
#if 0 /* TODO */
|
||||
#define HAVE_ADJUSTABLE_CPU_FREQ
|
||||
|
@ -107,8 +126,5 @@
|
|||
#define BOOTFILE_EXT "gigabeat"
|
||||
#define BOOTFILE "rockbox." BOOTFILE_EXT
|
||||
|
||||
#if 0 /* TODO */
|
||||
#define HAVE_BACKLIGHT_BRIGHTNESS
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
#define BATT_LIPOL1300 1300 /* the type used in iRiver h1x0 models */
|
||||
#define BATT_LPCS355385 1550 /* iriver h10 20Gb - SKC LPCS355385 */
|
||||
#define BATT_BP009 820 /* iriver H10 5/6Gb - iriver BP009 */
|
||||
#define BATT_LIION830 830 /* Toshiba Gigabeat Fxx and Xxx series MK11-2740 */
|
||||
|
||||
/* CONFIG_CHARGING */
|
||||
#define CHARGING_SIMPLE 1 /* Simple, hardware controlled charging */
|
||||
|
|
|
@ -56,7 +56,7 @@ void kernel_init(void)
|
|||
void sleep(int ticks)
|
||||
{
|
||||
#if CONFIG_CPU == S3C2440 && defined(BOOTLOADER)
|
||||
int counter;
|
||||
volatile int counter;
|
||||
TCON &= ~(1 << 20); // stop timer 4
|
||||
// TODO: this constant depends on dividers settings inherited from
|
||||
// firmware. Set them explicitly somwhere.
|
||||
|
@ -76,7 +76,7 @@ void sleep(int ticks)
|
|||
|
||||
void yield(void)
|
||||
{
|
||||
#if (CONFIG_CPU == S3C2440 || defined(ELIO_TPJ1022) && defined(BOOTLOADER))
|
||||
#if ((CONFIG_CPU == S3C2440 || defined(ELIO_TPJ1022)) && defined(BOOTLOADER))
|
||||
/* Some targets don't like yielding in the bootloader */
|
||||
#else
|
||||
switch_thread(true, NULL);
|
||||
|
@ -560,27 +560,34 @@ void tick_start(unsigned int interval_in_ms)
|
|||
#elif CONFIG_CPU == S3C2440
|
||||
void tick_start(unsigned int interval_in_ms)
|
||||
{
|
||||
unsigned long count;
|
||||
TCON &= ~(1 << 20); // stop timer 4
|
||||
// TODO: this constant depends on dividers settings inherited from
|
||||
// firmware. Set them explicitly somwhere.
|
||||
TCNTB4 = 12193 * interval_in_ms / 1000;
|
||||
TCON |= 1 << 21; // set manual bit
|
||||
TCON &= ~(1 << 21); // reset manual bit
|
||||
TCON |= 1 << 22; //interval mode
|
||||
TCON |= (1 << 20); // start timer 4
|
||||
|
||||
/* period = (n + 1) / 128 , n = tick time count (1~127)*/
|
||||
count = interval_in_ms / 1000 * 128 - 1;
|
||||
INTMOD &= ~(1 << 14); // timer 4 to IRQ mode
|
||||
INTMSK &= ~(1 << 14); // timer 4 unmask interrupts
|
||||
}
|
||||
|
||||
if(count > 127)
|
||||
void timer4(void) {
|
||||
int i;
|
||||
/* Run through the list of tick tasks */
|
||||
for(i = 0; i < MAX_NUM_TICK_TASKS; i++)
|
||||
{
|
||||
panicf("Error! The tick interval is too long (%d ms)\n",
|
||||
interval_in_ms);
|
||||
return;
|
||||
if(tick_funcs[i])
|
||||
{
|
||||
tick_funcs[i]();
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the tick */
|
||||
TICNT &= ~(1<<7);
|
||||
/* Set the count value */
|
||||
TICNT |= count;
|
||||
/* Start up the ticker */
|
||||
TICNT |= (1<<7);
|
||||
current_tick++;
|
||||
|
||||
/* need interrupt handler ??? */
|
||||
|
||||
/* following needs to be fixed. */
|
||||
/*wake_up_thread();*/
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -59,46 +59,9 @@ void pcm_play_pause_unpause(void);
|
|||
|
||||
/** Functions that require targeted implementation **/
|
||||
|
||||
#ifndef CPU_COLDFIRE
|
||||
#if !defined(CPU_COLDFIRE) && (CONFIG_CPU != S3C2440)
|
||||
|
||||
#if (CONFIG_CPU == S3C2440)
|
||||
|
||||
/* TODO: Implement for Gigabeat
|
||||
For now, just implement some dummy functions.
|
||||
*/
|
||||
void pcm_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
(void)addr;
|
||||
(void)size;
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
{
|
||||
}
|
||||
|
||||
void pcm_play_pause_pause(void)
|
||||
{
|
||||
}
|
||||
|
||||
void pcm_play_pause_unpause(void)
|
||||
{
|
||||
}
|
||||
|
||||
void pcm_set_frequency(unsigned int frequency)
|
||||
{
|
||||
(void)frequency;
|
||||
}
|
||||
|
||||
size_t pcm_get_bytes_waiting(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif (CONFIG_CPU == PNX0101)
|
||||
#if (CONFIG_CPU == PNX0101)
|
||||
|
||||
#define DMA_BUF_SAMPLES 0x100
|
||||
|
||||
|
|
|
@ -191,6 +191,8 @@ static const unsigned int battery_level_dangerous[BATTERY_TYPES_COUNT] =
|
|||
105, 115
|
||||
#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver H1x0: LiPolymer */
|
||||
338
|
||||
#elif CONFIG_BATTERY == BATT_LIION830 /* Gigabeat F */
|
||||
340
|
||||
#elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */
|
||||
354
|
||||
#elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB: LiPolymer*/
|
||||
|
@ -210,6 +212,8 @@ static const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
|
|||
270, 280
|
||||
#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver Hxxx */
|
||||
299
|
||||
#elif CONFIG_BATTERY == BATT_LIION830 /* Gigabeat F */
|
||||
338
|
||||
#elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */
|
||||
350
|
||||
#elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB */
|
||||
|
@ -252,6 +256,9 @@ static const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
|
|||
/* May need recalibration. */
|
||||
{ 93, 108, 114, 118, 121, 125, 128, 132, 136, 142, 158 }, /* alkaline */
|
||||
{ 103, 118, 121, 123, 124, 125, 126, 127, 128, 129, 135 } /* NiMH */
|
||||
#elif CONFIG_BATTERY == BATT_LIION830
|
||||
/* Toshiba Gigabeat Li Ion 830mAH figured from discharge curve */
|
||||
{ 342, 358, 361, 368, 371, 374, 377, 381, 387, 390, 397 }
|
||||
#else /* NiMH */
|
||||
/* original values were taken directly after charging, but it should show
|
||||
100% after turning off the device for some hours, too */
|
||||
|
@ -263,12 +270,16 @@ static const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
|
|||
#ifdef CONFIG_CHARGING
|
||||
charger_input_state_type charger_input_state IDATA_ATTR;
|
||||
|
||||
|
||||
/* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */
|
||||
static const unsigned short percent_to_volt_charge[11] =
|
||||
{
|
||||
#if CONFIG_BATTERY == BATT_LIPOL1300
|
||||
/* values measured over one full charging cycle */
|
||||
354, 386, 393, 398, 400, 402, 404, 408, 413, 418, 423 /* LiPo */
|
||||
#elif CONFIG_BATTERY == BATT_LIION830
|
||||
/* Toshiba Gigabeat Li Ion 830mAH */
|
||||
347, 363, 366, 373, 376, 379, 382, 386, 393, 403, 411
|
||||
#elif CONFIG_BATTERY == BATT_LPCS355385
|
||||
/* iriver H10 20GB */
|
||||
399, 403, 406, 408, 410, 412, 415, 418, 422, 426, 431
|
||||
|
|
|
@ -86,7 +86,15 @@ void cpu_idle_mode(bool on_off)
|
|||
void system_reboot(void) {
|
||||
}
|
||||
|
||||
void system_init(void) {
|
||||
void system_init(void)
|
||||
{
|
||||
/* Turn off un-needed devices */
|
||||
|
||||
/* Turn off all of the UARTS */
|
||||
CLKCON &= ~( (1<<10) | (1<<11) |(1<<12) );
|
||||
|
||||
/* Turn off AC97 and Camera */
|
||||
CLKCON &= ~( (1<<19) | (1<<20) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -122,7 +122,26 @@ start:
|
|||
/* Code for ARM bootloader targets other than iPod go here */
|
||||
|
||||
#if CONFIG_CPU == S3C2440
|
||||
bl main
|
||||
/* get the high part of our execute address */
|
||||
ldr r2, =0xffffff00
|
||||
and r4, pc, r2
|
||||
|
||||
/* Copy bootloader to safe area - 0x31000000 */
|
||||
mov r5, #0x30000000
|
||||
add r5, r5, #0x1000000
|
||||
ldr r6, = _dataend
|
||||
sub r0, r6, r5 /* length of loader */
|
||||
add r0, r4, r0 /* r0 points to start of loader */
|
||||
1:
|
||||
cmp r5, r6
|
||||
ldrcc r2, [r4], #4
|
||||
strcc r2, [r5], #4
|
||||
bcc 1b
|
||||
|
||||
ldr pc, =start_loc /* jump to the relocated start_loc: */
|
||||
|
||||
start_loc:
|
||||
bl main
|
||||
#endif
|
||||
|
||||
#else /* BOOTLOADER */
|
||||
|
@ -201,7 +220,10 @@ prefetch_abort_handler:
|
|||
fiq_handler:
|
||||
@ Branch straight to FIQ handler in pcm_playback.c. This also handles the
|
||||
@ the correct return sequence.
|
||||
ldr pc, =fiq
|
||||
stmfd sp!, {r0-r7, r12, lr}
|
||||
bl fiq
|
||||
ldmfd sp!, {r0-r7, r12, lr}
|
||||
subs pc, lr, #4
|
||||
|
||||
data_abort_handler:
|
||||
sub r0, lr, #8
|
||||
|
@ -210,9 +232,9 @@ data_abort_handler:
|
|||
|
||||
irq_handler:
|
||||
#ifndef STUB
|
||||
stmfd sp!, {r0-r3, r12, lr}
|
||||
stmfd sp!, {r0-r11, r12, lr}
|
||||
bl irq
|
||||
ldmfd sp!, {r0-r3, r12, lr}
|
||||
ldmfd sp!, {r0-r11, r12, lr}
|
||||
#endif
|
||||
subs pc, lr, #4
|
||||
|
||||
|
|
|
@ -18,24 +18,67 @@
|
|||
****************************************************************************/
|
||||
#include "cpu.h"
|
||||
#include "adc-target.h"
|
||||
#include "kernel.h"
|
||||
|
||||
|
||||
void adc_init(void) {
|
||||
/* Turn on the ADC PCLK */
|
||||
CLKCON |= (1<<15);
|
||||
|
||||
/* Set channel 0, normal mode, disable "start by read" */
|
||||
ADCCON &= ~(0x3F);
|
||||
static unsigned short adc_readings[NUM_ADC_CHANNELS];
|
||||
|
||||
/* No start delay. Use nromal conversion mode. */
|
||||
ADCDLY |= 0x1;
|
||||
/* prototypes */
|
||||
static unsigned short __adc_read(int channel);
|
||||
static void adc_tick(void);
|
||||
|
||||
/* Set and enable the prescaler */
|
||||
ADCCON = (ADCCON & ~(0xff<<6)) | (0x19<<6);
|
||||
ADCCON |= (1<<14);
|
||||
|
||||
|
||||
void adc_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Turn on the ADC PCLK */
|
||||
CLKCON |= (1<<15);
|
||||
|
||||
/* Set channel 0, normal mode, disable "start by read" */
|
||||
ADCCON &= ~(0x3F);
|
||||
|
||||
/* No start delay. Use normal conversion mode. */
|
||||
ADCDLY = 0x1;
|
||||
|
||||
/* Set and enable the prescaler */
|
||||
ADCCON = (ADCCON & ~(0xff<<6)) | (0x19<<6);
|
||||
ADCCON |= (1<<14);
|
||||
|
||||
/* prefill the adc channels */
|
||||
for (i = 0; i < NUM_ADC_CHANNELS; i++)
|
||||
{
|
||||
adc_readings[i] = __adc_read(i);
|
||||
}
|
||||
|
||||
/* start at zero so when the tick starts it is at zero */
|
||||
adc_readings[0] = __adc_read(0);
|
||||
|
||||
/* attach the adc reading to the tick */
|
||||
tick_add_task(adc_tick);
|
||||
|
||||
|
||||
}
|
||||
|
||||
unsigned short adc_read(int channel) {
|
||||
|
||||
|
||||
/* Called to get the recent ADC reading */
|
||||
inline unsigned short adc_read(int channel)
|
||||
{
|
||||
return adc_readings[channel];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Read the ADC by polling
|
||||
* @param channel The ADC channel to read
|
||||
* @return 10bit reading from ADC channel or ADC_READ_ERROR if timeout
|
||||
*/
|
||||
static unsigned short __adc_read(int channel)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Set the channel */
|
||||
|
@ -45,34 +88,57 @@ unsigned short adc_read(int channel) {
|
|||
ADCCON |= 0x1;
|
||||
|
||||
/* Wait for a low Enable_start */
|
||||
i = 20000;
|
||||
while(i > 0) {
|
||||
if(ADCCON & 0x1) {
|
||||
i--;
|
||||
}
|
||||
else {
|
||||
for (i = 20000;;) {
|
||||
if(0 == (ADCCON & 0x1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == 0) {
|
||||
/* Ran out of time */
|
||||
return(0);
|
||||
else {
|
||||
i--;
|
||||
if (0 == i) {
|
||||
/* Ran out of time */
|
||||
return ADC_READ_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for high End_of_Conversion */
|
||||
i = 20000;
|
||||
while(i > 0) {
|
||||
if(ADCCON & (1<<15)) {
|
||||
for(i = 20000;;) {
|
||||
if(ADCCON & (1<<15)) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
i--;
|
||||
if(0 == i) {
|
||||
/* Ran out of time */
|
||||
return ADC_READ_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(i == 0) {
|
||||
/* Ran out of time */
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(ADCDAT0 & 0x3ff);
|
||||
return (ADCDAT0 & 0x3ff);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* add this to the tick so that the ADC converts are done in the background */
|
||||
static void adc_tick(void)
|
||||
{
|
||||
static unsigned channel;
|
||||
|
||||
/* Check if the End Of Conversion is set */
|
||||
if (ADCCON & (1<<15))
|
||||
{
|
||||
adc_readings[channel] = (ADCDAT0 & 0x3FF);
|
||||
if (++channel >= NUM_ADC_CHANNELS)
|
||||
{
|
||||
channel = 0;
|
||||
}
|
||||
|
||||
/* setup the next conversion and start it*/
|
||||
ADCCON = (ADCCON & ~(0x7<<3)) | (channel<<3) | 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -19,12 +19,19 @@
|
|||
#ifndef _ADC_TARGET_H_
|
||||
#define _ADC_TARGET_H_
|
||||
|
||||
#define NUM_ADC_CHANNELS 4
|
||||
/* only two channels used by the Gigabeat */
|
||||
#define NUM_ADC_CHANNELS 2
|
||||
|
||||
#define ADC_BATTERY 0
|
||||
#define ADC_UNKNOWN_2 1
|
||||
#define ADC_HPREMOTE 1
|
||||
#define ADC_UNKNOWN_3 2
|
||||
#define ADC_UNKNOWN_4 3
|
||||
#define ADC_UNKNOWN_5 4
|
||||
#define ADC_UNKNOWN_6 5
|
||||
#define ADC_UNKNOWN_7 6
|
||||
#define ADC_UNKNOWN_8 7
|
||||
|
||||
#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */
|
||||
#define ADC_READ_ERROR 0xFFFF
|
||||
|
||||
#endif
|
||||
|
|
|
@ -26,11 +26,18 @@
|
|||
|
||||
void ata_reset(void)
|
||||
{
|
||||
GPGDAT &= ~(1 << 10);
|
||||
sleep(1); /* > 25us */
|
||||
GPGDAT |= (1 << 10);
|
||||
sleep(1); /* > 2ms */
|
||||
}
|
||||
|
||||
void ata_enable(bool on)
|
||||
{
|
||||
(void)on;
|
||||
if(on)
|
||||
GPGDAT &= ~(1 << 12);
|
||||
else
|
||||
GPGDAT |= (1 << 12);
|
||||
}
|
||||
|
||||
bool ata_is_coldstart(void)
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#define ATA_TARGET_H
|
||||
|
||||
/* Plain C read & write loops */
|
||||
#define PREFER_C_READING
|
||||
#define PREFER_C_WRITING
|
||||
|
||||
#define ATA_IOBASE 0x18000000
|
||||
#define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE)))
|
||||
|
|
|
@ -19,11 +19,16 @@
|
|||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include "system.h"
|
||||
#include "backlight-target.h"
|
||||
#include "backlight.h"
|
||||
#include "lcd.h"
|
||||
#include "sc606-meg-fx.h"
|
||||
|
||||
int confval = SC606_LOW_FREQ;
|
||||
static int confval = SC606_LOW_FREQ;
|
||||
|
||||
void __backlight_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __backlight_on(void)
|
||||
{
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#ifndef BACKLIGHT_TARGET_H
|
||||
#define BACKLIGHT_TARGET_H
|
||||
|
||||
void __backlight_init(void);
|
||||
void __backlight_on(void);
|
||||
void __backlight_off(void);
|
||||
void __backlight_set_brightness(int val);
|
||||
|
|
|
@ -27,58 +27,127 @@
|
|||
#include "adc.h"
|
||||
#include "system.h"
|
||||
|
||||
static bool headphones_detect;
|
||||
|
||||
static int const remote_buttons[] =
|
||||
{
|
||||
BUTTON_NONE, /* Headphones connected - remote disconnected */
|
||||
BUTTON_SELECT,
|
||||
BUTTON_MENU, /* could be changed to BUTTON_A */
|
||||
BUTTON_LEFT,
|
||||
BUTTON_RIGHT,
|
||||
BUTTON_UP, /* could be changed to BUTTON_VOL_UP */
|
||||
BUTTON_DOWN, /* could be changed to BUTTON_VOL_DOWN */
|
||||
BUTTON_NONE, /* Remote control attached - no buttons pressed */
|
||||
BUTTON_NONE, /* Nothing in the headphone socket */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void button_init_device(void)
|
||||
{
|
||||
/* Power, Remote Play & Hold switch */
|
||||
}
|
||||
|
||||
bool button_hold(void)
|
||||
|
||||
|
||||
inline bool button_hold(void)
|
||||
{
|
||||
return (GPGDAT & (1 << 15));
|
||||
}
|
||||
|
||||
|
||||
|
||||
int button_read_device(void)
|
||||
{
|
||||
int btn = BUTTON_NONE;
|
||||
int touchpad = GPJDAT;
|
||||
int buttons = GPGDAT;
|
||||
int btn;
|
||||
int touchpad;
|
||||
int buttons;
|
||||
static int lastbutton;
|
||||
unsigned short remote_adc;
|
||||
|
||||
/* Check for hold first */
|
||||
if (buttons & (1 << 15))
|
||||
return btn;
|
||||
/* Check for hold first - exit if asserted with no button pressed */
|
||||
if (button_hold())
|
||||
return BUTTON_NONE;
|
||||
|
||||
/* the side buttons */
|
||||
if (buttons & (1 << 0))
|
||||
btn |= BUTTON_POWER;
|
||||
/* See header for ADC values when remote control buttons are pressed */
|
||||
/* Only one button can be sensed at a time on the remote. */
|
||||
/* Need to filter the remote button because the ADC is so fast */
|
||||
remote_adc = adc_read(ADC_HPREMOTE);
|
||||
btn = remote_buttons[(remote_adc + 64) / 128];
|
||||
if (btn != lastbutton)
|
||||
{
|
||||
/* if the buttons dont agree twice in a row, then its none */
|
||||
lastbutton = btn;
|
||||
btn = BUTTON_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Code can be added that overrides the side buttons when the remote is
|
||||
* plugged in: Check for remote_adc > 64 && remote_adc < 930 then skip
|
||||
* reading the side and touch volume buttons, right, left, up, down, etc.
|
||||
* but keep reading the Power and 'A'.
|
||||
* For now, the buttons from remote and side and touch are used together.
|
||||
*/
|
||||
|
||||
if (buttons & (1 << 1))
|
||||
btn |= BUTTON_MENU;
|
||||
|
||||
/* the side buttons - Check before doing all of the work on each bit */
|
||||
buttons = GPGDAT & 0x1F;
|
||||
if (buttons)
|
||||
{
|
||||
if (buttons & (1 << 0))
|
||||
btn |= BUTTON_POWER;
|
||||
|
||||
if (buttons & (1 << 2))
|
||||
btn |= BUTTON_VOL_UP;
|
||||
if (buttons & (1 << 1))
|
||||
btn |= BUTTON_MENU;
|
||||
|
||||
if (buttons & (1 << 3))
|
||||
btn |= BUTTON_VOL_DOWN;
|
||||
if (buttons & (1 << 2))
|
||||
btn |= BUTTON_VOL_UP;
|
||||
|
||||
if (buttons & (1 << 4))
|
||||
btn |= BUTTON_A;
|
||||
if (buttons & (1 << 3))
|
||||
btn |= BUTTON_VOL_DOWN;
|
||||
|
||||
if (buttons & (1 << 4))
|
||||
btn |= BUTTON_A;
|
||||
}
|
||||
|
||||
/* the touchpad */
|
||||
if (touchpad & (1 << 0))
|
||||
btn |= BUTTON_UP;
|
||||
touchpad = GPJDAT & 0x10C9;
|
||||
if (touchpad)
|
||||
{
|
||||
if (touchpad & (1 << 0))
|
||||
btn |= BUTTON_UP;
|
||||
|
||||
if (touchpad & (1 << 12))
|
||||
btn |= BUTTON_RIGHT;
|
||||
if (touchpad & (1 << 12))
|
||||
btn |= BUTTON_RIGHT;
|
||||
|
||||
if (touchpad & (1 << 6))
|
||||
btn |= BUTTON_DOWN;
|
||||
if (touchpad & (1 << 6))
|
||||
btn |= BUTTON_DOWN;
|
||||
|
||||
if (touchpad & (1 << 7))
|
||||
btn |= BUTTON_LEFT;
|
||||
|
||||
if (touchpad & (1 << 3))
|
||||
btn |= BUTTON_SELECT;
|
||||
if (touchpad & (1 << 7))
|
||||
btn |= BUTTON_LEFT;
|
||||
|
||||
if (touchpad & (1 << 3))
|
||||
btn |= BUTTON_SELECT;
|
||||
}
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool headphones_inserted(void)
|
||||
{
|
||||
unsigned short remote_adc = adc_read(ADC_HPREMOTE);
|
||||
if (remote_adc != ADC_READ_ERROR)
|
||||
{
|
||||
/* If there is nothing in the headphone socket, the ADC reads high */
|
||||
if (remote_adc < 940)
|
||||
headphones_detect = true;
|
||||
else
|
||||
headphones_detect = false;
|
||||
}
|
||||
return headphones_detect;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,37 @@ int button_read_device(void);
|
|||
#define BUTTON_A 0x00000200
|
||||
|
||||
|
||||
/* Toshiba Gigabeat specific remote button ADC values */
|
||||
/* The remote control uses ADC 1 to emulate button pushes
|
||||
Reading (approx) Button HP plugged in? Remote plugged in?
|
||||
0 N/A Yes No
|
||||
125 Play/Pause Cant tell Yes
|
||||
241 Speaker+ Cant tell Yes
|
||||
369 Rewind Cant tell Yes
|
||||
492 Fast Fwd Cant tell Yes
|
||||
616 Vol + Cant tell Yes
|
||||
742 Vol - Cant tell Yes
|
||||
864 None Cant tell Yes
|
||||
1023 N/A No No
|
||||
*/
|
||||
|
||||
/*
|
||||
Notes:
|
||||
|
||||
Buttons on the remote are translated into equivalent button presses just
|
||||
as if you were pressing them on the Gigabeat itself.
|
||||
|
||||
We cannot tell if the hold is asserted on the remote. The Hold function on
|
||||
the remote is to block the output of the buttons changing.
|
||||
|
||||
Only one button can be sensed at a time. If another is pressed, the button
|
||||
with the lowest reading is dominant. So, if Rewind and Vol + are pressed
|
||||
at the same time, Rewind value is the one that is read.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#define BUTTON_MAIN (BUTTON_POWER|BUTTON_MENU|BUTTON_LEFT|BUTTON_RIGHT\
|
||||
|BUTTON_UP|BUTTON_DOWN|BUTTON_VOL_UP|BUTTON_VOL_DOWN\
|
||||
|BUTTON_SELECT|BUTTON_A)
|
||||
|
|
8
firmware/target/arm/gigabeat/meg-fx/dma_start.c
Normal file
8
firmware/target/arm/gigabeat/meg-fx/dma_start.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <sys/types.h>
|
||||
|
||||
void dma_start(const void* addr, size_t size) {
|
||||
(void) addr;
|
||||
(void) size;
|
||||
//TODO:
|
||||
}
|
||||
|
25
firmware/target/arm/gigabeat/meg-fx/kernel-meg-fx.c
Normal file
25
firmware/target/arm/gigabeat/meg-fx/kernel-meg-fx.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include "kernel.h"
|
||||
#include "thread.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "lcd.h"
|
||||
|
||||
extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
|
||||
|
||||
void timer4(void) {
|
||||
int i;
|
||||
/* Run through the list of tick tasks */
|
||||
for(i = 0; i < MAX_NUM_TICK_TASKS; i++)
|
||||
{
|
||||
if(tick_funcs[i])
|
||||
{
|
||||
tick_funcs[i]();
|
||||
}
|
||||
}
|
||||
|
||||
current_tick++;
|
||||
|
||||
/* following needs to be fixed. */
|
||||
/*wake_up_thread();*/
|
||||
}
|
||||
|
|
@ -1,27 +1,56 @@
|
|||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include "cpu.h"
|
||||
#include "lcd.h"
|
||||
#include "kernel.h"
|
||||
#include "system.h"
|
||||
#include "string.h"
|
||||
|
||||
void lcd_init_device(void);
|
||||
void lcd_update_rec(int, int, int, int);
|
||||
void lcd_update(void);
|
||||
|
||||
bool usedmablit = false;
|
||||
|
||||
/* LCD init */
|
||||
void lcd_init_device(void)
|
||||
{
|
||||
/* Switch from 555I mode to 565 mode */
|
||||
LCDCON5 |= 1 << 11;
|
||||
|
||||
}
|
||||
|
||||
/* Update a fraction of the display. */
|
||||
void lcd_update_rect(int x, int y, int width, int height)
|
||||
{
|
||||
(void)x;
|
||||
(void)y;
|
||||
(void)width;
|
||||
(void)height;
|
||||
memcpy(FRAME, &lcd_framebuffer, sizeof(lcd_framebuffer));
|
||||
|
||||
if (usedmablit)
|
||||
{
|
||||
/* Spin waiting for DMA to become available */
|
||||
//while (DSTAT0 & (1<<20)) ;
|
||||
if (DSTAT0 & (1<<20)) return;
|
||||
|
||||
/* set DMA dest */
|
||||
DIDST0 = (int) FRAME + y * sizeof(fb_data) * LCD_WIDTH;
|
||||
|
||||
/* FRAME on AHB buf, increment */
|
||||
DIDSTC0 = 0;
|
||||
DCON0 = (((1<<30) | (1<<28) | (1<<27) | (1<<22) | (2<<20)) | ((height * sizeof(fb_data) * LCD_WIDTH) >> 4));
|
||||
|
||||
/* set DMA source and options */
|
||||
DISRC0 = (int) &lcd_framebuffer + (y * sizeof(fb_data) * LCD_WIDTH) + 0x30000000;
|
||||
DISRCC0 = 0x00; /* memory is on AHB bus, increment addresses */
|
||||
|
||||
/* Activate the channel */
|
||||
DMASKTRIG0 = 0x2;
|
||||
/* Start DMA */
|
||||
DMASKTRIG0 |= 0x1;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy((void*)FRAME, &lcd_framebuffer, sizeof(lcd_framebuffer));
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the display.
|
||||
|
@ -44,6 +73,138 @@ void lcd_update(void)
|
|||
|
||||
#define ROUNDOFFS (127*257)
|
||||
|
||||
/* Performance function to blit a YUV bitmap directly to the LCD */
|
||||
/* For the Gigabeat - show it rotated */
|
||||
/* So the LCD_WIDTH is now the height */
|
||||
void lcd_yuv_blit(unsigned char * const src[3],
|
||||
int src_x, int src_y, int stride,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
width = (width + 1) & ~1;
|
||||
fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1;
|
||||
fb_data *dst_last = dst - (height - 1);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
fb_data *dst_row = dst;
|
||||
int count = width;
|
||||
const unsigned char *ysrc = src[0] + stride * src_y + src_x;
|
||||
int y, u, v;
|
||||
int red, green, blue;
|
||||
unsigned rbits, gbits, bbits;
|
||||
|
||||
/* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
|
||||
const unsigned char *usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y)
|
||||
+ (src_x/CSUB_X);
|
||||
const unsigned char *vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y)
|
||||
+ (src_x/CSUB_X);
|
||||
int xphase = src_x % CSUB_X;
|
||||
int rc, gc, bc;
|
||||
|
||||
u = *usrc++ - 128;
|
||||
v = *vsrc++ - 128;
|
||||
rc = RVFAC * v + ROUNDOFFS;
|
||||
gc = GVFAC * v + GUFAC * u + ROUNDOFFS;
|
||||
bc = BUFAC * u + ROUNDOFFS;
|
||||
|
||||
do
|
||||
{
|
||||
y = *ysrc++;
|
||||
red = RYFAC * y + rc;
|
||||
green = GYFAC * y + gc;
|
||||
blue = BYFAC * y + bc;
|
||||
|
||||
if ((unsigned)red > (RYFAC*255+ROUNDOFFS))
|
||||
{
|
||||
if (red < 0)
|
||||
red = 0;
|
||||
else
|
||||
red = (RYFAC*255+ROUNDOFFS);
|
||||
}
|
||||
if ((unsigned)green > (GYFAC*255+ROUNDOFFS))
|
||||
{
|
||||
if (green < 0)
|
||||
green = 0;
|
||||
else
|
||||
green = (GYFAC*255+ROUNDOFFS);
|
||||
}
|
||||
if ((unsigned)blue > (BYFAC*255+ROUNDOFFS))
|
||||
{
|
||||
if (blue < 0)
|
||||
blue = 0;
|
||||
else
|
||||
blue = (BYFAC*255+ROUNDOFFS);
|
||||
}
|
||||
rbits = ((unsigned)red) >> 16 ;
|
||||
gbits = ((unsigned)green) >> 16 ;
|
||||
bbits = ((unsigned)blue) >> 16 ;
|
||||
|
||||
*dst_row = (rbits << 11) | (gbits << 5) | bbits;
|
||||
|
||||
/* next pixel - since rotated, add WIDTH */
|
||||
dst_row += LCD_WIDTH;
|
||||
|
||||
if (++xphase >= CSUB_X)
|
||||
{
|
||||
u = *usrc++ - 128;
|
||||
v = *vsrc++ - 128;
|
||||
rc = RVFAC * v + ROUNDOFFS;
|
||||
gc = GVFAC * v + GUFAC * u + ROUNDOFFS;
|
||||
bc = BUFAC * u + ROUNDOFFS;
|
||||
xphase = 0;
|
||||
}
|
||||
}
|
||||
while (--count);
|
||||
|
||||
if (dst == dst_last) break;
|
||||
|
||||
dst--;
|
||||
src_y++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void lcd_set_contrast(int val) {
|
||||
(void) val;
|
||||
// TODO:
|
||||
}
|
||||
|
||||
void lcd_set_invert_display(bool yesno) {
|
||||
(void) yesno;
|
||||
// TODO:
|
||||
}
|
||||
|
||||
void lcd_blit(const fb_data* data, int bx, int y, int bwidth,
|
||||
int height, int stride)
|
||||
{
|
||||
(void) data;
|
||||
(void) bx;
|
||||
(void) y;
|
||||
(void) bwidth;
|
||||
(void) height;
|
||||
(void) stride;
|
||||
//TODO:
|
||||
}
|
||||
|
||||
void lcd_set_flip(bool yesno) {
|
||||
(void) yesno;
|
||||
// TODO:
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
/* Performance function to blit a YUV bitmap directly to the LCD */
|
||||
void lcd_yuv_blit(unsigned char * const src[3],
|
||||
int src_x, int src_y, int stride,
|
||||
|
@ -129,3 +290,7 @@ void lcd_yuv_blit(unsigned char * const src[3],
|
|||
}
|
||||
while (dst < dst_end);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
84
firmware/target/arm/gigabeat/meg-fx/mmu-meg-fx.c
Normal file
84
firmware/target/arm/gigabeat/meg-fx/mmu-meg-fx.c
Normal file
|
@ -0,0 +1,84 @@
|
|||
#include <string.h>
|
||||
#include "s3c2440.h"
|
||||
|
||||
void map_memory(void);
|
||||
static void enable_mmu(void);
|
||||
static void set_ttb(void);
|
||||
static void set_page_tables(void);
|
||||
static void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags);
|
||||
|
||||
#define SECTION_ADDRESS_MASK (-1 << 20)
|
||||
#define CACHE_ALL (1 << 3 | 1 << 2 )
|
||||
#define CACHE_NONE 0
|
||||
#define BUFFERED (1 << 2)
|
||||
#define MB (1 << 20)
|
||||
|
||||
void map_memory(void) {
|
||||
set_ttb();
|
||||
set_page_tables();
|
||||
enable_mmu();
|
||||
}
|
||||
|
||||
unsigned int* ttb_base;
|
||||
const int ttb_size = 4096;
|
||||
|
||||
void set_ttb() {
|
||||
int i;
|
||||
int* ttbPtr;
|
||||
int domain_access;
|
||||
|
||||
/* must be 16Kb (0x4000) aligned */
|
||||
ttb_base = (int*)0x31F00000;
|
||||
for (i=0; i<ttb_size; i++,ttbPtr++)
|
||||
ttbPtr = 0;
|
||||
asm volatile("mcr p15, 0, %0, c2, c0, 0" : : "r" (ttb_base));
|
||||
|
||||
/* set domain D0 to "client" permission access */
|
||||
|
||||
domain_access = 3;
|
||||
asm volatile("mcr p15, 0, %0, c3, c0, 0" : : "r" (domain_access));
|
||||
|
||||
}
|
||||
|
||||
void set_page_tables() {
|
||||
|
||||
map_section(0, 0, 0x1000, CACHE_NONE);
|
||||
|
||||
map_section(0x30000000, 0, 32, CACHE_NONE); /* map RAM to 0 */
|
||||
|
||||
map_section(0x30000000, 0, 30, CACHE_ALL); /* cache the first 30 MB or RAM */
|
||||
map_section(0x31E00000, 0x31E00000, 1, BUFFERED); /* enable buffered writing for the framebuffer */
|
||||
}
|
||||
|
||||
void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags) {
|
||||
unsigned int* ttbPtr;
|
||||
int i;
|
||||
int section_no;
|
||||
|
||||
section_no = va >> 20; /* sections are 1Mb size */
|
||||
ttbPtr = ttb_base + section_no;
|
||||
pa &= SECTION_ADDRESS_MASK; /* align to 1Mb */
|
||||
for(i=0; i<mb; i++, pa += MB) {
|
||||
*(ttbPtr + i) =
|
||||
pa |
|
||||
1 << 10 | /* superuser - r/w, user - no access */
|
||||
0 << 5 | /* domain 0th */
|
||||
1 << 4 | /* should be "1" */
|
||||
cache_flags |
|
||||
1 << 1; /* Section signature */
|
||||
}
|
||||
}
|
||||
|
||||
static void enable_mmu(void) {
|
||||
asm volatile("mov r0, #0\n"
|
||||
"mcr p15, 0, r0, c8, c7, 0\n" /* invalidate TLB */
|
||||
|
||||
"mcr p15, 0, r0, c7, c7,0\n" /* invalidate both icache and dcache */
|
||||
|
||||
"mrc p15, 0, r0, c1, c0, 0\n"
|
||||
"orr r0, r0, #1<<0\n" /* enable mmu bit, icache and dcache */
|
||||
"orr r0, r0, #1<<2\n" /* enable dcache */
|
||||
"orr r0, r0, #1<<12\n" /* enable icache */
|
||||
"mcr p15, 0, r0, c1, c0, 0" : : : "r0");
|
||||
asm volatile("nop \n nop \n nop \n nop");
|
||||
}
|
347
firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c
Normal file
347
firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c
Normal file
|
@ -0,0 +1,347 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 by Michael Sevakis
|
||||
*
|
||||
* 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 "system.h"
|
||||
#include "kernel.h"
|
||||
#include "logf.h"
|
||||
#include "audio.h"
|
||||
#include "wm8975.h"
|
||||
#include "file.h"
|
||||
|
||||
static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */
|
||||
|
||||
#define FIFO_COUNT ((IISFCON >> 6) & 0x01F)
|
||||
|
||||
/* number of bytes in FIFO */
|
||||
#define IIS_FIFO_SIZE 64
|
||||
|
||||
/* Setup for the DMA controller */
|
||||
#define DMA_CONTROL_SETUP ((1<<31) | (1<<29) | (1<<23) | (1<<22) | (1<<20))
|
||||
|
||||
unsigned short * p;
|
||||
size_t p_size;
|
||||
|
||||
|
||||
|
||||
/* DMA count has hit zero - no more data */
|
||||
/* Get more data from the callback and top off the FIFO */
|
||||
//void fiq(void) __attribute__ ((interrupt ("naked")));
|
||||
void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ")));
|
||||
void fiq(void)
|
||||
{
|
||||
/* clear any pending interrupt */
|
||||
SRCPND = (1<<19);
|
||||
|
||||
/* Buffer empty. Try to get more. */
|
||||
if (pcm_callback_for_more)
|
||||
{
|
||||
pcm_callback_for_more((unsigned char**)&p, &p_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* callback func is missing? */
|
||||
pcm_play_dma_stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_size)
|
||||
{
|
||||
/* set the new DMA values */
|
||||
DCON2 = DMA_CONTROL_SETUP | (p_size >> 1);
|
||||
DISRC2 = (int)p + 0x30000000;
|
||||
|
||||
/* Re-Activate the channel */
|
||||
DMASKTRIG2 = 0x2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No more DMA to do */
|
||||
pcm_play_dma_stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pcm_init(void)
|
||||
{
|
||||
pcm_playing = false;
|
||||
pcm_paused = false;
|
||||
pcm_callback_for_more = NULL;
|
||||
|
||||
audiohw_init();
|
||||
audiohw_enable_output(true);
|
||||
audiohw_mute(true);
|
||||
|
||||
/* cannot use the WM8975 defaults since our clock is not the same */
|
||||
/* the input master clock is 16.9344MHz - we can divide exact for that */
|
||||
audiohw_set_sample_rate( (0<<6) | (0x11 << 1) | (0<<0));
|
||||
|
||||
/* init GPIO */
|
||||
GPCCON = (GPCCON & ~(3<<14)) | (1<<14);
|
||||
GPCDAT |= 1<<7;
|
||||
GPECON |= 0x2aa;
|
||||
|
||||
/* Do no service DMA0 requests, yet */
|
||||
/* clear any pending int and mask it */
|
||||
INTMSK |= (1<<19); /* mask the interrupt */
|
||||
SRCPND = (1<<19); /* clear any pending interrupts */
|
||||
INTMOD |= (1<<19); /* connect to FIQ */
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
//FIXME
|
||||
//return;
|
||||
|
||||
int i;
|
||||
|
||||
/* sanity check: bad pointer or too small file */
|
||||
if ((NULL == addr) || (size & ~1) <= IIS_FIFO_SIZE) return;
|
||||
|
||||
p = (unsigned short *)addr;
|
||||
p_size = size;
|
||||
|
||||
|
||||
/* Enable the IIS clock */
|
||||
CLKCON |= (1<<17);
|
||||
|
||||
/* IIS interface setup and set to idle */
|
||||
IISCON = (1<<5) | (1<<3);
|
||||
|
||||
/* slave, transmit mode, 16 bit samples - 384fs - use 16.9344Mhz */
|
||||
IISMOD = (1<<9) | (1<<8) | (2<<6) | (1<<3) | (1<<2);
|
||||
|
||||
/* connect DMA to the FIFO and enable the FIFO */
|
||||
IISFCON = (1<<15) | (1<<13);
|
||||
|
||||
/* prefill the FIFO with half words */
|
||||
for (i=0; i < IIS_FIFO_SIZE; i+=2)
|
||||
{
|
||||
IISFIFO = *p++;
|
||||
p_size -= 2;
|
||||
}
|
||||
|
||||
/* set DMA dest */
|
||||
DIDST2 = (int)&IISFIFO;
|
||||
|
||||
/* IIS is on the APB bus, INT when TC reaches 0, fixed dest addr */
|
||||
DIDSTC2 = 0x03;
|
||||
|
||||
/* How many transfers to make - we transfer half-word at a time = 2 bytes */
|
||||
/* DMA control: CURR_TC int, single service mode, I2SSDO int, HW trig */
|
||||
/* no auto-reload, half-word (16bit) */
|
||||
DCON2 = DMA_CONTROL_SETUP | (p_size / 2);
|
||||
|
||||
/* set DMA source and options */
|
||||
DISRC2 = (int)p + 0x30000000;
|
||||
DISRCC2 = 0x00; /* memory is on AHB bus, increment addresses */
|
||||
|
||||
/* clear pending DMA interrupt */
|
||||
SRCPND = 1<<19;
|
||||
|
||||
enable_fiq(fiq);
|
||||
|
||||
/* unmask the DMA interrupt */
|
||||
INTMSK &= ~(1<<19);
|
||||
|
||||
/* Activate the channel */
|
||||
DMASKTRIG2 = 0x2;
|
||||
|
||||
/* turn off the idle */
|
||||
IISCON &= ~(1<<3);
|
||||
|
||||
pcm_playing = true;
|
||||
|
||||
/* start the IIS */
|
||||
IISCON |= (1<<0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Disconnect the DMA and wait for the FIFO to clear */
|
||||
void pcm_play_dma_stop(void)
|
||||
{
|
||||
pcm_playing = false;
|
||||
|
||||
/* mask the DMA interrupt */
|
||||
INTMSK |= (1<<19);
|
||||
|
||||
/* De-Activate the channel */
|
||||
DMASKTRIG2 = 0x4;
|
||||
|
||||
/* idle the IIS transmit */
|
||||
IISCON |= (1<<3);
|
||||
|
||||
/* stop the IIS interface */
|
||||
IISCON &= ~(1<<0);
|
||||
|
||||
/* Disconnect the IIS IIS clock */
|
||||
CLKCON &= ~(1<<17);
|
||||
|
||||
|
||||
disable_fiq();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pcm_play_pause_pause(void)
|
||||
{
|
||||
/* idle */
|
||||
IISCON |= (1<<3);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pcm_play_pause_unpause(void)
|
||||
{
|
||||
/* no idle */
|
||||
IISCON &= ~(1<<3);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pcm_set_frequency(unsigned int frequency)
|
||||
{
|
||||
int sr_ctrl;
|
||||
|
||||
switch(frequency)
|
||||
{
|
||||
case SAMPR_11:
|
||||
sr_ctrl = 0x19 << 1;
|
||||
break;
|
||||
case SAMPR_22:
|
||||
sr_ctrl = 0x1B << 1;
|
||||
break;
|
||||
default:
|
||||
case SAMPR_44:
|
||||
sr_ctrl = 0x11 << 1;
|
||||
break;
|
||||
case SAMPR_88:
|
||||
sr_ctrl = 0x1F << 1;
|
||||
break;
|
||||
}
|
||||
audiohw_set_sample_rate(sr_ctrl);
|
||||
pcm_freq = frequency;
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t pcm_get_bytes_waiting(void)
|
||||
{
|
||||
return (DSTAT2 & 0xFFFFF) * 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* dummy functions for those not actually supporting all this yet */
|
||||
void pcm_apply_settings(bool reset)
|
||||
{
|
||||
(void)reset;
|
||||
}
|
||||
|
||||
void pcm_set_monitor(int monitor)
|
||||
{
|
||||
(void)monitor;
|
||||
}
|
||||
/** **/
|
||||
|
||||
void pcm_mute(bool mute)
|
||||
{
|
||||
audiohw_mute(mute);
|
||||
if (mute)
|
||||
sleep(HZ/16);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function goes directly into the DMA buffer to calculate the left and
|
||||
* right peak values. To avoid missing peaks it tries to look forward two full
|
||||
* peek periods (2/HZ sec, 100% overlap), although it's always possible that
|
||||
* the entire period will not be visible. To reduce CPU load it only looks at
|
||||
* every third sample, and this can be reduced even further if needed (even
|
||||
* every tenth sample would still be pretty accurate).
|
||||
*/
|
||||
|
||||
/* Check for a peak every PEAK_STRIDE samples */
|
||||
#define PEAK_STRIDE 3
|
||||
/* Up to 1/50th of a second of audio for peak calculation */
|
||||
/* This should use NATIVE_FREQUENCY, or eventually an adjustable freq. value */
|
||||
#define PEAK_SAMPLES (44100/50)
|
||||
void pcm_calculate_peaks(int *left, int *right)
|
||||
{
|
||||
short *addr;
|
||||
short *end;
|
||||
{
|
||||
size_t samples = p_size / 4;
|
||||
addr = p;
|
||||
|
||||
if (samples > PEAK_SAMPLES)
|
||||
samples = PEAK_SAMPLES - (PEAK_STRIDE - 1);
|
||||
else
|
||||
samples -= MIN(PEAK_STRIDE - 1, samples);
|
||||
|
||||
end = &addr[samples * 2];
|
||||
}
|
||||
|
||||
if (left && right) {
|
||||
int left_peak = 0, right_peak = 0;
|
||||
|
||||
while (addr < end) {
|
||||
int value;
|
||||
if ((value = addr [0]) > left_peak)
|
||||
left_peak = value;
|
||||
else if (-value > left_peak)
|
||||
left_peak = -value;
|
||||
|
||||
if ((value = addr [PEAK_STRIDE | 1]) > right_peak)
|
||||
right_peak = value;
|
||||
else if (-value > right_peak)
|
||||
right_peak = -value;
|
||||
|
||||
addr = &addr[PEAK_STRIDE * 2];
|
||||
}
|
||||
|
||||
*left = left_peak;
|
||||
*right = right_peak;
|
||||
}
|
||||
else if (left || right) {
|
||||
int peak_value = 0, value;
|
||||
|
||||
if (right)
|
||||
addr += (PEAK_STRIDE | 1);
|
||||
|
||||
while (addr < end) {
|
||||
if ((value = addr [0]) > peak_value)
|
||||
peak_value = value;
|
||||
else if (-value > peak_value)
|
||||
peak_value = -value;
|
||||
|
||||
addr += PEAK_STRIDE * 2;
|
||||
}
|
||||
|
||||
if (left)
|
||||
*left = peak_value;
|
||||
else
|
||||
*right = peak_value;
|
||||
}
|
||||
}
|
|
@ -23,6 +23,8 @@
|
|||
#include "system.h"
|
||||
#include "power.h"
|
||||
#include "pcf50606.h"
|
||||
#include "backlight.h"
|
||||
#include "backlight-target.h"
|
||||
|
||||
#ifndef SIMULATOR
|
||||
|
||||
|
@ -33,21 +35,34 @@ void power_init(void)
|
|||
|
||||
bool charger_inserted(void)
|
||||
{
|
||||
return !(GPFDAT & (1 << 4));
|
||||
return (GPFDAT & (1 << 4)) ? false : true;
|
||||
}
|
||||
|
||||
/* Returns true if the unit is charging the batteries. */
|
||||
bool charging_state(void) {
|
||||
return (GPGDAT & (1 << 8)) ? false : true;
|
||||
}
|
||||
|
||||
void ide_power_enable(bool on)
|
||||
{
|
||||
(void)on;
|
||||
if (on)
|
||||
GPGDAT |= (1 << 11);
|
||||
else
|
||||
GPGDAT &= ~(1 << 11);
|
||||
}
|
||||
|
||||
bool ide_powered(void)
|
||||
{
|
||||
return true;
|
||||
return (GPGDAT & (1 << 11)) != 0;
|
||||
}
|
||||
|
||||
void power_off(void)
|
||||
{
|
||||
/* turn off backlight and wait for 1 second */
|
||||
__backlight_off();
|
||||
sleep(HZ/2);
|
||||
/* set SLEEP bit to on in CLKCON to turn off */
|
||||
CLKCON |=(1<<3);
|
||||
}
|
||||
|
||||
#else /* SIMULATOR */
|
||||
|
|
|
@ -24,10 +24,11 @@
|
|||
|
||||
#define SCL_SDA_HI GPHDAT |= (3 << 9)
|
||||
|
||||
/* arbitrary delay loop */
|
||||
#define DELAY do { int _x; for(_x=0;_x<2000;_x++);} while (0)
|
||||
/* The SC606 can clock at 400KHz: 2.5uS period -> 1.25uS half period */
|
||||
/* At 300Mhz - if loop takes 6 cycles @ 3.3nS each -> 1.25uS / 20nS -> 63 */
|
||||
#define DELAY do { volatile int _x; for(_x=0;_x<63;_x++);} while (0)
|
||||
|
||||
void sc606_i2c_start(void)
|
||||
static void sc606_i2c_start(void)
|
||||
{
|
||||
SCL_SDA_HI;
|
||||
DELAY;
|
||||
|
@ -36,7 +37,7 @@ void sc606_i2c_start(void)
|
|||
SCL_LO;
|
||||
}
|
||||
|
||||
void sc606_i2c_restart(void)
|
||||
static void sc606_i2c_restart(void)
|
||||
{
|
||||
SCL_SDA_HI;
|
||||
DELAY;
|
||||
|
@ -45,7 +46,7 @@ void sc606_i2c_restart(void)
|
|||
SCL_LO;
|
||||
}
|
||||
|
||||
void sc606_i2c_stop(void)
|
||||
static void sc606_i2c_stop(void)
|
||||
{
|
||||
SDA_LO;
|
||||
DELAY;
|
||||
|
@ -55,7 +56,7 @@ void sc606_i2c_stop(void)
|
|||
DELAY;
|
||||
}
|
||||
|
||||
void sc606_i2c_ack(void)
|
||||
static void sc606_i2c_ack(void)
|
||||
{
|
||||
|
||||
SDA_LO;
|
||||
|
@ -64,11 +65,11 @@ void sc606_i2c_ack(void)
|
|||
SCL_LO;
|
||||
}
|
||||
|
||||
int sc606_i2c_getack(void)
|
||||
static int sc606_i2c_getack(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Don't need a delay since this follows a data bit with a delay on the end */
|
||||
/* Don't need a delay since follows a data bit with a delay on the end */
|
||||
SDA_INPUT; /* And set to input */
|
||||
SCL_HI;
|
||||
DELAY;
|
||||
|
@ -83,7 +84,7 @@ int sc606_i2c_getack(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int sc606_i2c_outb(unsigned char byte)
|
||||
static int sc606_i2c_outb(unsigned char byte)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -106,7 +107,7 @@ int sc606_i2c_outb(unsigned char byte)
|
|||
return sc606_i2c_getack();
|
||||
}
|
||||
|
||||
unsigned char sc606_i2c_inb(void)
|
||||
static unsigned char sc606_i2c_inb(void)
|
||||
{
|
||||
int i;
|
||||
unsigned char byte = 0;
|
||||
|
@ -128,6 +129,8 @@ unsigned char sc606_i2c_inb(void)
|
|||
return byte;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int sc606_write(unsigned char reg, unsigned char data)
|
||||
{
|
||||
int x = 0;
|
||||
|
|
35
firmware/target/arm/gigabeat/meg-fx/system-meg-fx.c
Normal file
35
firmware/target/arm/gigabeat/meg-fx/system-meg-fx.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include "kernel.h"
|
||||
#include "system.h"
|
||||
#include "panic.h"
|
||||
|
||||
#include "lcd.h"
|
||||
#include <stdio.h>
|
||||
|
||||
const int TIMER4_MASK = 1 << 14;
|
||||
|
||||
int system_memory_guard(int newmode)
|
||||
{
|
||||
(void)newmode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void timer4(void);
|
||||
|
||||
void irq(void)
|
||||
{
|
||||
int intpending = INTPND;
|
||||
|
||||
SRCPND = intpending; /* Clear this interrupt. */
|
||||
INTPND = intpending; /* Clear this interrupt. */
|
||||
|
||||
/* Timer 4 */
|
||||
if ((intpending & TIMER4_MASK) != 0)
|
||||
{
|
||||
timer4();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unexpected interrupt */
|
||||
}
|
||||
}
|
||||
|
|
@ -20,33 +20,72 @@
|
|||
#include <stdbool.h>
|
||||
#include "cpu.h"
|
||||
#include "system.h"
|
||||
#include "kernel.h"
|
||||
|
||||
#define USB_RST_ASSERT GPBDAT &= ~(1 << 4)
|
||||
#define USB_RST_DEASSERT GPBDAT |= (1 << 4)
|
||||
|
||||
#define USB_ATA_ENABLE GPBDAT |= (1 << 5)
|
||||
#define USB_ATA_DISABLE GPBDAT &= ~(1 << 5)
|
||||
|
||||
#define USB_VPLUS_PWR_ASSERT GPBDAT |= (1 << 6)
|
||||
#define USB_VPLUS_PWR_DEASSERT GPBDAT &= ~(1 << 6)
|
||||
|
||||
#define USB_IS_PRESENT (!(GPFDAT & 1))
|
||||
|
||||
|
||||
|
||||
/* The usb detect is one pin to the cpu active low */
|
||||
inline bool usb_detect(void)
|
||||
{
|
||||
return USB_IS_PRESENT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void usb_init_device(void)
|
||||
{
|
||||
USB_VPLUS_PWR_ASSERT;
|
||||
sleep(HZ/20);
|
||||
|
||||
/* Reset the usb port */
|
||||
/* Make sure the cpu pin for reset line is set to output */
|
||||
GPBCON = (GPBCON & ~0x300) | 0x100;
|
||||
USB_RST_ASSERT;
|
||||
sleep(HZ/25);
|
||||
USB_RST_DEASSERT;
|
||||
|
||||
/* needed to complete the reset */
|
||||
USB_ATA_ENABLE;
|
||||
|
||||
sleep(HZ/15); /* 66ms */
|
||||
|
||||
USB_ATA_DISABLE;
|
||||
|
||||
sleep(HZ/25);
|
||||
|
||||
/* leave chip in low power mode */
|
||||
USB_VPLUS_PWR_DEASSERT;
|
||||
|
||||
sleep(HZ/25);
|
||||
}
|
||||
|
||||
bool usb_detect(void)
|
||||
{
|
||||
return (GPFDAT & 1) ? false : true;
|
||||
}
|
||||
|
||||
|
||||
void usb_enable(bool on)
|
||||
{
|
||||
if(on) {
|
||||
int i;
|
||||
|
||||
GPBDAT &= 0x7EF;
|
||||
GPBCON |= 1<<8;
|
||||
|
||||
GPGDAT &= 0xE7FF;
|
||||
GPGDAT |= 1<<11;
|
||||
|
||||
for (i = 0; i < 10000000; i++) {continue;}
|
||||
|
||||
GPBCON &= 0x2FFCFF;
|
||||
GPBDAT |= 1<<5;
|
||||
GPBDAT |= 1<<6;
|
||||
} else {
|
||||
/* TODO how turn USB mode back off again? */
|
||||
if (on)
|
||||
{
|
||||
/* make sure ata_en is high */
|
||||
USB_VPLUS_PWR_ASSERT;
|
||||
USB_ATA_ENABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* make sure ata_en is low */
|
||||
USB_ATA_DISABLE;
|
||||
USB_VPLUS_PWR_DEASSERT;
|
||||
}
|
||||
|
||||
sleep(HZ/20); // > 50ms for detecting the enable state change
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include "file.h"
|
||||
#include "buffer.h"
|
||||
#include "audio.h"
|
||||
#include "i2s.h"
|
||||
#include "i2c.h"
|
||||
#include "i2c-meg-fx.h"
|
||||
/*
|
||||
|
@ -53,11 +52,16 @@ void i2s_reset(void)
|
|||
int audiohw_init(void) {
|
||||
/* reset I2C */
|
||||
i2c_init();
|
||||
|
||||
/* GPC5 controls headphone output */
|
||||
GPCCON &= ~(0x3 << 10);
|
||||
GPCCON |= (1 << 10);
|
||||
GPCDAT |= (1 << 5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wmcodec_write(int reg, int data)
|
||||
{
|
||||
i2c_send(0x34, (reg<<1) | ((data&0x100)>>8),data&0xff);
|
||||
i2c_send(0x34, (reg<<1) | ((data&0x100)>>8), data&0xff);
|
||||
}
|
||||
|
|
2
tools/configure
vendored
2
tools/configure
vendored
|
@ -1031,7 +1031,7 @@ EOF
|
|||
target_id=20
|
||||
archos="gigabeatf"
|
||||
target="-DGIGABEAT_F"
|
||||
memory=32 # always
|
||||
memory=30 # always
|
||||
arm9tdmicc
|
||||
tool="cp"
|
||||
bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue