mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 10:37:38 -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 DRAMORIG 0xc00000 + STUBOFFSET
|
||||||
#define IRAMORIG 0x407000
|
#define IRAMORIG 0x407000
|
||||||
#define IRAMSIZE 0x9000
|
#define IRAMSIZE 0x9000
|
||||||
|
#elif CONFIG_CPU == S3C2440
|
||||||
|
#define DRAMORIG 0x100 + STUBOFFSET
|
||||||
|
#define IRAMORIG DRAMORIG
|
||||||
|
#define IRAMSIZE 4K
|
||||||
|
#define IRAM DRAM
|
||||||
#else
|
#else
|
||||||
#define DRAMORIG 0x09000000 + STUBOFFSET
|
#define DRAMORIG 0x09000000 + STUBOFFSET
|
||||||
#endif
|
#endif
|
||||||
|
@ -73,7 +78,7 @@ SECTIONS
|
||||||
.text :
|
.text :
|
||||||
{
|
{
|
||||||
*(.text*)
|
*(.text*)
|
||||||
#if defined(CPU_PP) || (CONFIG_CPU==PNX0101)
|
#ifdef CPU_ARM
|
||||||
*(.glue_7)
|
*(.glue_7)
|
||||||
*(.glue_7t)
|
*(.glue_7t)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,12 +17,133 @@
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "button-target.h"
|
||||||
|
|
||||||
|
void map_memory(void);
|
||||||
|
|
||||||
|
int line = 0;
|
||||||
|
|
||||||
char version[] = APPSVERSION;
|
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. */
|
/* Drop into USB mode. This does not check for disconnection. */
|
||||||
|
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
GPBDAT &= 0x7EF;
|
GPBDAT &= 0x7EF;
|
||||||
|
@ -38,13 +159,156 @@ void go_usb_mode(void) {
|
||||||
GPBDAT |= 1<<6;
|
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)
|
void * main(void)
|
||||||
{
|
{
|
||||||
int line = 0, i;
|
int i;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
struct partinfo* pinfo;
|
struct partinfo* pinfo;
|
||||||
unsigned short* identify_info;
|
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_init();
|
||||||
lcd_setfont(FONT_SYSFIXED);
|
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++, "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();
|
lcd_update();
|
||||||
|
sleep(1*HZ);
|
||||||
|
|
||||||
/* hold MENU to enter rescue mode */
|
/* hold MENU to enter rescue mode */
|
||||||
if (GPGDAT & 2) {
|
if (GPGDAT & 2) {
|
||||||
|
@ -67,12 +334,44 @@ void * main(void)
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sleep(5*HZ);
|
||||||
|
|
||||||
|
if(GPGDAT & 0x10) {
|
||||||
|
load_original = true;
|
||||||
|
lcd_puts(0, line++, "Loading original firmware...");
|
||||||
|
lcd_update();
|
||||||
|
}
|
||||||
|
|
||||||
i = ata_init();
|
i = ata_init();
|
||||||
i = disk_mount_all();
|
i = disk_mount_all();
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "disk_mount_all: %d", i);
|
snprintf(buf, sizeof(buf), "disk_mount_all: %d", i);
|
||||||
lcd_puts(0, line++, buf);
|
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();
|
identify_info = ata_get_identify();
|
||||||
|
|
||||||
for (i=0; i < 20; i++)
|
for (i=0; i < 20; i++)
|
||||||
|
@ -99,13 +398,65 @@ void * main(void)
|
||||||
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);
|
pinfo->type, pinfo->size / 2048);
|
||||||
lcd_puts(0, line++, buf);
|
lcd_puts(0, line++, buf);
|
||||||
|
|
||||||
testfile = open("/boottest.txt", O_WRONLY|O_CREAT|O_TRUNC);
|
|
||||||
write(testfile, "It works!", 9);
|
|
||||||
close(testfile);
|
|
||||||
|
|
||||||
lcd_update();
|
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 */
|
/* now wait in USB mode so the bootloader can be updated */
|
||||||
go_usb_mode();
|
go_usb_mode();
|
||||||
while(1);
|
while(1);
|
||||||
|
|
|
@ -136,6 +136,8 @@ drivers/rtc/rtc_pcf50606.c
|
||||||
drivers/rtc/rtc_pcf50605.c
|
drivers/rtc/rtc_pcf50605.c
|
||||||
#elif (CONFIG_RTC == RTC_E8564)
|
#elif (CONFIG_RTC == RTC_E8564)
|
||||||
drivers/rtc/rtc_e8564.c
|
drivers/rtc/rtc_e8564.c
|
||||||
|
#elif (CONFIG_RTC == RTC_S3C2440)
|
||||||
|
drivers/rtc/rtc_s3c2440.c
|
||||||
#endif /* (CONFIG_RTC == RTC_) */
|
#endif /* (CONFIG_RTC == RTC_) */
|
||||||
#endif /* SIMULATOR */
|
#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/sc606-meg-fx.c
|
||||||
target/arm/gigabeat/meg-fx/usb-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/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 /* SIMULATOR */
|
||||||
#endif /* GIGABEAT_F */
|
#endif /* GIGABEAT_F */
|
||||||
|
|
||||||
|
|
|
@ -45,9 +45,10 @@ INPUT(target/sh/crt0.o)
|
||||||
#define IRAMORIG 0x400000
|
#define IRAMORIG 0x400000
|
||||||
#define IRAMSIZE 0x7000
|
#define IRAMSIZE 0x7000
|
||||||
#elif CONFIG_CPU==S3C2440
|
#elif CONFIG_CPU==S3C2440
|
||||||
#define DRAMORIG 0x30000000 + STUBOFFSET
|
#define DRAMORIG 0x100 + STUBOFFSET
|
||||||
#define IRAMORIG 0x40000000
|
#define IRAMORIG DRAMORIG
|
||||||
#define IRAMSIZE 4K
|
#define IRAMSIZE 4K
|
||||||
|
#define IRAM DRAM
|
||||||
#else
|
#else
|
||||||
#define DRAMORIG 0x09000000 + STUBOFFSET
|
#define DRAMORIG 0x09000000 + STUBOFFSET
|
||||||
#define IRAMORIG 0x0f000000
|
#define IRAMORIG 0x0f000000
|
||||||
|
@ -63,7 +64,9 @@ INPUT(target/sh/crt0.o)
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
|
DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
|
||||||
|
#if CONFIG_CPU != S3C2440
|
||||||
IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
|
IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
|
||||||
|
#endif
|
||||||
#if CONFIG_CPU==PNX0101
|
#if CONFIG_CPU==PNX0101
|
||||||
IRAM0 : ORIGIN = 0x0, LENGTH = IRAMSIZE
|
IRAM0 : ORIGIN = 0x0, LENGTH = IRAMSIZE
|
||||||
#endif
|
#endif
|
||||||
|
@ -146,6 +149,8 @@ SECTIONS
|
||||||
|
|
||||||
#if CONFIG_CPU==PNX0101
|
#if CONFIG_CPU==PNX0101
|
||||||
.iram IRAMORIG + SIZEOF(.vectors) :
|
.iram IRAMORIG + SIZEOF(.vectors) :
|
||||||
|
#elif CONFIG_CPU==S3C2440
|
||||||
|
.iram :
|
||||||
#else
|
#else
|
||||||
.iram IRAMORIG :
|
.iram IRAMORIG :
|
||||||
#endif
|
#endif
|
||||||
|
@ -200,7 +205,7 @@ SECTIONS
|
||||||
|
|
||||||
#if defined(CPU_COLDFIRE)
|
#if defined(CPU_COLDFIRE)
|
||||||
.bss ADDR(.data) + SIZEOF(.data) + SIZEOF(.iram):
|
.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):
|
.bss ADDR(.data) + SIZEOF(.data) + SIZEOF(.iram) + SIZEOF(.vectors):
|
||||||
#else
|
#else
|
||||||
.bss :
|
.bss :
|
||||||
|
|
|
@ -119,7 +119,7 @@ SECTIONS
|
||||||
}
|
}
|
||||||
#elif (CONFIG_CPU==S3C2440)
|
#elif (CONFIG_CPU==S3C2440)
|
||||||
{
|
{
|
||||||
. = DRAMORIG + 0x8000;
|
. = DRAMORIG + 0x1000000;
|
||||||
.text : {
|
.text : {
|
||||||
*(.init.text)
|
*(.init.text)
|
||||||
*(.text)
|
*(.text)
|
||||||
|
|
|
@ -14,6 +14,12 @@
|
||||||
/* define this if you have a colour LCD */
|
/* define this if you have a colour LCD */
|
||||||
#define HAVE_LCD_COLOR 1
|
#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 this if you would like tagcache to build on this target */
|
||||||
#define HAVE_TAGCACHE
|
#define HAVE_TAGCACHE
|
||||||
|
|
||||||
|
@ -30,14 +36,24 @@
|
||||||
#define CONFIG_CODEC SWCODEC
|
#define CONFIG_CODEC SWCODEC
|
||||||
|
|
||||||
/* define this if you have a real-time clock */
|
/* define this if you have a real-time clock */
|
||||||
|
|
||||||
#if 0 /* TODO */
|
|
||||||
#define CONFIG_RTC RTC_S3C2440
|
#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 this for LCD backlight available */
|
||||||
#define CONFIG_BACKLIGHT BL_GIGABEAT /* port controlled PWM */
|
#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 this if you have a software controlled poweroff */
|
||||||
#define HAVE_SW_POWEROFF
|
#define HAVE_SW_POWEROFF
|
||||||
|
|
||||||
|
@ -54,23 +70,27 @@
|
||||||
|
|
||||||
#ifndef SIMULATOR
|
#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 this if you have a Motorola SCF5249 */
|
||||||
#define CONFIG_CPU S3C2440
|
#define CONFIG_CPU S3C2440
|
||||||
|
|
||||||
/* Define this if you want to use coldfire's i2c interface */
|
/* Define this if you want to use coldfire's i2c interface */
|
||||||
#define CONFIG_I2C I2C_S3C2440
|
#define CONFIG_I2C I2C_S3C2440
|
||||||
|
|
||||||
/* Type of mobile power */
|
/* Type of mobile power - check this out */
|
||||||
#define CONFIG_BATTERY BATT_LIPOL1300
|
#define CONFIG_BATTERY BATT_LIION830 /* could change this later */
|
||||||
#define BATTERY_CAPACITY_MIN 1300 /* min. capacity selectable */
|
#define BATTERY_CAPACITY_MIN 750 /* min. capacity selectable */
|
||||||
#define BATTERY_CAPACITY_MAX 3200 /* max. capacity selectable */
|
#define BATTERY_CAPACITY_MAX 850 /* max. capacity selectable */
|
||||||
#define BATTERY_CAPACITY_INC 50 /* capacity increment */
|
#define BATTERY_CAPACITY_INC 25 /* capacity increment */
|
||||||
#define BATTERY_TYPES_COUNT 1 /* only one type */
|
#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 */
|
/* Hardware controlled charging with monitoring */
|
||||||
#define CONFIG_CHARGING CHARGING_SIMPLE
|
#define CONFIG_CHARGING CHARGING_MONITOR
|
||||||
|
|
||||||
/* define this if the hardware can be powered off while charging */
|
/* define this if the hardware can be powered off while charging */
|
||||||
#define HAVE_POWEROFF_WHILE_CHARGING
|
#define HAVE_POWEROFF_WHILE_CHARGING
|
||||||
|
@ -82,9 +102,7 @@
|
||||||
#define CPU_FREQ 16934400
|
#define CPU_FREQ 16934400
|
||||||
|
|
||||||
/* Define this if you have ATA power-off control */
|
/* Define this if you have ATA power-off control */
|
||||||
#if 0 /* TODO */
|
|
||||||
#define HAVE_ATA_POWER_OFF
|
#define HAVE_ATA_POWER_OFF
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Virtual LED (icon) */
|
/* Virtual LED (icon) */
|
||||||
#define CONFIG_LED LED_VIRTUAL
|
#define CONFIG_LED LED_VIRTUAL
|
||||||
|
@ -99,6 +117,7 @@
|
||||||
|
|
||||||
#define USB_GIGABEAT_STYLE
|
#define USB_GIGABEAT_STYLE
|
||||||
|
|
||||||
|
#define HAVE_HEADPHONE_DETECTION
|
||||||
/* Define this if you have adjustable CPU frequency */
|
/* Define this if you have adjustable CPU frequency */
|
||||||
#if 0 /* TODO */
|
#if 0 /* TODO */
|
||||||
#define HAVE_ADJUSTABLE_CPU_FREQ
|
#define HAVE_ADJUSTABLE_CPU_FREQ
|
||||||
|
@ -107,8 +126,5 @@
|
||||||
#define BOOTFILE_EXT "gigabeat"
|
#define BOOTFILE_EXT "gigabeat"
|
||||||
#define BOOTFILE "rockbox." BOOTFILE_EXT
|
#define BOOTFILE "rockbox." BOOTFILE_EXT
|
||||||
|
|
||||||
#if 0 /* TODO */
|
|
||||||
#define HAVE_BACKLIGHT_BRIGHTNESS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
#define BATT_LIPOL1300 1300 /* the type used in iRiver h1x0 models */
|
#define BATT_LIPOL1300 1300 /* the type used in iRiver h1x0 models */
|
||||||
#define BATT_LPCS355385 1550 /* iriver h10 20Gb - SKC LPCS355385 */
|
#define BATT_LPCS355385 1550 /* iriver h10 20Gb - SKC LPCS355385 */
|
||||||
#define BATT_BP009 820 /* iriver H10 5/6Gb - iriver BP009 */
|
#define BATT_BP009 820 /* iriver H10 5/6Gb - iriver BP009 */
|
||||||
|
#define BATT_LIION830 830 /* Toshiba Gigabeat Fxx and Xxx series MK11-2740 */
|
||||||
|
|
||||||
/* CONFIG_CHARGING */
|
/* CONFIG_CHARGING */
|
||||||
#define CHARGING_SIMPLE 1 /* Simple, hardware controlled charging */
|
#define CHARGING_SIMPLE 1 /* Simple, hardware controlled charging */
|
||||||
|
|
|
@ -56,7 +56,7 @@ void kernel_init(void)
|
||||||
void sleep(int ticks)
|
void sleep(int ticks)
|
||||||
{
|
{
|
||||||
#if CONFIG_CPU == S3C2440 && defined(BOOTLOADER)
|
#if CONFIG_CPU == S3C2440 && defined(BOOTLOADER)
|
||||||
int counter;
|
volatile int counter;
|
||||||
TCON &= ~(1 << 20); // stop timer 4
|
TCON &= ~(1 << 20); // stop timer 4
|
||||||
// TODO: this constant depends on dividers settings inherited from
|
// TODO: this constant depends on dividers settings inherited from
|
||||||
// firmware. Set them explicitly somwhere.
|
// firmware. Set them explicitly somwhere.
|
||||||
|
@ -76,7 +76,7 @@ void sleep(int ticks)
|
||||||
|
|
||||||
void yield(void)
|
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 */
|
/* Some targets don't like yielding in the bootloader */
|
||||||
#else
|
#else
|
||||||
switch_thread(true, NULL);
|
switch_thread(true, NULL);
|
||||||
|
@ -560,27 +560,34 @@ void tick_start(unsigned int interval_in_ms)
|
||||||
#elif CONFIG_CPU == S3C2440
|
#elif CONFIG_CPU == S3C2440
|
||||||
void tick_start(unsigned int interval_in_ms)
|
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)*/
|
INTMOD &= ~(1 << 14); // timer 4 to IRQ mode
|
||||||
count = interval_in_ms / 1000 * 128 - 1;
|
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",
|
if(tick_funcs[i])
|
||||||
interval_in_ms);
|
{
|
||||||
return;
|
tick_funcs[i]();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable the tick */
|
current_tick++;
|
||||||
TICNT &= ~(1<<7);
|
|
||||||
/* Set the count value */
|
|
||||||
TICNT |= count;
|
|
||||||
/* Start up the ticker */
|
|
||||||
TICNT |= (1<<7);
|
|
||||||
|
|
||||||
/* need interrupt handler ??? */
|
|
||||||
|
|
||||||
|
/* following needs to be fixed. */
|
||||||
|
/*wake_up_thread();*/
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -59,46 +59,9 @@ void pcm_play_pause_unpause(void);
|
||||||
|
|
||||||
/** Functions that require targeted implementation **/
|
/** Functions that require targeted implementation **/
|
||||||
|
|
||||||
#ifndef CPU_COLDFIRE
|
#if !defined(CPU_COLDFIRE) && (CONFIG_CPU != S3C2440)
|
||||||
|
|
||||||
#if (CONFIG_CPU == S3C2440)
|
#if (CONFIG_CPU == PNX0101)
|
||||||
|
|
||||||
/* 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)
|
|
||||||
|
|
||||||
#define DMA_BUF_SAMPLES 0x100
|
#define DMA_BUF_SAMPLES 0x100
|
||||||
|
|
||||||
|
|
|
@ -191,6 +191,8 @@ static const unsigned int battery_level_dangerous[BATTERY_TYPES_COUNT] =
|
||||||
105, 115
|
105, 115
|
||||||
#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver H1x0: LiPolymer */
|
#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver H1x0: LiPolymer */
|
||||||
338
|
338
|
||||||
|
#elif CONFIG_BATTERY == BATT_LIION830 /* Gigabeat F */
|
||||||
|
340
|
||||||
#elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */
|
#elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */
|
||||||
354
|
354
|
||||||
#elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB: LiPolymer*/
|
#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
|
270, 280
|
||||||
#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver Hxxx */
|
#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver Hxxx */
|
||||||
299
|
299
|
||||||
|
#elif CONFIG_BATTERY == BATT_LIION830 /* Gigabeat F */
|
||||||
|
338
|
||||||
#elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */
|
#elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */
|
||||||
350
|
350
|
||||||
#elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB */
|
#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. */
|
/* May need recalibration. */
|
||||||
{ 93, 108, 114, 118, 121, 125, 128, 132, 136, 142, 158 }, /* alkaline */
|
{ 93, 108, 114, 118, 121, 125, 128, 132, 136, 142, 158 }, /* alkaline */
|
||||||
{ 103, 118, 121, 123, 124, 125, 126, 127, 128, 129, 135 } /* NiMH */
|
{ 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 */
|
#else /* NiMH */
|
||||||
/* original values were taken directly after charging, but it should show
|
/* original values were taken directly after charging, but it should show
|
||||||
100% after turning off the device for some hours, too */
|
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
|
#ifdef CONFIG_CHARGING
|
||||||
charger_input_state_type charger_input_state IDATA_ATTR;
|
charger_input_state_type charger_input_state IDATA_ATTR;
|
||||||
|
|
||||||
|
|
||||||
/* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */
|
/* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */
|
||||||
static const unsigned short percent_to_volt_charge[11] =
|
static const unsigned short percent_to_volt_charge[11] =
|
||||||
{
|
{
|
||||||
#if CONFIG_BATTERY == BATT_LIPOL1300
|
#if CONFIG_BATTERY == BATT_LIPOL1300
|
||||||
/* values measured over one full charging cycle */
|
/* values measured over one full charging cycle */
|
||||||
354, 386, 393, 398, 400, 402, 404, 408, 413, 418, 423 /* LiPo */
|
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
|
#elif CONFIG_BATTERY == BATT_LPCS355385
|
||||||
/* iriver H10 20GB */
|
/* iriver H10 20GB */
|
||||||
399, 403, 406, 408, 410, 412, 415, 418, 422, 426, 431
|
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_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
|
#endif
|
||||||
|
|
|
@ -122,6 +122,25 @@ start:
|
||||||
/* Code for ARM bootloader targets other than iPod go here */
|
/* Code for ARM bootloader targets other than iPod go here */
|
||||||
|
|
||||||
#if CONFIG_CPU == S3C2440
|
#if CONFIG_CPU == S3C2440
|
||||||
|
/* 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
|
bl main
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -201,7 +220,10 @@ prefetch_abort_handler:
|
||||||
fiq_handler:
|
fiq_handler:
|
||||||
@ Branch straight to FIQ handler in pcm_playback.c. This also handles the
|
@ Branch straight to FIQ handler in pcm_playback.c. This also handles the
|
||||||
@ the correct return sequence.
|
@ 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:
|
data_abort_handler:
|
||||||
sub r0, lr, #8
|
sub r0, lr, #8
|
||||||
|
@ -210,9 +232,9 @@ data_abort_handler:
|
||||||
|
|
||||||
irq_handler:
|
irq_handler:
|
||||||
#ifndef STUB
|
#ifndef STUB
|
||||||
stmfd sp!, {r0-r3, r12, lr}
|
stmfd sp!, {r0-r11, r12, lr}
|
||||||
bl irq
|
bl irq
|
||||||
ldmfd sp!, {r0-r3, r12, lr}
|
ldmfd sp!, {r0-r11, r12, lr}
|
||||||
#endif
|
#endif
|
||||||
subs pc, lr, #4
|
subs pc, lr, #4
|
||||||
|
|
||||||
|
|
|
@ -18,24 +18,67 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "adc-target.h"
|
#include "adc-target.h"
|
||||||
|
#include "kernel.h"
|
||||||
|
|
||||||
|
|
||||||
void adc_init(void) {
|
|
||||||
|
static unsigned short adc_readings[NUM_ADC_CHANNELS];
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
static unsigned short __adc_read(int channel);
|
||||||
|
static void adc_tick(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void adc_init(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
/* Turn on the ADC PCLK */
|
/* Turn on the ADC PCLK */
|
||||||
CLKCON |= (1<<15);
|
CLKCON |= (1<<15);
|
||||||
|
|
||||||
/* Set channel 0, normal mode, disable "start by read" */
|
/* Set channel 0, normal mode, disable "start by read" */
|
||||||
ADCCON &= ~(0x3F);
|
ADCCON &= ~(0x3F);
|
||||||
|
|
||||||
/* No start delay. Use nromal conversion mode. */
|
/* No start delay. Use normal conversion mode. */
|
||||||
ADCDLY |= 0x1;
|
ADCDLY = 0x1;
|
||||||
|
|
||||||
/* Set and enable the prescaler */
|
/* Set and enable the prescaler */
|
||||||
ADCCON = (ADCCON & ~(0xff<<6)) | (0x19<<6);
|
ADCCON = (ADCCON & ~(0xff<<6)) | (0x19<<6);
|
||||||
ADCCON |= (1<<14);
|
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;
|
int i;
|
||||||
|
|
||||||
/* Set the channel */
|
/* Set the channel */
|
||||||
|
@ -45,34 +88,57 @@ unsigned short adc_read(int channel) {
|
||||||
ADCCON |= 0x1;
|
ADCCON |= 0x1;
|
||||||
|
|
||||||
/* Wait for a low Enable_start */
|
/* Wait for a low Enable_start */
|
||||||
i = 20000;
|
for (i = 20000;;) {
|
||||||
while(i > 0) {
|
if(0 == (ADCCON & 0x1)) {
|
||||||
if(ADCCON & 0x1) {
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
if(i == 0) {
|
i--;
|
||||||
|
if (0 == i) {
|
||||||
/* Ran out of time */
|
/* Ran out of time */
|
||||||
return(0);
|
return ADC_READ_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for high End_of_Conversion */
|
/* Wait for high End_of_Conversion */
|
||||||
i = 20000;
|
for(i = 20000;;) {
|
||||||
while(i > 0) {
|
|
||||||
if(ADCCON & (1<<15)) {
|
if(ADCCON & (1<<15)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
i--;
|
i--;
|
||||||
}
|
if(0 == i) {
|
||||||
}
|
|
||||||
if(i == 0) {
|
|
||||||
/* Ran out of time */
|
/* Ran out of time */
|
||||||
return(0);
|
return ADC_READ_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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_
|
#ifndef _ADC_TARGET_H_
|
||||||
#define _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_BATTERY 0
|
||||||
#define ADC_UNKNOWN_2 1
|
#define ADC_HPREMOTE 1
|
||||||
#define ADC_UNKNOWN_3 2
|
#define ADC_UNKNOWN_3 2
|
||||||
#define ADC_UNKNOWN_4 3
|
#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_UNREG_POWER ADC_BATTERY /* For compatibility */
|
||||||
|
#define ADC_READ_ERROR 0xFFFF
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,11 +26,18 @@
|
||||||
|
|
||||||
void ata_reset(void)
|
void ata_reset(void)
|
||||||
{
|
{
|
||||||
|
GPGDAT &= ~(1 << 10);
|
||||||
|
sleep(1); /* > 25us */
|
||||||
|
GPGDAT |= (1 << 10);
|
||||||
|
sleep(1); /* > 2ms */
|
||||||
}
|
}
|
||||||
|
|
||||||
void ata_enable(bool on)
|
void ata_enable(bool on)
|
||||||
{
|
{
|
||||||
(void)on;
|
if(on)
|
||||||
|
GPGDAT &= ~(1 << 12);
|
||||||
|
else
|
||||||
|
GPGDAT |= (1 << 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ata_is_coldstart(void)
|
bool ata_is_coldstart(void)
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#define ATA_TARGET_H
|
#define ATA_TARGET_H
|
||||||
|
|
||||||
/* Plain C read & write loops */
|
/* Plain C read & write loops */
|
||||||
|
#define PREFER_C_READING
|
||||||
|
#define PREFER_C_WRITING
|
||||||
|
|
||||||
#define ATA_IOBASE 0x18000000
|
#define ATA_IOBASE 0x18000000
|
||||||
#define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE)))
|
#define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE)))
|
||||||
|
|
|
@ -19,11 +19,16 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
#include "backlight-target.h"
|
||||||
#include "backlight.h"
|
#include "backlight.h"
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
#include "sc606-meg-fx.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)
|
void __backlight_on(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#ifndef BACKLIGHT_TARGET_H
|
#ifndef BACKLIGHT_TARGET_H
|
||||||
#define BACKLIGHT_TARGET_H
|
#define BACKLIGHT_TARGET_H
|
||||||
|
|
||||||
|
void __backlight_init(void);
|
||||||
void __backlight_on(void);
|
void __backlight_on(void);
|
||||||
void __backlight_off(void);
|
void __backlight_off(void);
|
||||||
void __backlight_set_brightness(int val);
|
void __backlight_set_brightness(int val);
|
||||||
|
|
|
@ -27,27 +27,76 @@
|
||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "system.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)
|
void button_init_device(void)
|
||||||
{
|
{
|
||||||
/* Power, Remote Play & Hold switch */
|
/* Power, Remote Play & Hold switch */
|
||||||
}
|
}
|
||||||
|
|
||||||
bool button_hold(void)
|
|
||||||
|
|
||||||
|
inline bool button_hold(void)
|
||||||
{
|
{
|
||||||
return (GPGDAT & (1 << 15));
|
return (GPGDAT & (1 << 15));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int button_read_device(void)
|
int button_read_device(void)
|
||||||
{
|
{
|
||||||
int btn = BUTTON_NONE;
|
int btn;
|
||||||
int touchpad = GPJDAT;
|
int touchpad;
|
||||||
int buttons = GPGDAT;
|
int buttons;
|
||||||
|
static int lastbutton;
|
||||||
|
unsigned short remote_adc;
|
||||||
|
|
||||||
/* Check for hold first */
|
/* Check for hold first - exit if asserted with no button pressed */
|
||||||
if (buttons & (1 << 15))
|
if (button_hold())
|
||||||
return btn;
|
return BUTTON_NONE;
|
||||||
|
|
||||||
/* the side buttons */
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* the side buttons - Check before doing all of the work on each bit */
|
||||||
|
buttons = GPGDAT & 0x1F;
|
||||||
|
if (buttons)
|
||||||
|
{
|
||||||
if (buttons & (1 << 0))
|
if (buttons & (1 << 0))
|
||||||
btn |= BUTTON_POWER;
|
btn |= BUTTON_POWER;
|
||||||
|
|
||||||
|
@ -62,8 +111,12 @@ int button_read_device(void)
|
||||||
|
|
||||||
if (buttons & (1 << 4))
|
if (buttons & (1 << 4))
|
||||||
btn |= BUTTON_A;
|
btn |= BUTTON_A;
|
||||||
|
}
|
||||||
|
|
||||||
/* the touchpad */
|
/* the touchpad */
|
||||||
|
touchpad = GPJDAT & 0x10C9;
|
||||||
|
if (touchpad)
|
||||||
|
{
|
||||||
if (touchpad & (1 << 0))
|
if (touchpad & (1 << 0))
|
||||||
btn |= BUTTON_UP;
|
btn |= BUTTON_UP;
|
||||||
|
|
||||||
|
@ -78,7 +131,23 @@ int button_read_device(void)
|
||||||
|
|
||||||
if (touchpad & (1 << 3))
|
if (touchpad & (1 << 3))
|
||||||
btn |= BUTTON_SELECT;
|
btn |= BUTTON_SELECT;
|
||||||
|
}
|
||||||
|
|
||||||
return btn;
|
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
|
#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\
|
#define BUTTON_MAIN (BUTTON_POWER|BUTTON_MENU|BUTTON_LEFT|BUTTON_RIGHT\
|
||||||
|BUTTON_UP|BUTTON_DOWN|BUTTON_VOL_UP|BUTTON_VOL_DOWN\
|
|BUTTON_UP|BUTTON_DOWN|BUTTON_VOL_UP|BUTTON_VOL_DOWN\
|
||||||
|BUTTON_SELECT|BUTTON_A)
|
|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 "config.h"
|
||||||
|
#include <string.h>
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "string.h"
|
|
||||||
|
|
||||||
void lcd_init_device(void);
|
void lcd_init_device(void);
|
||||||
void lcd_update_rec(int, int, int, int);
|
void lcd_update_rec(int, int, int, int);
|
||||||
void lcd_update(void);
|
void lcd_update(void);
|
||||||
|
|
||||||
|
bool usedmablit = false;
|
||||||
|
|
||||||
/* LCD init */
|
/* LCD init */
|
||||||
void lcd_init_device(void)
|
void lcd_init_device(void)
|
||||||
{
|
{
|
||||||
|
/* Switch from 555I mode to 565 mode */
|
||||||
|
LCDCON5 |= 1 << 11;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update a fraction of the display. */
|
/* Update a fraction of the display. */
|
||||||
void lcd_update_rect(int x, int y, int width, int height)
|
void lcd_update_rect(int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
(void)x;
|
(void)x;
|
||||||
(void)y;
|
|
||||||
(void)width;
|
(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.
|
/* Update the display.
|
||||||
|
@ -44,6 +73,138 @@ void lcd_update(void)
|
||||||
|
|
||||||
#define ROUNDOFFS (127*257)
|
#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 */
|
/* Performance function to blit a YUV bitmap directly to the LCD */
|
||||||
void lcd_yuv_blit(unsigned char * const src[3],
|
void lcd_yuv_blit(unsigned char * const src[3],
|
||||||
int src_x, int src_y, int stride,
|
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);
|
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 "system.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
#include "pcf50606.h"
|
#include "pcf50606.h"
|
||||||
|
#include "backlight.h"
|
||||||
|
#include "backlight-target.h"
|
||||||
|
|
||||||
#ifndef SIMULATOR
|
#ifndef SIMULATOR
|
||||||
|
|
||||||
|
@ -33,21 +35,34 @@ void power_init(void)
|
||||||
|
|
||||||
bool charger_inserted(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 ide_power_enable(bool on)
|
||||||
{
|
{
|
||||||
(void)on;
|
if (on)
|
||||||
|
GPGDAT |= (1 << 11);
|
||||||
|
else
|
||||||
|
GPGDAT &= ~(1 << 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ide_powered(void)
|
bool ide_powered(void)
|
||||||
{
|
{
|
||||||
return true;
|
return (GPGDAT & (1 << 11)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void power_off(void)
|
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 */
|
#else /* SIMULATOR */
|
||||||
|
|
|
@ -24,10 +24,11 @@
|
||||||
|
|
||||||
#define SCL_SDA_HI GPHDAT |= (3 << 9)
|
#define SCL_SDA_HI GPHDAT |= (3 << 9)
|
||||||
|
|
||||||
/* arbitrary delay loop */
|
/* The SC606 can clock at 400KHz: 2.5uS period -> 1.25uS half period */
|
||||||
#define DELAY do { int _x; for(_x=0;_x<2000;_x++);} while (0)
|
/* 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;
|
SCL_SDA_HI;
|
||||||
DELAY;
|
DELAY;
|
||||||
|
@ -36,7 +37,7 @@ void sc606_i2c_start(void)
|
||||||
SCL_LO;
|
SCL_LO;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sc606_i2c_restart(void)
|
static void sc606_i2c_restart(void)
|
||||||
{
|
{
|
||||||
SCL_SDA_HI;
|
SCL_SDA_HI;
|
||||||
DELAY;
|
DELAY;
|
||||||
|
@ -45,7 +46,7 @@ void sc606_i2c_restart(void)
|
||||||
SCL_LO;
|
SCL_LO;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sc606_i2c_stop(void)
|
static void sc606_i2c_stop(void)
|
||||||
{
|
{
|
||||||
SDA_LO;
|
SDA_LO;
|
||||||
DELAY;
|
DELAY;
|
||||||
|
@ -55,7 +56,7 @@ void sc606_i2c_stop(void)
|
||||||
DELAY;
|
DELAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sc606_i2c_ack(void)
|
static void sc606_i2c_ack(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
SDA_LO;
|
SDA_LO;
|
||||||
|
@ -64,11 +65,11 @@ void sc606_i2c_ack(void)
|
||||||
SCL_LO;
|
SCL_LO;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sc606_i2c_getack(void)
|
static int sc606_i2c_getack(void)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
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 */
|
SDA_INPUT; /* And set to input */
|
||||||
SCL_HI;
|
SCL_HI;
|
||||||
DELAY;
|
DELAY;
|
||||||
|
@ -83,7 +84,7 @@ int sc606_i2c_getack(void)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sc606_i2c_outb(unsigned char byte)
|
static int sc606_i2c_outb(unsigned char byte)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -106,7 +107,7 @@ int sc606_i2c_outb(unsigned char byte)
|
||||||
return sc606_i2c_getack();
|
return sc606_i2c_getack();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char sc606_i2c_inb(void)
|
static unsigned char sc606_i2c_inb(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned char byte = 0;
|
unsigned char byte = 0;
|
||||||
|
@ -128,6 +129,8 @@ unsigned char sc606_i2c_inb(void)
|
||||||
return byte;
|
return byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int sc606_write(unsigned char reg, unsigned char data)
|
int sc606_write(unsigned char reg, unsigned char data)
|
||||||
{
|
{
|
||||||
int x = 0;
|
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 <stdbool.h>
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "system.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)
|
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)
|
void usb_enable(bool on)
|
||||||
{
|
{
|
||||||
if(on) {
|
if (on)
|
||||||
int i;
|
{
|
||||||
|
/* make sure ata_en is high */
|
||||||
GPBDAT &= 0x7EF;
|
USB_VPLUS_PWR_ASSERT;
|
||||||
GPBCON |= 1<<8;
|
USB_ATA_ENABLE;
|
||||||
|
|
||||||
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? */
|
|
||||||
}
|
}
|
||||||
|
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 "file.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "i2s.h"
|
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "i2c-meg-fx.h"
|
#include "i2c-meg-fx.h"
|
||||||
/*
|
/*
|
||||||
|
@ -54,10 +53,15 @@ int audiohw_init(void) {
|
||||||
/* reset I2C */
|
/* reset I2C */
|
||||||
i2c_init();
|
i2c_init();
|
||||||
|
|
||||||
|
/* GPC5 controls headphone output */
|
||||||
|
GPCCON &= ~(0x3 << 10);
|
||||||
|
GPCCON |= (1 << 10);
|
||||||
|
GPCDAT |= (1 << 5);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wmcodec_write(int reg, int data)
|
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
|
target_id=20
|
||||||
archos="gigabeatf"
|
archos="gigabeatf"
|
||||||
target="-DGIGABEAT_F"
|
target="-DGIGABEAT_F"
|
||||||
memory=32 # always
|
memory=30 # always
|
||||||
arm9tdmicc
|
arm9tdmicc
|
||||||
tool="cp"
|
tool="cp"
|
||||||
bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"
|
bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue