summaryrefslogtreecommitdiff
path: root/firmware/target/sh
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/sh')
-rw-r--r--firmware/target/sh/adc-sh.c110
-rw-r--r--firmware/target/sh/archos/app.lds145
-rw-r--r--firmware/target/sh/archos/ata-archos.c71
-rw-r--r--firmware/target/sh/archos/ata-as-archos.S233
-rw-r--r--firmware/target/sh/archos/ata-target.h45
-rw-r--r--firmware/target/sh/archos/audio-archos.c543
-rw-r--r--firmware/target/sh/archos/boot.lds81
-rw-r--r--firmware/target/sh/archos/descramble.S121
-rw-r--r--firmware/target/sh/archos/fm_v2/adc-target.h41
-rw-r--r--firmware/target/sh/archos/fm_v2/backlight-target.h51
-rw-r--r--firmware/target/sh/archos/fm_v2/button-fm_v2.c99
-rw-r--r--firmware/target/sh/archos/fm_v2/button-target.h47
-rw-r--r--firmware/target/sh/archos/fm_v2/power-fm_v2.c115
-rw-r--r--firmware/target/sh/archos/fm_v2/powermgmt-fm_v2.c60
-rw-r--r--firmware/target/sh/archos/fm_v2/usb-fm_v2.c49
-rw-r--r--firmware/target/sh/archos/i2c-archos.c254
-rw-r--r--firmware/target/sh/archos/lcd-archos-bitmap.c224
-rw-r--r--firmware/target/sh/archos/lcd-as-archos-bitmap.S354
-rw-r--r--firmware/target/sh/archos/mascodec-archos.c491
-rw-r--r--firmware/target/sh/archos/ondio/adc-target.h37
-rw-r--r--firmware/target/sh/archos/ondio/ata_mmc.c978
-rw-r--r--firmware/target/sh/archos/ondio/backlight-target.h49
-rw-r--r--firmware/target/sh/archos/ondio/button-ondio.c71
-rw-r--r--firmware/target/sh/archos/ondio/button-target.h39
-rw-r--r--firmware/target/sh/archos/ondio/fmradio_i2c-ondio.c202
-rw-r--r--firmware/target/sh/archos/ondio/power-ondio.c78
-rw-r--r--firmware/target/sh/archos/ondio/powermgmt-ondio.c53
-rw-r--r--firmware/target/sh/archos/ondio/usb-ondio.c61
-rw-r--r--firmware/target/sh/archos/player/adc-target.h35
-rw-r--r--firmware/target/sh/archos/player/backlight-target.h46
-rw-r--r--firmware/target/sh/archos/player/button-player.c76
-rw-r--r--firmware/target/sh/archos/player/button-target.h52
-rw-r--r--firmware/target/sh/archos/player/hwcompat-player.c28
-rw-r--r--firmware/target/sh/archos/player/lcd-as-player.S274
-rw-r--r--firmware/target/sh/archos/player/lcd-player.c213
-rw-r--r--firmware/target/sh/archos/player/power-player.c84
-rw-r--r--firmware/target/sh/archos/player/powermgmt-player.c64
-rw-r--r--firmware/target/sh/archos/player/usb-player.c44
-rw-r--r--firmware/target/sh/archos/recorder/adc-target.h41
-rw-r--r--firmware/target/sh/archos/recorder/backlight-target.h51
-rw-r--r--firmware/target/sh/archos/recorder/button-recorder.c110
-rw-r--r--firmware/target/sh/archos/recorder/button-target.h59
-rw-r--r--firmware/target/sh/archos/recorder/power-recorder.c107
-rw-r--r--firmware/target/sh/archos/recorder/powermgmt-recorder.c501
-rw-r--r--firmware/target/sh/archos/recorder/powermgmt-target.h89
-rw-r--r--firmware/target/sh/archos/recorder/usb-recorder.c49
-rw-r--r--firmware/target/sh/archos/timer-archos.c84
-rw-r--r--firmware/target/sh/archos/uart-archos.c167
-rw-r--r--firmware/target/sh/bitswap.S152
-rw-r--r--firmware/target/sh/crt0.S219
-rw-r--r--firmware/target/sh/debug-sh.c285
-rw-r--r--firmware/target/sh/kernel-sh.c65
-rw-r--r--firmware/target/sh/system-sh.c450
-rw-r--r--firmware/target/sh/system-target.h154
54 files changed, 0 insertions, 8201 deletions
diff --git a/firmware/target/sh/adc-sh.c b/firmware/target/sh/adc-sh.c
deleted file mode 100644
index 2e6d6407b8..0000000000
--- a/firmware/target/sh/adc-sh.c
+++ /dev/null
@@ -1,110 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "cpu.h"
23#include "system.h"
24#include "kernel.h"
25#include "thread.h"
26#include "string.h"
27#include "adc.h"
28
29/**************************************************************************
30 ** The A/D conversion is done every tick, in three steps:
31 **
32 ** 1) On the tick interrupt, the conversion of channels 0-3 is started, and
33 ** the A/D interrupt is enabled.
34 **
35 ** 2) After the conversion is done (approx. 256*4 cycles later), an interrupt
36 ** is generated at level 1, which is the same level as the tick interrupt
37 ** itself. This interrupt will be pending until the tick interrupt is
38 ** finished.
39 ** When the A/D interrupt is finally served, it will read the results
40 ** from the first conversion and start the conversion of channels 4-7.
41 **
42 ** 3) When the conversion of channels 4-7 is finished, the interrupt is
43 ** triggered again, and the results are read. This time, no new
44 ** conversion is started, it will be done in the next tick interrupt.
45 **
46 ** Thus, each channel will be updated HZ times per second.
47 **
48 *************************************************************************/
49
50static int current_channel;
51static unsigned short adcdata[NUM_ADC_CHANNELS];
52
53static void adc_tick(void)
54{
55 /* Start a conversion of channel group 0. This will trigger an interrupt,
56 and the interrupt handler will take care of group 1. */
57
58 current_channel = 0;
59 ADCSR = ADCSR_ADST | ADCSR_ADIE | ADCSR_SCAN | 3;
60}
61
62void ADITI(void) __attribute__((interrupt_handler));
63void ADITI(void)
64{
65 if(ADCSR & ADCSR_ADF)
66 {
67 ADCSR = 0;
68
69 if(current_channel == 0)
70 {
71 adcdata[0] = ADDRA >> 6;
72 adcdata[1] = ADDRB >> 6;
73 adcdata[2] = ADDRC >> 6;
74 adcdata[3] = ADDRD >> 6;
75 current_channel = 4;
76
77 /* Convert the next group */
78 ADCSR = ADCSR_ADST | ADCSR_ADIE | ADCSR_SCAN | 7;
79 }
80 else
81 {
82 adcdata[4] = ADDRA >> 6;
83 adcdata[5] = ADDRB >> 6;
84 adcdata[6] = ADDRC >> 6;
85 adcdata[7] = ADDRD >> 6;
86 }
87 }
88}
89
90unsigned short adc_read(int channel)
91{
92 return adcdata[channel];
93}
94
95void adc_init(void)
96{
97 ADCR = 0x7f; /* No external trigger; other bits should be 1 according
98 to the manual... */
99
100 ADCSR = 0;
101
102 current_channel = 0;
103
104 /* Enable the A/D IRQ on level 1 */
105 IPRE = (IPRE & 0xf0ff) | 0x0100;
106
107 tick_add_task(adc_tick);
108
109 sleep(2); /* Ensure valid readings when adc_init returns */
110}
diff --git a/firmware/target/sh/archos/app.lds b/firmware/target/sh/archos/app.lds
deleted file mode 100644
index 225f11f705..0000000000
--- a/firmware/target/sh/archos/app.lds
+++ /dev/null
@@ -1,145 +0,0 @@
1#include "config.h"
2
3ENTRY(start)
4
5OUTPUT_FORMAT(elf32-sh)
6STARTUP(target/sh/crt0.o)
7
8#define PLUGINSIZE PLUGIN_BUFFER_SIZE
9#define CODECSIZE CODEC_SIZE
10
11#ifdef DEBUG
12#define STUBOFFSET 0x10000
13#else
14#define STUBOFFSET 0
15#endif
16
17#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGINSIZE - STUBOFFSET - CODECSIZE
18
19#define DRAMORIG 0x09000000 + STUBOFFSET
20#define IRAMORIG 0x0f000000
21#define IRAMSIZE 0x1000
22
23/* End of the audio buffer, where the codec buffer starts */
24#define ENDAUDIOADDR (DRAMORIG + DRAMSIZE)
25
26/* Where the codec buffer ends, and the plugin buffer starts */
27#define ENDADDR (ENDAUDIOADDR + CODECSIZE)
28
29MEMORY
30{
31 DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
32 IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
33}
34
35SECTIONS
36{
37 .vectors :
38 {
39 loadaddress = .;
40 _loadaddress = .;
41 KEEP(*(.resetvectors));
42 *(.resetvectors);
43 KEEP(*(.vectors));
44 *(.vectors);
45 } > DRAM
46
47 .text :
48 {
49 . = ALIGN(0x200);
50 *(.init.text)
51 *(.text*)
52 . = ALIGN(0x4);
53 } > DRAM
54
55 .rodata :
56 {
57 *(.rodata) /* problems without this, dunno why */
58 *(.rodata*)
59 *(.rodata.str1.1)
60 *(.rodata.str1.4)
61 . = ALIGN(0x4);
62
63 /* Pseudo-allocate the copies of the data sections */
64 _datacopy = .;
65 } > DRAM
66
67 /* TRICK ALERT! For RAM execution, we put the .data section at the
68 same load address as the copy. Thus, we don't waste extra RAM
69 when we don't actually need the copy. */
70 .data : AT ( _datacopy )
71 {
72 _datastart = .;
73 *(.data*)
74 . = ALIGN(0x4);
75 _dataend = .;
76 } > DRAM
77
78 /DISCARD/ :
79 {
80 *(.eh_frame)
81 }
82
83 .iram IRAMORIG :
84 {
85 _iramstart = .;
86 *(.icode)
87 *(.irodata)
88 *(.idata)
89 _iramend = .;
90 } > IRAM AT> DRAM
91
92 _iramcopy = LOADADDR(.iram);
93 _noloaddram = LOADADDR(.iram);
94
95 .ibss (NOLOAD) :
96 {
97 _iedata = .;
98 *(.ibss)
99 . = ALIGN(0x4);
100 _iend = .;
101 } > IRAM
102
103 .stack _noloaddram (NOLOAD) :
104 {
105 *(.stack)
106 _stackbegin = .;
107 . += 0x2000;
108 _stackend = .;
109 } > DRAM
110
111 .bss (NOLOAD) :
112 {
113 _edata = .;
114 *(.bss*)
115 *(COMMON)
116 . = ALIGN(0x4);
117 _end = .;
118 } > DRAM
119
120 .audiobuf (NOLOAD) :
121 {
122 . = ALIGN(4);
123 _audiobuffer = .;
124 audiobuffer = .;
125 } > DRAM
126
127 .audiobufend ENDAUDIOADDR (NOLOAD) :
128 {
129 audiobufend = .;
130 _audiobufend = .;
131 } > DRAM
132
133 .codec ENDAUDIOADDR (NOLOAD) :
134 {
135 codecbuf = .;
136 _codecbuf = .;
137 }
138
139 .plugin ENDADDR (NOLOAD) :
140 {
141 _pluginbuf = .;
142 pluginbuf = .;
143 }
144}
145
diff --git a/firmware/target/sh/archos/ata-archos.c b/firmware/target/sh/archos/ata-archos.c
deleted file mode 100644
index 2046d3b33f..0000000000
--- a/firmware/target/sh/archos/ata-archos.c
+++ /dev/null
@@ -1,71 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "cpu.h"
24#include <stdbool.h>
25#include "kernel.h"
26#include "system.h"
27#include "ata-driver.h"
28#include "hwcompat.h"
29
30#define ATA_CONTROL1 ((volatile unsigned char*)0x06200206)
31#define ATA_CONTROL2 ((volatile unsigned char*)0x06200306)
32
33volatile unsigned char* ata_control;
34
35void ata_reset(void)
36{
37 /* state HRR0 */
38 and_b(~0x02, &PADRH); /* assert _RESET */
39 sleep(1); /* > 25us */
40
41 /* state HRR1 */
42 or_b(0x02, &PADRH); /* negate _RESET */
43 sleep(1); /* > 2ms */
44}
45
46void ata_enable(bool on)
47{
48 if(on)
49 and_b(~0x80, &PADRL); /* enable ATA */
50 else
51 or_b(0x80, &PADRL); /* disable ATA */
52
53 or_b(0x80, &PAIORL);
54}
55
56void ata_device_init(void)
57{
58 or_b(0x02, &PAIORH); /* output for ATA reset */
59 or_b(0x02, &PADRH); /* release ATA reset */
60 PACR2 &= 0xBFFF; /* GPIO function for PA7 (IDE enable) */
61
62 if (HW_MASK & ATA_ADDRESS_200)
63 ata_control = ATA_CONTROL1;
64 else
65 ata_control = ATA_CONTROL2;
66}
67
68bool ata_is_coldstart(void)
69{
70 return (PACR2 & 0x4000) != 0;
71}
diff --git a/firmware/target/sh/archos/ata-as-archos.S b/firmware/target/sh/archos/ata-as-archos.S
deleted file mode 100644
index c403c4c921..0000000000
--- a/firmware/target/sh/archos/ata-as-archos.S
+++ /dev/null
@@ -1,233 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004-2006 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22 .section .icode,"ax",@progbits
23
24 .align 2
25 .global _copy_read_sectors
26 .type _copy_read_sectors,@function
27
28/* Read a number of words from the ATA data port
29 *
30 * Assumes wordcount to be a multiple of 4
31 *
32 * Arguments:
33 * r4 - buffer address
34 * r5 - word count
35 *
36 * Register usage:
37 * r0 - scratch
38 * r1/r2 - read buffers
39 * r3 - mask (if unaligned)
40 * r4 - current address
41 * r5 - end address
42 * r6 - ata port
43 */
44
45_copy_read_sectors:
46 add r5, r5 /* words -> bytes */
47 add r4, r5 /* bytes -> end address */
48 add #-12, r5 /* adjust for offsets */
49 mov.l .ata_data, r6
50
51 mov r4, r0
52 tst #1, r0 /* 16-bit aligned ? */
53 bt .r_aligned /* yes, do word copy */
54
55 /* not 16-bit aligned */
56 mov #-1, r3 /* prepare a bit mask for high byte */
57 shll8 r3 /* r3 = 0xFFFFFF00 */
58
59 mov.w @r6, r2 /* read first word (1st round) */
60 mov.b r2, @r4 /* store low byte of first word */
61 bra .r_start_b /* jump into loop after next instr. */
62 add #-5, r4 /* adjust for dest. offsets; now even */
63
64 .align 2
65.r_loop_b: /* main loop: copy 4 words in a row */
66 mov.w @r6, r2 /* read first word (2+ round) */
67 and r3, r1 /* get high byte of fourth word (2+ round) */
68 extu.b r2, r0 /* get low byte of first word (2+ round) */
69 or r1, r0 /* combine with high byte of fourth word */
70 mov.w r0, @(4, r4) /* store at buf[4] */
71 nop /* maintain alignment */
72.r_start_b:
73 mov.w @r6, r1 /* read second word */
74 and r3, r2 /* get high byte of first word */
75 extu.b r1, r0 /* get low byte of second word */
76 or r2, r0 /* combine with high byte of first word */
77 mov.w r0, @(6, r4) /* store at buf[6] */
78 add #8, r4 /* buf += 8 */
79 mov.w @r6, r2 /* read third word */
80 and r3, r1 /* get high byte of second word */
81 extu.b r2, r0 /* get low byte of third word */
82 or r1, r0 /* combine with high byte of second word */
83 mov.w r0, @r4 /* store at buf[0] */
84 cmp/hi r4, r5 /* check for end */
85 mov.w @r6, r1 /* read fourth word */
86 and r3, r2 /* get high byte of third word */
87 extu.b r1, r0 /* get low byte of fourth word */
88 or r2, r0 /* combine with high byte of third word */
89 mov.w r0, @(2, r4) /* store at buf[2] */
90 bt .r_loop_b
91 /* 24 instructions for 4 copies, takes 30 clock cycles (4 wait) */
92 /* avg. 7.5 cycles per word */
93
94 swap.b r1, r0 /* get high byte of last word */
95 rts
96 mov.b r0, @(4, r4) /* and store it */
97
98 /* 16-bit aligned, loop(read and store word) */
99.r_aligned:
100 mov.w @r6, r2 /* read first word (1st round) */
101 bra .r_start_w /* jump into loop after next instr. */
102 add #-6, r4 /* adjust for destination offsets */
103
104 .align 2
105.r_loop_w: /* main loop: copy 4 words in a row */
106 mov.w @r6, r2 /* read first word (2+ round) */
107 swap.b r1, r0 /* swap fourth word (2+ round) */
108 mov.w r0, @(4, r4) /* store fourth word (2+ round) */
109 nop /* maintain alignment */
110.r_start_w:
111 mov.w @r6, r1 /* read second word */
112 swap.b r2, r0 /* swap first word */
113 mov.w r0, @(6, r4) /* store first word in buf[6] */
114 add #8, r4 /* buf += 8 */
115 mov.w @r6, r2 /* read third word */
116 swap.b r1, r0 /* swap second word */
117 mov.w r0, @r4 /* store second word in buf[0] */
118 cmp/hi r4, r5 /* check for end */
119 mov.w @r6, r1 /* read fourth word */
120 swap.b r2, r0 /* swap third word */
121 mov.w r0, @(2, r4) /* store third word */
122 bt .r_loop_w
123 /* 16 instructions for 4 copies, takes 22 clock cycles (4 wait) */
124 /* avg. 5.5 cycles per word */
125
126 swap.b r1, r0 /* swap fourth word (last round) */
127 rts
128 mov.w r0, @(4, r4) /* and store it */
129
130.r_end:
131 .size _copy_read_sectors,.r_end-_copy_read_sectors
132
133 .align 2
134 .global _copy_write_sectors
135 .type _copy_write_sectors,@function
136
137/* Write a number of words to the ATA data port
138 *
139 * Assumes wordcount to be a multiple of 2.
140 * Writing is not unrolled as much as reading, for several reasons:
141 *
142 * - a similar instruction sequence is faster for writing than for reading
143 * because the auto-incrementing load instructions can be used
144 * - writing profits from warp mode
145 *
146 * Both of these add up to have writing faster than the more unrolled reading.
147 *
148 * Arguments:
149 * r4 - buffer address
150 * r5 - word count
151 *
152 * Register usage:
153 * r0/r1 - scratch
154 * r2/r3 - write buffers
155 * r4 - current address
156 * r5 - end address
157 * r6 - mask (if unaligned)
158 * r7 - ata port
159 */
160
161_copy_write_sectors:
162 add r5, r5 /* words -> bytes */
163 add r4, r5 /* bytes -> end address */
164 add #-4, r5 /* adjust for offsets */
165 mov.l .ata_data, r7
166
167 mov r4, r0
168 tst #1, r0 /* 16-bit aligned ? */
169 bt .w_aligned /* yes, do word copy */
170
171 /* not 16-bit aligned */
172 mov #-1, r6 /* prepare a bit mask for high byte */
173 shll8 r6 /* r6 = 0xFFFFFF00 */
174
175 mov.b @r4+, r2 /* load (initial old second) first byte */
176 mov.w @r4+, r3 /* load (initial) first word */
177 bra .w_start_b
178 extu.b r2, r0 /* extend unsigned */
179
180 .align 2
181.w_loop_b: /* main loop: copy 2 words in a row */
182 mov.w @r4+, r3 /* load first word (2+ round) */
183 extu.b r2, r0 /* put away low byte of second word (2+ round) */
184 and r6, r2 /* get high byte of second word (2+ round) */
185 or r1, r2 /* combine with low byte of old first word */
186 mov.w r2, @r7 /* write that */
187.w_start_b:
188 cmp/hi r4, r5 /* check for end */
189 mov.w @r4+, r2 /* load second word */
190 extu.b r3, r1 /* put away low byte of first word */
191 and r6, r3 /* get high byte of first word */
192 or r0, r3 /* combine with high byte of old second word */
193 mov.w r3, @r7 /* write that */
194 bt .w_loop_b
195 /* 12 instructions for 2 copies, takes 14 clock cycles */
196 /* avg. 7 cycles per word */
197
198 /* the loop "overreads" 1 byte past the buffer end, however, the last */
199 /* byte is not written to disk */
200 and r6, r2 /* get high byte of last word */
201 or r1, r2 /* combine with low byte of old first word */
202 rts
203 mov.w r2, @r7 /* write last word */
204
205 /* 16-bit aligned, loop(load and write word) */
206.w_aligned:
207 bra .w_start_w /* jump into loop after next instr. */
208 mov.w @r4+, r2 /* load first word (1st round) */
209
210 .align 2
211.w_loop_w: /* main loop: copy 2 words in a row */
212 mov.w @r4+, r2 /* load first word (2+ round) */
213 swap.b r1, r0 /* swap second word (2+ round) */
214 mov.w r0, @r7 /* write second word (2+ round) */
215.w_start_w:
216 cmp/hi r4, r5 /* check for end */
217 mov.w @r4+, r1 /* load second word */
218 swap.b r2, r0 /* swap first word */
219 mov.w r0, @r7 /* write first word */
220 bt .w_loop_w
221 /* 8 instructions for 2 copies, takes 10 clock cycles */
222 /* avg. 5 cycles per word */
223
224 swap.b r1, r0 /* swap second word (last round) */
225 rts
226 mov.w r0, @r7 /* and write it */
227
228.w_end:
229 .size _copy_write_sectors,.w_end-_copy_write_sectors
230
231 .align 2
232.ata_data:
233 .long 0x06104100 /* ATA data port */
diff --git a/firmware/target/sh/archos/ata-target.h b/firmware/target/sh/archos/ata-target.h
deleted file mode 100644
index dc55cdd5d5..0000000000
--- a/firmware/target/sh/archos/ata-target.h
+++ /dev/null
@@ -1,45 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef ATA_TARGET_H
22#define ATA_TARGET_H
23
24/* asm optimised read & write loops */
25#define ATA_OPTIMIZED_READING
26#define ATA_OPTIMIZED_WRITING
27
28#define ATA_SWAP_WORDS
29
30#define ATA_IOBASE 0x06100100
31#define ATA_DATA (*((volatile unsigned short*)0x06104100))
32#define ATA_CONTROL (*ata_control)
33
34#define ATA_ERROR (*((volatile unsigned char*)ATA_IOBASE + 1))
35#define ATA_NSECTOR (*((volatile unsigned char*)ATA_IOBASE + 2))
36#define ATA_SECTOR (*((volatile unsigned char*)ATA_IOBASE + 3))
37#define ATA_LCYL (*((volatile unsigned char*)ATA_IOBASE + 4))
38#define ATA_HCYL (*((volatile unsigned char*)ATA_IOBASE + 5))
39#define ATA_SELECT (*((volatile unsigned char*)ATA_IOBASE + 6))
40#define ATA_COMMAND (*((volatile unsigned char*)ATA_IOBASE + 7))
41
42extern volatile unsigned char* ata_control;
43
44
45#endif
diff --git a/firmware/target/sh/archos/audio-archos.c b/firmware/target/sh/archos/audio-archos.c
deleted file mode 100644
index 2c2579bec5..0000000000
--- a/firmware/target/sh/archos/audio-archos.c
+++ /dev/null
@@ -1,543 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Code that has been in mpeg.c before, now creating an encapsulated play
11 * data module, to be used by other sources than file playback as well.
12 *
13 * Copyright (C) 2004 by Linus Nielsen Feltzing
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24#include <stdbool.h>
25#include "config.h"
26#include "debug.h"
27#include "panic.h"
28#include <kernel.h>
29#include "mp3_playback.h"
30#include "sound.h"
31#include "i2c.h"
32#include "system.h"
33#include "audiohw.h"
34
35/* hacking into mpeg.c, recording is still there */
36#if CONFIG_CODEC == MAS3587F
37enum
38{
39 MPEG_DECODER,
40 MPEG_ENCODER
41} mpeg_mode;
42#endif /* #ifdef MAS3587F */
43
44#if ((CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)) && !defined(SIMULATOR)
45extern unsigned long shadow_io_control_main;
46extern unsigned shadow_codec_reg0;
47#endif
48
49/**** globals ****/
50
51/* own version, independent of mpeg.c */
52static bool paused; /* playback is paused */
53static bool playing; /* We are playing an MP3 stream */
54
55/* the registered callback function to ask for more mp3 data */
56static mp3_play_callback_t callback_for_more;
57
58/* list of tracks in memory */
59#define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */
60#define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)
61
62bool audio_is_initialized = false;
63
64/* FIX: this code pretty much assumes a MAS */
65
66/* dirty calls to mpeg.c */
67extern void playback_tick(void);
68extern void rec_tick(void);
69
70unsigned long mas_version_code;
71
72#if CONFIG_CODEC == MAS3507D
73static void mas_poll_start(void)
74{
75 unsigned int count;
76
77 count = 9 * FREQ / 10000 / 8; /* 0.9 ms */
78
79 /* We are using timer 1 */
80
81 TSTR &= ~0x02; /* Stop the timer */
82 TSNC &= ~0x02; /* No synchronization */
83 TMDR &= ~0x02; /* Operate normally */
84
85 TCNT1 = 0; /* Start counting at 0 */
86 GRA1 = count;
87 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
88
89 /* Enable interrupt on level 5 */
90 IPRC = (IPRC & ~0x000f) | 0x0005;
91
92 TSR1 &= ~0x02;
93 TIER1 = 0xf9; /* Enable GRA match interrupt */
94
95 TSTR |= 0x02; /* Start timer 1 */
96}
97#elif CONFIG_CODEC != SWCODEC
98static void postpone_dma_tick(void)
99{
100 unsigned int count;
101
102 count = 8 * FREQ / 10000 / 8; /* 0.8 ms */
103
104 /* We are using timer 1 */
105
106 TSTR &= ~0x02; /* Stop the timer */
107 TSNC &= ~0x02; /* No synchronization */
108 TMDR &= ~0x02; /* Operate normally */
109
110 TCNT1 = 0; /* Start counting at 0 */
111 GRA1 = count;
112 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
113
114 /* Enable interrupt on level 5 */
115 IPRC = (IPRC & ~0x000f) | 0x0005;
116
117 TSR1 &= ~0x02;
118 TIER1 = 0xf9; /* Enable GRA match interrupt */
119
120 TSTR |= 0x02; /* Start timer 1 */
121}
122#endif
123
124#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
125void demand_irq_enable(bool on)
126{
127 int oldlevel = disable_irq_save();
128
129 if(on)
130 {
131 IPRA = (IPRA & 0xfff0) | 0x000b;
132 ICR &= ~0x0010; /* IRQ3 level sensitive */
133 }
134 else
135 IPRA &= 0xfff0;
136
137 restore_irq(oldlevel);
138}
139#endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
140
141
142static void play_tick(void)
143{
144 if(playing && !paused)
145 {
146 /* Start DMA if it is disabled and the DEMAND pin is high */
147 if(!(SCR0 & 0x80) && (PBDR & 0x4000))
148 {
149 SCR0 |= 0x80;
150 }
151
152 playback_tick(); /* dirty call to mpeg.c */
153 }
154}
155
156void DEI3(void) __attribute__((interrupt_handler));
157void DEI3(void)
158{
159 const void* start;
160 size_t size = 0;
161
162 if (callback_for_more != NULL)
163 {
164 callback_for_more(&start, &size);
165 }
166
167 if (size > 0)
168 {
169 DTCR3 = size & 0xffff;
170 SAR3 = (unsigned int) start;
171 }
172 else
173 {
174 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
175 }
176
177 CHCR3 &= ~0x0002; /* Clear DMA interrupt */
178}
179
180void IMIA1(void) __attribute__((interrupt_handler));
181void IMIA1(void) /* Timer 1 interrupt */
182{
183 if(playing)
184 play_tick();
185 TSR1 &= ~0x01;
186#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
187 /* Disable interrupt */
188 IPRC &= ~0x000f;
189#endif
190}
191
192void IRQ6(void) __attribute__((interrupt_handler));
193void IRQ6(void) /* PB14: MAS stop demand IRQ */
194{
195 SCR0 &= ~0x80;
196}
197
198#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
199void IRQ3(void) __attribute__((interrupt_handler));
200void IRQ3(void) /* PA15: MAS demand IRQ */
201{
202 /* Begin with setting the IRQ to edge sensitive */
203 ICR |= 0x0010;
204
205#if CONFIG_CODEC == MAS3587F
206 if(mpeg_mode == MPEG_ENCODER)
207 rec_tick();
208 else
209#endif
210 postpone_dma_tick();
211
212 /* Workaround for sh-elf-gcc 3.3.x bug with -O2 or -Os and ISRs
213 * (invalid cross-jump optimisation) */
214 asm volatile ("");
215}
216#endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
217
218static void setup_sci0(void)
219{
220 /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0, PB9 is TxD0 */
221 PBCR1 = (PBCR1 & 0x0cff) | 0x1208;
222
223 /* Set PB12 to output */
224 or_b(0x10, &PBIORH);
225
226 /* Disable serial port */
227 SCR0 = 0x00;
228
229 /* Synchronous, no prescale */
230 SMR0 = 0x80;
231
232 /* Set baudrate 1Mbit/s */
233 BRR0 = 0x02;
234
235 /* use SCK as serial clock output */
236 SCR0 = 0x01;
237
238 /* Clear FER and PER */
239 SSR0 &= 0xe7;
240
241 /* Set interrupt ITU2 and SCI0 priority to 0 */
242 IPRD &= 0x0ff0;
243
244 /* set PB15 and PB14 to inputs */
245 and_b(~0x80, &PBIORH);
246 and_b(~0x40, &PBIORH);
247
248 /* Enable End of DMA interrupt at prio 8 */
249 IPRC = (IPRC & 0xf0ff) | 0x0800;
250
251 /* Enable Tx (only!) */
252 SCR0 |= 0x20;
253}
254
255#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
256static void init_playback(void)
257{
258 unsigned long val;
259 int rc;
260
261 mp3_play_pause(false);
262
263 mas_reset();
264
265 /* Enable the audio CODEC and the DSP core, max analog voltage range */
266 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
267 if(rc < 0)
268 panicf("mas_ctrl_w: %d", rc);
269
270 /* Stop the current application */
271 val = 0;
272 mas_writemem(MAS_BANK_D0, MAS_D0_APP_SELECT, &val, 1);
273 do
274 {
275 mas_readmem(MAS_BANK_D0, MAS_D0_APP_RUNNING, &val, 1);
276 } while(val);
277
278 /* Enable the D/A Converter */
279 shadow_codec_reg0 = 0x0001;
280 mas_codec_writereg(0x0, shadow_codec_reg0);
281
282 /* ADC scale 0%, DSP scale 100% */
283 mas_codec_writereg(6, 0x0000);
284 mas_codec_writereg(7, 0x4000);
285
286#ifdef HAVE_SPDIF_OUT
287 val = 0x09; /* Disable SDO and SDI, low impedance S/PDIF outputs */
288#else
289 val = 0x2d; /* Disable SDO and SDI, disable S/PDIF output */
290#endif
291 mas_writemem(MAS_BANK_D0, MAS_D0_INTERFACE_CONTROL, &val, 1);
292
293 /* Set Demand mode and validate all settings */
294 shadow_io_control_main = 0x25;
295 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
296
297 /* Start the Layer2/3 decoder applications */
298 val = 0x0c;
299 mas_writemem(MAS_BANK_D0, MAS_D0_APP_SELECT, &val, 1);
300 do
301 {
302 mas_readmem(MAS_BANK_D0, MAS_D0_APP_RUNNING, &val, 1);
303 } while((val & 0x0c) != 0x0c);
304
305#if CONFIG_CODEC == MAS3587F
306 mpeg_mode = MPEG_DECODER;
307#endif
308
309 /* set IRQ6 to edge detect */
310 ICR |= 0x02;
311
312 /* set IRQ6 prio 8 */
313 IPRB = ( IPRB & 0xff0f ) | 0x0080;
314
315 DEBUGF("MAS Decoding application started\n");
316}
317#endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
318
319void mp3_init(int volume, int bass, int treble, int balance, int loudness,
320 int avc, int channel_config, int stereo_width,
321 int mdb_strength, int mdb_harmonics,
322 int mdb_center, int mdb_shape, bool mdb_enable,
323 bool superbass)
324{
325#if CONFIG_CODEC == MAS3507D
326 unsigned long val;
327 (void)loudness;
328 (void)avc;
329 (void)mdb_strength;
330 (void)mdb_harmonics;
331 (void)mdb_center;
332 (void)mdb_shape;
333 (void)mdb_enable;
334 (void)superbass;
335#endif
336
337 setup_sci0();
338
339#ifdef HAVE_MAS_SIBI_CONTROL
340 and_b(~0x01, &PBDRH); /* drive SIBI low */
341 or_b(0x01, &PBIORH); /* output for PB8 */
342#endif
343
344#if CONFIG_CODEC == MAS3507D
345 mas_reset();
346#elif CONFIG_CODEC == MAS3587F
347 or_b(0x08, &PAIORH); /* output for /PR */
348 init_playback();
349
350 mas_version_code = mas_readver();
351 DEBUGF("MAS3587 derivate %d, version %c%d\n",
352 (mas_version_code & 0xf000) >> 12,
353 'A' + ((mas_version_code & 0x0f00) >> 8), mas_version_code & 0xff);
354#elif CONFIG_CODEC == MAS3539F
355 or_b(0x08, &PAIORH); /* output for /PR */
356 init_playback();
357
358 mas_version_code = mas_readver();
359 DEBUGF("MAS3539 derivate %d, version %c%d\n",
360 (mas_version_code & 0xf000) >> 12,
361 'A' + ((mas_version_code & 0x0f00) >> 8), mas_version_code & 0xff);
362#endif
363
364#ifdef HAVE_DAC3550A
365 dac_init();
366#endif
367
368#if CONFIG_CODEC == MAS3507D
369 /* set IRQ6 to edge detect */
370 ICR |= 0x02;
371
372 /* set IRQ6 prio 8 */
373 IPRB = ( IPRB & 0xff0f ) | 0x0080;
374
375 mas_readmem(MAS_BANK_D1, 0xff7, &mas_version_code, 1);
376
377 mas_writereg(0x3b, 0x20); /* Don't ask why. The data sheet doesn't say */
378 mas_run(1);
379 sleep(HZ);
380
381 /* Clear the upper 12 bits of the 32-bit samples */
382 mas_writereg(0xc5, 0);
383 mas_writereg(0xc6, 0);
384
385 /* We need to set the PLL for a 14.31818MHz crystal */
386 if(mas_version_code == 0x0601) /* Version F10? */
387 {
388 val = 0x5d9d0;
389 mas_writemem(MAS_BANK_D0, 0x32d, &val, 1);
390 val = 0xfffceceb;
391 mas_writemem(MAS_BANK_D0, 0x32e, &val, 1);
392 val = 0x0;
393 mas_writemem(MAS_BANK_D0, 0x32f, &val, 1);
394 mas_run(0x475);
395 }
396 else
397 {
398 val = 0x5d9d0;
399 mas_writemem(MAS_BANK_D0, 0x36d, &val, 1);
400 val = 0xfffceceb;
401 mas_writemem(MAS_BANK_D0, 0x36e, &val, 1);
402 val = 0x0;
403 mas_writemem(MAS_BANK_D0, 0x36f, &val, 1);
404 mas_run(0xfcb);
405 }
406
407#endif
408
409#if CONFIG_CODEC == MAS3507D
410 mas_poll_start();
411
412 mas_writereg(MAS_REG_KPRESCALE, 0xe9400);
413 dac_enable(true);
414#endif
415
416#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
417 ICR &= ~0x0010; /* IRQ3 level sensitive */
418 PACR1 = (PACR1 & 0x3fff) | 0x4000; /* PA15 is IRQ3 */
419#endif
420
421 /* Must be done before calling sound_set() */
422 audio_is_initialized = true;
423
424 sound_set(SOUND_BASS, bass);
425 sound_set(SOUND_TREBLE, treble);
426 sound_set(SOUND_BALANCE, balance);
427 sound_set(SOUND_VOLUME, volume);
428 sound_set(SOUND_CHANNELS, channel_config);
429 sound_set(SOUND_STEREO_WIDTH, stereo_width);
430
431#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
432 sound_set(SOUND_LOUDNESS, loudness);
433 sound_set(SOUND_AVC, avc);
434 sound_set(SOUND_MDB_STRENGTH, mdb_strength);
435 sound_set(SOUND_MDB_HARMONICS, mdb_harmonics);
436 sound_set(SOUND_MDB_CENTER, mdb_center);
437 sound_set(SOUND_MDB_SHAPE, mdb_shape);
438 sound_set(SOUND_MDB_ENABLE, mdb_enable);
439 sound_set(SOUND_SUPERBASS, superbass);
440#endif
441
442 playing = false;
443 paused = true;
444}
445
446void mp3_shutdown(void)
447{
448#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
449 unsigned long val = 1;
450 mas_writemem(MAS_BANK_D0, MAS_D0_SOFT_MUTE, &val, 1); /* Mute */
451#endif
452
453#if CONFIG_CODEC == MAS3507D
454 dac_volume(0, 0, false);
455#endif
456}
457
458/* new functions, to be exported to plugin API */
459
460#if CONFIG_CODEC == MAS3587F
461void mp3_play_init(void)
462{
463#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
464 init_playback();
465#endif
466 playing = false;
467 paused = true;
468 callback_for_more = NULL;
469}
470#endif
471
472void mp3_play_data(const void* start, size_t size,
473 mp3_play_callback_t get_more)
474{
475 /* init DMA */
476 DAR3 = 0x5FFFEC3;
477 CHCR3 &= ~0x0002; /* Clear interrupt */
478 CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
479 DMAOR = 0x0001; /* Enable DMA */
480
481 callback_for_more = get_more;
482
483 SAR3 = (unsigned int)start;
484 DTCR3 = size & 0xffff;
485
486 playing = true;
487 paused = true;
488
489 CHCR3 |= 0x0001; /* Enable DMA IRQ */
490
491#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
492 demand_irq_enable(true);
493#endif
494}
495
496void mp3_play_pause(bool play)
497{
498 if (paused && play)
499 { /* resume playback */
500 SCR0 |= 0x80;
501 paused = false;
502 }
503 else if (!paused && !play)
504 { /* stop playback */
505 SCR0 &= 0x7f;
506 paused = true;
507 }
508}
509
510bool mp3_pause_done(void)
511{
512 unsigned long frame_count;
513
514 if (!paused)
515 return false;
516
517 mas_readmem(MAS_BANK_D0, MAS_D0_MPEG_FRAME_COUNT, &frame_count, 1);
518 /* This works because the frame counter never wraps,
519 * i.e. zero always means lost sync. */
520 return frame_count == 0;
521}
522
523void mp3_play_stop(void)
524{
525 playing = false;
526 mp3_play_pause(false);
527 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
528#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
529 demand_irq_enable(false);
530#endif
531}
532
533bool mp3_is_playing(void)
534{
535 return playing;
536}
537
538
539/* returns the next byte position which would be transferred */
540unsigned char* mp3_get_pos(void)
541{
542 return (unsigned char*)SAR3;
543}
diff --git a/firmware/target/sh/archos/boot.lds b/firmware/target/sh/archos/boot.lds
deleted file mode 100644
index b3c2c90a6c..0000000000
--- a/firmware/target/sh/archos/boot.lds
+++ /dev/null
@@ -1,81 +0,0 @@
1#include "config.h"
2
3ENTRY(start)
4OUTPUT_FORMAT(elf32-sh)
5STARTUP(target/sh/crt0.o)
6
7#define DRAMSIZE (MEMORYSIZE * 0x100000)
8
9#define DRAMORIG 0x09000000
10#define IRAMORIG 0x0f000000
11#define IRAMSIZE 0x1000
12#define FLASHORIG 0x02000000 + ROM_START
13#define FLASHSIZE 256K - ROM_START
14
15MEMORY
16{
17 DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
18 IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
19 FLASH : ORIGIN = FLASHORIG, LENGTH = FLASHSIZE
20}
21
22SECTIONS
23{
24 .vectors :
25 {
26 _datacopy = .;
27 } > FLASH
28
29 .data : AT ( _datacopy )
30 {
31 _datastart = .;
32 KEEP(*(.resetvectors));
33 *(.resetvectors);
34 KEEP(*(.vectors));
35 *(.vectors);
36 . = ALIGN(0x200);
37 *(.icode)
38 *(.irodata)
39 *(.idata)
40 *(.data*)
41 . = ALIGN(0x4);
42 _dataend = .;
43 . = ALIGN(0x10); /* Maintain proper alignment for .text section */
44 } > IRAM
45
46 /* TRICK ALERT! Newer versions of the linker don't allow output sections
47 to overlap even if one of them is empty, so advance the location pointer
48 "by hand" */
49 .text LOADADDR(.data) + SIZEOF(.data) :
50 {
51 *(.init.text)
52 *(.text*)
53 . = ALIGN(0x4);
54 } > FLASH
55
56 .rodata :
57 {
58 *(.rodata*)
59 . = ALIGN(0x4);
60 _iramcopy = .;
61 } > FLASH
62
63 .stack :
64 {
65 *(.stack)
66 _stackbegin = .;
67 stackbegin = .;
68 . += 0x2000;
69 _stackend = .;
70 stackend = .;
71 } > IRAM
72
73 .bss :
74 {
75 _edata = .;
76 *(.ibss)
77 *(.bss*)
78 *(COMMON)
79 _end = .;
80 } > IRAM
81}
diff --git a/firmware/target/sh/archos/descramble.S b/firmware/target/sh/archos/descramble.S
deleted file mode 100644
index 0ab5e93dce..0000000000
--- a/firmware/target/sh/archos/descramble.S
+++ /dev/null
@@ -1,121 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22 .section .icode,"ax",@progbits
23
24 .align 2 /* this aligns to 2^2=4 byte bounday */
25 .global _descramble
26 .type _descramble,@function
27
28/* Descramble a block of byte data, from source to dest, processing len
29 * bytes. Size only limited by the len argument. Note that len must
30 * be an even multiple of 4 (something rolo_load() already assumes.
31 * (Does the Archos firmware loader also require that?).
32 *
33 * Returns the 16-bit "sum" checksum of the descrambled data.
34 *
35 * Arguments:
36 * r4 - source (unsigned char*)
37 * r5 - dest (unsigned char*)
38 * r6 - len (unsigned int)
39 *
40 * Register usage:
41 * r0 - data
42 * r1 - temp
43 * r2 - checksum
44 * r3 - current src address
45 * r4 - source
46 * r5 - dest
47 * r6 - len -> source_end
48 * r7 - dest_end
49 * r8 - len / 4
50 */
51
52_descramble:
53 mov.l r8,@-r15
54 mov r6,r8
55 shlr2 r8 /* r8 = len / 4 */
56 mov r5,r7
57 add r6,r7 /* dest_end = dest + len */
58 add r4,r6 /* source_end = source + len */
59 mov r4,r3 /* addr = source */
60 mov #0,r2 /* checksum = 0 */
61
62.loop:
63 mov.b @r3,r0 /* data = *addr */
64 add r8,r3 /* addr += len / 4 */
65 extu.b r0,r0 /* zero extend data byte */
66 swap.b r0,r1 /* byte swap low word to temp */
67 or r1,r0 /* r0's two lower bytes now identical */
68 shlr r0 /* -> this equals "rotr.b r0" now */
69 not r0,r0 /* negate */
70 extu.b r0,r0 /* zero extend low byte (only needed for sum) */
71 mov.b r0,@r5 /* *dest = data */
72 add r0,r2 /* checksum += data */
73 add #1,r5 /* dest++ */
74 cmp/hi r3,r6 /* addr < source_end ? */
75 bt .loop
76
77 add #1,r4 /* source++ */
78 mov r4,r3 /* addr = source */
79 cmp/hi r5,r7 /* dest < dest_end */
80 bt .loop
81
82/* 15 clock cycles if no reset of source address, 19 if reset,
83 * avg. 16 cycles per byte. Magnus' Version needed 17-22 cycles per byte
84 */
85
86 mov.l @r15+,r8
87 rts
88 extu.w r2,r0
89
90
91/* Move len bytes from source to dest (which must be suitably aligned for
92 * long moves) and jump to dest + 0x200.
93 *
94 * Arguments:
95 * r4 - source
96 * r5 - dest
97 * r6 - len
98 */
99
100 .align 2
101 .global _rolo_restart
102 .type _rolo_restart,@function
103
104_rolo_restart:
105 mov r5,r0
106 sub r4,r0 /* r0 = dest - source */
107 add #-4,r0 /* adjust for early increment */
108 add r4,r6 /* r6 = source + len */
109
110.copy: /* loop takes 6 cycles per longword */
111 mov.l @r4+,r1
112 cmp/hi r4,r6
113 mov.l r1,@(r0,r4)
114 bt .copy
115
116 mov.l @r5+,r0 /* start address from image */
117 jmp @r0
118 mov.l @r5+,r15 /* stack pointer from image */
119
120.end:
121 .size _descramble,.end-_descramble
diff --git a/firmware/target/sh/archos/fm_v2/adc-target.h b/firmware/target/sh/archos/fm_v2/adc-target.h
deleted file mode 100644
index 0070828cf3..0000000000
--- a/firmware/target/sh/archos/fm_v2/adc-target.h
+++ /dev/null
@@ -1,41 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _ADC_TARGET_H_
22#define _ADC_TARGET_H_
23
24#define NUM_ADC_CHANNELS 8
25
26#define ADC_BATTERY 0 /* Battery voltage always reads 0x3FF due to
27 silly scaling */
28#define ADC_CHARGE_REGULATOR 0 /* Uh, we read the battery voltage? */
29#define ADC_USB_POWER 1 /* USB, reads 0x000 when USB is inserted */
30#define ADC_BUTTON_OFF 2 /* the off button, high value if pressed */
31#define ADC_BUTTON_ON 3 /* the on button, low value if pressed */
32#define ADC_BUTTON_ROW1 4 /* Used for scanning the keys, different
33 voltages for different keys */
34#define ADC_BUTTON_ROW2 5 /* Used for scanning the keys, different
35 voltages for different keys */
36#define ADC_UNREG_POWER 6 /* Battery voltage with a better scaling */
37#define ADC_EXT_POWER 7 /* The external power voltage, 0v or 2.7v */
38
39#define EXT_SCALE_FACTOR 14800
40
41#endif /* _ADC_TARGET_H_ */
diff --git a/firmware/target/sh/archos/fm_v2/backlight-target.h b/firmware/target/sh/archos/fm_v2/backlight-target.h
deleted file mode 100644
index c3dd395eca..0000000000
--- a/firmware/target/sh/archos/fm_v2/backlight-target.h
+++ /dev/null
@@ -1,51 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef BACKLIGHT_TARGET_H
22#define BACKLIGHT_TARGET_H
23
24#include "config.h"
25#include "rtc.h"
26
27#define backlight_hw_init() true
28
29static inline void backlight_hw_on(void)
30{
31 rtc_write(0x13, 0x10); /* 32 kHz square wave */
32 rtc_write(0x0a, rtc_read(0x0a) | 0x40); /* Enable square wave */
33}
34
35static inline void backlight_hw_off(void)
36{
37 /* While on, backlight is flashing at 32 kHz. If the square wave output
38 is disabled while the backlight is lit, it will become constantly lit,
39 (brighter) and slowly fade. This resets the square wave counter and
40 results in the unlit state */
41 unsigned char rtc_0a = rtc_read(0x0a) & ~0x40;
42 rtc_write(0x0a, rtc_0a); /* Disable square wave */
43 rtc_write(0x13, 0xF0); /* 1 Hz square wave */
44 rtc_write(0x0a, rtc_0a | 0x40); /* Enable square wave */
45
46 /* When the square wave output is disabled in the unlit state,
47 the backlight stays off */
48 rtc_write(0x0a, rtc_0a);
49}
50
51#endif
diff --git a/firmware/target/sh/archos/fm_v2/button-fm_v2.c b/firmware/target/sh/archos/fm_v2/button-fm_v2.c
deleted file mode 100644
index 458917d2d5..0000000000
--- a/firmware/target/sh/archos/fm_v2/button-fm_v2.c
+++ /dev/null
@@ -1,99 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "system.h"
24#include "button.h"
25#include "backlight.h"
26#include "adc.h"
27
28/*
29 Recorder FM/V2 hardware button hookup
30 =====================================
31
32 F1, F2, F3, UP: connected to AN4 through a resistor network
33 DOWN, PLAY, LEFT, RIGHT: likewise connected to AN5
34
35 The voltage on AN4/ AN5 depends on which keys (or key combo) is pressed
36 FM/V2 has PLAY and RIGHT switched compared to plain recorder
37
38 ON: AN3, low active
39 OFF: AN2, high active
40*/
41
42void button_init_device(void)
43{
44 /* Set PB4 and PB8 as input pins */
45 PBCR1 &= 0xfffc; /* PB8MD = 00 */
46 PBCR2 &= 0xfcff; /* PB4MD = 00 */
47 PBIOR &= ~0x0110; /* Inputs */
48}
49
50int button_read_device(void)
51{
52 int btn = BUTTON_NONE;
53 int data;
54
55 /* check F1..F3 and UP */
56 data = adc_read(ADC_BUTTON_ROW1);
57 if (data >= 150)
58 {
59 if (data >= 545)
60 if (data >= 700)
61 btn = BUTTON_F3;
62 else
63 btn = BUTTON_UP;
64 else
65 if (data >= 385)
66 btn = BUTTON_F2;
67 else
68 btn = BUTTON_F1;
69 }
70
71 /* Some units have mushy keypads, so pressing UP also activates
72 the Left/Right buttons. Let's combat that by skipping the AN5
73 checks when UP is pressed. */
74 if(!(btn & BUTTON_UP))
75 {
76 /* check DOWN, PLAY, LEFT, RIGHT */
77 data = adc_read(ADC_BUTTON_ROW2);
78 if (data >= 150)
79 {
80 if (data >= 545)
81 if (data >= 700)
82 btn |= BUTTON_DOWN;
83 else
84 btn |= BUTTON_RIGHT;
85 else
86 if (data >= 385)
87 btn |= BUTTON_LEFT;
88 else
89 btn |= BUTTON_PLAY;
90 }
91 }
92
93 if ( adc_read(ADC_BUTTON_ON) < 512 )
94 btn |= BUTTON_ON;
95 if ( adc_read(ADC_BUTTON_OFF) > 512 )
96 btn |= BUTTON_OFF;
97
98 return btn;
99}
diff --git a/firmware/target/sh/archos/fm_v2/button-target.h b/firmware/target/sh/archos/fm_v2/button-target.h
deleted file mode 100644
index 47eb48c32d..0000000000
--- a/firmware/target/sh/archos/fm_v2/button-target.h
+++ /dev/null
@@ -1,47 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef _BUTTON_TARGET_H_
23#define _BUTTON_TARGET_H_
24
25 /* Main unit's buttons */
26#define BUTTON_ON 0x00000001
27#define BUTTON_OFF 0x00000002
28
29#define BUTTON_LEFT 0x00000004
30#define BUTTON_RIGHT 0x00000008
31#define BUTTON_UP 0x00000010
32#define BUTTON_DOWN 0x00000020
33
34#define BUTTON_PLAY 0x00000040
35
36#define BUTTON_F1 0x00000080
37#define BUTTON_F2 0x00000100
38#define BUTTON_F3 0x00000200
39
40#define BUTTON_MAIN (BUTTON_ON|BUTTON_OFF|BUTTON_LEFT|BUTTON_RIGHT\
41 |BUTTON_UP|BUTTON_DOWN|BUTTON_PLAY\
42 |BUTTON_F1|BUTTON_F2|BUTTON_F3)
43
44#define POWEROFF_BUTTON BUTTON_OFF
45#define POWEROFF_COUNT 10
46
47#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/sh/archos/fm_v2/power-fm_v2.c b/firmware/target/sh/archos/fm_v2/power-fm_v2.c
deleted file mode 100644
index ce1ef19970..0000000000
--- a/firmware/target/sh/archos/fm_v2/power-fm_v2.c
+++ /dev/null
@@ -1,115 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "cpu.h"
23#include <stdbool.h>
24#include "adc.h"
25#include "kernel.h"
26#include "system.h"
27#include "power.h"
28#include "usb.h"
29
30#if CONFIG_TUNER
31bool tuner_power(bool status)
32{
33 (void)status;
34 return true;
35}
36
37#endif /* #if CONFIG_TUNER */
38
39void power_init(void)
40{
41 PBCR2 &= ~0x0c00; /* GPIO for PB5 */
42 or_b(0x20, &PBIORL);
43 or_b(0x20, &PBDRL); /* hold power */
44}
45
46unsigned int power_input_status(void)
47{
48 unsigned int status = POWER_INPUT_NONE;
49
50 /* FM or V2 can also charge from the USB port */
51 if (adc_read(ADC_CHARGE_REGULATOR) < 0x1FF)
52 status = POWER_INPUT_MAIN_CHARGER;
53
54#ifdef HAVE_USB_POWER
55 if (usb_detect() == USB_INSERTED)
56 status |= POWER_INPUT_USB_CHARGER;
57#endif
58
59 return status;
60}
61
62/* Returns true if the unit is charging the batteries. */
63bool charging_state(void)
64{
65 /* We use the information from the ADC_EXT_POWER ADC channel, which
66 tells us the charging current from the LTC1734. When DC is
67 connected (either via the external adapter, or via USB), we try
68 to determine if it is actively charging or only maintaining the
69 charge. My tests show that ADC readings below about 0x80 means
70 that the LTC1734 is only maintaining the charge. */
71 return adc_read(ADC_EXT_POWER) >= 0x80;
72}
73
74void ide_power_enable(bool on)
75{
76 bool touched = false;
77
78 if(on)
79 {
80 or_b(0x20, &PADRL);
81 touched = true;
82 }
83#ifdef HAVE_ATA_POWER_OFF
84 if(!on)
85 {
86 and_b(~0x20, &PADRL);
87 touched = true;
88 }
89#endif /* HAVE_ATA_POWER_OFF */
90
91/* late port preparation, else problems with read/modify/write
92 of other bits on same port, while input and floating high */
93 if (touched)
94 {
95 or_b(0x20, &PAIORL); /* PA5 is an output */
96 PACR2 &= 0xFBFF; /* GPIO for PA5 */
97 }
98}
99
100
101bool ide_powered(void)
102{
103 if ((PACR2 & 0x0400) || !(PAIORL & 0x20)) /* not configured for output */
104 return true; /* would be floating high, disk on */
105 else
106 return (PADRL & 0x20) != 0;
107}
108
109void power_off(void)
110{
111 disable_irq();
112 and_b(~0x20, &PBDRL);
113 or_b(0x20, &PBIORL);
114 while(1);
115}
diff --git a/firmware/target/sh/archos/fm_v2/powermgmt-fm_v2.c b/firmware/target/sh/archos/fm_v2/powermgmt-fm_v2.c
deleted file mode 100644
index 5dd7f26d2f..0000000000
--- a/firmware/target/sh/archos/fm_v2/powermgmt-fm_v2.c
+++ /dev/null
@@ -1,60 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese
11 * Revisions copyright (C) 2005 by Gerald Van Baren
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "config.h"
24#include "adc.h"
25#include "powermgmt.h"
26
27const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
28{
29 2800
30};
31
32const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
33{
34 2580
35};
36
37/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
38const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
39{
40 /* measured values */
41 { 2600, 2850, 2950, 3030, 3110, 3200, 3300, 3450, 3600, 3800, 4000 }
42};
43
44/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
45const unsigned short percent_to_volt_charge[11] =
46{
47 /* TODO: This is identical to the discharge curve.
48 * Calibrate charging curve using a battery_bench log. */
49 2600, 2850, 2950, 3030, 3110, 3200, 3300, 3450, 3600, 3800, 4000
50};
51
52/* Battery scale factor (guessed, seems to be 1,25 * value from recorder) */
53#define BATTERY_SCALE_FACTOR 8275
54/* full-scale ADC readout (2^10) in millivolt */
55
56/* Returns battery voltage from ADC [millivolts] */
57int _battery_voltage(void)
58{
59 return (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) >> 10;
60}
diff --git a/firmware/target/sh/archos/fm_v2/usb-fm_v2.c b/firmware/target/sh/archos/fm_v2/usb-fm_v2.c
deleted file mode 100644
index 5b11d778b6..0000000000
--- a/firmware/target/sh/archos/fm_v2/usb-fm_v2.c
+++ /dev/null
@@ -1,49 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include <stdbool.h>
23#include "adc.h"
24#include "cpu.h"
25#include "hwcompat.h"
26#include "system.h"
27#include "usb.h"
28
29int usb_detect(void)
30{
31 return (adc_read(ADC_USB_POWER) <= 512) ? USB_INSERTED : USB_EXTRACTED;
32}
33
34void usb_enable(bool on)
35{
36 if(HW_MASK & USB_ACTIVE_HIGH)
37 on = !on;
38
39 if(on)
40 and_b(~0x04, &PADRH); /* enable USB */
41 else
42 or_b(0x04, &PADRH);
43}
44
45void usb_init_device(void)
46{
47 usb_enable(false);
48 or_b(0x04, &PAIORH);
49}
diff --git a/firmware/target/sh/archos/i2c-archos.c b/firmware/target/sh/archos/i2c-archos.c
deleted file mode 100644
index 5b415926f2..0000000000
--- a/firmware/target/sh/archos/i2c-archos.c
+++ /dev/null
@@ -1,254 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "lcd.h"
22#include "cpu.h"
23#include "kernel.h"
24#include "thread.h"
25#include "debug.h"
26#include "system.h"
27#include "i2c.h"
28
29/* cute little functions, atomic read-modify-write */
30
31/* SDA is PB7 */
32#define SDA_LO and_b(~0x80, &PBDRL)
33#define SDA_HI or_b(0x80, &PBDRL)
34#define SDA_INPUT and_b(~0x80, &PBIORL)
35#define SDA_OUTPUT or_b(0x80, &PBIORL)
36#define SDA (PBDRL & 0x80)
37
38#if CONFIG_I2C == I2C_ONDIO
39/* Ondio pinout, SCL moved to PB6 */
40#define SCL_INPUT and_b(~0x40, &PBIORL)
41#define SCL_OUTPUT or_b(0x40, &PBIORL)
42#define SCL_LO and_b(~0x40, &PBDRL)
43#define SCL_HI or_b(0x40, &PBDRL)
44#define SCL (PBDRL & 0x40)
45#else
46/* "classic" pinout, SCL is PB13 */
47#define SCL_INPUT and_b(~0x20, &PBIORH)
48#define SCL_OUTPUT or_b(0x20, &PBIORH)
49#define SCL_LO and_b(~0x20, &PBDRH)
50#define SCL_HI or_b(0x20, &PBDRH)
51#define SCL (PBDRH & 0x20)
52#endif
53
54/* arbitrary delay loop */
55#define DELAY do { int _x; for(_x=0;_x<20;_x++);} while (0)
56
57static struct mutex i2c_mtx SHAREDBSS_ATTR;
58
59void i2c_begin(void)
60{
61 mutex_lock(&i2c_mtx);
62}
63
64void i2c_end(void)
65{
66 mutex_unlock(&i2c_mtx);
67}
68
69void i2c_start(void)
70{
71 SDA_OUTPUT;
72 SDA_HI;
73 SCL_HI;
74 SDA_LO;
75 DELAY;
76 SCL_LO;
77}
78
79void i2c_stop(void)
80{
81 SDA_LO;
82 SCL_HI;
83 DELAY;
84 SDA_HI;
85}
86
87void i2c_init(void)
88{
89 int i;
90
91 mutex_init(&i2c_mtx);
92
93#if CONFIG_I2C == I2C_ONDIO
94 /* make PB6 & PB7 general I/O */
95 PBCR2 &= ~0xf000;
96#else /* not Ondio */
97 /* make PB7 & PB13 general I/O */
98 PBCR1 &= ~0x0c00; /* PB13 */
99 PBCR2 &= ~0xc000; /* PB7 */
100#endif
101
102 SCL_OUTPUT;
103 SDA_OUTPUT;
104 SDA_HI;
105 SCL_LO;
106 for (i=0;i<3;i++)
107 i2c_stop();
108}
109
110void i2c_ack(int bit)
111{
112 /* Here's the deal. The MAS is slow, and sometimes needs to wait
113 before it can receive the acknowledge. Therefore it forces the clock
114 low until it is ready. We need to poll the clock line until it goes
115 high before we release the ack. */
116
117 SCL_LO; /* Set the clock low */
118 if ( bit )
119 {
120 SDA_HI;
121 }
122 else
123 {
124 SDA_LO;
125 }
126
127 SCL_INPUT; /* Set the clock to input */
128 while(!SCL) /* and wait for the MAS to release it */
129 sleep(0);
130
131 DELAY;
132 SCL_OUTPUT;
133 SCL_LO;
134}
135
136int i2c_getack(void)
137{
138 int ret = 1;
139
140 /* Here's the deal. The MAS is slow, and sometimes needs to wait
141 before it can send the acknowledge. Therefore it forces the clock
142 low until it is ready. We need to poll the clock line until it goes
143 high before we read the ack. */
144
145#ifdef HAVE_I2C_LOW_FIRST
146 SDA_LO; /* First, discharge the data line */
147#endif
148 SDA_INPUT; /* And set to input */
149 SCL_INPUT; /* Set the clock to input */
150 while(!SCL) /* and wait for the MAS to release it */
151 sleep(0);
152
153 if (SDA)
154 /* ack failed */
155 ret = 0;
156
157 SCL_OUTPUT;
158 SCL_LO;
159 SDA_HI;
160 SDA_OUTPUT;
161 return ret;
162}
163
164void i2c_outb(unsigned char byte)
165{
166 int i;
167
168 /* clock out each bit, MSB first */
169 for ( i=0x80; i; i>>=1 ) {
170 if ( i & byte )
171 {
172 SDA_HI;
173 }
174 else
175 {
176 SDA_LO;
177 }
178 SCL_HI;
179 SCL_LO;
180 }
181
182 SDA_HI;
183}
184
185unsigned char i2c_inb(int ack)
186{
187 int i;
188 unsigned char byte = 0;
189
190 /* clock in each bit, MSB first */
191 for ( i=0x80; i; i>>=1 ) {
192#ifdef HAVE_I2C_LOW_FIRST
193 /* Tricky business. Here we discharge the data line by driving it low
194 and then set it to input to see if it stays low or goes high */
195 SDA_LO; /* First, discharge the data line */
196#endif
197 SDA_INPUT; /* And set to input */
198 SCL_HI;
199 if ( SDA )
200 byte |= i;
201 SCL_LO;
202 SDA_OUTPUT;
203 }
204
205 i2c_ack(ack);
206
207 return byte;
208}
209
210int i2c_write(int address, const unsigned char* buf, int count )
211{
212 int i,x=0;
213
214 i2c_start();
215 i2c_outb(address & 0xfe);
216 if (i2c_getack())
217 {
218 for (i=0; i<count; i++)
219 {
220 i2c_outb(buf[i]);
221 if (!i2c_getack())
222 {
223 x=-2;
224 break;
225 }
226 }
227 }
228 else
229 {
230 debugf("i2c_write() - no ack\n");
231 x=-1;
232 }
233 i2c_stop();
234 return x;
235}
236
237#if 0 /* Currently unused, left for reference and future use */
238int i2c_read(int address, unsigned char* buf, int count )
239{
240 int i,x=0;
241
242 i2c_start();
243 i2c_outb(address | 1);
244 if (i2c_getack()) {
245 for (i=0; i<count; i++) {
246 buf[i] = i2c_inb(0);
247 }
248 }
249 else
250 x=-1;
251 i2c_stop();
252 return x;
253}
254#endif
diff --git a/firmware/target/sh/archos/lcd-archos-bitmap.c b/firmware/target/sh/archos/lcd-archos-bitmap.c
deleted file mode 100644
index f23289053d..0000000000
--- a/firmware/target/sh/archos/lcd-archos-bitmap.c
+++ /dev/null
@@ -1,224 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22
23#include "hwcompat.h"
24#include "kernel.h"
25#include "lcd.h"
26#include "system.h"
27
28/*** definitions ***/
29
30#define LCD_SET_LOWER_COLUMN_ADDRESS ((char)0x00)
31#define LCD_SET_HIGHER_COLUMN_ADDRESS ((char)0x10)
32#define LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO ((char)0x20)
33#define LCD_SET_POWER_CONTROL_REGISTER ((char)0x28)
34#define LCD_SET_DISPLAY_START_LINE ((char)0x40)
35#define LCD_SET_CONTRAST_CONTROL_REGISTER ((char)0x81)
36#define LCD_SET_SEGMENT_REMAP ((char)0xA0)
37#define LCD_SET_LCD_BIAS ((char)0xA2)
38#define LCD_SET_ENTIRE_DISPLAY_OFF ((char)0xA4)
39#define LCD_SET_ENTIRE_DISPLAY_ON ((char)0xA5)
40#define LCD_SET_NORMAL_DISPLAY ((char)0xA6)
41#define LCD_SET_REVERSE_DISPLAY ((char)0xA7)
42#define LCD_SET_MULTIPLEX_RATIO ((char)0xA8)
43#define LCD_SET_BIAS_TC_OSC ((char)0xA9)
44#define LCD_SET_1OVER4_BIAS_RATIO ((char)0xAA)
45#define LCD_SET_INDICATOR_OFF ((char)0xAC)
46#define LCD_SET_INDICATOR_ON ((char)0xAD)
47#define LCD_SET_DISPLAY_OFF ((char)0xAE)
48#define LCD_SET_DISPLAY_ON ((char)0xAF)
49#define LCD_SET_PAGE_ADDRESS ((char)0xB0)
50#define LCD_SET_COM_OUTPUT_SCAN_DIRECTION ((char)0xC0)
51#define LCD_SET_TOTAL_FRAME_PHASES ((char)0xD2)
52#define LCD_SET_DISPLAY_OFFSET ((char)0xD3)
53#define LCD_SET_READ_MODIFY_WRITE_MODE ((char)0xE0)
54#define LCD_SOFTWARE_RESET ((char)0xE2)
55#define LCD_NOP ((char)0xE3)
56#define LCD_SET_END_OF_READ_MODIFY_WRITE_MODE ((char)0xEE)
57
58/* LCD command codes */
59#define LCD_CNTL_RESET 0xe2 /* Software reset */
60#define LCD_CNTL_POWER 0x2f /* Power control */
61#define LCD_CNTL_CONTRAST 0x81 /* Contrast */
62#define LCD_CNTL_OUTSCAN 0xc8 /* Output scan direction */
63#define LCD_CNTL_SEGREMAP 0xa1 /* Segment remap */
64#define LCD_CNTL_DISPON 0xaf /* Display on */
65
66#define LCD_CNTL_PAGE 0xb0 /* Page address */
67#define LCD_CNTL_HIGHCOL 0x10 /* Upper column address */
68#define LCD_CNTL_LOWCOL 0x00 /* Lower column address */
69
70/** globals **/
71
72static int xoffset; /* needed for flip */
73
74/*** hardware configuration ***/
75
76int lcd_default_contrast(void)
77{
78 return (HW_MASK & LCD_CONTRAST_BIAS) ? 31 : 49;
79}
80
81void lcd_set_contrast(int val)
82{
83 lcd_write_command(LCD_CNTL_CONTRAST);
84 lcd_write_command(val);
85}
86
87void lcd_set_invert_display(bool yesno)
88{
89 if (yesno)
90 lcd_write_command(LCD_SET_REVERSE_DISPLAY);
91 else
92 lcd_write_command(LCD_SET_NORMAL_DISPLAY);
93}
94
95/* turn the display upside down (call lcd_update() afterwards) */
96void lcd_set_flip(bool yesno)
97{
98#ifdef HAVE_DISPLAY_FLIPPED
99 if (!yesno)
100#else
101 if (yesno)
102#endif
103 {
104 lcd_write_command(LCD_SET_SEGMENT_REMAP);
105 lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION);
106 xoffset = 132 - LCD_WIDTH; /* 132 colums minus the 112 we have */
107 }
108 else
109 {
110 lcd_write_command(LCD_SET_SEGMENT_REMAP | 0x01);
111 lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION | 0x08);
112 xoffset = 0;
113 }
114}
115
116void lcd_init_device(void)
117{
118 /* Initialize PB0-3 as output pins */
119 PBCR2 &= 0xff00; /* MD = 00 */
120 PBIOR |= 0x000f; /* IOR = 1 */
121
122 /* inits like the original firmware */
123 lcd_write_command(LCD_SOFTWARE_RESET);
124 lcd_write_command(LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO + 4);
125 lcd_write_command(LCD_SET_1OVER4_BIAS_RATIO + 0); /* force 1/4 bias: 0 */
126 lcd_write_command(LCD_SET_POWER_CONTROL_REGISTER + 7);
127 /* power control register: op-amp=1, regulator=1, booster=1 */
128 lcd_write_command(LCD_SET_DISPLAY_ON);
129 lcd_write_command(LCD_SET_NORMAL_DISPLAY);
130 lcd_set_flip(false);
131 lcd_write_command(LCD_SET_DISPLAY_START_LINE + 0);
132 lcd_set_contrast(lcd_default_contrast());
133 lcd_write_command(LCD_SET_PAGE_ADDRESS);
134 lcd_write_command(LCD_SET_LOWER_COLUMN_ADDRESS + 0);
135 lcd_write_command(LCD_SET_HIGHER_COLUMN_ADDRESS + 0);
136
137 lcd_clear_display();
138 lcd_update();
139}
140
141/*** Update functions ***/
142
143/* Performance function that works with an external buffer
144 note that by and bheight are in 8-pixel units! */
145void lcd_blit_mono(const unsigned char *data, int x, int by, int width,
146 int bheight, int stride)
147{
148 /* Copy display bitmap to hardware */
149 while (bheight--)
150 {
151 lcd_write_command (LCD_CNTL_PAGE | (by++ & 0xf));
152 lcd_write_command (LCD_CNTL_HIGHCOL | (((x+xoffset)>>4) & 0xf));
153 lcd_write_command (LCD_CNTL_LOWCOL | ((x+xoffset) & 0xf));
154
155 lcd_write_data(data, width);
156 data += stride;
157 }
158}
159
160/* Helper function for lcd_grey_phase_blit(). */
161void lcd_grey_data(unsigned char *values, unsigned char *phases, int count);
162
163/* Performance function that works with an external buffer
164 note that by and bheight are in 8-pixel units! */
165void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases,
166 int x, int by, int width, int bheight, int stride)
167{
168 stride <<= 3; /* 8 pixels per block */
169 while (bheight--)
170 {
171 lcd_write_command (LCD_CNTL_PAGE | (by++ & 0xf));
172 lcd_write_command (LCD_CNTL_HIGHCOL | (((x+xoffset)>>4) & 0xf));
173 lcd_write_command (LCD_CNTL_LOWCOL | ((x+xoffset) & 0xf));
174
175 lcd_grey_data(values, phases, width);
176 values += stride;
177 phases += stride;
178 }
179}
180
181
182/* Update the display.
183 This must be called after all other LCD functions that change the display. */
184void lcd_update(void)
185{
186 int y;
187
188 /* Copy display bitmap to hardware */
189 for (y = 0; y < LCD_FBHEIGHT; y++)
190 {
191 lcd_write_command (LCD_CNTL_PAGE | (y & 0xf));
192 lcd_write_command (LCD_CNTL_HIGHCOL | ((xoffset >> 4) & 0xf));
193 lcd_write_command (LCD_CNTL_LOWCOL | (xoffset & 0xf));
194
195 lcd_write_data (FBADDR(0, y), LCD_WIDTH);
196 }
197}
198
199/* Update a fraction of the display. */
200void lcd_update_rect(int x, int y, int width, int height)
201{
202 int ymax;
203
204 /* The Y coordinates have to work on even 8 pixel rows */
205 ymax = (y + height-1) >> 3;
206 y >>= 3;
207
208 if(x + width > LCD_WIDTH)
209 width = LCD_WIDTH - x;
210 if (width <= 0)
211 return; /* nothing left to do, 0 is harmful to lcd_write_data() */
212 if(ymax >= LCD_FBHEIGHT)
213 ymax = LCD_FBHEIGHT-1;
214
215 /* Copy specified rectange bitmap to hardware */
216 for (; y <= ymax; y++)
217 {
218 lcd_write_command (LCD_CNTL_PAGE | (y & 0xf));
219 lcd_write_command (LCD_CNTL_HIGHCOL | (((x+xoffset) >> 4) & 0xf));
220 lcd_write_command (LCD_CNTL_LOWCOL | ((x+xoffset) & 0xf));
221
222 lcd_write_data (FBADDR(x,y), width);
223 }
224}
diff --git a/firmware/target/sh/archos/lcd-as-archos-bitmap.S b/firmware/target/sh/archos/lcd-as-archos-bitmap.S
deleted file mode 100644
index 0396483737..0000000000
--- a/firmware/target/sh/archos/lcd-as-archos-bitmap.S
+++ /dev/null
@@ -1,354 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 by Jens Arnold
11 * Based on the work of Alan Korr and Jörg Hohensohn
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "config.h"
24#include "cpu.h"
25
26#define LCDR (PBDR_ADDR+1)
27
28#define LCD_SD 1 /* PB0 = 1 --- 0001 */
29#define LCD_SC 2 /* PB1 = 1 --- 0010 */
30#define LCD_DS 4 /* PB2 = 1 --- 0100 */
31#define LCD_CS 8 /* PB3 = 1 --- 1000 */
32
33/*
34 * About /CS,DS,SC,SD
35 * ------------------
36 *
37 * LCD on JBP and JBR uses a SPI protocol to receive orders (SDA and SCK lines)
38 *
39 * - /CS -> Chip Selection line :
40 * 0 : LCD chipset is activated.
41 * - DS -> Data Selection line, latched at the rising edge
42 * of the 8th serial clock (*) :
43 * 0 : instruction register,
44 * 1 : data register;
45 * - SC -> Serial Clock line (SDA).
46 * - SD -> Serial Data line (SCK), latched at the rising edge
47 * of each serial clock (*).
48 *
49 * _ _
50 * /CS \ /
51 * \______________________________________________________/
52 * _____ ____ ____ ____ ____ ____ ____ ____ ____ _____
53 * SD \/ D7 \/ D6 \/ D5 \/ D4 \/ D3 \/ D2 \/ D1 \/ D0 \/
54 * _____/\____/\____/\____/\____/\____/\____/\____/\____/\_____
55 *
56 * _____ _ _ _ _ _ _ _ ________
57 * SC \ * \ * \ * \ * \ * \ * \ * \ *
58 * \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
59 * _ _________________________________________________________
60 * DS \/
61 * _/\_________________________________________________________
62 *
63 */
64
65 .section .icode,"ax",@progbits
66
67 .align 2
68 .global _lcd_write_command
69 .type _lcd_write_command,@function
70
71/* Write a command byte to the lcd controller
72 *
73 * Arguments:
74 * r4 - data byte (int)
75 *
76 * Register usage:
77 * r0 - scratch
78 * r1 - data byte (copied)
79 * r2 - precalculated port value (CS, DS and SC low, SD high),
80 * negated (neg)!
81 * r3 - lcd port address
82 * r5 - 1 (byte count for reuse of the loop in _lcd_write_data)
83 */
84
85_lcd_write_command:
86 mov.l .lcdr, r3 /* put lcd data port address in r3 */
87 mov r4, r1 /* copy data byte to r1 */
88
89 /* This code will fail if an interrupt changes the contents of PBDRL.
90 * If so, we must disable the interrupt here. */
91
92 mov.b @r3, r0 /* r0 = PBDRL */
93 mov #0, r5 /* fake end address - stop after first iteration */
94 or #(LCD_SD), r0 /* r0 |= LCD_SD */
95 and #(~(LCD_CS|LCD_DS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_DS|LCD_SC) */
96
97 bra .single_transfer /* jump into the transfer loop */
98 neg r0, r2 /* r2 = 0 - r0 */
99
100
101 .align 2
102 .global _lcd_write_data
103 .type _lcd_write_data,@function
104
105/* A high performance function to write data to the display,
106 * one or multiple bytes.
107 *
108 * Arguments:
109 * r4 - data address
110 * r5 - byte count
111 *
112 * Register usage:
113 * r0 - scratch
114 * r1 - current data byte
115 * r2 - precalculated port value (CS and SC low, DS and SD high),
116 * negated (neg)!
117 * r3 - lcd port address
118 */
119
120_lcd_write_data:
121 mov.l .lcdr, r3 /* put lcd data port address in r3 */
122 add r4, r5 /* end address */
123
124 /* This code will fail if an interrupt changes the contents of PBDRL.
125 * If so, we must disable the interrupt here. If disabling interrupts
126 * for a long time (~9200 clks = ~830 µs for transferring 112 bytes on
127 * recorders)is undesirable, the loop has to be rewritten to
128 * disable/precalculate/transfer/enable for each iteration. However,
129 * this would significantly decrease performance. */
130
131 mov.b @r3, r0 /* r0 = PBDRL */
132 or #(LCD_DS|LCD_SD), r0 /* r0 |= LCD_DS|LCD_SD */
133 and #(~(LCD_CS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_SC) */
134 neg r0, r2 /* r2 = 0 - r0 */
135
136 /* loop exploits that SD is on bit 0 for recorders and Ondios */
137
138 .align 2
139.multi_transfer:
140 mov.b @r4+, r1 /* load data byte from memory */
141 nop
142
143.single_transfer:
144 shll16 r1 /* shift data to most significant byte */
145 shll8 r1
146 not r1, r1 /* and invert for use with negc */
147
148 shll r1 /* shift the MSB into carry */
149 negc r2, r0 /* carry to SD, SC low */
150 shll r1 /* next shift here for alignment */
151 mov.b r0, @r3 /* set data to port */
152 or #(LCD_SC), r0 /* rise SC (independent of SD level) */
153 mov.b r0, @r3 /* set to port */
154
155 negc r2, r0
156 mov.b r0, @r3
157 or #(LCD_SC), r0
158 mov.b r0, @r3
159
160 shll r1
161 negc r2, r0
162 shll r1
163 mov.b r0, @r3
164 or #(LCD_SC), r0
165 mov.b r0, @r3
166
167 negc r2, r0
168 mov.b r0, @r3
169 or #(LCD_SC), r0
170 mov.b r0, @r3
171
172 shll r1
173 negc r2, r0
174 shll r1
175 mov.b r0, @r3
176 or #(LCD_SC), r0
177 mov.b r0, @r3
178
179 negc r2, r0
180 mov.b r0, @r3
181 or #(LCD_SC), r0
182 mov.b r0, @r3
183
184 shll r1
185 negc r2, r0
186 shll r1
187 mov.b r0, @r3
188 or #(LCD_SC), r0
189 mov.b r0, @r3
190
191 negc r2, r0
192 mov.b r0, @r3
193 or #(LCD_SC), r0
194 mov.b r0, @r3
195
196 cmp/hi r4, r5 /* some blocks left? */
197 bt .multi_transfer
198
199 or #(LCD_CS|LCD_DS|LCD_SD|LCD_SC), r0 /* restore port */
200 rts
201 mov.b r0, @r3
202
203 /* This is the place to reenable the interrupts, if we have disabled
204 * them. See above. */
205
206#ifndef BOOTLOADER
207 .align 2
208 .global _lcd_grey_data
209 .type _lcd_grey_data,@function
210
211/* A high performance function to write grey phase data to the display,
212 * one or multiple pixels.
213 *
214 * Arguments:
215 * r4 - pixel value data address
216 * r5 - pixel phase data address
217 * r6 - pixel block count
218 *
219 * Register usage:
220 * r0 - scratch / phase signs mask
221 * r1 - scratch
222 * r2 - precalculated port value (CS and SC low, DS and SD high),
223 * negated (neg)!
224 * r3 - lcd port address
225 * r4 - current value address
226 * r5 - current phase address
227 * r6 - end address
228 * r7/r8 - current/next block of phases (alternating)
229 * r9/r10 - current blocks of values
230 * r11 - 0x00000080 \
231 * r12 - 0x00008000 > for phase sign check
232 * r13 - 0x00800000 /
233 */
234
235_lcd_grey_data:
236 mov.l r8, @-r15 /* save r8 */
237 mov.l r9, @-r15 /* save r9 */
238 mov.l r10, @-r15 /* save r10 */
239 shll2 r6 /* v */
240 mov.l r11, @-r15 /* save r11 */
241 shll r6 /* r6 *= 8; (8 pixels per block) */
242 mov.l .lcdr, r3 /* put lcd data port address in r3 */
243 add r4, r6 /* end address */
244
245 /* This code will fail if an interrupt changes the contents of PBDRL.
246 * If so, we must disable the interrupt here. If disabling interrupts
247 * for a long time is undesirable, the loop has to be rewritten to
248 * disable/precalculate/transfer/enable for each iteration. However,
249 * this would significantly decrease performance. */
250
251 mov.b @r3, r0 /* r0 = PBDRL */
252 or #(LCD_DS|LCD_SD), r0 /* r0 |= LCD_DS|LCD_SD */
253 mov.l r12, @-r15 /* save r12 */
254 and #(~(LCD_CS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_SC) */
255 mov.l r13, @-r15 /* save r13 */
256 neg r0, r2 /* r2 = 0 - r0 */
257
258 /* loop exploits that SD is on bit 0 for recorders and Ondios */
259
260 mov.w .ptest, r11
261 swap.b r11, r12
262 mov.l @r5, r7
263 swap.w r11, r13
264 mov.l .pmask, r0
265
266.greyloop:
267 cmp/pz r7
268 mov.l @r4+, r9
269 negc r2, r1
270 mov.b r1, @r3
271 add #(LCD_SC), r1
272 mov.b r1, @r3
273
274 tst r13, r7
275 mov.l @r4+, r10
276 negc r2, r1
277 mov.b r1, @r3
278 add #(LCD_SC), r1
279 mov.b r1, @r3
280
281 tst r12, r7
282 mov.l @(4,r5), r8
283 negc r2, r1
284 mov.b r1, @r3
285 add #(LCD_SC), r1
286 mov.b r1, @r3
287
288 tst r11, r7
289 or r0, r7
290 negc r2, r1
291 mov.b r1, @r3
292 add #(LCD_SC), r1
293 mov.b r1, @r3
294
295 cmp/pz r8
296 sub r9, r7
297 negc r2, r1
298 mov.b r1, @r3
299 add #(LCD_SC), r1
300 mov.b r1, @r3
301
302 tst r13, r8
303 mov.l r7, @r5
304 negc r2, r1
305 mov.b r1, @r3
306 add #(LCD_SC), r1
307 mov.b r1, @r3
308
309 tst r12, r8
310 mov.l @(8,r5), r7
311 negc r2, r1
312 mov.b r1, @r3
313 add #(LCD_SC), r1
314 mov.b r1, @r3
315
316 tst r11, r8
317 or r0, r8
318 negc r2, r1
319 mov.b r1, @r3
320 add #(LCD_SC), r1
321 mov.b r1, @r3
322
323 sub r10, r8
324 mov.l r8, @(4,r5)
325
326 add #8, r5
327 cmp/hi r4, r6
328 bt .greyloop
329
330 mov.l @r15+, r13 /* restore r13 */
331 mov #(LCD_CS|LCD_DS|LCD_SD|LCD_SC), r0
332 mov.l @r15+, r12 /* restore r12 */
333 or r0, r1 /* restore port */
334 mov.l @r15+, r11 /* restore r11 */
335 mov.l @r15+, r10 /* restore r10 */
336 mov.l @r15+, r9 /* restore r9 */
337 mov.l @r15+, r8 /* restore r8 */
338 rts
339 mov.b r1, @r3
340
341 /* This is the place to reenable the interrupts, if we have disabled
342 * them. See above. */
343
344.ptest:
345 .short 0x0080
346
347 .align 2
348.pmask:
349 .long 0x80808080
350#endif
351
352 .align 2
353.lcdr:
354 .long LCDR
diff --git a/firmware/target/sh/archos/mascodec-archos.c b/firmware/target/sh/archos/mascodec-archos.c
deleted file mode 100644
index faa5c7ef2b..0000000000
--- a/firmware/target/sh/archos/mascodec-archos.c
+++ /dev/null
@@ -1,491 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "stdbool.h"
22#include "config.h"
23#include "sh7034.h"
24#include "i2c.h"
25#include "debug.h"
26#include "mas35xx.h"
27#include "kernel.h"
28#include "system.h"
29#include "hwcompat.h"
30
31static int mas_devread(unsigned long *dest, int len);
32
33#if 0 /* Currently unused, left for reference and future use */
34int mas_default_read(unsigned short *buf)
35{
36 unsigned char *dest = (unsigned char *)buf;
37 int ret = 0;
38
39 i2c_begin();
40
41 i2c_start();
42 i2c_outb(MAS_DEV_WRITE);
43 if (i2c_getack()) {
44 i2c_outb(MAS_DATA_READ);
45 if (i2c_getack()) {
46 i2c_start();
47 i2c_outb(MAS_DEV_READ);
48 if (i2c_getack()) {
49 dest[0] = i2c_inb(0);
50 dest[1] = i2c_inb(1);
51 }
52 else
53 ret = -3;
54 }
55 else
56 ret = -2;
57 }
58 else
59 ret = -1;
60
61 i2c_stop();
62
63 i2c_end();
64 return ret;
65}
66#endif
67
68#if CONFIG_CODEC == MAS3507D
69int mas_run(unsigned short address)
70{
71 int ret = 0;
72 unsigned char buf[3];
73
74 i2c_begin();
75
76 buf[0] = MAS_DATA_WRITE;
77 buf[1] = address >> 8;
78 buf[2] = address & 0xff;
79
80 /* send run command */
81 if (i2c_write(MAS_DEV_WRITE,buf,3))
82 {
83 ret = -1;
84 }
85
86 i2c_end();
87 return ret;
88}
89#endif
90
91/* note: 'len' is number of 32-bit words, not number of bytes! */
92int mas_readmem(int bank, int addr, unsigned long* dest, int len)
93{
94 int ret = 0;
95 unsigned char buf[7];
96
97 i2c_begin();
98
99 buf[0] = MAS_DATA_WRITE;
100 buf[1] = bank?MAS_CMD_READ_D1_MEM:MAS_CMD_READ_D0_MEM;
101 buf[2] = 0x00;
102 buf[3] = (len & 0xff00) >> 8;
103 buf[4] = len & 0xff;
104 buf[5] = (addr & 0xff00) >> 8;
105 buf[6] = addr & 0xff;
106
107 /* send read command */
108 if (i2c_write(MAS_DEV_WRITE,buf,7))
109 {
110 ret = -1;
111 }
112
113 ret = mas_devread(dest, len);
114
115 i2c_end();
116 return ret;
117}
118
119/* note: 'len' is number of 32-bit words, not number of bytes! */
120int mas_writemem(int bank, int addr, const unsigned long* src, int len)
121{
122 int ret = 0;
123 int i, j;
124 unsigned char buf[60];
125 const unsigned char* ptr = (const unsigned char*)src;
126
127 i2c_begin();
128
129 i=0;
130 buf[i++] = MAS_DATA_WRITE;
131 buf[i++] = bank?MAS_CMD_WRITE_D1_MEM:MAS_CMD_WRITE_D0_MEM;
132 buf[i++] = 0x00;
133 buf[i++] = (len & 0xff00) >> 8;
134 buf[i++] = len & 0xff;
135 buf[i++] = (addr & 0xff00) >> 8;
136 buf[i++] = addr & 0xff;
137
138 j = 0;
139 while(len--) {
140#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
141 buf[i++] = 0;
142 buf[i++] = ptr[j+1];
143 buf[i++] = ptr[j+2];
144 buf[i++] = ptr[j+3];
145#else
146 buf[i++] = ptr[j+2];
147 buf[i++] = ptr[j+3];
148 buf[i++] = 0;
149 buf[i++] = ptr[j+1];
150#endif
151 j += 4;
152 }
153
154 /* send write command */
155 if (i2c_write(MAS_DEV_WRITE,buf,i))
156 {
157 ret = -1;
158 }
159
160 i2c_end();
161 return ret;
162}
163
164int mas_readreg(int reg)
165{
166 int ret = 0;
167 unsigned char buf[16];
168 unsigned long value;
169
170 i2c_begin();
171
172 buf[0] = MAS_DATA_WRITE;
173 buf[1] = MAS_CMD_READ_REG | (reg >> 4);
174 buf[2] = (reg & 0x0f) << 4;
175
176 /* send read command */
177 if (i2c_write(MAS_DEV_WRITE,buf,3))
178 {
179 ret = -1;
180 }
181 else
182 {
183 if(mas_devread(&value, 1))
184 {
185 ret = -2;
186 }
187 else
188 {
189 ret = value;
190 }
191 }
192
193 i2c_end();
194 return ret;
195}
196
197int mas_writereg(int reg, unsigned int val)
198{
199 int ret = 0;
200 unsigned char buf[5];
201
202 i2c_begin();
203
204 buf[0] = MAS_DATA_WRITE;
205 buf[1] = MAS_CMD_WRITE_REG | (reg >> 4);
206#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
207 buf[2] = ((reg & 0x0f) << 4) | (val >> 16 & 0x0f);
208 buf[3] = (val >> 8) & 0xff;
209 buf[4] = val & 0xff;
210#else
211 buf[2] = ((reg & 0x0f) << 4) | (val & 0x0f);
212 buf[3] = (val >> 12) & 0xff;
213 buf[4] = (val >> 4) & 0xff;
214#endif
215
216 /* send write command */
217 if (i2c_write(MAS_DEV_WRITE,buf,5))
218 {
219 ret = -1;
220 }
221
222 i2c_end();
223 return ret;
224}
225
226/* note: 'len' is number of 32-bit words, not number of bytes! */
227static int mas_devread(unsigned long *dest, int len)
228{
229 int ret = 0;
230 unsigned char* ptr = (unsigned char*)dest;
231 int i;
232
233 /* handle read-back */
234 /* Remember, the MAS values are only 20 bits, so we set
235 the upper 12 bits to 0 */
236 i2c_start();
237 i2c_outb(MAS_DEV_WRITE);
238 if (i2c_getack()) {
239 i2c_outb(MAS_DATA_READ);
240 if (i2c_getack()) {
241 i2c_start();
242 i2c_outb(MAS_DEV_READ);
243 if (i2c_getack()) {
244 for (i=0;len;i++) {
245 len--;
246#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
247 i2c_inb(0); /* Dummy read */
248 ptr[i*4+0] = 0;
249 ptr[i*4+1] = i2c_inb(0) & 0x0f;
250 ptr[i*4+2] = i2c_inb(0);
251 if(len)
252 ptr[i*4+3] = i2c_inb(0);
253 else
254 ptr[i*4+3] = i2c_inb(1); /* NAK the last byte */
255#else
256 ptr[i*4+2] = i2c_inb(0);
257 ptr[i*4+3] = i2c_inb(0);
258 ptr[i*4+0] = i2c_inb(0);
259 if(len)
260 ptr[i*4+1] = i2c_inb(0);
261 else
262 ptr[i*4+1] = i2c_inb(1); /* NAK the last byte */
263#endif
264 }
265 }
266 else
267 ret = -3;
268 }
269 else
270 ret = -2;
271 }
272 else
273 ret = -1;
274
275 i2c_stop();
276
277 return ret;
278}
279
280void mas_reset(void)
281{
282 or_b(0x01, &PAIORH);
283
284#if CONFIG_CODEC == MAS3507D
285 /* PB5 is "MAS enable". make it GPIO output and high */
286 PBCR2 &= ~0x0c00;
287 or_b(0x20, &PBIORL);
288 or_b(0x20, &PBDRL);
289
290 and_b(~0x01, &PADRH);
291 sleep(HZ/100);
292 or_b(0x01, &PADRH);
293 sleep(HZ/5);
294#elif (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
295 if (HW_MASK & ATA_ADDRESS_200)
296 {
297 and_b(~0x01, &PADRH);
298 sleep(HZ/100);
299 or_b(0x01, &PADRH);
300 sleep(HZ/5);
301 }
302 else
303 {
304 /* Older recorder models don't invert the POR signal */
305 or_b(0x01, &PADRH);
306 sleep(HZ/100);
307 and_b(~0x01, &PADRH);
308 sleep(HZ/5);
309 }
310#endif
311}
312
313#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
314#if 0 /* Currently unused, left for reference and future use */
315int mas_direct_config_read(unsigned char reg)
316{
317 int ret = 0;
318 unsigned char tmp[2];
319
320 i2c_begin();
321
322 i2c_start();
323 i2c_outb(MAS_DEV_WRITE);
324 if (i2c_getack()) {
325 i2c_outb(reg);
326 if (i2c_getack()) {
327 i2c_start();
328 i2c_outb(MAS_DEV_READ);
329 if (i2c_getack()) {
330 tmp[0] = i2c_inb(0);
331 tmp[1] = i2c_inb(1); /* NAK the last byte */
332 ret = (tmp[0] << 8) | tmp[1];
333 }
334 else
335 ret = -3;
336 }
337 else
338 ret = -2;
339 }
340 else
341 ret = -1;
342
343 i2c_stop();
344
345 i2c_end();
346 return ret;
347}
348#endif
349
350int mas_direct_config_write(unsigned char reg, unsigned int val)
351{
352 int ret = 0;
353 unsigned char buf[3];
354
355 i2c_begin();
356
357 buf[0] = reg;
358 buf[1] = (val >> 8) & 0xff;
359 buf[2] = val & 0xff;
360
361 /* send write command */
362 if (i2c_write(MAS_DEV_WRITE,buf,3))
363 {
364 ret = -1;
365 }
366
367 i2c_end();
368 return ret;
369}
370
371int mas_codec_writereg(int reg, unsigned int val)
372{
373 int ret = 0;
374 unsigned char buf[5];
375
376 i2c_begin();
377
378 buf[0] = MAS_CODEC_WRITE;
379 buf[1] = (reg >> 8) & 0xff;
380 buf[2] = reg & 0xff;
381 buf[3] = (val >> 8) & 0xff;
382 buf[4] = val & 0xff;
383
384 /* send write command */
385 if (i2c_write(MAS_DEV_WRITE,buf,5))
386 {
387 ret = -1;
388 }
389
390 i2c_end();
391 return ret;
392}
393
394int mas_codec_readreg(int reg)
395{
396 int ret = 0;
397 unsigned char buf[16];
398 unsigned char tmp[2];
399
400 i2c_begin();
401
402 buf[0] = MAS_CODEC_WRITE;
403 buf[1] = (reg >> 8) & 0xff;
404 buf[2] = reg & 0xff;
405
406 /* send read command */
407 if (i2c_write(MAS_DEV_WRITE,buf,3))
408 {
409 ret = -1;
410 }
411 else
412 {
413 i2c_start();
414 i2c_outb(MAS_DEV_WRITE);
415 if (i2c_getack()) {
416 i2c_outb(MAS_CODEC_READ);
417 if (i2c_getack()) {
418 i2c_start();
419 i2c_outb(MAS_DEV_READ);
420 if (i2c_getack()) {
421 tmp[0] = i2c_inb(0);
422 tmp[1] = i2c_inb(1); /* NAK the last byte */
423 ret = (tmp[0] << 8) | tmp[1];
424 }
425 else
426 ret = -4;
427 }
428 else
429 ret = -3;
430 }
431 else
432 ret = -2;
433
434 i2c_stop();
435 }
436
437 i2c_end();
438 return ret;
439}
440
441unsigned long mas_readver(void)
442{
443 int ret = 0;
444 unsigned char buf[16];
445 unsigned long value;
446
447 i2c_begin();
448
449 buf[0] = MAS_DATA_WRITE;
450 buf[1] = MAS_CMD_READ_IC_VER;
451 buf[2] = 0;
452
453 /* send read command */
454 if (i2c_write(MAS_DEV_WRITE,buf,3))
455 {
456 ret = -1;
457 }
458 else
459 {
460 if(mas_devread(&value, 1))
461 {
462 ret = -2;
463 }
464 else
465 {
466 ret = value;
467 }
468 }
469
470 i2c_end();
471 return ret;
472}
473
474#endif
475
476#if CONFIG_TUNER & S1A0903X01
477static int pllfreq;
478
479void mas_store_pllfreq(int freq)
480{
481 pllfreq = freq;
482}
483
484int mas_get_pllfreq(void)
485{
486 return pllfreq;
487}
488#endif
489
490
491
diff --git a/firmware/target/sh/archos/ondio/adc-target.h b/firmware/target/sh/archos/ondio/adc-target.h
deleted file mode 100644
index a39ee110f3..0000000000
--- a/firmware/target/sh/archos/ondio/adc-target.h
+++ /dev/null
@@ -1,37 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _ADC_TARGET_H_
22#define _ADC_TARGET_H_
23
24#define NUM_ADC_CHANNELS 8
25
26#define ADC_MMC_SWITCH 0 /* low values if MMC inserted */
27#define ADC_USB_POWER 1 /* USB, reads 0x000 when USB is inserted */
28#define ADC_BUTTON_OPTION 2 /* the option button, low value if pressed */
29#define ADC_BUTTON_ONOFF 3 /* the on/off button, high value if pressed */
30#define ADC_BUTTON_ROW1 4 /* Used for scanning the keys, different
31 voltages for different keys */
32#define ADC_USB_ACTIVE 5 /* USB bridge activity */
33#define ADC_UNREG_POWER 7 /* Battery voltage */
34
35#define EXT_SCALE_FACTOR 14800
36
37#endif /* _ADC_TARGET_H_ */
diff --git a/firmware/target/sh/archos/ondio/ata_mmc.c b/firmware/target/sh/archos/ondio/ata_mmc.c
deleted file mode 100644
index f252e1c4ce..0000000000
--- a/firmware/target/sh/archos/ondio/ata_mmc.c
+++ /dev/null
@@ -1,978 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "ata_mmc.h"
23#include "sdmmc.h"
24#include "kernel.h"
25#include "led.h"
26#include "sh7034.h"
27#include "system.h"
28#include "debug.h"
29#include "panic.h"
30#include "power.h"
31#include "string.h"
32#include "hwcompat.h"
33#include "adc.h"
34#include "bitswap.h"
35#include "storage.h"
36
37
38#ifdef HAVE_MULTIDRIVE
39#define MMC_NUM_DRIVES 2
40#else
41#define MMC_NUM_DRIVES 1
42#endif
43
44#define BLOCK_SIZE 512 /* fixed */
45
46/* Command definitions */
47#define CMD_GO_IDLE_STATE 0x40 /* R1 */
48#define CMD_SEND_OP_COND 0x41 /* R1 */
49#define CMD_SEND_CSD 0x49 /* R1 */
50#define CMD_SEND_CID 0x4a /* R1 */
51#define CMD_STOP_TRANSMISSION 0x4c /* R1 */
52#define CMD_SEND_STATUS 0x4d /* R2 */
53#define CMD_SET_BLOCKLEN 0x50 /* R1 */
54#define CMD_READ_SINGLE_BLOCK 0x51 /* R1 */
55#define CMD_READ_MULTIPLE_BLOCK 0x52 /* R1 */
56#define CMD_WRITE_BLOCK 0x58 /* R1b */
57#define CMD_WRITE_MULTIPLE_BLOCK 0x59 /* R1b */
58#define CMD_READ_OCR 0x7a /* R3 */
59
60/* Response formats:
61 R1 = single byte, msb=0, various error flags
62 R1b = R1 + busy token(s)
63 R2 = 2 bytes (1st byte identical to R1), additional flags
64 R3 = 5 bytes (R1 + OCR register)
65*/
66
67#define R1_PARAMETER_ERR 0x40
68#define R1_ADDRESS_ERR 0x20
69#define R1_ERASE_SEQ_ERR 0x10
70#define R1_COM_CRC_ERR 0x08
71#define R1_ILLEGAL_CMD 0x04
72#define R1_ERASE_RESET 0x02
73#define R1_IN_IDLE_STATE 0x01
74
75#define R2_OUT_OF_RANGE 0x80
76#define R2_ERASE_PARAM 0x40
77#define R2_WP_VIOLATION 0x20
78#define R2_CARD_ECC_FAIL 0x10
79#define R2_CC_ERROR 0x08
80#define R2_ERROR 0x04
81#define R2_ERASE_SKIP 0x02
82#define R2_CARD_LOCKED 0x01
83
84/* Data start tokens */
85
86#define DT_START_BLOCK 0xfe
87#define DT_START_WRITE_MULTIPLE 0xfc
88#define DT_STOP_TRAN 0xfd
89
90/* for compatibility */
91static long last_disk_activity = -1;
92
93/* private variables */
94
95#ifdef CONFIG_STORAGE_MULTI
96static int mmc_first_drive = 0;
97#else
98#define mmc_first_drive 0
99#endif
100
101static struct mutex mmc_mutex SHAREDBSS_ATTR;
102
103static bool initialized = false;
104static bool new_mmc_circuit;
105
106static enum {
107 MMC_UNKNOWN,
108 MMC_UNTOUCHED,
109 MMC_TOUCHED
110} mmc_status = MMC_UNKNOWN;
111
112static enum {
113 SER_POLL_WRITE,
114 SER_POLL_READ,
115 SER_DISABLED
116} serial_mode;
117
118static const unsigned char dummy[] = {
119 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
120};
121
122/* 2 buffers used alternatively for writing, including start token,
123 * dummy CRC and an extra byte to keep word alignment. */
124static unsigned char write_buffer[2][BLOCK_SIZE+4];
125static int current_buffer = 0;
126static const unsigned char *send_block_addr = NULL;
127
128static tCardInfo card_info[2];
129#ifndef HAVE_MULTIDRIVE
130static int current_card = 0;
131#endif
132static bool last_mmc_status = false;
133static int countdown = -1; /* for mmc switch debouncing. -1 because the
134 countdown should not happen if the card
135 is inserted at boot */
136static bool usb_activity; /* monitoring the USB bridge */
137static long last_usb_activity;
138
139/* private function declarations */
140
141static int select_card(int card_no);
142static void deselect_card(void);
143static void setup_sci1(int bitrate_register);
144static void set_sci1_poll_read(void);
145static void write_transfer(const unsigned char *buf, int len)
146 __attribute__ ((section(".icode")));
147static void read_transfer(unsigned char *buf, int len)
148 __attribute__ ((section(".icode")));
149static unsigned char poll_byte(long timeout);
150static unsigned char poll_busy(long timeout);
151static unsigned char send_cmd(int cmd, unsigned long parameter, void *data);
152static int receive_cxd(unsigned char *buf);
153static int initialize_card(int card_no);
154static int receive_block(unsigned char *inbuf, long timeout);
155static void send_block_prepare(void);
156static int send_block_send(unsigned char start_token, long timeout,
157 bool prepare_next);
158static void mmc_tick(void);
159
160/* implementation */
161
162static void enable_controller(bool on)
163{
164 PBCR1 &= ~0x0CF0; /* PB13, PB11 and PB10 become GPIO,
165 * if not modified below */
166 if (on)
167 PBCR1 |= 0x08A0; /* as SCK1, TxD1, RxD1 */
168
169 and_b(~0x80, &PADRL); /* assert flash reset */
170 sleep(HZ/100);
171 or_b(0x80, &PADRL); /* de-assert flash reset */
172 sleep(HZ/100);
173 card_info[0].initialized = false;
174 card_info[1].initialized = false;
175}
176
177void mmc_enable_int_flash_clock(bool on)
178{
179 /* Internal flash clock is enabled by setting PA12 high with the new
180 * clock circuit, and by setting it low with the old clock circuit */
181 if (on ^ new_mmc_circuit)
182 and_b(~0x10, &PADRH); /* clear clock gate PA12 */
183 else
184 or_b(0x10, &PADRH); /* set clock gate PA12 */
185}
186
187static int select_card(int card_no)
188{
189 mutex_lock(&mmc_mutex);
190 led(true);
191 last_disk_activity = current_tick;
192
193 mmc_enable_int_flash_clock(card_no == 0);
194
195 if (!card_info[card_no].initialized)
196 {
197 setup_sci1(7); /* Initial rate: 375 kbps (need <= 400 per mmc specs) */
198 write_transfer(dummy, 10); /* allow the card to synchronize */
199 while (!(SSR1 & SCI_TEND));
200 }
201
202 if (card_no == 0) /* internal */
203 and_b(~0x04, &PADRH); /* assert CS */
204 else /* external */
205 and_b(~0x02, &PADRH); /* assert CS */
206
207 if (card_info[card_no].initialized)
208 {
209 setup_sci1(card_info[card_no].bitrate_register);
210 return 0;
211 }
212 else
213 {
214 return initialize_card(card_no);
215 }
216}
217
218static void deselect_card(void)
219{
220 while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */
221 or_b(0x06, &PADRH); /* deassert CS (both cards) */
222
223 led(false);
224 mutex_unlock(&mmc_mutex);
225 last_disk_activity = current_tick;
226}
227
228static void setup_sci1(int bitrate_register)
229{
230 while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */
231
232 SCR1 = 0; /* disable serial port */
233 SMR1 = SYNC_MODE; /* no prescale */
234 BRR1 = bitrate_register;
235 SSR1 = 0;
236
237 SCR1 = SCI_TE; /* enable transmitter */
238 serial_mode = SER_POLL_WRITE;
239}
240
241static void set_sci1_poll_read(void)
242{
243 while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */
244 SCR1 = 0; /* disable transmitter (& receiver) */
245 SCR1 = (SCI_TE|SCI_RE); /* re-enable transmitter & receiver */
246 while (!(SSR1 & SCI_TEND)); /* wait for SCI init completion (!) */
247 serial_mode = SER_POLL_READ;
248 TDR1 = 0xFF; /* send do-nothing while reading */
249}
250
251static void write_transfer(const unsigned char *buf, int len)
252{
253 const unsigned char *buf_end = buf + len;
254 register unsigned char data;
255
256 if (serial_mode != SER_POLL_WRITE)
257 {
258 while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */
259 SCR1 = 0; /* disable transmitter & receiver */
260 SSR1 = 0; /* clear all flags */
261 SCR1 = SCI_TE; /* enable transmitter only */
262 serial_mode = SER_POLL_WRITE;
263 }
264
265 while (buf < buf_end)
266 {
267 data = fliptable[(signed char)(*buf++)]; /* bitswap */
268 while (!(SSR1 & SCI_TDRE)); /* wait for end of transfer */
269 TDR1 = data; /* write byte */
270 SSR1 = 0; /* start transmitting */
271 }
272}
273
274/* don't call this with len == 0 */
275static void read_transfer(unsigned char *buf, int len)
276{
277 unsigned char *buf_end = buf + len - 1;
278 register signed char data;
279
280 if (serial_mode != SER_POLL_READ)
281 set_sci1_poll_read();
282
283 SSR1 = 0; /* start receiving first byte */
284 while (buf < buf_end)
285 {
286 while (!(SSR1 & SCI_RDRF)); /* wait for data */
287 data = RDR1; /* read byte */
288 SSR1 = 0; /* start receiving */
289 *buf++ = fliptable[data]; /* bitswap */
290 }
291 while (!(SSR1 & SCI_RDRF)); /* wait for last byte */
292 *buf = fliptable[(signed char)(RDR1)]; /* read & bitswap */
293}
294
295/* returns 0xFF on timeout, timeout is in bytes */
296static unsigned char poll_byte(long timeout)
297{
298 long i;
299 unsigned char data = 0; /* stop the compiler complaining */
300
301 if (serial_mode != SER_POLL_READ)
302 set_sci1_poll_read();
303
304 i = 0;
305 do {
306 SSR1 = 0; /* start receiving */
307 while (!(SSR1 & SCI_RDRF)); /* wait for data */
308 data = RDR1; /* read byte */
309 } while ((data == 0xFF) && (++i < timeout));
310
311 return fliptable[(signed char)data];
312}
313
314/* returns 0 on timeout, timeout is in bytes */
315static unsigned char poll_busy(long timeout)
316{
317 long i;
318 unsigned char data, dummy;
319
320 if (serial_mode != SER_POLL_READ)
321 set_sci1_poll_read();
322
323 /* get data response */
324 SSR1 = 0; /* start receiving */
325 while (!(SSR1 & SCI_RDRF)); /* wait for data */
326 data = fliptable[(signed char)(RDR1)]; /* read byte */
327
328 /* wait until the card is ready again */
329 i = 0;
330 do {
331 SSR1 = 0; /* start receiving */
332 while (!(SSR1 & SCI_RDRF)); /* wait for data */
333 dummy = RDR1; /* read byte */
334 } while ((dummy != 0xFF) && (++i < timeout));
335
336 return (dummy == 0xFF) ? data : 0;
337}
338
339/* Send MMC command and get response. Returns R1 byte directly.
340 * Returns further R2 or R3 bytes in *data (can be NULL for other commands) */
341static unsigned char send_cmd(int cmd, unsigned long parameter, void *data)
342{
343 static struct {
344 unsigned char cmd;
345 unsigned long parameter;
346 const unsigned char crc7; /* fixed, valid for CMD0 only */
347 const unsigned char trailer;
348 } __attribute__((packed)) command = {0x40, 0, 0x95, 0xFF};
349
350 unsigned char ret;
351
352 command.cmd = cmd;
353 command.parameter = htobe32(parameter);
354
355 write_transfer((unsigned char *)&command, sizeof(command));
356
357 ret = poll_byte(20);
358
359 switch (cmd)
360 {
361 case CMD_SEND_CSD: /* R1 response, leave open */
362 case CMD_SEND_CID:
363 case CMD_READ_SINGLE_BLOCK:
364 case CMD_READ_MULTIPLE_BLOCK:
365 return ret;
366
367 case CMD_SEND_STATUS: /* R2 response, close with dummy */
368 read_transfer(data, 1);
369 break;
370
371 case CMD_READ_OCR: /* R3 response, close with dummy */
372 read_transfer(data, 4);
373 break;
374
375 default: /* R1 response, close with dummy */
376 break; /* also catches block writes */
377 }
378 write_transfer(dummy, 1);
379 return ret;
380}
381
382/* Receive CID/ CSD data (16 bytes) */
383static int receive_cxd(unsigned char *buf)
384{
385 if (poll_byte(20) != DT_START_BLOCK)
386 {
387 write_transfer(dummy, 1);
388 return -1; /* not start of data */
389 }
390
391 read_transfer(buf, 16);
392 write_transfer(dummy, 3); /* 2 bytes dontcare crc + 1 byte trailer */
393 return 0;
394}
395
396
397static int initialize_card(int card_no)
398{
399 int rc, i;
400 int blk_exp, ts_exp, taac_exp;
401 tCardInfo *card = &card_info[card_no];
402
403 static const char mantissa[] = { /* *10 */
404 0, 10, 12, 13, 15, 20, 25, 30,
405 35, 40, 45, 50, 55, 60, 70, 80
406 };
407 static const int exponent[] = { /* use varies */
408 1, 10, 100, 1000, 10000, 100000, 1000000,
409 10000000, 100000000, 1000000000
410 };
411
412 if (card_no == 1)
413 mmc_status = MMC_TOUCHED;
414
415 /* switch to SPI mode */
416 if (send_cmd(CMD_GO_IDLE_STATE, 0, NULL) != 0x01)
417 return -1; /* error or no response */
418
419 /* initialize card */
420 for (i = HZ;;) /* try for 1 second*/
421 {
422 sleep(1);
423 if (send_cmd(CMD_SEND_OP_COND, 0, NULL) == 0)
424 break;
425 if (--i <= 0)
426 return -2; /* timeout */
427 }
428
429 /* get OCR register */
430 if (send_cmd(CMD_READ_OCR, 0, &card->ocr))
431 return -3;
432 card->ocr = betoh32(card->ocr); /* no-op on big endian */
433
434 /* check voltage */
435 if (!(card->ocr & 0x00100000)) /* 3.2 .. 3.3 V */
436 return -4;
437
438 /* get CSD register */
439 if (send_cmd(CMD_SEND_CSD, 0, NULL))
440 return -5;
441 rc = receive_cxd((unsigned char*)card->csd);
442 if (rc)
443 return rc * 10 - 5;
444
445 blk_exp = card_extract_bits(card->csd, 83, 4);
446 if (blk_exp < 9) /* block size < 512 bytes not supported */
447 return -6;
448
449 card->numblocks = (card_extract_bits(card->csd, 73, 12) + 1)
450 << (card_extract_bits(card->csd, 49, 3) + 2 + blk_exp - 9);
451 card->blocksize = BLOCK_SIZE;
452
453 /* max transmission speed, clock divider */
454 ts_exp = card_extract_bits(card->csd, 98, 3);
455 ts_exp = (ts_exp > 3) ? 3 : ts_exp;
456 card->speed = mantissa[card_extract_bits(card->csd, 102, 4)]
457 * exponent[ts_exp + 4];
458 card->bitrate_register = (FREQ/4-1) / card->speed;
459
460 /* NSAC, TAAC, read timeout */
461 card->nsac = 100 * card_extract_bits(card->csd, 111, 8);
462 card->taac = mantissa[card_extract_bits(card->csd, 118, 4)];
463 taac_exp = card_extract_bits(card->csd, 114, 3);
464 card->read_timeout = ((FREQ/4) / (card->bitrate_register + 1)
465 * card->taac / exponent[9 - taac_exp]
466 + (10 * card->nsac));
467 card->read_timeout /= 8; /* clocks -> bytes */
468 card->taac = card->taac * exponent[taac_exp] / 10;
469
470 /* r2w_factor, write timeout */
471 card->r2w_factor = BIT_N(card_extract_bits(card->csd, 28, 3));
472 card->write_timeout = card->read_timeout * card->r2w_factor;
473
474 if (card->r2w_factor > 32) /* Such cards often need extra read delay */
475 card->read_timeout *= 4;
476
477 /* switch to full speed */
478 setup_sci1(card->bitrate_register);
479
480 /* always use 512 byte blocks */
481 if (send_cmd(CMD_SET_BLOCKLEN, BLOCK_SIZE, NULL))
482 return -7;
483
484 /* get CID register */
485 if (send_cmd(CMD_SEND_CID, 0, NULL))
486 return -8;
487 rc = receive_cxd((unsigned char*)card->cid);
488 if (rc)
489 return rc * 10 - 8;
490
491 card->initialized = true;
492 return 0;
493}
494
495tCardInfo *mmc_card_info(int card_no)
496{
497 tCardInfo *card = &card_info[card_no];
498
499 if (!card->initialized && ((card_no == 0) || mmc_detect()))
500 {
501 select_card(card_no);
502 deselect_card();
503 }
504 return card;
505}
506
507/* Receive one block with DMA and bitswap it (chasing bitswap). */
508static int receive_block(unsigned char *inbuf, long timeout)
509{
510 unsigned long buf_end;
511
512 if (poll_byte(timeout) != DT_START_BLOCK)
513 {
514 write_transfer(dummy, 1);
515 return -1; /* not start of data */
516 }
517
518 while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */
519
520 SCR1 = 0; /* disable serial */
521 SSR1 = 0; /* clear all flags */
522
523 /* setup DMA channel 0 */
524 CHCR0 = 0; /* disable */
525 SAR0 = RDR1_ADDR;
526 DAR0 = (unsigned long) inbuf;
527 DTCR0 = BLOCK_SIZE;
528 CHCR0 = 0x4601; /* fixed source address, RXI1, enable */
529 DMAOR = 0x0001;
530 SCR1 = (SCI_RE|SCI_RIE); /* kick off DMA */
531
532 /* DMA receives 2 bytes more than DTCR2, but the last 2 bytes are not
533 * stored. The first extra byte is available from RDR1 after the DMA ends,
534 * the second one is lost because of the SCI overrun. However, this
535 * behaviour conveniently discards the crc. */
536
537 yield(); /* be nice */
538
539 /* Bitswap received data, chasing the DMA pointer */
540 buf_end = (unsigned long)inbuf + BLOCK_SIZE;
541 do
542 {
543 /* Call bitswap whenever (a multiple of) 8 bytes are
544 * available (value optimised by experimentation). */
545 int swap_now = (DAR0 - (unsigned long)inbuf) & ~0x00000007;
546 if (swap_now)
547 {
548 bitswap(inbuf, swap_now);
549 inbuf += swap_now;
550 }
551 }
552 while ((unsigned long)inbuf < buf_end);
553
554 while (!(CHCR0 & 0x0002)); /* wait for end of DMA */
555 while (!(SSR1 & SCI_ORER)); /* wait for the trailing bytes */
556 SCR1 = 0;
557 serial_mode = SER_DISABLED;
558
559 write_transfer(dummy, 1); /* send trailer */
560 last_disk_activity = current_tick;
561 return 0;
562}
563
564/* Prepare a block for sending by copying it to the next write buffer
565 * and bitswapping it. */
566static void send_block_prepare(void)
567{
568 unsigned char *dest;
569
570 current_buffer ^= 1; /* toggle buffer */
571 dest = write_buffer[current_buffer] + 2;
572
573 memcpy(dest, send_block_addr, BLOCK_SIZE);
574 bitswap(dest, BLOCK_SIZE);
575
576 send_block_addr += BLOCK_SIZE;
577}
578
579/* Send one block with DMA from the current write buffer, possibly preparing
580 * the next block within the next write buffer in the background. */
581static int send_block_send(unsigned char start_token, long timeout,
582 bool prepare_next)
583{
584 int rc = 0;
585 unsigned char *curbuf = write_buffer[current_buffer];
586
587 curbuf[1] = fliptable[(signed char)start_token];
588 *(unsigned short *)(curbuf + BLOCK_SIZE + 2) = 0xFFFF;
589
590 while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */
591
592 SCR1 = 0; /* disable serial */
593 SSR1 = 0; /* clear all flags */
594
595 /* setup DMA channel 0 */
596 CHCR0 = 0; /* disable */
597 SAR0 = (unsigned long)(curbuf + 1);
598 DAR0 = TDR1_ADDR;
599 DTCR0 = BLOCK_SIZE + 3; /* start token + block + dummy crc */
600 CHCR0 = 0x1701; /* fixed dest. address, TXI1, enable */
601 DMAOR = 0x0001;
602 SCR1 = (SCI_TE|SCI_TIE); /* kick off DMA */
603
604 if (prepare_next)
605 send_block_prepare();
606 yield(); /* be nice */
607
608 while (!(CHCR0 & 0x0002)); /* wait for end of DMA */
609 while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */
610 SCR1 = 0;
611 serial_mode = SER_DISABLED;
612
613 if ((poll_busy(timeout) & 0x1F) != 0x05) /* something went wrong */
614 rc = -1;
615
616 write_transfer(dummy, 1);
617 last_disk_activity = current_tick;
618
619 return rc;
620}
621
622int mmc_read_sectors(IF_MD(int drive,)
623 unsigned long start,
624 int incount,
625 void* inbuf)
626{
627 int rc = 0;
628 int lastblock = 0;
629 unsigned long end_block;
630 tCardInfo *card;
631#ifndef HAVE_MULTIDRIVE
632 int drive = current_card;
633#endif
634
635 card = &card_info[drive];
636 rc = select_card(drive);
637 if (rc)
638 {
639 rc = rc * 10 - 1;
640 goto error;
641 }
642
643 end_block = start + incount;
644 if (end_block > card->numblocks)
645 {
646 rc = -2;
647 goto error;
648 }
649
650 /* Some cards don't like reading the very last block with
651 * CMD_READ_MULTIPLE_BLOCK, so make sure this block is always
652 * read with CMD_READ_SINGLE_BLOCK. */
653 if (end_block == card->numblocks)
654 lastblock = 1;
655
656 if (incount > 1)
657 {
658 /* MMC4.2: make multiplication conditional */
659 if (send_cmd(CMD_READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, NULL))
660 {
661 rc = -3;
662 goto error;
663 }
664 while (--incount >= lastblock)
665 {
666 rc = receive_block(inbuf, card->read_timeout);
667 if (rc)
668 {
669 /* If an error occurs during multiple block reading, the
670 * host still needs to send CMD_STOP_TRANSMISSION */
671 send_cmd(CMD_STOP_TRANSMISSION, 0, NULL);
672 rc = rc * 10 - 4;
673 goto error;
674 }
675 inbuf += BLOCK_SIZE;
676 start++;
677 /* ^^ necessary for the abovementioned last block special case */
678 }
679 if (send_cmd(CMD_STOP_TRANSMISSION, 0, NULL))
680 {
681 rc = -5;
682 goto error;
683 }
684 }
685 if (incount > 0)
686 {
687 /* MMC4.2: make multiplication conditional */
688 if (send_cmd(CMD_READ_SINGLE_BLOCK, start * BLOCK_SIZE, NULL))
689 {
690 rc = -6;
691 goto error;
692 }
693 rc = receive_block(inbuf, card->read_timeout);
694 if (rc)
695 {
696 rc = rc * 10 - 7;
697 goto error;
698 }
699 }
700
701 error:
702
703 deselect_card();
704
705 return rc;
706}
707
708int mmc_write_sectors(IF_MD(int drive,)
709 unsigned long start,
710 int count,
711 const void* buf)
712{
713 int rc = 0;
714 int write_cmd;
715 unsigned char start_token;
716 tCardInfo *card;
717#ifndef HAVE_MULTIDRIVE
718 int drive = current_card;
719#endif
720
721 card = &card_info[drive];
722 rc = select_card(drive);
723 if (rc)
724 {
725 rc = rc * 10 - 1;
726 goto error;
727 }
728
729 if (start + count > card->numblocks)
730 panicf("Writing past end of card");
731
732 send_block_addr = buf;
733 send_block_prepare();
734
735 if (count > 1)
736 {
737 write_cmd = CMD_WRITE_MULTIPLE_BLOCK;
738 start_token = DT_START_WRITE_MULTIPLE;
739 }
740 else
741 {
742 write_cmd = CMD_WRITE_BLOCK;
743 start_token = DT_START_BLOCK;
744 }
745 /* MMC4.2: make multiplication conditional */
746 if (send_cmd(write_cmd, start * BLOCK_SIZE, NULL))
747 {
748 rc = -2;
749 goto error;
750 }
751 while (--count >= 0)
752 {
753 rc = send_block_send(start_token, card->write_timeout, count > 0);
754 if (rc)
755 {
756 rc = rc * 10 - 3;
757 break;
758 /* If an error occurs during multiple block writing,
759 * the STOP_TRAN token still needs to be sent. */
760 }
761 }
762 if (write_cmd == CMD_WRITE_MULTIPLE_BLOCK)
763 {
764 static const unsigned char stop_tran = DT_STOP_TRAN;
765 write_transfer(&stop_tran, 1);
766 poll_busy(card->write_timeout);
767 }
768
769 error:
770
771 deselect_card();
772
773 return rc;
774}
775
776bool mmc_disk_is_active(void)
777{
778 /* this is correct unless early return from write gets implemented */
779 return mutex_test(&mmc_mutex);
780}
781
782bool mmc_detect(void)
783{
784 return (adc_read(ADC_MMC_SWITCH) < 0x200);
785}
786
787bool mmc_touched(void)
788{
789 if (mmc_status == MMC_UNKNOWN) /* try to detect */
790 {
791 mutex_lock(&mmc_mutex);
792 setup_sci1(7); /* safe value */
793 and_b(~0x02, &PADRH); /* assert CS */
794 if (send_cmd(CMD_SEND_OP_COND, 0, NULL) == 0xFF)
795 mmc_status = MMC_UNTOUCHED;
796 else
797 mmc_status = MMC_TOUCHED;
798
799 deselect_card();
800 }
801 return mmc_status == MMC_TOUCHED;
802}
803
804bool mmc_usb_active(int delayticks)
805{
806 /* reading "inactive" is delayed by user-supplied monoflop value */
807 return (usb_activity ||
808 TIME_BEFORE(current_tick, last_usb_activity + delayticks));
809}
810
811static void mmc_tick(void)
812{
813 bool current_status;
814
815 if (new_mmc_circuit)
816 /* USB bridge activity is 0 on idle, ~527 on active */
817 current_status = adc_read(ADC_USB_ACTIVE) > 0x100;
818 else
819 current_status = adc_read(ADC_USB_ACTIVE) < 0x190;
820
821 if (!current_status && usb_activity)
822 last_usb_activity = current_tick;
823 usb_activity = current_status;
824
825 current_status = mmc_detect();
826 /* Only report when the status has changed */
827 if (current_status != last_mmc_status)
828 {
829 last_mmc_status = current_status;
830 countdown = HZ/3;
831 }
832 else
833 {
834 /* Count down until it gets negative */
835 if (countdown >= 0)
836 countdown--;
837
838 if (countdown == 0)
839 {
840 if (current_status)
841 {
842 queue_broadcast(SYS_HOTSWAP_INSERTED, mmc_first_drive + 1);
843 }
844 else
845 {
846 queue_broadcast(SYS_HOTSWAP_EXTRACTED, mmc_first_drive + 1);
847 mmc_status = MMC_UNTOUCHED;
848 card_info[1].initialized = false;
849 }
850 }
851 }
852}
853
854void mmc_enable(bool on)
855{
856 mutex_lock(&mmc_mutex);
857 enable_controller(on);
858 mutex_unlock(&mmc_mutex);
859}
860
861int mmc_init(void)
862{
863 int rc = 0;
864
865 if (!initialized)
866 mutex_init(&mmc_mutex);
867
868 mutex_lock(&mmc_mutex);
869 led(false);
870
871 last_mmc_status = mmc_detect();
872#ifndef HAVE_MULTIDRIVE
873 /* Use MMC if inserted, internal flash otherwise */
874 current_card = last_mmc_status ? 1 : 0;
875#endif
876
877 if (!initialized)
878 {
879 if (!last_mmc_status)
880 mmc_status = MMC_UNTOUCHED;
881
882 /* Port setup */
883 PACR1 &= ~0x0F3C; /* GPIO function for PA13 (flash busy), PA12
884 * (clk gate), PA10 (flash CS), PA9 (MMC CS) */
885 PACR2 &= ~0x4000; /* GPIO for PA7 (flash reset) */
886 PADR |= 0x0680; /* set all the selects + reset high (=inactive) */
887 PAIOR |= 0x1680; /* make outputs for them and the PA12 clock gate */
888
889 PBCR1 &= ~0x0CF0; /* GPIO function for PB13, PB11 and PB10 */
890 PBDR |= 0x2C00; /* SCK1, TxD1 and RxD1 high in GPIO */
891 PBIOR |= 0x2000; /* SCK1 output */
892 PBIOR &= ~0x0C00; /* TxD1, RxD1 input */
893
894 IPRE &= 0x0FFF; /* disable SCI1 interrupts for the CPU */
895
896 new_mmc_circuit = ((HW_MASK & MMC_CLOCK_POLARITY) != 0);
897 tick_add_task(mmc_tick);
898 initialized = true;
899 }
900 enable_controller(true);
901
902 mutex_unlock(&mmc_mutex);
903 return rc;
904}
905
906long mmc_last_disk_activity(void)
907{
908 return last_disk_activity;
909}
910
911#ifdef STORAGE_GET_INFO
912void mmc_get_info(IF_MD(int drive,) struct storage_info *info)
913{
914#ifndef HAVE_MULTIDRIVE
915 const int drive=0;
916#endif
917 info->sector_size=card_info[drive].blocksize;
918 info->num_sectors=card_info[drive].numblocks;
919 info->vendor="Rockbox";
920 if(drive==0)
921 {
922 info->product="Internal Storage";
923 }
924 else
925 {
926 info->product="MMC Card Slot";
927 }
928 info->revision="0.00";
929}
930#endif
931
932#ifdef HAVE_HOTSWAP
933bool mmc_removable(IF_MD_NONVOID(int drive))
934{
935#ifndef HAVE_MULTIDRIVE
936 const int drive=0;
937#endif
938 return (drive==1);
939}
940
941bool mmc_present(IF_MD_NONVOID(int drive))
942{
943#ifndef HAVE_MULTIDRIVE
944 const int drive=0;
945#endif
946 if(drive==0)
947 {
948 return true;
949 }
950 else
951 {
952 return mmc_detect();
953 }
954}
955#endif
956
957void mmc_spin(void)
958{
959}
960
961void mmc_spindown(int seconds)
962{
963 (void)seconds;
964}
965
966#ifdef CONFIG_STORAGE_MULTI
967int mmc_num_drives(int first_drive)
968{
969 mmc_first_drive = first_drive;
970 return MMC_NUM_DRIVES;
971}
972#endif /* CONFIG_STORAGE_MULTI */
973
974int mmc_event(long id, intptr_t data)
975{
976 return storage_event_default_handler(id, data, last_disk_activity,
977 STORAGE_MMC);
978}
diff --git a/firmware/target/sh/archos/ondio/backlight-target.h b/firmware/target/sh/archos/ondio/backlight-target.h
deleted file mode 100644
index 438c8c926a..0000000000
--- a/firmware/target/sh/archos/ondio/backlight-target.h
+++ /dev/null
@@ -1,49 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef BACKLIGHT_TARGET_H
22#define BACKLIGHT_TARGET_H
23
24#include "config.h"
25#include "cpu.h"
26
27#ifdef HAVE_BACKLIGHT
28/* A stock Ondio has no backlight, it needs a hardware mod. */
29
30static inline bool backlight_hw_init(void)
31{
32 PACR1 &= ~0x3000; /* Set PA14 (backlight control) to GPIO */
33 or_b(0x40, &PADRH); /* drive it high */
34 or_b(0x40, &PAIORH); /* ..and output */
35 return true;
36}
37
38static inline void backlight_hw_on(void)
39{
40 or_b(0x40, &PADRH); /* drive it high */
41}
42
43static inline void backlight_hw_off(void)
44{
45 and_b(~0x40, &PADRH); /* drive it low */
46}
47#endif /* HAVE_BACKLIGHT */
48
49#endif
diff --git a/firmware/target/sh/archos/ondio/button-ondio.c b/firmware/target/sh/archos/ondio/button-ondio.c
deleted file mode 100644
index e3b370bc1f..0000000000
--- a/firmware/target/sh/archos/ondio/button-ondio.c
+++ /dev/null
@@ -1,71 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "system.h"
24#include "button.h"
25#include "backlight.h"
26#include "adc.h"
27
28/*
29 Ondio hardware button hookup
30 ============================
31
32 LEFT, RIGHT, UP, DOWN: connected to AN4 through a resistor network
33
34 The voltage on AN4 depends on which keys (or key combo) is pressed
35
36 OPTION: AN2, high active (assigned as MENU)
37 ON/OFF: AN3, low active (assigned as OFF)
38*/
39
40void button_init_device(void)
41{
42}
43
44int button_read_device(void)
45{
46 int btn = BUTTON_NONE;
47 int data;
48
49 /* Check the 4 direction keys */
50 data = adc_read(ADC_BUTTON_ROW1);
51 if (data >= 165)
52 {
53 if (data >= 585)
54 if (data >= 755)
55 btn = BUTTON_LEFT;
56 else
57 btn = BUTTON_RIGHT;
58 else
59 if (data >= 415)
60 btn = BUTTON_UP;
61 else
62 btn = BUTTON_DOWN;
63 }
64
65 if(adc_read(ADC_BUTTON_OPTION) > 0x200) /* active high */
66 btn |= BUTTON_MENU;
67 if(adc_read(ADC_BUTTON_ONOFF) < 0x120) /* active low */
68 btn |= BUTTON_OFF;
69
70 return btn;
71}
diff --git a/firmware/target/sh/archos/ondio/button-target.h b/firmware/target/sh/archos/ondio/button-target.h
deleted file mode 100644
index a84be2851a..0000000000
--- a/firmware/target/sh/archos/ondio/button-target.h
+++ /dev/null
@@ -1,39 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef _BUTTON_TARGET_H_
23#define _BUTTON_TARGET_H_
24
25#define BUTTON_OFF 0x00000001
26#define BUTTON_MENU 0x00000002
27
28#define BUTTON_LEFT 0x00000004
29#define BUTTON_RIGHT 0x00000008
30#define BUTTON_UP 0x00000010
31#define BUTTON_DOWN 0x00000020
32
33#define BUTTON_MAIN (BUTTON_OFF|BUTTON_MENU|BUTTON_LEFT|BUTTON_RIGHT\
34 |BUTTON_UP|BUTTON_DOWN)
35
36#define POWEROFF_BUTTON BUTTON_OFF
37#define POWEROFF_COUNT 10
38
39#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/sh/archos/ondio/fmradio_i2c-ondio.c b/firmware/target/sh/archos/ondio/fmradio_i2c-ondio.c
deleted file mode 100644
index b901bd0019..0000000000
--- a/firmware/target/sh/archos/ondio/fmradio_i2c-ondio.c
+++ /dev/null
@@ -1,202 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 * Physical interface of the Philips TEA5767 in Archos Ondio
10 *
11 * Copyright (C) 2002 by Linus Nielsen Feltzing
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "config.h"
24#include "cpu.h"
25#include "kernel.h"
26#include "logf.h"
27#include "system.h"
28#include "fmradio_i2c.h"
29
30#if (CONFIG_TUNER & TEA5767)
31
32/* cute little functions, atomic read-modify-write */
33/* SDA is PB4 */
34#define SDA_LO and_b(~0x10, &PBDRL)
35#define SDA_HI or_b(0x10, &PBDRL)
36#define SDA_INPUT and_b(~0x10, &PBIORL)
37#define SDA_OUTPUT or_b(0x10, &PBIORL)
38#define SDA (PBDR & 0x0010)
39
40/* SCL is PB1 */
41#define SCL_INPUT and_b(~0x02, &PBIORL)
42#define SCL_OUTPUT or_b(0x02, &PBIORL)
43#define SCL_LO and_b(~0x02, &PBDRL)
44#define SCL_HI or_b(0x02, &PBDRL)
45#define SCL (PBDR & 0x0002)
46
47/* arbitrary delay loop */
48#define DELAY do { int _x; for(_x=0;_x<20;_x++);} while (0)
49
50static void fmradio_i2c_start(void)
51{
52 SDA_OUTPUT;
53 SDA_HI;
54 SCL_HI;
55 SDA_LO;
56 DELAY;
57 SCL_LO;
58}
59
60static void fmradio_i2c_stop(void)
61{
62 SDA_LO;
63 SCL_HI;
64 DELAY;
65 SDA_HI;
66}
67
68
69static void fmradio_i2c_ack(bool nack)
70{
71 /* Here's the deal. The slave is slow, and sometimes needs to wait
72 before it can receive the acknowledge. Therefore it forces the clock
73 low until it is ready. We need to poll the clock line until it goes
74 high before we release the ack. */
75
76 SCL_LO; /* Set the clock low */
77
78 if (nack)
79 SDA_HI;
80 else
81 SDA_LO;
82
83 SCL_INPUT; /* Set the clock to input */
84 while(!SCL) /* and wait for the slave to release it */
85 sleep(0);
86
87 DELAY;
88 SCL_OUTPUT;
89 SCL_LO;
90}
91
92static int fmradio_i2c_getack(void)
93{
94 int ret = 1;
95
96 /* Here's the deal. The slave is slow, and sometimes needs to wait
97 before it can send the acknowledge. Therefore it forces the clock
98 low until it is ready. We need to poll the clock line until it goes
99 high before we read the ack. */
100
101 SDA_INPUT; /* And set to input */
102 SCL_INPUT; /* Set the clock to input */
103 while(!SCL) /* and wait for the slave to release it */
104 sleep(0);
105
106 if (SDA)
107 /* ack failed */
108 ret = 0;
109
110 SCL_OUTPUT;
111 SCL_LO;
112 SDA_HI;
113 SDA_OUTPUT;
114 return ret;
115}
116
117static void fmradio_i2c_outb(unsigned char byte)
118{
119 int i;
120
121 /* clock out each bit, MSB first */
122 for ( i=0x80; i; i>>=1 ) {
123 if ( i & byte )
124 {
125 SDA_HI;
126 }
127 else
128 {
129 SDA_LO;
130 }
131 SCL_HI;
132 SCL_LO;
133 }
134
135 SDA_HI;
136}
137
138static unsigned char fmradio_i2c_inb(void)
139{
140 int i;
141 unsigned char byte = 0;
142
143 /* clock in each bit, MSB first */
144 for ( i=0x80; i; i>>=1 ) {
145 SDA_INPUT; /* And set to input */
146 SCL_HI;
147 if ( SDA )
148 byte |= i;
149 SCL_LO;
150 SDA_OUTPUT;
151 }
152
153 return byte;
154}
155
156int fmradio_i2c_write(unsigned char address, const unsigned char* buf, int count)
157{
158 int i,x=0;
159
160 fmradio_i2c_start();
161 fmradio_i2c_outb(address & 0xfe);
162 if (fmradio_i2c_getack())
163 {
164 for (i=0; i<count; i++)
165 {
166 fmradio_i2c_outb(buf[i]);
167 if (!fmradio_i2c_getack())
168 {
169 x=-2;
170 break;
171 }
172 }
173 }
174 else
175 {
176 logf("fmradio_i2c_write() - no ack\n");
177 x=-1;
178 }
179 fmradio_i2c_stop();
180 return x;
181}
182
183int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
184{
185 int i,x=0;
186
187 fmradio_i2c_start();
188 fmradio_i2c_outb(address | 1);
189 if (fmradio_i2c_getack()) {
190 for (i=count; i>0; i--)
191 {
192 *buf++ = fmradio_i2c_inb();
193 fmradio_i2c_ack(i == 1);
194 }
195 }
196 else
197 x=-1;
198 fmradio_i2c_stop();
199 return x;
200}
201
202#endif
diff --git a/firmware/target/sh/archos/ondio/power-ondio.c b/firmware/target/sh/archos/ondio/power-ondio.c
deleted file mode 100644
index d7bbc08f4f..0000000000
--- a/firmware/target/sh/archos/ondio/power-ondio.c
+++ /dev/null
@@ -1,78 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "cpu.h"
23#include <stdbool.h>
24#include "kernel.h"
25#include "system.h"
26#include "power.h"
27#include "usb.h"
28#include "backlight-target.h"
29
30#if CONFIG_TUNER
31
32static bool powered = false;
33
34bool tuner_power(bool status)
35{
36 bool old_status = powered;
37
38 powered = status;
39 if (status)
40 {
41 and_b(~0x04, &PADRL); /* drive PA2 low for tuner enable */
42 sleep(1); /* let the voltage settle */
43 }
44 else
45 or_b(0x04, &PADRL); /* drive PA2 high for tuner disable */
46 return old_status;
47}
48
49#endif /* #if CONFIG_TUNER */
50
51void power_init(void)
52{
53 PBCR2 &= ~0x0c00; /* GPIO for PB5 */
54 or_b(0x20, &PBIORL);
55 or_b(0x20, &PBDRL); /* hold power */
56#ifndef HAVE_BACKLIGHT
57 /* Disable backlight on backlight-modded Ondios when running
58 * a standard build (always on otherwise). */
59 PACR1 &= ~0x3000; /* Set PA14 (backlight control) to GPIO */
60 and_b(~0x40, &PADRH); /* drive it low */
61 or_b(0x40, &PAIORH); /* ..and output */
62#endif
63 PACR2 &= ~0x0030; /* GPIO for PA2 */
64 or_b(0x04, &PADRL); /* drive PA2 high for tuner disable */
65 or_b(0x04, &PAIORL); /* output for PA2 */
66}
67
68void power_off(void)
69{
70 disable_irq();
71#ifdef HAVE_BACKLIGHT
72 /* Switch off the light on backlight-modded Ondios */
73 backlight_hw_off();
74#endif
75 and_b(~0x20, &PBDRL);
76 or_b(0x20, &PBIORL);
77 while(1);
78}
diff --git a/firmware/target/sh/archos/ondio/powermgmt-ondio.c b/firmware/target/sh/archos/ondio/powermgmt-ondio.c
deleted file mode 100644
index dc3cab031f..0000000000
--- a/firmware/target/sh/archos/ondio/powermgmt-ondio.c
+++ /dev/null
@@ -1,53 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese
11 * Revisions copyright (C) 2005 by Gerald Van Baren
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "config.h"
24#include "adc.h"
25#include "powermgmt.h"
26
27const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
28{
29 3100, 3450
30};
31
32const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
33{
34 2700, 2800
35};
36
37/* voltages (millivolt) of 0%, 10%, ... 100% */
38const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
39{
40 /* measured values */
41 { 2800, 3250, 3410, 3530, 3640, 3740, 3850, 3950, 4090, 4270, 4750 }, /* Alkaline */
42 { 3100, 3550, 3630, 3690, 3720, 3740, 3760, 3780, 3800, 3860, 4050 } /* NiMH */
43};
44
45#define BATTERY_SCALE_FACTOR 4849 /* average from 3 Ondios */
46/* full-scale ADC readout (2^10) in millivolt */
47
48/* Returns battery voltage from ADC [millivolts] */
49int _battery_voltage(void)
50{
51 return (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) >> 10;
52}
53
diff --git a/firmware/target/sh/archos/ondio/usb-ondio.c b/firmware/target/sh/archos/ondio/usb-ondio.c
deleted file mode 100644
index 093ebd3ad8..0000000000
--- a/firmware/target/sh/archos/ondio/usb-ondio.c
+++ /dev/null
@@ -1,61 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include <stdbool.h>
23#include "adc.h"
24#include "ata_mmc.h"
25#include "cpu.h"
26#include "hwcompat.h"
27#include "system.h"
28#include "usb.h"
29
30int usb_detect(void)
31{
32 return (adc_read(ADC_USB_POWER) <= 512) ? USB_INSERTED : USB_EXTRACTED;
33}
34
35void usb_enable(bool on)
36{
37 if (on)
38 {
39 mmc_enable_int_flash_clock(!mmc_detect());
40
41 if (!(HW_MASK & MMC_CLOCK_POLARITY))
42 and_b(~0x20, &PBDRH); /* old circuit needs SCK1 = low while on USB */
43 or_b(0x20, &PADRL); /* enable USB */
44 and_b(~0x08, &PADRL); /* assert card detect */
45 }
46 else
47 {
48 if (!(HW_MASK & MMC_CLOCK_POLARITY))
49 or_b(0x20, &PBDRH); /* reset SCK1 = high for old circuit */
50 and_b(~0x20, &PADRL); /* disable USB */
51 or_b(0x08, &PADRL); /* deassert card detect */
52 }
53}
54
55void usb_init_device(void)
56{
57 PACR2 &= ~0x04C0; /* use PA3 (card detect) and PA5 (USB enabled) as GPIO */
58 and_b(~0x20, &PADRL); /* disable USB */
59 or_b(0x08, &PADRL); /* deassert card detect */
60 or_b(0x28, &PAIORL); /* output for USB enable and card detect */
61}
diff --git a/firmware/target/sh/archos/player/adc-target.h b/firmware/target/sh/archos/player/adc-target.h
deleted file mode 100644
index a26f79de28..0000000000
--- a/firmware/target/sh/archos/player/adc-target.h
+++ /dev/null
@@ -1,35 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _ADC_TARGET_H_
22#define _ADC_TARGET_H_
23
24#define NUM_ADC_CHANNELS 8
25
26#define ADC_BUTTON_LEFT 0
27#define ADC_BUTTON_MENU 1
28#define ADC_BUTTON_RIGHT 2
29#define ADC_BUTTON_PLAY 3
30#define ADC_UNREG_POWER 6 /* Battery voltage with a better scaling */
31#define ADC_EXT_POWER 7 /* The external power voltage, 0v or 2.7v */
32
33#define EXT_SCALE_FACTOR 14800
34
35#endif /* _ADC_TARGET_H_ */
diff --git a/firmware/target/sh/archos/player/backlight-target.h b/firmware/target/sh/archos/player/backlight-target.h
deleted file mode 100644
index b97d21a40f..0000000000
--- a/firmware/target/sh/archos/player/backlight-target.h
+++ /dev/null
@@ -1,46 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef BACKLIGHT_TARGET_H
22#define BACKLIGHT_TARGET_H
23
24#include "config.h"
25#include "cpu.h"
26
27static inline bool backlight_hw_init(void)
28{
29 PACR1 &= ~0x3000; /* Set PA14 (backlight control) to GPIO */
30 and_b(~0x40, &PADRH); /* drive and set low */
31 or_b(0x40, &PAIORH); /* ..and output */
32 return true;
33}
34
35static inline void backlight_hw_on(void)
36{
37 and_b(~0x40, &PADRH); /* drive and set low */
38 or_b(0x40, &PAIORH);
39}
40
41static inline void backlight_hw_off(void)
42{
43 and_b(~0x40, &PAIORH); /* let it float (up) */
44}
45
46#endif
diff --git a/firmware/target/sh/archos/player/button-player.c b/firmware/target/sh/archos/player/button-player.c
deleted file mode 100644
index 3cf634853e..0000000000
--- a/firmware/target/sh/archos/player/button-player.c
+++ /dev/null
@@ -1,76 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "system.h"
24#include "button.h"
25#include "backlight.h"
26#include "adc.h"
27
28/*
29 Player hardware button hookup
30 =============================
31
32 Player
33 ------
34 LEFT: AN0
35 MENU: AN1
36 RIGHT: AN2
37 PLAY: AN3
38
39 STOP: PA11
40 ON: PA5
41
42 All buttons are low active
43*/
44
45void button_init_device(void)
46{
47 /* set PA5 and PA11 as input pins */
48 PACR1 &= 0xff3f; /* PA11MD = 00 */
49 PACR2 &= 0xfbff; /* PA5MD = 0 */
50 PAIOR &= ~0x0820; /* Inputs */
51}
52
53int button_read_device(void)
54{
55 int btn = BUTTON_NONE;
56 int data;
57
58 /* buttons are active low */
59 if (adc_read(ADC_BUTTON_LEFT) < 0x180)
60 btn = BUTTON_LEFT;
61 if (adc_read(ADC_BUTTON_MENU) < 0x180)
62 btn |= BUTTON_MENU;
63 if (adc_read(ADC_BUTTON_RIGHT) < 0x180)
64 btn |= BUTTON_RIGHT;
65 if (adc_read(ADC_BUTTON_PLAY) < 0x180)
66 btn |= BUTTON_PLAY;
67
68 /* check port A pins for ON and STOP */
69 data = PADR;
70 if ( !(data & 0x0020) )
71 btn |= BUTTON_ON;
72 if ( !(data & 0x0800) )
73 btn |= BUTTON_STOP;
74
75 return btn;
76}
diff --git a/firmware/target/sh/archos/player/button-target.h b/firmware/target/sh/archos/player/button-target.h
deleted file mode 100644
index dd85d731be..0000000000
--- a/firmware/target/sh/archos/player/button-target.h
+++ /dev/null
@@ -1,52 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef _BUTTON_TARGET_H_
23#define _BUTTON_TARGET_H_
24
25#define HAS_SERIAL_REMOTE
26
27 /* Main unit's buttons */
28#define BUTTON_ON 0x00000001
29#define BUTTON_STOP 0x00000002
30
31#define BUTTON_LEFT 0x00000004
32#define BUTTON_RIGHT 0x00000008
33#define BUTTON_PLAY 0x00000010
34#define BUTTON_MENU 0x00000020
35
36#define BUTTON_MAIN (BUTTON_ON|BUTTON_STOP|BUTTON_LEFT|BUTTON_RIGHT\
37 |BUTTON_PLAY|BUTTON_MENU)
38
39 /* Remote control's buttons */
40#define BUTTON_RC_PLAY 0x00100000
41#define BUTTON_RC_STOP 0x00080000
42
43#define BUTTON_RC_LEFT 0x00040000
44#define BUTTON_RC_RIGHT 0x00020000
45#define BUTTON_RC_VOL_UP 0x00010000
46#define BUTTON_RC_VOL_DOWN 0x00008000
47
48#define BUTTON_REMOTE (BUTTON_RC_PLAY|BUTTON_RC_STOP\
49 |BUTTON_RC_LEFT|BUTTON_RC_RIGHT\
50 |BUTTON_RC_VOL_UP|BUTTON_RC_VOL_DOWN)
51
52#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/sh/archos/player/hwcompat-player.c b/firmware/target/sh/archos/player/hwcompat-player.c
deleted file mode 100644
index 49a333d708..0000000000
--- a/firmware/target/sh/archos/player/hwcompat-player.c
+++ /dev/null
@@ -1,28 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include <stdbool.h>
23#include "hwcompat.h"
24
25bool is_new_player(void)
26{
27 return (ROM_VERSION > 449) || (ROM_VERSION == 116);
28}
diff --git a/firmware/target/sh/archos/player/lcd-as-player.S b/firmware/target/sh/archos/player/lcd-as-player.S
deleted file mode 100644
index 19f812c1c7..0000000000
--- a/firmware/target/sh/archos/player/lcd-as-player.S
+++ /dev/null
@@ -1,274 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 by Jens Arnold
11 * Based on the work of Alan Korr and Jörg Hohensohn
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "config.h"
24#include "cpu.h"
25
26#define LCDR (PBDR_ADDR+1)
27
28#define LCD_DS 1 /* PB0 = 1 --- 0001 --- LCD-DS */
29#define LCD_CS 2 /* PB1 = 1 --- 0010 --- /LCD-CS */
30#define LCD_SD 4 /* PB2 = 1 --- 0100 --- LCD-SD */
31#define LCD_SC 8 /* PB3 = 1 --- 1000 --- LCD-SC */
32
33/*
34 * About /CS,DS,SC,SD
35 * ------------------
36 *
37 * LCD on JBP and JBR uses a SPI protocol to receive orders (SDA and SCK lines)
38 *
39 * - /CS -> Chip Selection line :
40 * 0 : LCD chipset is activated.
41 * - DS -> Data Selection line, latched at the rising edge
42 * of the 8th serial clock (*) :
43 * 0 : instruction register,
44 * 1 : data register;
45 * - SC -> Serial Clock line (SDA).
46 * - SD -> Serial Data line (SCK), latched at the rising edge
47 * of each serial clock (*).
48 *
49 * _ _
50 * /CS \ /
51 * \______________________________________________________/
52 * _____ ____ ____ ____ ____ ____ ____ ____ ____ _____
53 * SD \/ D7 \/ D6 \/ D5 \/ D4 \/ D3 \/ D2 \/ D1 \/ D0 \/
54 * _____/\____/\____/\____/\____/\____/\____/\____/\____/\_____
55 *
56 * _____ _ _ _ _ _ _ _ ________
57 * SC \ * \ * \ * \ * \ * \ * \ * \ *
58 * \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
59 * _ _________________________________________________________
60 * DS \/
61 * _/\_________________________________________________________
62 *
63 */
64
65 .section .icode,"ax",@progbits
66
67 .align 2
68 .global _lcd_write_command
69 .type _lcd_write_command,@function
70
71/* Write a command byte to the lcd controller
72 *
73 * Arguments:
74 * r4 - command byte (int)
75 *
76 * Register usage:
77 * r0 - scratch
78 * r1 - command byte (copied)
79 * r2 - precalculated port value (CS, DS and SC low, SD high)
80 * r3 - lcd port address
81 * r5 - 1 (byte count for reuse of the loop in _lcd_write_data)
82 */
83
84_lcd_write_command:
85 mov.l .lcdr, r3 /* put lcd data port address in r3 */
86 mov r4, r1 /* copy data byte to r1 */
87 mov #0, r5 /* fake end address - stop after first iteration */
88
89 /* This code will fail if an interrupt changes the contents of PBDRL.
90 * If so, we must disable the interrupt here. */
91
92 mov.b @r3, r0 /* r0 = PBDRL */
93 or #(LCD_SD), r0 /* r0 |= LCD_SD */
94 and #(~(LCD_CS|LCD_DS|LCD_SC)),r0 /* r0 &= ~(LCD_CS|LCD_DS|LCD_SC) */
95
96 bra .single_transfer /* jump into the transfer loop */
97 mov r0, r2
98
99
100 .align 2
101 .global _lcd_write_command_e
102 .type _lcd_write_command_e,@function
103
104/* Write a command byte and a data byte to the lcd controller
105 *
106 * Arguments:
107 * r4 - command byte
108 * r5 - data byte
109 *
110 * Register usage:
111 * r0 - scratch
112 * r1 - command/data byte (copied)
113 * r2 - precalculated port value (CS, DS and SC low, SD high)
114 * r3 - lcd port address
115 * r5 - fake end address
116 * r6 - data byte (saved)
117 * r7 - saved pr
118 */
119
120_lcd_write_command_e:
121 mov.l .lcdr, r3 /* put lcd data port address in r3 */
122 mov r4, r1 /* copy data byte to r1 */
123 mov r5, r6
124 mov #0, r5 /* fake end address - stop after first iteration */
125
126 /* This code will fail if an interrupt changes the contents of PBDRL.
127 * If so, we must disable the interrupt here. */
128
129 mov.b @r3, r0 /* r0 = PBDRL */
130 or #(LCD_SD), r0 /* r0 |= LCD_SD */
131 and #(~(LCD_CS|LCD_DS|LCD_SC)),r0 /* r0 &= ~(LCD_CS|LCD_DS|LCD_SC) */
132
133 sts pr, r7
134 bsr .single_transfer /* jump into the transfer loop */
135 mov r0, r2
136
137 lds r7, pr
138 mov r6, r1
139 or #(LCD_DS|LCD_SD), r0 /* r0 |= LCD_DS|LCD_SD */
140 and #(~(LCD_CS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_SC) */
141 bra .single_transfer /* jump into the transfer loop */
142 mov r0, r2
143
144
145 .align 2
146 .global _lcd_write_data
147 .type _lcd_write_data,@function
148
149
150/* A high performance function to write data to the display,
151 * one or multiple bytes.
152 *
153 * Arguments:
154 * r4 - data address
155 * r5 - byte count
156 *
157 * Register usage:
158 * r0 - scratch
159 * r1 - current data byte
160 * r2 - precalculated port value (CS and SC low, DS and SD high)
161 * r3 - lcd port address
162 * r4 - current address
163 * r5 - end address
164 */
165
166_lcd_write_data:
167 mov.l .lcdr, r3 /* put lcd data port address in r3 */
168 add r4, r5 /* end address */
169
170 /* This code will fail if an interrupt changes the contents of PBDRL.
171 * If so, we must disable the interrupt here. If disabling interrupts
172 * for a long time (~9200 clks = ~830 µs for transferring 112 bytes on
173 * recorders)is undesirable, the loop has to be rewritten to
174 * disable/precalculate/transfer/enable for each iteration. However,
175 * this would significantly decrease performance. */
176
177 mov.b @r3, r0 /* r0 = PBDRL */
178 or #(LCD_DS|LCD_SD), r0 /* r0 |= LCD_DS|LCD_SD */
179 and #(~(LCD_CS|LCD_SC)), r0 /* r0 &= ~(LCD_CS|LCD_SC) */
180 mov r0, r2
181
182 .align 2
183.multi_transfer:
184 mov.b @r4+, r1 /* load data byte from memory */
185
186.single_transfer:
187 shll16 r1 /* shift data to most significant byte */
188 shll8 r1
189
190 shll r1 /* shift the msb into carry */
191 mov r2, r0 /* copy precalculated port value */
192 bt 1f /* data bit = 1? */
193 and #(~LCD_SD), r0 /* no: r0 &= ~LCD_SD */
1941:
195 shll r1 /* next shift here for alignment */
196 mov.b r0, @r3 /* set data to port */
197 or #(LCD_SC), r0 /* rise SC (independent of SD level) */
198 mov.b r0, @r3 /* set to port */
199
200 mov r2, r0
201 bt 1f
202 and #(~LCD_SD), r0
2031:
204 mov.b r0, @r3
205 or #(LCD_SC), r0
206 mov.b r0, @r3
207
208 shll r1
209 mov r2, r0
210 bt 1f
211 and #(~LCD_SD), r0
2121:
213 shll r1
214 mov.b r0, @r3
215 or #(LCD_SC), r0
216 mov.b r0, @r3
217
218 mov r2, r0
219 bt 1f
220 and #(~LCD_SD), r0
2211:
222 mov.b r0, @r3
223 or #(LCD_SC), r0
224 mov.b r0, @r3
225
226 shll r1
227 mov r2, r0
228 bt 1f
229 and #(~LCD_SD), r0
2301:
231 shll r1
232 mov.b r0, @r3
233 or #(LCD_SC), r0
234 mov.b r0, @r3
235
236 mov r2, r0
237 bt 1f
238 and #(~LCD_SD), r0
2391:
240 mov.b r0, @r3
241 or #(LCD_SC), r0
242 mov.b r0, @r3
243
244 shll r1
245 mov r2, r0
246 bt 1f
247 and #(~LCD_SD), r0
2481:
249 shll r1
250 mov.b r0, @r3
251 or #(LCD_SC), r0
252 mov.b r0, @r3
253
254 mov r2, r0
255 bt 1f
256 and #(~LCD_SD), r0
2571:
258 mov.b r0, @r3
259 or #(LCD_SC), r0
260 mov.b r0, @r3
261
262 cmp/hi r4, r5 /* some blocks left? */
263 bt .multi_transfer
264
265 or #(LCD_CS|LCD_DS|LCD_SD|LCD_SC),r0 /* restore port */
266 rts
267 mov.b r0, @r3
268
269 /* This is the place to reenable the interrupts, if we have disabled
270 * them. See above. */
271
272 .align 2
273.lcdr:
274 .long LCDR
diff --git a/firmware/target/sh/archos/player/lcd-player.c b/firmware/target/sh/archos/player/lcd-player.c
deleted file mode 100644
index 95b0164bf5..0000000000
--- a/firmware/target/sh/archos/player/lcd-player.c
+++ /dev/null
@@ -1,213 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Jens Arnold
11 * Based on the work of Alan Korr, Kjell Ericson and others
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include <string.h>
24#include "config.h"
25#include "system.h"
26#include "kernel.h"
27#include "hwcompat.h"
28#include "lcd.h"
29#include "lcd-charcell.h"
30
31#define OLD_LCD_DDRAM ((char)0xB0) /* Display data (characters) */
32#define OLD_LCD_CGRAM ((char)0x80) /* Character generator (patterns) */
33#define OLD_LCD_ICONRAM ((char)0xE0)
34#define OLD_LCD_CONTRAST_SET ((char)0xA8)
35#define OLD_LCD_NOP ((char)0x00)
36#define OLD_LCD_SYSTEM_SET ((char)0x60)
37#define OLD_LCD_SET_POWER_SAVE_OSC_CONTROL ((char)0x40)
38#define OLD_LCD_SET_POWER_CONTROL ((char)0x50)
39#define OLD_LCD_SET_DISPLAY_CONTROL ((char)0x30)
40
41#define NEW_LCD_DDRAM ((char)0x80) /* Display data (characters) */
42#define NEW_LCD_CGRAM ((char)0xC0) /* Character generator (patterns) */
43#define NEW_LCD_ICONRAM ((char)0x40)
44#define NEW_LCD_CONTRAST_SET ((char)0x50)
45#define NEW_LCD_NOP ((char)0x00)
46#define NEW_LCD_FUNCTION_SET ((char)0x10)
47#define NEW_LCD_SET_POWER_SAVE_OSC_CONTROL ((char)0x0c)
48#define NEW_LCD_SET_POWER_CONTROL_REG ((char)0x20)
49#define NEW_LCD_SET_DISPLAY_CONTROL ((char)0x28)
50#define NEW_LCD_SET_DOUBLE_HEIGHT ((char)0x08)
51
52#define LCD_CURSOR(x,y) ((char)(lcd_ddram+((y)*16+(x))))
53#define LCD_ICON(i) ((char)(lcd_iconram+i))
54
55static bool new_lcd;
56static char lcd_contrast_set;
57static char lcd_ddram;
58static char lcd_cgram;
59static char lcd_iconram;
60
61/* hardware configuration */
62
63int lcd_default_contrast(void)
64{
65 return 30;
66}
67
68void lcd_set_contrast(int val)
69{
70 lcd_write_command_e(lcd_contrast_set, 31 - val);
71}
72
73/* charcell specific */
74
75void lcd_double_height(bool on)
76{
77 if(new_lcd)
78 lcd_write_command(on ? (NEW_LCD_SET_DOUBLE_HEIGHT|1)
79 : NEW_LCD_SET_DOUBLE_HEIGHT);
80}
81
82void lcd_icon(int icon, bool enable)
83{
84 static const struct {
85 char pos;
86 char mask;
87 } icontab[] = {
88 { 0, 0x02}, { 0, 0x08}, { 0, 0x04}, { 0, 0x10}, /* Battery */
89 { 2, 0x04}, /* USB */
90 { 3, 0x10}, /* Play */
91 { 4, 0x10}, /* Record */
92 { 5, 0x02}, /* Pause */
93 { 5, 0x10}, /* Audio */
94 { 6, 0x02}, /* Repeat */
95 { 7, 0x01}, /* 1 */
96 { 9, 0x04}, /* Volume */
97 { 9, 0x02}, { 9, 0x01}, {10, 0x08}, {10, 0x04}, {10, 0x01}, /* Vol 1-5 */
98 {10, 0x10}, /* Param */
99 };
100 static char icon_mirror[11] = {0};
101
102 int pos, mask;
103
104 pos = icontab[icon].pos;
105 mask = icontab[icon].mask;
106
107 if (enable)
108 icon_mirror[pos] |= mask;
109 else
110 icon_mirror[pos] &= ~mask;
111
112 lcd_write_command_e(LCD_ICON(pos), icon_mirror[pos]);
113}
114
115/* device specific init */
116void lcd_init_device(void)
117{
118 unsigned char data_vector[64];
119
120 /* LCD init for cold start */
121 PBCR2 &= 0xff00; /* Set PB0..PB3 to GPIO */
122 or_b(0x0f, &PBDRL); /* ... high */
123 or_b(0x0f, &PBIORL); /* ... and output */
124
125 new_lcd = is_new_player();
126
127 if (new_lcd)
128 {
129 lcd_contrast_set = NEW_LCD_CONTRAST_SET;
130 lcd_ddram = NEW_LCD_DDRAM;
131 lcd_cgram = NEW_LCD_CGRAM;
132 lcd_iconram = NEW_LCD_ICONRAM;
133
134 lcd_write_command(NEW_LCD_FUNCTION_SET|1); /* CGRAM selected */
135 lcd_write_command_e(NEW_LCD_CONTRAST_SET, 0x08);
136 lcd_write_command(NEW_LCD_SET_POWER_SAVE_OSC_CONTROL|2);
137 /* oscillator on */
138 lcd_write_command(NEW_LCD_SET_POWER_CONTROL_REG|7);
139 /* opamp buffer + voltage booster on */
140
141 memset(data_vector, 0x20, 64);
142 lcd_write_command(NEW_LCD_DDRAM); /* Set DDRAM address */
143 lcd_write_data(data_vector, 64); /* all spaces */
144
145 memset(data_vector, 0, 64);
146 lcd_write_command(NEW_LCD_CGRAM); /* Set CGRAM address */
147 lcd_write_data(data_vector, 64); /* zero out */
148 lcd_write_command(NEW_LCD_ICONRAM); /* Set ICONRAM address */
149 lcd_write_data(data_vector, 16); /* zero out */
150
151 lcd_write_command(NEW_LCD_SET_DISPLAY_CONTROL|1); /* display on */
152 }
153 else
154 {
155 lcd_contrast_set = OLD_LCD_CONTRAST_SET;
156 lcd_ddram = OLD_LCD_DDRAM;
157 lcd_cgram = OLD_LCD_CGRAM;
158 lcd_iconram = OLD_LCD_ICONRAM;
159
160 lcd_write_command(OLD_LCD_NOP);
161 lcd_write_command(OLD_LCD_SYSTEM_SET|1); /* CGRAM selected */
162 lcd_write_command(OLD_LCD_SET_POWER_SAVE_OSC_CONTROL|2);
163 /* oscillator on */
164 lcd_write_command(OLD_LCD_SET_POWER_CONTROL|7);
165 /* voltage regulator, voltage follower and booster on */
166
167 memset(data_vector, 0x24, 13);
168 lcd_write_command(OLD_LCD_DDRAM); /* Set DDRAM address */
169 lcd_write_data(data_vector, 13); /* all spaces */
170 lcd_write_command(OLD_LCD_DDRAM + 0x10);
171 lcd_write_data(data_vector, 13);
172 lcd_write_command(OLD_LCD_DDRAM + 0x20);
173 lcd_write_data(data_vector, 13);
174
175 memset(data_vector, 0, 32);
176 lcd_write_command(OLD_LCD_CGRAM); /* Set CGRAM address */
177 lcd_write_data(data_vector, 32); /* zero out */
178 lcd_write_command(OLD_LCD_ICONRAM); /* Set ICONRAM address */
179 lcd_write_data(data_vector, 13); /* zero out */
180 lcd_write_command(OLD_LCD_ICONRAM + 0x10);
181 lcd_write_data(data_vector, 13);
182
183 sleep(HZ/10);
184 lcd_write_command(OLD_LCD_SET_DISPLAY_CONTROL|1); /* display on */
185 }
186 lcd_set_contrast(lcd_default_contrast());
187}
188
189/*** Update functions ***/
190
191void lcd_update(void)
192{
193 int y;
194
195 for (y = 0; y < lcd_pattern_count; y++)
196 {
197 if (lcd_patterns[y].count > 0)
198 {
199 lcd_write_command(lcd_cgram | (y << 3));
200 lcd_write_data(lcd_patterns[y].pattern, 7);
201 }
202 }
203 for (y = 0; y < LCD_HEIGHT; y++)
204 {
205 lcd_write_command(LCD_CURSOR(0, y));
206 lcd_write_data(lcd_charbuffer[y], LCD_WIDTH);
207 }
208 if (lcd_cursor.visible)
209 {
210 lcd_write_command_e(LCD_CURSOR(lcd_cursor.x, lcd_cursor.y),
211 lcd_cursor.hw_char);
212 }
213}
diff --git a/firmware/target/sh/archos/player/power-player.c b/firmware/target/sh/archos/player/power-player.c
deleted file mode 100644
index 33f5959021..0000000000
--- a/firmware/target/sh/archos/player/power-player.c
+++ /dev/null
@@ -1,84 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "cpu.h"
23#include <stdbool.h>
24#include "kernel.h"
25#include "system.h"
26#include "power.h"
27#include "usb.h"
28
29void power_init(void)
30{
31}
32
33unsigned int power_input_status(void)
34{
35 /* Player */
36 return ((PADR & 1) == 0) ?
37 POWER_INPUT_MAIN_CHARGER : POWER_INPUT_NONE;
38}
39
40void ide_power_enable(bool on)
41{
42 bool touched = false;
43
44 if(on)
45 {
46 or_b(0x10, &PBDRL);
47 touched = true;
48 }
49#ifdef HAVE_ATA_POWER_OFF
50 if(!on)
51 {
52 and_b(~0x10, &PBDRL);
53 touched = true;
54 }
55#endif /* HAVE_ATA_POWER_OFF */
56
57/* late port preparation, else problems with read/modify/write
58 of other bits on same port, while input and floating high */
59 if (touched)
60 {
61 or_b(0x10, &PBIORL); /* PB4 is an output */
62 PBCR2 &= ~0x0300; /* GPIO for PB4 */
63 }
64}
65
66
67bool ide_powered(void)
68{
69 /* This is not correct for very old players, since these are unable to
70 * control hd power. However, driving the pin doesn't hurt, because it
71 * is not connected anywhere */
72 if ((PBCR2 & 0x0300) || !(PBIORL & 0x10)) /* not configured for output */
73 return false; /* would be floating low, disk off */
74 else
75 return (PBDRL & 0x10) != 0;
76}
77
78void power_off(void)
79{
80 disable_irq();
81 and_b(~0x08, &PADRH);
82 or_b(0x08, &PAIORH);
83 while(1);
84}
diff --git a/firmware/target/sh/archos/player/powermgmt-player.c b/firmware/target/sh/archos/player/powermgmt-player.c
deleted file mode 100644
index 8aa03d88a5..0000000000
--- a/firmware/target/sh/archos/player/powermgmt-player.c
+++ /dev/null
@@ -1,64 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese
11 * Revisions copyright (C) 2005 by Gerald Van Baren
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "config.h"
24#include "adc.h"
25#include "powermgmt.h"
26
27const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
28{
29 4750
30};
31
32const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
33{
34 4400
35};
36
37/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
38const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
39{
40 /* original values were taken directly after charging, but it should show
41 100% after turning off the device for some hours, too */
42 { 4500, 4810, 4910, 4970, 5030, 5070, 5120, 5140, 5170, 5250, 5400 }
43 /* orig. values: ...,5280,5600 */
44};
45
46/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
47const unsigned short percent_to_volt_charge[11] =
48{
49 /* values guessed, see
50 http://www.seattlerobotics.org/encoder/200210/LiIon2.pdf until someone
51 measures voltages over a charging cycle */
52 4760, 5440, 5510, 5560, 5610, 5640, 5660, 5760, 5820, 5840, 5850 /* NiMH */
53};
54
55#define BATTERY_SCALE_FACTOR 6703
56/* full-scale ADC readout (2^10) in millivolt */
57
58/* Returns battery voltage from ADC [millivolts] */
59int _battery_voltage(void)
60{
61 return (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) >> 10;
62}
63
64
diff --git a/firmware/target/sh/archos/player/usb-player.c b/firmware/target/sh/archos/player/usb-player.c
deleted file mode 100644
index 76f2a2dcdd..0000000000
--- a/firmware/target/sh/archos/player/usb-player.c
+++ /dev/null
@@ -1,44 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include <stdbool.h>
23#include "cpu.h"
24#include "system.h"
25#include "usb.h"
26
27int usb_detect(void)
28{
29 return (PADR & 0x8000) ? USB_EXTRACTED : USB_INSERTED;
30}
31
32void usb_enable(bool on)
33{
34 if(on)
35 and_b(~0x04, &PADRH);
36 else
37 or_b(0x04, &PADRH);
38}
39
40void usb_init_device(void)
41{
42 or_b(0x04, &PADRH);
43 or_b(0x04, &PAIORH);
44}
diff --git a/firmware/target/sh/archos/recorder/adc-target.h b/firmware/target/sh/archos/recorder/adc-target.h
deleted file mode 100644
index 06c48a5021..0000000000
--- a/firmware/target/sh/archos/recorder/adc-target.h
+++ /dev/null
@@ -1,41 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _ADC_TARGET_H_
22#define _ADC_TARGET_H_
23
24#define NUM_ADC_CHANNELS 8
25
26/* normal JBR channel assignment */
27#define ADC_BATTERY 0 /* Battery voltage always reads 0x3FF due to
28 silly scaling */
29#define ADC_CHARGE_REGULATOR 1 /* Regulator reference voltage, should read
30 about 0x1c0 when charging, else 0x3FF */
31#define ADC_USB_POWER 2 /* USB, reads 0x3FF when USB is inserted */
32#define ADC_BUTTON_ROW1 4 /* Used for scanning the keys, different
33 voltages for different keys */
34#define ADC_BUTTON_ROW2 5 /* Used for scanning the keys, different
35 voltages for different keys */
36#define ADC_UNREG_POWER 6 /* Battery voltage with a better scaling */
37#define ADC_EXT_POWER 7 /* The external power voltage, 0v or 2.7v */
38
39#define EXT_SCALE_FACTOR 14800
40
41#endif /* _ADC_TARGET_H_ */
diff --git a/firmware/target/sh/archos/recorder/backlight-target.h b/firmware/target/sh/archos/recorder/backlight-target.h
deleted file mode 100644
index c3dd395eca..0000000000
--- a/firmware/target/sh/archos/recorder/backlight-target.h
+++ /dev/null
@@ -1,51 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef BACKLIGHT_TARGET_H
22#define BACKLIGHT_TARGET_H
23
24#include "config.h"
25#include "rtc.h"
26
27#define backlight_hw_init() true
28
29static inline void backlight_hw_on(void)
30{
31 rtc_write(0x13, 0x10); /* 32 kHz square wave */
32 rtc_write(0x0a, rtc_read(0x0a) | 0x40); /* Enable square wave */
33}
34
35static inline void backlight_hw_off(void)
36{
37 /* While on, backlight is flashing at 32 kHz. If the square wave output
38 is disabled while the backlight is lit, it will become constantly lit,
39 (brighter) and slowly fade. This resets the square wave counter and
40 results in the unlit state */
41 unsigned char rtc_0a = rtc_read(0x0a) & ~0x40;
42 rtc_write(0x0a, rtc_0a); /* Disable square wave */
43 rtc_write(0x13, 0xF0); /* 1 Hz square wave */
44 rtc_write(0x0a, rtc_0a | 0x40); /* Enable square wave */
45
46 /* When the square wave output is disabled in the unlit state,
47 the backlight stays off */
48 rtc_write(0x0a, rtc_0a);
49}
50
51#endif
diff --git a/firmware/target/sh/archos/recorder/button-recorder.c b/firmware/target/sh/archos/recorder/button-recorder.c
deleted file mode 100644
index 5e5e67487d..0000000000
--- a/firmware/target/sh/archos/recorder/button-recorder.c
+++ /dev/null
@@ -1,110 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "system.h"
24#include "button.h"
25#include "backlight.h"
26#include "adc.h"
27
28/*
29 Recorder hardware button hookup
30 ===============================
31
32 F1, F2, F3, UP: connected to AN4 through a resistor network
33 DOWN, PLAY, LEFT, RIGHT: likewise connected to AN5
34
35 The voltage on AN4/ AN5 depends on which keys (or key combo) is pressed
36
37 ON: PB8, low active
38 OFF: PB4, low active
39*/
40
41void button_init_device(void)
42{
43 /* Set PB4 and PB8 as input pins */
44 PBCR1 &= 0xfffc; /* PB8MD = 00 */
45 PBCR2 &= 0xfcff; /* PB4MD = 00 */
46 PBIOR &= ~0x0110; /* Inputs */
47}
48
49int button_read_device(void)
50{
51 int btn = BUTTON_NONE;
52 int data;
53 static int off_button_count = 0;
54
55 /* check F1..F3 and UP */
56 data = adc_read(ADC_BUTTON_ROW1);
57 if (data >= 250)
58 {
59 if (data >= 700)
60 if (data >= 900)
61 btn = BUTTON_F3;
62 else
63 btn = BUTTON_UP;
64 else
65 if (data >= 500)
66 btn = BUTTON_F2;
67 else
68 btn = BUTTON_F1;
69 }
70
71 /* Some units have mushy keypads, so pressing UP also activates
72 the Left/Right buttons. Let's combat that by skipping the AN5
73 checks when UP is pressed. */
74 if(!(btn & BUTTON_UP))
75 {
76 /* check DOWN, PLAY, LEFT, RIGHT */
77 data = adc_read(ADC_BUTTON_ROW2);
78 if (data >= 250)
79 {
80 if (data >= 700)
81 if (data >= 900)
82 btn |= BUTTON_DOWN;
83 else
84 btn |= BUTTON_PLAY;
85 else
86 if (data >= 500)
87 btn |= BUTTON_LEFT;
88 else
89 btn |= BUTTON_RIGHT;
90 }
91 }
92
93 /* check port B pins for ON and OFF */
94 data = PBDR;
95 if ((data & 0x0100) == 0)
96 btn |= BUTTON_ON;
97
98 if ((data & 0x0010) == 0)
99 {
100 /* When the batteries are low, the low-battery shutdown logic causes
101 * spurious OFF events due to voltage fluctuation on some units.
102 * Only accept OFF when read several times in sequence. */
103 if (++off_button_count > 3)
104 btn |= BUTTON_OFF;
105 }
106 else
107 off_button_count = 0;
108
109 return btn;
110}
diff --git a/firmware/target/sh/archos/recorder/button-target.h b/firmware/target/sh/archos/recorder/button-target.h
deleted file mode 100644
index f387fafe10..0000000000
--- a/firmware/target/sh/archos/recorder/button-target.h
+++ /dev/null
@@ -1,59 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef _BUTTON_TARGET_H_
23#define _BUTTON_TARGET_H_
24
25#define HAS_SERIAL_REMOTE
26
27 /* Main unit's buttons */
28#define BUTTON_ON 0x00000001
29#define BUTTON_OFF 0x00000002
30
31#define BUTTON_LEFT 0x00000004
32#define BUTTON_RIGHT 0x00000008
33#define BUTTON_UP 0x00000010
34#define BUTTON_DOWN 0x00000020
35
36#define BUTTON_PLAY 0x00000040
37
38#define BUTTON_F1 0x00000080
39#define BUTTON_F2 0x00000100
40#define BUTTON_F3 0x00000200
41
42#define BUTTON_MAIN (BUTTON_ON|BUTTON_OFF|BUTTON_LEFT|BUTTON_RIGHT\
43 |BUTTON_UP|BUTTON_DOWN|BUTTON_PLAY\
44 |BUTTON_F1|BUTTON_F2|BUTTON_F3)
45
46 /* Remote control's buttons */
47#define BUTTON_RC_PLAY 0x00100000
48#define BUTTON_RC_STOP 0x00080000
49
50#define BUTTON_RC_LEFT 0x00040000
51#define BUTTON_RC_RIGHT 0x00020000
52#define BUTTON_RC_VOL_UP 0x00010000
53#define BUTTON_RC_VOL_DOWN 0x00008000
54
55#define BUTTON_REMOTE (BUTTON_RC_PLAY|BUTTON_RC_STOP\
56 |BUTTON_RC_LEFT|BUTTON_RC_RIGHT\
57 |BUTTON_RC_VOL_UP|BUTTON_RC_VOL_DOWN)
58
59#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/sh/archos/recorder/power-recorder.c b/firmware/target/sh/archos/recorder/power-recorder.c
deleted file mode 100644
index 48cfdc1e17..0000000000
--- a/firmware/target/sh/archos/recorder/power-recorder.c
+++ /dev/null
@@ -1,107 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "cpu.h"
23#include <stdbool.h>
24#include "adc.h"
25#include "kernel.h"
26#include "system.h"
27#include "power.h"
28#include "powermgmt-target.h"
29#include "usb.h"
30
31static bool charger_on;
32
33void power_init(void)
34{
35 PBCR2 &= ~0x0c00; /* GPIO for PB5 */
36 or_b(0x20, &PBIORL); /* Set charging control bit to output */
37 charger_enable(false); /* Default to charger OFF */
38}
39
40unsigned int power_input_status(void)
41{
42 /* Recorder */
43 return (adc_read(ADC_EXT_POWER) > 0x100) ?
44 POWER_INPUT_MAIN_CHARGER : POWER_INPUT_NONE;
45}
46
47void charger_enable(bool on)
48{
49 if(on)
50 {
51 and_b(~0x20, &PBDRL);
52 }
53 else
54 {
55 or_b(0x20, &PBDRL);
56 }
57
58 charger_on = on;
59}
60
61bool charger_enabled(void)
62{
63 return charger_on;
64}
65
66void ide_power_enable(bool on)
67{
68 bool touched = false;
69
70 if(on)
71 {
72 or_b(0x20, &PADRL);
73 touched = true;
74 }
75#ifdef HAVE_ATA_POWER_OFF
76 if(!on)
77 {
78 and_b(~0x20, &PADRL);
79 touched = true;
80 }
81#endif /* HAVE_ATA_POWER_OFF */
82
83/* late port preparation, else problems with read/modify/write
84 of other bits on same port, while input and floating high */
85 if (touched)
86 {
87 or_b(0x20, &PAIORL); /* PA5 is an output */
88 PACR2 &= 0xFBFF; /* GPIO for PA5 */
89 }
90}
91
92
93bool ide_powered(void)
94{
95 if ((PACR2 & 0x0400) || !(PAIORL & 0x20)) /* not configured for output */
96 return true; /* would be floating high, disk on */
97 else
98 return (PADRL & 0x20) != 0;
99}
100
101void power_off(void)
102{
103 disable_irq();
104 and_b(~0x10, &PBDRL);
105 or_b(0x10, &PBIORL);
106 while(1);
107}
diff --git a/firmware/target/sh/archos/recorder/powermgmt-recorder.c b/firmware/target/sh/archos/recorder/powermgmt-recorder.c
deleted file mode 100644
index ca6067a4cc..0000000000
--- a/firmware/target/sh/archos/recorder/powermgmt-recorder.c
+++ /dev/null
@@ -1,501 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese
11 * Revisions copyright (C) 2005 by Gerald Van Baren
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#include "config.h"
23#include "system.h"
24#include <stdio.h>
25#include "debug.h"
26#include "storage.h"
27#include "adc.h"
28#include "power.h"
29#include "powermgmt.h"
30
31const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
32{
33 4750
34};
35
36const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
37{
38 4400
39};
40
41/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
42const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
43{
44 /* original values were taken directly after charging, but it should show
45 100% after turning off the device for some hours, too */
46 { 4500, 4810, 4910, 4970, 5030, 5070, 5120, 5140, 5170, 5250, 5400 }
47 /* orig. values: ...,5280,5600 */
48};
49
50/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
51const unsigned short percent_to_volt_charge[11] =
52{
53 /* values guessed, see
54 http://www.seattlerobotics.org/encoder/200210/LiIon2.pdf until someone
55 measures voltages over a charging cycle */
56 4760, 5440, 5510, 5560, 5610, 5640, 5660, 5760, 5820, 5840, 5850 /* NiMH */
57};
58
59#define BATTERY_SCALE_FACTOR 6620
60/* full-scale ADC readout (2^10) in millivolt */
61
62/* Returns battery voltage from ADC [millivolts] */
63int _battery_voltage(void)
64{
65 return (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) >> 10;
66}
67
68void powermgmt_init_target(void)
69{
70}
71
72/** Charger control **/
73#ifdef CHARGING_DEBUG_FILE
74#include "file.h"
75#define DEBUG_FILE_NAME "/powermgmt.csv"
76#define DEBUG_MESSAGE_LEN 133
77static char debug_message[DEBUG_MESSAGE_LEN];
78static int fd = -1; /* write debug information to this file */
79static int wrcount = 0;
80#endif /* CHARGING_DEBUG_FILE */
81
82/*
83 * For a complete description of the charging algorithm read
84 * docs/CHARGING_ALGORITHM.
85 */
86int long_delta; /* long term delta battery voltage */
87int short_delta; /* short term delta battery voltage */
88static bool disk_activity_last_cycle = false; /* flag set to aid charger time
89 * calculation */
90char power_message[POWER_MESSAGE_LEN] = ""; /* message that's shown in
91 debug menu */
92 /* percentage at which charging
93 starts */
94int powermgmt_last_cycle_startstop_min = 0; /* how many minutes ago was the
95 charging started or
96 stopped? */
97int powermgmt_last_cycle_level = 0; /* which level had the
98 batteries at this time? */
99int trickle_sec = 0; /* how many seconds should the
100 charger be enabled per
101 minute for trickle
102 charging? */
103int pid_p = 0; /* PID proportional term */
104int pid_i = 0; /* PID integral term */
105
106static unsigned int target_voltage = TRICKLE_VOLTAGE; /* desired topoff/trickle
107 * voltage level */
108static int charge_max_time_idle = 0; /* max. charging duration, calculated at
109 * beginning of charging */
110static int charge_max_time_now = 0; /* max. charging duration including
111 * hdd activity */
112static int minutes_disk_activity = 0; /* count minutes of hdd use during
113 * charging */
114static int last_disk_activity = CHARGE_END_LONGD + 1; /* last hdd use x mins ago */
115
116#ifdef CHARGING_DEBUG_FILE
117static void debug_file_close(void)
118{
119 if (fd >= 0) {
120 close(fd);
121 fd = -1;
122 }
123}
124
125static void debug_file_log(void)
126{
127 if (usb_inserted()) {
128 /* It is probably too late to close the file but we can try... */
129 debug_file_close();
130 }
131 else if (fd < 0) {
132 fd = open(DEBUG_FILE_NAME, O_WRONLY | O_APPEND | O_CREAT, 0666);
133
134 if (fd >= 0) {
135 snprintf(debug_message, DEBUG_MESSAGE_LEN,
136 "cycle_min, bat_millivolts, bat_percent, chgr_state"
137 " ,charge_state, pid_p, pid_i, trickle_sec\n");
138 write(fd, debug_message, strlen(debug_message));
139 wrcount = 99; /* force a flush */
140 }
141 }
142 else {
143 snprintf(debug_message, DEBUG_MESSAGE_LEN,
144 "%d, %d, %d, %d, %d, %d, %d, %d\n",
145 powermgmt_last_cycle_startstop_min, battery_voltage(),
146 battery_level(), charger_input_state, charge_state,
147 pid_p, pid_i, trickle_sec);
148 write(fd, debug_message, strlen(debug_message));
149 wrcount++;
150 }
151}
152
153static void debug_file_sync(void)
154{
155 /*
156 * If we have a lot of pending writes or if the disk is spining,
157 * fsync the debug log file.
158 */
159 if (wrcount > 10 || (wrcount > 0 && storage_disk_is_active())) {
160 if (fd >= 0)
161 fsync(fd);
162
163 wrcount = 0;
164 }
165}
166#else /* !CHARGING_DEBUG_FILE */
167#define debug_file_close()
168#define debug_file_log()
169#define debug_file_sync()
170#endif /* CHARGING_DEBUG_FILE */
171
172/*
173 * Do tasks that should be done every step.
174 */
175static void do_frequent_tasks(void)
176{
177 if (storage_disk_is_active()) {
178 /* flag hdd use for charging calculation */
179 disk_activity_last_cycle = true;
180 }
181
182 debug_file_sync();
183}
184
185/*
186 * The charger was just plugged in. If the battery level is
187 * nearly charged, just trickle. If the battery is low, start
188 * a full charge cycle. If the battery level is in between,
189 * top-off and then trickle.
190 */
191static void charger_plugged(void)
192{
193 int battery_percent = battery_level();
194
195 pid_p = 0;
196 pid_i = 0;
197 powermgmt_last_cycle_level = battery_percent;
198 powermgmt_last_cycle_startstop_min = 0;
199
200 snprintf(power_message, POWER_MESSAGE_LEN, "Charger plugged in");
201
202 if (battery_percent > START_TOPOFF_CHG) {
203
204 if (battery_percent >= START_TRICKLE_CHG) {
205 charge_state = TRICKLE;
206 target_voltage = TRICKLE_VOLTAGE;
207 }
208 else {
209 charge_state = TOPOFF;
210 target_voltage = TOPOFF_VOLTAGE;
211 }
212 }
213 else {
214 /*
215 * Start the charger full strength
216 */
217 int i = CHARGE_MAX_MIN_1500 * get_battery_capacity() / 1500;
218 charge_max_time_idle = i * (100 + 35 - battery_percent) / 100;
219
220 if (charge_max_time_idle > i)
221 charge_max_time_idle = i;
222
223 charge_max_time_now = charge_max_time_idle;
224
225 snprintf(power_message, POWER_MESSAGE_LEN,
226 "ChgAt %d%% max %dm", battery_percent,
227 charge_max_time_now);
228
229 /*
230 * Enable the charger after the max time calc is done,
231 * because battery_level depends on if the charger is
232 * on.
233 */
234 DEBUGF("power: charger inserted and battery"
235 " not full, charging\n");
236 trickle_sec = 60;
237 long_delta = short_delta = 999999;
238 charge_state = CHARGING;
239 }
240}
241
242/*
243 * The charger was just unplugged.
244 */
245static void charger_unplugged(void)
246{
247 DEBUGF("power: charger disconnected, disabling\n");
248
249 charger_enable(false);
250 powermgmt_last_cycle_level = battery_level();
251 powermgmt_last_cycle_startstop_min = 0;
252 trickle_sec = 0;
253 pid_p = 0;
254 pid_i = 0;
255 charge_state = DISCHARGING;
256 snprintf(power_message, POWER_MESSAGE_LEN, "Charger: discharge");
257}
258
259static void charging_step(void)
260{
261 int i;
262
263 /* alter charge time max length with extra disk use */
264 if (disk_activity_last_cycle) {
265 minutes_disk_activity++;
266 charge_max_time_now = charge_max_time_idle +
267 minutes_disk_activity*2 / 5;
268 disk_activity_last_cycle = false;
269 last_disk_activity = 0;
270 }
271 else {
272 last_disk_activity++;
273 }
274
275 /*
276 * Check the delta voltage over the last X minutes so we can do
277 * our end-of-charge logic based on the battery level change
278 * (no longer use minimum time as logic for charge end has 50
279 * minutes minimum charge built in).
280 */
281 if (powermgmt_last_cycle_startstop_min > CHARGE_END_SHORTD) {
282 short_delta = power_history[0] -
283 power_history[CHARGE_END_SHORTD - 1];
284 }
285
286 if (powermgmt_last_cycle_startstop_min > CHARGE_END_LONGD) {
287 /*
288 * Scan the history: the points where measurement is taken need to
289 * be fairly static. Check prior to short delta 'area'. Also only
290 * check first and last 10 cycles (delta in middle OK).
291 */
292 long_delta = power_history[0] -
293 power_history[CHARGE_END_LONGD - 1];
294
295 for (i = CHARGE_END_SHORTD; i < CHARGE_END_SHORTD + 10; i++)
296 {
297 if ((power_history[i] - power_history[i+1]) > 50 ||
298 (power_history[i] - power_history[i+1]) < -50) {
299 long_delta = 777777;
300 break;
301 }
302 }
303
304 for (i = CHARGE_END_LONGD - 11; i < CHARGE_END_LONGD - 1 ; i++)
305 {
306 if ((power_history[i] - power_history[i+1]) > 50 ||
307 (power_history[i] - power_history[i+1]) < -50) {
308 long_delta = 888888;
309 break;
310 }
311 }
312 }
313
314 snprintf(power_message, POWER_MESSAGE_LEN,
315 "Chg %dm, max %dm", powermgmt_last_cycle_startstop_min,
316 charge_max_time_now);
317
318 /*
319 * End of charge criteria (any qualify):
320 * 1) Charged a long time
321 * 2) DeltaV went negative for a short time ( & long delta static)
322 * 3) DeltaV was negative over a longer period (no disk use only)
323 *
324 * Note: short_delta and long_delta are millivolts
325 */
326 if (powermgmt_last_cycle_startstop_min >= charge_max_time_now ||
327 (short_delta <= -50 && long_delta < 50) ||
328 (long_delta < -20 && last_disk_activity > CHARGE_END_LONGD)) {
329
330 int battery_percent = battery_level();
331
332 if (powermgmt_last_cycle_startstop_min > charge_max_time_now) {
333 DEBUGF("power: powermgmt_last_cycle_startstop_min > charge_max_time_now, "
334 "enough!\n");
335 /*
336 * Have charged too long and deltaV detection did not
337 * work!
338 */
339 snprintf(power_message, POWER_MESSAGE_LEN,
340 "Chg tmout %d min", charge_max_time_now);
341 /*
342 * Switch to trickle charging. We skip the top-off
343 * since we've effectively done the top-off operation
344 * already since we charged for the maximum full
345 * charge time.
346 */
347 powermgmt_last_cycle_level = battery_percent;
348 powermgmt_last_cycle_startstop_min = 0;
349 charge_state = TRICKLE;
350
351 /*
352 * Set trickle charge target to a relative voltage instead
353 * of an arbitrary value - the fully charged voltage may
354 * vary according to ambient temp, battery condition etc.
355 * Trickle target is -0.15v from full voltage acheived.
356 * Topup target is -0.05v from full voltage.
357 */
358 target_voltage = power_history[0] - 150;
359
360 }
361 else {
362 if(short_delta <= -5) {
363 DEBUGF("power: short-term negative"
364 " delta, enough!\n");
365 snprintf(power_message, POWER_MESSAGE_LEN,
366 "end negd %d %dmin", short_delta,
367 powermgmt_last_cycle_startstop_min);
368 target_voltage = power_history[CHARGE_END_SHORTD - 1] - 50;
369 }
370 else {
371 DEBUGF("power: long-term small "
372 "positive delta, enough!\n");
373 snprintf(power_message, POWER_MESSAGE_LEN,
374 "end lowd %d %dmin", long_delta,
375 powermgmt_last_cycle_startstop_min);
376 target_voltage = power_history[CHARGE_END_LONGD - 1] - 50;
377 }
378
379 /*
380 * Switch to top-off charging.
381 */
382 powermgmt_last_cycle_level = battery_percent;
383 powermgmt_last_cycle_startstop_min = 0;
384 charge_state = TOPOFF;
385 }
386 }
387}
388
389static void topoff_trickle_step(void)
390{
391 unsigned int millivolts;
392
393 /*
394 *Time to switch from topoff to trickle?
395 */
396 if (charge_state == TOPOFF &&
397 powermgmt_last_cycle_startstop_min > TOPOFF_MAX_MIN) {
398
399 powermgmt_last_cycle_level = battery_level();
400 powermgmt_last_cycle_startstop_min = 0;
401 charge_state = TRICKLE;
402 target_voltage = target_voltage - 100;
403 }
404 /*
405 * Adjust trickle charge time (proportional and integral terms).
406 * Note: I considered setting the level higher if the USB is
407 * plugged in, but it doesn't appear to be necessary and will
408 * generate more heat [gvb].
409 */
410 millivolts = battery_voltage();
411
412 pid_p = ((signed)target_voltage - (signed)millivolts) / 5;
413 if (pid_p <= PID_DEADZONE && pid_p >= -PID_DEADZONE)
414 pid_p = 0;
415
416 if ((unsigned)millivolts < target_voltage) {
417 if (pid_i < 60)
418 pid_i++; /* limit so it doesn't "wind up" */
419 }
420 else {
421 if (pid_i > 0)
422 pid_i--; /* limit so it doesn't "wind up" */
423 }
424
425 trickle_sec = pid_p + pid_i;
426
427 if (trickle_sec > 60)
428 trickle_sec = 60;
429
430 if (trickle_sec < 0)
431 trickle_sec = 0;
432}
433
434void charging_algorithm_step(void)
435{
436 static int pwm_counter = 0; /* PWM total cycle in steps */
437 static int pwm_duty = 0; /* PWM duty cycle in steps */
438
439 switch (charger_input_state)
440 {
441 case CHARGER_PLUGGED:
442 charger_plugged();
443 break;
444
445 case CHARGER_UNPLUGGED:
446 charger_unplugged();
447 break;
448
449 case CHARGER:
450 case NO_CHARGER:
451 do_frequent_tasks();
452
453 if (pwm_counter > 0) {
454 if (pwm_duty > 0 && --pwm_duty <= 0)
455 charger_enable(false); /* Duty cycle expired */
456
457 if (--pwm_counter > 0)
458 return;
459
460 /* PWM cycle is complete */
461 powermgmt_last_cycle_startstop_min++;
462 debug_file_log();
463 }
464 break;
465 }
466
467 switch (charge_state)
468 {
469 case CHARGING:
470 charging_step();
471 break;
472
473 case TOPOFF:
474 case TRICKLE:
475 topoff_trickle_step();
476 break;
477
478 case DISCHARGING:
479 default:
480 break;
481 }
482
483 /* If 100%, ensure pwm_on never expires and briefly disables the
484 * charger. */
485 pwm_duty = (trickle_sec < 60) ? trickle_sec*2 : 0;
486 pwm_counter = 60*2;
487 charger_enable(trickle_sec > 0);
488}
489
490void charging_algorithm_close(void)
491{
492#ifdef CHARGING_DEBUG_FILE
493 debug_file_close();
494#endif /* CHARGING_DEBUG_FILE */
495}
496
497/* Returns true if the unit is charging the batteries. */
498bool charging_state(void)
499{
500 return charge_state == CHARGING;
501}
diff --git a/firmware/target/sh/archos/recorder/powermgmt-target.h b/firmware/target/sh/archos/recorder/powermgmt-target.h
deleted file mode 100644
index 6b68d05bd4..0000000000
--- a/firmware/target/sh/archos/recorder/powermgmt-target.h
+++ /dev/null
@@ -1,89 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese
11 * Revisions copyright (C) 2005 by Gerald Van Baren
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#ifndef POWERMGMT_TARGET_H
23#define POWERMGMT_TARGET_H
24
25/*
26 * Define CHARGING_DEBUG_FILE to create a csv (spreadsheet) with battery
27 * information in it (one sample per minute/connect/disconnect).
28 *
29 * This is only for very low level debug.
30 */
31#undef CHARGING_DEBUG_FILE
32
33
34/* stop when N minutes have passed with avg delta being < -0.05 V */
35#define CHARGE_END_SHORTD 6
36/* stop when N minutes have passed with avg delta being < -0.02 V */
37#define CHARGE_END_LONGD 50
38
39/* Battery % to start at top-off */
40#define START_TOPOFF_CHG 85
41/* Battery % to start at trickle */
42#define START_TRICKLE_CHG 95
43/* power thread status message */
44#define POWER_MESSAGE_LEN 32
45/* minutes: maximum charging time for 1500 mAh batteries
46 * actual max time depends also on BATTERY_CAPACITY! */
47#define CHARGE_MAX_MIN_1500 450
48/* minutes: minimum charging time */
49#define CHARGE_MIN_MIN 10
50/* After charging, go to top off charge. How long should top off charge be? */
51#define TOPOFF_MAX_MIN 90
52/* which voltage is best? (millivolts) */
53#define TOPOFF_VOLTAGE 5650
54/* After top off charge, go to trickle harge. How long should trickle
55 * charge be? */
56#define TRICKLE_MAX_MIN 720 /* 12 hrs */
57/* which voltage is best? (millivolts) */
58#define TRICKLE_VOLTAGE 5450
59/* initial trickle_sec for topoff */
60#define START_TOPOFF_SEC 25
61/* initial trickle_sec for trickle */
62#define START_TRICKLE_SEC 15
63
64#define PID_DEADZONE 4 /* PID proportional deadzone */
65
66extern char power_message[POWER_MESSAGE_LEN];
67
68extern int long_delta; /* long term delta battery voltage */
69extern int short_delta; /* short term delta battery voltage */
70
71extern int powermgmt_last_cycle_startstop_min; /* how many minutes ago was
72 the charging started or
73 stopped? */
74extern int powermgmt_last_cycle_level; /* which level had the batteries
75 at this time? */
76
77extern int pid_p; /* PID proportional term */
78extern int pid_i; /* PID integral term */
79extern int trickle_sec; /* how many seconds should the
80 charger be enabled per
81 minute for trickle
82 charging? */
83void charger_enable(bool on);
84bool charger_enabled(void);
85
86/* Battery filter lengths in samples */
87#define BATT_AVE_SAMPLES 32
88
89#endif /* POWERMGMT_TARGET_H */
diff --git a/firmware/target/sh/archos/recorder/usb-recorder.c b/firmware/target/sh/archos/recorder/usb-recorder.c
deleted file mode 100644
index f8b462b802..0000000000
--- a/firmware/target/sh/archos/recorder/usb-recorder.c
+++ /dev/null
@@ -1,49 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include <stdbool.h>
23#include "adc.h"
24#include "cpu.h"
25#include "hwcompat.h"
26#include "system.h"
27#include "usb.h"
28
29int usb_detect(void)
30{
31 return (adc_read(ADC_USB_POWER) > 500) ? USB_INSERTED : USB_EXTRACTED;
32}
33
34void usb_enable(bool on)
35{
36 if(HW_MASK & USB_ACTIVE_HIGH)
37 on = !on;
38
39 if(on)
40 and_b(~0x04, &PADRH); /* enable USB */
41 else
42 or_b(0x04, &PADRH);
43}
44
45void usb_init_device(void)
46{
47 usb_enable(false);
48 or_b(0x04, &PAIORH);
49}
diff --git a/firmware/target/sh/archos/timer-archos.c b/firmware/target/sh/archos/timer-archos.c
deleted file mode 100644
index 98a3afb4b6..0000000000
--- a/firmware/target/sh/archos/timer-archos.c
+++ /dev/null
@@ -1,84 +0,0 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Copyright (C) 2005 Jens Arnold
11*
12* This program is free software; you can redistribute it and/or
13* modify it under the terms of the GNU General Public License
14* as published by the Free Software Foundation; either version 2
15* of the License, or (at your option) any later version.
16*
17* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18* KIND, either express or implied.
19*
20****************************************************************************/
21
22#include "cpu.h"
23#include "system.h"
24#include "timer.h"
25
26void IMIA4(void) __attribute__((interrupt_handler));
27void IMIA4(void)
28{
29 if (pfn_timer != NULL)
30 pfn_timer();
31 and_b(~0x01, &TSR4); /* clear the interrupt */
32}
33
34bool timer_set(long cycles, bool start)
35{
36 int phi = 0; /* bits for the prescaler */
37 int prescale = 1;
38
39 while (cycles > 0x10000)
40 { /* work out the smallest prescaler that makes it fit */
41 phi++;
42 prescale <<= 1;
43 cycles >>= 1;
44 }
45
46 if (prescale > 8)
47 return false;
48
49 if (start)
50 {
51 if (pfn_unregister != NULL)
52 {
53 pfn_unregister();
54 pfn_unregister = NULL;
55 }
56
57 and_b(~0x10, &TSTR); /* Stop the timer 4 */
58 and_b(~0x10, &TSNC); /* No synchronization */
59 and_b(~0x10, &TMDR); /* Operate normally */
60
61 TIER4 = 0xF9; /* Enable GRA match interrupt */
62 }
63
64 TCR4 = 0x20 | phi; /* clear at GRA match, set prescaler */
65 GRA4 = (unsigned short)(cycles - 1);
66 if (start || (TCNT4 >= GRA4))
67 TCNT4 = 0;
68 and_b(~0x01, &TSR4); /* clear an eventual interrupt */
69
70 return true;
71}
72
73bool timer_start(void)
74{
75 IPRD = (IPRD & 0xFF0F) | 1 << 4; /* interrupt priority */
76 or_b(0x10, &TSTR); /* start timer 4 */
77 return true;
78}
79
80void timer_stop(void)
81{
82 and_b(~0x10, &TSTR); /* stop the timer 4 */
83 IPRD = (IPRD & 0xFF0F); /* disable interrupt */
84}
diff --git a/firmware/target/sh/archos/uart-archos.c b/firmware/target/sh/archos/uart-archos.c
deleted file mode 100644
index d17678f812..0000000000
--- a/firmware/target/sh/archos/uart-archos.c
+++ /dev/null
@@ -1,167 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr & Nick Robinson
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include <stdio.h>
22#include <stdlib.h>
23#include <stdarg.h>
24
25#include "config.h"
26#include "button.h"
27#include "cpu.h"
28#include "system.h"
29#include "kernel.h"
30#include "serial.h"
31
32/* FIX: this doesn't work on iRiver or iPod yet */
33/* iFP7xx has no remote */
34
35/* Received byte identifiers */
36#define PLAY 0xC1
37#define STOP 0xC2
38#define PREV 0xC4
39#define NEXT 0xC8
40#define VOLUP 0xD0
41#define VOLDN 0xE0
42
43void serial_setup (void)
44{
45 /* Set PB10 function to serial Rx */
46 PBCR1 = (PBCR1 & 0xffcf) | 0x0020;
47
48 SMR1 = 0x00;
49 SCR1 = 0;
50 BRR1 = (FREQ/(32*9600))-1;
51 and_b(0, &SSR1); /* The status bits must be read before they are cleared,
52 so we do an AND operation */
53
54 /* Let the hardware settle. The serial port needs to wait "at least
55 the interval required to transmit or receive one bit" before it
56 can be used. */
57 sleep(1);
58
59 SCR1 = 0x10; /* Enable the receiver, no interrupt */
60}
61
62int tx_rdy(void)
63{
64 /* a dummy */
65 return 1;
66}
67
68static int rx_rdy(void)
69{
70 if(SSR1 & SCI_RDRF)
71 return 1;
72 else
73 return 0;
74}
75
76void tx_writec(unsigned char c)
77{
78 /* a dummy */
79 (void)c;
80}
81
82static unsigned char rx_readc(void)
83{
84 char tmp;
85 /* Read byte and clear the Rx Full bit */
86 tmp = RDR1;
87 and_b(~SCI_RDRF, &SSR1);
88 return tmp;
89}
90
91
92/* This function returns the received remote control code only if it is
93 received without errors before or after the reception.
94 It therefore returns the received code on the second call after the
95 code has been received. */
96int remote_control_rx(void)
97{
98 static int last_valid_button = BUTTON_NONE;
99 static int last_was_error = false;
100 int btn;
101 int ret = BUTTON_NONE;
102
103 /* Errors? Just clear'em. The receiver stops if we don't */
104 if(SSR1 & (SCI_ORER | SCI_FER | SCI_PER)) {
105 and_b(~(SCI_ORER | SCI_FER | SCI_PER), &SSR1);
106 last_valid_button = BUTTON_NONE;
107 last_was_error = true;
108 return BUTTON_NONE;
109 }
110
111 if(rx_rdy()) {
112 btn = rx_readc();
113
114 if(last_was_error)
115 {
116 last_valid_button = BUTTON_NONE;
117 ret = BUTTON_NONE;
118 }
119 else
120 {
121 switch (btn)
122 {
123 case STOP:
124 last_valid_button = BUTTON_RC_STOP;
125 break;
126
127 case PLAY:
128 last_valid_button = BUTTON_RC_PLAY;
129 break;
130
131 case VOLUP:
132 last_valid_button = BUTTON_RC_VOL_UP;
133 break;
134
135 case VOLDN:
136 last_valid_button = BUTTON_RC_VOL_DOWN;
137 break;
138
139 case PREV:
140 last_valid_button = BUTTON_RC_LEFT;
141 break;
142
143 case NEXT:
144 last_valid_button = BUTTON_RC_RIGHT;
145 break;
146
147 default:
148 last_valid_button = BUTTON_NONE;
149 break;
150 }
151 }
152 }
153 else
154 {
155 /* This means that a valid remote control character was received
156 the last time we were called, with no receiver errors either before
157 or after. Then we can assume that there really is a remote control
158 attached, and return the button code. */
159 ret = last_valid_button;
160 last_valid_button = BUTTON_NONE;
161 }
162
163 last_was_error = false;
164
165 return ret;
166}
167
diff --git a/firmware/target/sh/bitswap.S b/firmware/target/sh/bitswap.S
deleted file mode 100644
index ba8dd0cc1a..0000000000
--- a/firmware/target/sh/bitswap.S
+++ /dev/null
@@ -1,152 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 by Jens Arnold
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22 .section .icode,"ax",@progbits
23 .align 2
24 .global _bitswap
25 .type _bitswap,@function
26
27/* Flips the bits of all bytes in a memory area (required for mp3 data on
28 * the Archos). This version is optimized for speed and size.
29 *
30 * arguments:
31 * r4 - start address
32 * r5 - length
33 *
34 * return value: void
35 *
36 * register usage:
37 * r0 - temporary
38 * r1 - bit mask for rounding to long bound / low byte (after swap)
39 * r2 - high byte (after swap) / combined result
40 * r4 - data address - 4
41 * r5 - end address - 4
42 * r7 - flip table (addressing with signed offset)
43 *
44 * The instruction order below is devised in a way to utilize the pipelining
45 * of the SH1 to the max.
46 */
47
48_bitswap:
49 mova _fliptable,r0
50 mov r0,r7
51 add #-4,r4 /* address is shifted by 4 */
52 add r4,r5 /* r5 = end_address - 4 */
53 cmp/hi r4,r5 /* at least something to do? */
54 bf .exit /* no, get out of here! */
55
56 add #-3,r5 /* end offset for flipping 4 bytes per pass */
57 mov r4,r0
58 tst #1,r0 /* even address? */
59 bt .start2_w /* yes, jump into main loop */
60
61 /* no, flip first byte */
62 mov.b @(4,r4),r0 /* load byte, sign extension! */
63 add #1,r4 /* early increment */
64 mov.b @(r0,r7),r0 /* fliptable offset is signed */
65 bra .start2_w /* jump into main loop */
66 mov.b r0,@(3,r4) /* store byte */
67
68 /* main loop: flips 2 words per pass */
69 .align 2
70.loop2_w:
71 mov.w @(6,r4),r0 /* load second word */
72 add #4,r4 /* early increment */
73 swap.b r0,r2 /* get high byte (2nd word) */
74 exts.b r0,r0 /* prepare low byte (2nd word) */
75 mov.b @(r0,r7),r1 /* swap low byte (2nd word) */
76 exts.b r2,r0 /* prepare high byte (2nd word) */
77 mov.b @(r0,r7),r2 /* swap high byte (2nd word) */
78 extu.b r1,r0 /* zero extend low byte (2nd word) */
79 mov.w @r4,r1 /* load first word */
80 shll8 r2 /* shift high byte (2nd word), low byte zeroed */
81 or r2,r0 /* put low byte (2nd word) in result */
82 swap.b r1,r2 /* get high byte (1st word) */
83 mov.w r0,@(2,r4) /* store result (2nd word) */
84 exts.b r1,r0 /* prepare low byte (1st word) */
85 mov.b @(r0,r7),r1 /* swap low byte (1st word) */
86 exts.b r2,r0 /* prepare high byte (1st word) */
87 mov.b @(r0,r7),r2 /* swap high byte (1st word) */
88 extu.b r1,r0 /* zero extend low byte (1st word) */
89 shll8 r2 /* shift high byte (1st word), low byte zeroed */
90 or r2,r0 /* put low byte (1st word) in result */
91 mov.w r0,@r4 /* store result (1st word) */
92.start2_w:
93 cmp/hi r4,r5 /* runs r4 up to last long bound */
94 bt .loop2_w
95
96 bra .start_b2 /* jump into trailing byte loop */
97 add #3,r5 /* reset end offset */
98
99 /* trailing byte loop: flips 0..3 bytes */
100.loop_b2:
101 mov.b @(4,r4),r0 /* loand byte, sign extension! */
102 add #1,r4 /* early increment */
103 mov.b @(r0,r7),r0 /* fliptable offset is signed */
104 mov.b r0,@(3,r4) /* store byte */
105.start_b2:
106 cmp/hi r4,r5 /* runs r4 up to end address */
107 bt .loop_b2
108
109.exit:
110 rts
111 nop
112
113 .align 2
114 .global _fliptable
115
116 .byte 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1
117 .byte 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1
118 .byte 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9
119 .byte 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9
120 .byte 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5
121 .byte 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5
122 .byte 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed
123 .byte 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd
124 .byte 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3
125 .byte 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3
126 .byte 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb
127 .byte 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb
128 .byte 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7
129 .byte 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7
130 .byte 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef
131 .byte 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
132_fliptable:
133 .byte 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0
134 .byte 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0
135 .byte 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8
136 .byte 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8
137 .byte 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4
138 .byte 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4
139 .byte 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec
140 .byte 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc
141 .byte 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2
142 .byte 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2
143 .byte 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea
144 .byte 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa
145 .byte 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6
146 .byte 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6
147 .byte 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee
148 .byte 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe
149
150
151.end:
152 .size _bitswap,.end-_bitswap
diff --git a/firmware/target/sh/crt0.S b/firmware/target/sh/crt0.S
deleted file mode 100644
index 0e8bbfdd68..0000000000
--- a/firmware/target/sh/crt0.S
+++ /dev/null
@@ -1,219 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "cpu.h"
23
24 .section .init.text,"ax",@progbits
25
26 .global start
27start:
28
29 mov.l .vbr_k,r1
30#ifdef DEBUG
31 /* If we have built our code to be loaded via the standalone GDB
32 * stub, we will have out VBR at some other location than 0x9000000.
33 * We must copy the trap vectors for the GDB stub to our vector table. */
34 mov.l .orig_vbr_k,r2
35
36 /* Move the invalid instruction vector (4) */
37 mov #4,r0
38 shll2 r0
39 mov.l @(r0,r2),r3
40 mov.l r3,@(r0,r1)
41
42 /* Move the invalid slot vector (6) */
43 mov #6,r0
44 shll2 r0
45 mov.l @(r0,r2),r3
46 mov.l r3,@(r0,r1)
47
48 /* Move the bus error vector (9) */
49 mov #9,r0
50 shll2 r0
51 mov.l @(r0,r2),r3
52 mov.l r3,@(r0,r1)
53
54 /* Move the DMA bus error vector (10) */
55 mov #10,r0
56 shll2 r0
57 mov.l @(r0,r2),r3
58 mov.l r3,@(r0,r1)
59
60 /* Move the NMI vector as well (11) */
61 mov #11,r0
62 shll2 r0
63 mov.l @(r0,r2),r3
64 mov.l r3,@(r0,r1)
65
66 /* Move the UserBreak vector as well (12) */
67 mov #12,r0
68 shll2 r0
69 mov.l @(r0,r2),r3
70 mov.l r3,@(r0,r1)
71
72 /* Move the breakpoint trap vector (32) */
73 mov #32,r0
74 shll2 r0
75 mov.l @(r0,r2),r3
76 mov.l r3,@(r0,r1)
77
78 /* Move the IO trap vector (33) */
79 mov #33,r0
80 shll2 r0
81 mov.l @(r0,r2),r3
82 mov.l r3,@(r0,r1)
83
84 /* Move the serial Rx interrupt vector (105) */
85 mov #105,r0
86 shll2 r0
87 mov.l @(r0,r2),r3
88 mov.l r3,@(r0,r1)
89
90 /* Move the single step trap vector (127) */
91 mov #127,r0
92 shll2 r0
93 mov.l @(r0,r2),r3
94 mov.l r3,@(r0,r1)
95#endif /* DEBUG */
96 ldc r1,vbr
97
98 mov #0,r0
99 ldc r0,gbr
100
101 /* .iram copy is done first since it is reclaimed for other
102 * uninitialized sections */
103
104 /* copy the .iram section */
105 mov.l .iramcopy_k,r0
106 mov.l .iram_k,r1
107 mov.l .iramend_k,r2
108 /* Note: We cannot put a PC relative load into the delay slot of a 'bra'
109 instruction (the offset would be wrong), but there is nothing else to
110 do before the loop, so the delay slot would be 'nop'. The cmp / bf
111 sequence is the same length, but more efficient. */
112 cmp/hi r1,r2
113 bf .noiramcopy
114.iramloop:
115 mov.l @r0+,r3
116 mov.l r3,@r1
117 add #4,r1
118 cmp/hi r1,r2
119 bt .iramloop
120.noiramcopy:
121
122 /* zero out .ibss */
123 mov.l .iedata_k,r0
124 mov.l .iend_k,r1
125 bra .iedatastart
126 mov #0,r2
127.iedataloop: /* backwards is faster and shorter */
128 mov.l r2,@-r1
129.iedatastart:
130 cmp/hi r0,r1
131 bt .iedataloop
132
133 /* zero out bss */
134 mov.l .edata_k,r0
135 mov.l .end_k,r1
136 bra .edatastart
137 mov #0,r2
138.edataloop: /* backwards is faster and shorter */
139 mov.l r2,@-r1
140.edatastart:
141 cmp/hi r0,r1
142 bt .edataloop
143
144 /* copy the .data section, for rombased execution */
145 mov.l .datacopy_k,r0
146 mov.l .data_k,r1
147 cmp/eq r0,r1
148 bt .nodatacopy /* Don't copy if src and dest are equal */
149 mov.l .dataend_k,r2
150 cmp/hi r1,r2
151 bf .nodatacopy
152.dataloop:
153 mov.l @r0+,r3
154 mov.l r3,@r1
155 add #4,r1
156 cmp/hi r1,r2
157 bt .dataloop
158.nodatacopy:
159
160 /* Munge the main thread stack */
161 mov.l .stackbegin_k,r0
162 mov.l .stackend_k,r1
163 mov r1,r15
164 mov.l .deadbeef_k,r2
165.mungeloop: /* backwards is faster and shorter */
166 mov.l r2,@-r1
167 cmp/hi r0,r1
168 bt .mungeloop
169
170 /* call the mainline */
171 mov.l .main_k,r0
172 jsr @r0
173 nop
174.hoo:
175 bra .hoo
176 nop
177
178 .align 2
179.vbr_k:
180 .long vectors
181#ifdef DEBUG
182.orig_vbr_k:
183 .long 0x09000000
184#endif
185.iedata_k:
186 .long _iedata
187.iend_k:
188 .long _iend
189.iramcopy_k:
190 .long _iramcopy
191.iram_k:
192 .long _iramstart
193.iramend_k:
194 .long _iramend
195.edata_k:
196 .long _edata
197.end_k:
198 .long _end
199.datacopy_k:
200 .long _datacopy
201.data_k:
202 .long _datastart
203.dataend_k:
204 .long _dataend
205.stackbegin_k:
206 .long _stackbegin
207.stackend_k:
208 .long _stackend
209.deadbeef_k:
210 .long 0xdeadbeef
211.main_k:
212 .long _main
213
214 .section .resetvectors
215vectors:
216 .long start
217 .long _stackend
218 .long start
219 .long _stackend
diff --git a/firmware/target/sh/debug-sh.c b/firmware/target/sh/debug-sh.c
deleted file mode 100644
index bee4896174..0000000000
--- a/firmware/target/sh/debug-sh.c
+++ /dev/null
@@ -1,285 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Heikki Hannikainen
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include <stdbool.h>
23#include <string.h>
24
25#include "config.h"
26#include "system.h"
27#include "kernel.h"
28#include "font.h"
29#include "lcd.h"
30#include "button.h"
31#include "powermgmt.h"
32#include "adc.h"
33#include "hwcompat.h" /* ROM_VERSION */
34#include "crc32.h"
35
36#if CONFIG_KEYPAD == RECORDER_PAD
37# define DEBUG_CANCEL BUTTON_OFF
38
39#elif CONFIG_KEYPAD == ONDIO_PAD
40# define DEBUG_CANCEL BUTTON_MENU
41#endif
42
43/* Tool function to read the flash manufacturer and type, if available.
44 Only chips which could be reprogrammed in system will return values.
45 (The mode switch addresses vary between flash manufacturers, hence addr1/2) */
46 /* In IRAM to avoid problems when running directly from Flash */
47static bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device,
48 unsigned addr1, unsigned addr2)
49 ICODE_ATTR __attribute__((noinline));
50static bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device,
51 unsigned addr1, unsigned addr2)
52{
53 unsigned not_manu, not_id; /* read values before switching to ID mode */
54 unsigned manu, id; /* read values when in ID mode */
55
56 volatile unsigned char* flash = (unsigned char*)0x2000000; /* flash mapping */
57 int old_level; /* saved interrupt level */
58
59 not_manu = flash[0]; /* read the normal content */
60 not_id = flash[1]; /* should be 'A' (0x41) and 'R' (0x52) from the "ARCH" marker */
61
62 /* disable interrupts, prevent any stray flash access */
63 old_level = disable_irq_save();
64
65 flash[addr1] = 0xAA; /* enter command mode */
66 flash[addr2] = 0x55;
67 flash[addr1] = 0x90; /* ID command */
68 /* Atmel wants 20ms pause here */
69 /* sleep(HZ/50); no sleeping possible while interrupts are disabled */
70
71 manu = flash[0]; /* read the IDs */
72 id = flash[1];
73
74 flash[0] = 0xF0; /* reset flash (back to normal read mode) */
75 /* Atmel wants 20ms pause here */
76 /* sleep(HZ/50); no sleeping possible while interrupts are disabled */
77
78 restore_irq(old_level); /* enable interrupts again */
79 /* I assume success if the obtained values are different from
80 the normal flash content. This is not perfectly bulletproof, they
81 could theoretically be the same by chance, causing us to fail. */
82 if (not_manu != manu || not_id != id) /* a value has changed */
83 {
84 *p_manufacturer = manu; /* return the results */
85 *p_device = id;
86 return true; /* success */
87 }
88 return false; /* fail */
89}
90
91bool dbg_ports(void)
92{
93 int adc_battery_voltage;
94#ifndef HAVE_LCD_BITMAP
95 int currval = 0;
96 int button;
97#else
98 int adc_battery_level;
99
100 lcd_setfont(FONT_SYSFIXED);
101#endif
102 lcd_clear_display();
103
104 while(1)
105 {
106#ifdef HAVE_LCD_BITMAP
107 lcd_putsf(0, 0, "PADR: %04x", (unsigned short)PADR);
108 lcd_putsf(0, 1, "PBDR: %04x", (unsigned short)PBDR);
109
110 lcd_putsf(0, 2, "AN0: %03x AN4: %03x", adc_read(0), adc_read(4));
111 lcd_putsf(0, 3, "AN1: %03x AN5: %03x", adc_read(1), adc_read(5));
112 lcd_putsf(0, 4, "AN2: %03x AN6: %03x", adc_read(2), adc_read(6));
113 lcd_putsf(0, 5, "AN3: %03x AN7: %03x", adc_read(3), adc_read(7));
114
115 battery_read_info(&adc_battery_voltage, &adc_battery_level);
116 lcd_putsf(0, 6, "Batt: %d.%03dV %d%% ", adc_battery_voltage / 1000,
117 adc_battery_voltage % 1000, adc_battery_level);
118
119 lcd_update();
120
121 while (button_get_w_tmo(HZ/10) != (DEBUG_CANCEL|BUTTON_REL));
122
123 lcd_setfont(FONT_UI);
124
125#else /* !HAVE_LCD_BITMAP */
126
127 if (currval == 0) {
128 lcd_putsf(0, 0, "PADR: %04x", (unsigned short)PADR);
129 } else if (currval == 1) {
130 lcd_putsf(0, 0, "PBDR: %04x", (unsigned short)PBDR);
131 } else {
132 int idx = currval - 2; /* idx < 7 */
133 lcd_putsf(0, 0, "AN%d: %03x", idx, adc_read(idx));
134 }
135
136 battery_read_info(&adc_battery_voltage, NULL);
137 lcd_putsf(0, 1, "Batt: %d.%03dV", adc_battery_voltage / 1000,
138 adc_battery_voltage % 1000);
139 lcd_update();
140
141 button = button_get_w_tmo(HZ/5);
142 switch(button)
143 {
144 case BUTTON_STOP:
145 return false;
146
147 case BUTTON_LEFT:
148 currval--;
149 if(currval < 0)
150 currval = 9;
151 break;
152
153 case BUTTON_RIGHT:
154 currval++;
155 if(currval > 9)
156 currval = 0;
157 break;
158 }
159#endif
160 }
161 return false;
162}
163
164bool dbg_hw_info(void)
165{
166#ifndef HAVE_LCD_BITMAP
167 int button;
168 int currval = 0;
169#else
170 int bitmask = HW_MASK;
171#endif
172 int rom_version = ROM_VERSION;
173 unsigned manu, id; /* flash IDs */
174 bool got_id; /* flag if we managed to get the flash IDs */
175 unsigned rom_crc = 0xffffffff; /* CRC32 of the boot ROM */
176 bool has_bootrom; /* flag for boot ROM present */
177 int oldmode; /* saved memory guard mode */
178
179 oldmode = system_memory_guard(MEMGUARD_NONE); /* disable memory guard */
180
181 /* get flash ROM type */
182 got_id = dbg_flash_id(&manu, &id, 0x5555, 0x2AAA); /* try SST, Atmel, NexFlash */
183 if (!got_id)
184 got_id = dbg_flash_id(&manu, &id, 0x555, 0x2AA); /* try AMD, Macronix */
185
186 /* check if the boot ROM area is a flash mirror */
187 has_bootrom = (memcmp((char*)0, (char*)0x02000000, 64*1024) != 0);
188 if (has_bootrom) /* if ROM and Flash different */
189 {
190 /* calculate CRC16 checksum of boot ROM */
191 rom_crc = crc_32((unsigned char*)0x0000, 64*1024, 0xffffffff);
192 }
193
194 system_memory_guard(oldmode); /* re-enable memory guard */
195
196 lcd_clear_display();
197
198#ifdef HAVE_LCD_BITMAP
199 lcd_setfont(FONT_SYSFIXED);
200
201 lcd_puts(0, 0, "[Hardware info]");
202
203 lcd_putsf(0, 1, "ROM: %d.%02d", rom_version/100, rom_version%100);
204
205 lcd_putsf(0, 2, "Mask: 0x%04x", bitmask);
206 if (got_id)
207 lcd_putsf(0, 3, "Flash: M=%02x D=%02x", manu, id);
208 else
209 lcd_puts(0, 3, "Flash: M=?? D=??"); /* unknown, sorry */
210
211 if (has_bootrom)
212 {
213 if (rom_crc == 0x56DBA4EE) /* known Version 1 */
214 lcd_puts(0, 4, "Boot ROM: V1");
215 else
216 lcd_putsf(0, 4, "ROMcrc: 0x%08x", rom_crc);
217 }
218 else
219 {
220 lcd_puts(0, 4, "Boot ROM: none");
221 }
222
223 lcd_update();
224
225 /* wait for exit */
226 while (button_get_w_tmo(HZ/10) != (DEBUG_CANCEL|BUTTON_REL));
227
228 lcd_setfont(FONT_UI);
229
230#else /* !HAVE_LCD_BITMAP */
231 lcd_puts(0, 0, "[HW Info]");
232 while(1)
233 {
234 switch(currval)
235 {
236 case 0:
237 lcd_putsf(0, 1, "ROM: %d.%02d",
238 rom_version/100, rom_version%100);
239 break;
240 case 1:
241 if (got_id)
242 lcd_putsf(0, 1, "Flash:%02x,%02x", manu, id);
243 else
244 lcd_puts(0, 1, "Flash:??,??"); /* unknown, sorry */
245 break;
246 case 2:
247 if (has_bootrom)
248 {
249 if (rom_crc == 0x56DBA4EE) /* known Version 1 */
250 lcd_puts(0, 1, "BootROM: V1");
251 else if (rom_crc == 0x358099E8)
252 lcd_puts(0, 1, "BootROM: V2");
253 /* alternative boot ROM found in one single player so far */
254 else
255 lcd_putsf(0, 1, "R: %08x", rom_crc);
256 }
257 else
258 lcd_puts(0, 1, "BootROM: no");
259 }
260
261 lcd_update();
262
263 button = button_get_w_tmo(HZ/10);
264
265 switch(button)
266 {
267 case BUTTON_STOP:
268 return false;
269
270 case BUTTON_LEFT:
271 currval--;
272 if(currval < 0)
273 currval = 2;
274 break;
275
276 case BUTTON_RIGHT:
277 currval++;
278 if(currval > 2)
279 currval = 0;
280 break;
281 }
282 }
283#endif
284 return false;
285}
diff --git a/firmware/target/sh/kernel-sh.c b/firmware/target/sh/kernel-sh.c
deleted file mode 100644
index 65b27e47f0..0000000000
--- a/firmware/target/sh/kernel-sh.c
+++ /dev/null
@@ -1,65 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Björn Stenberg
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "system.h"
23#include "kernel.h"
24#include "panic.h"
25
26void tick_start(unsigned int interval_in_ms)
27{
28 unsigned long count;
29
30 count = CPU_FREQ * interval_in_ms / 1000 / 8;
31
32 if(count > 0x10000)
33 {
34 panicf("Error! The tick interval is too long (%d ms)\n",
35 interval_in_ms);
36 return;
37 }
38
39 /* We are using timer 0 */
40
41 TSTR &= ~0x01; /* Stop the timer */
42 TSNC &= ~0x01; /* No synchronization */
43 TMDR &= ~0x01; /* Operate normally */
44
45 TCNT0 = 0; /* Start counting at 0 */
46 GRA0 = (unsigned short)(count - 1);
47 TCR0 = 0x23; /* Clear at GRA match, sysclock/8 */
48
49 /* Enable interrupt on level 1 */
50 IPRC = (IPRC & ~0x00f0) | 0x0010;
51
52 TSR0 &= ~0x01;
53 TIER0 = 0xf9; /* Enable GRA match interrupt */
54
55 TSTR |= 0x01; /* Start timer 1 */
56}
57
58void IMIA0(void) __attribute__ ((interrupt_handler));
59void IMIA0(void)
60{
61 /* Run through the list of tick tasks */
62 call_tick_tasks();
63
64 TSR0 &= ~0x01;
65}
diff --git a/firmware/target/sh/system-sh.c b/firmware/target/sh/system-sh.c
deleted file mode 100644
index e054801b57..0000000000
--- a/firmware/target/sh/system-sh.c
+++ /dev/null
@@ -1,450 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Jens Arnold
11 * Based on the work of Alan Korr and others
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include <stdio.h>
24#include "config.h"
25#include "system.h"
26#include "lcd.h"
27#include "font.h"
28#include "led.h"
29
30const unsigned bit_n_table[32] = {
31 1LU<< 0, 1LU<< 1, 1LU<< 2, 1LU<< 3,
32 1LU<< 4, 1LU<< 5, 1LU<< 6, 1LU<< 7,
33 1LU<< 8, 1LU<< 9, 1LU<<10, 1LU<<11,
34 1LU<<12, 1LU<<13, 1LU<<14, 1LU<<15,
35 1LU<<16, 1LU<<17, 1LU<<18, 1LU<<19,
36 1LU<<20, 1LU<<21, 1LU<<22, 1LU<<23,
37 1LU<<24, 1LU<<25, 1LU<<26, 1LU<<27,
38 1LU<<28, 1LU<<29, 1LU<<30, 1LU<<31
39};
40
41static const char* const irqname[] = {
42 "", "", "", "", "IllInstr", "", "IllSltIn","","",
43 "CPUAdrEr", "DMAAdrEr", "NMI", "UserBrk",
44 "","","","","","","","","","","","","","","","","","","",
45 "Trap32","Trap33","Trap34","Trap35","Trap36","Trap37","Trap38","Trap39",
46 "Trap40","Trap41","Trap42","Trap43","Trap44","Trap45","Trap46","Trap47",
47 "Trap48","Trap49","Trap50","Trap51","Trap52","Trap53","Trap54","Trap55",
48 "Trap56","Trap57","Trap58","Trap59","Trap60","Trap61","Trap62","Trap63",
49 "Irq0","Irq1","Irq2","Irq3","Irq4","Irq5","Irq6","Irq7",
50 "Dma0","","Dma1","","Dma2","","Dma3","",
51 "IMIA0","IMIB0","OVI0","", "IMIA1","IMIB1","OVI1","",
52 "IMIA2","IMIB2","OVI2","", "IMIA3","IMIB3","OVI3","",
53 "IMIA4","IMIB4","OVI4","",
54 "Ser0Err","Ser0Rx","Ser0Tx","Ser0TE",
55 "Ser1Err","Ser1Rx","Ser1Tx","Ser1TE",
56 "ParityEr","A/D conv","","","Watchdog","DRAMRefr"
57};
58
59#define RESERVE_INTERRUPT(number) "\t.long\t_UIE" #number "\n"
60#define DEFAULT_INTERRUPT(name, number) "\t.weak\t_" #name \
61 "\n\t.set\t_" #name ",_UIE" #number \
62 "\n\t.long\t_" #name "\n"
63
64asm (
65
66/* Vector table.
67 * Handled in asm because gcc 4.x doesn't allow weak aliases to symbols
68 * defined in an asm block -- silly.
69 * Reset vectors (0..3) are handled in crt0.S */
70
71 ".section\t.vectors,\"aw\",@progbits\n"
72 DEFAULT_INTERRUPT (GII, 4)
73 RESERVE_INTERRUPT ( 5)
74 DEFAULT_INTERRUPT (ISI, 6)
75 RESERVE_INTERRUPT ( 7)
76 RESERVE_INTERRUPT ( 8)
77 DEFAULT_INTERRUPT (CPUAE, 9)
78 DEFAULT_INTERRUPT (DMAAE, 10)
79 DEFAULT_INTERRUPT (NMI, 11)
80 DEFAULT_INTERRUPT (UB, 12)
81 RESERVE_INTERRUPT ( 13)
82 RESERVE_INTERRUPT ( 14)
83 RESERVE_INTERRUPT ( 15)
84 RESERVE_INTERRUPT ( 16) /* TCB #0 */
85 RESERVE_INTERRUPT ( 17) /* TCB #1 */
86 RESERVE_INTERRUPT ( 18) /* TCB #2 */
87 RESERVE_INTERRUPT ( 19) /* TCB #3 */
88 RESERVE_INTERRUPT ( 20) /* TCB #4 */
89 RESERVE_INTERRUPT ( 21) /* TCB #5 */
90 RESERVE_INTERRUPT ( 22) /* TCB #6 */
91 RESERVE_INTERRUPT ( 23) /* TCB #7 */
92 RESERVE_INTERRUPT ( 24) /* TCB #8 */
93 RESERVE_INTERRUPT ( 25) /* TCB #9 */
94 RESERVE_INTERRUPT ( 26) /* TCB #10 */
95 RESERVE_INTERRUPT ( 27) /* TCB #11 */
96 RESERVE_INTERRUPT ( 28) /* TCB #12 */
97 RESERVE_INTERRUPT ( 29) /* TCB #13 */
98 RESERVE_INTERRUPT ( 30) /* TCB #14 */
99 RESERVE_INTERRUPT ( 31) /* TCB #15 */
100 DEFAULT_INTERRUPT (TRAPA32, 32)
101 DEFAULT_INTERRUPT (TRAPA33, 33)
102 DEFAULT_INTERRUPT (TRAPA34, 34)
103 DEFAULT_INTERRUPT (TRAPA35, 35)
104 DEFAULT_INTERRUPT (TRAPA36, 36)
105 DEFAULT_INTERRUPT (TRAPA37, 37)
106 DEFAULT_INTERRUPT (TRAPA38, 38)
107 DEFAULT_INTERRUPT (TRAPA39, 39)
108 DEFAULT_INTERRUPT (TRAPA40, 40)
109 DEFAULT_INTERRUPT (TRAPA41, 41)
110 DEFAULT_INTERRUPT (TRAPA42, 42)
111 DEFAULT_INTERRUPT (TRAPA43, 43)
112 DEFAULT_INTERRUPT (TRAPA44, 44)
113 DEFAULT_INTERRUPT (TRAPA45, 45)
114 DEFAULT_INTERRUPT (TRAPA46, 46)
115 DEFAULT_INTERRUPT (TRAPA47, 47)
116 DEFAULT_INTERRUPT (TRAPA48, 48)
117 DEFAULT_INTERRUPT (TRAPA49, 49)
118 DEFAULT_INTERRUPT (TRAPA50, 50)
119 DEFAULT_INTERRUPT (TRAPA51, 51)
120 DEFAULT_INTERRUPT (TRAPA52, 52)
121 DEFAULT_INTERRUPT (TRAPA53, 53)
122 DEFAULT_INTERRUPT (TRAPA54, 54)
123 DEFAULT_INTERRUPT (TRAPA55, 55)
124 DEFAULT_INTERRUPT (TRAPA56, 56)
125 DEFAULT_INTERRUPT (TRAPA57, 57)
126 DEFAULT_INTERRUPT (TRAPA58, 58)
127 DEFAULT_INTERRUPT (TRAPA59, 59)
128 DEFAULT_INTERRUPT (TRAPA60, 60)
129 DEFAULT_INTERRUPT (TRAPA61, 61)
130 DEFAULT_INTERRUPT (TRAPA62, 62)
131 DEFAULT_INTERRUPT (TRAPA63, 63)
132 DEFAULT_INTERRUPT (IRQ0, 64)
133 DEFAULT_INTERRUPT (IRQ1, 65)
134 DEFAULT_INTERRUPT (IRQ2, 66)
135 DEFAULT_INTERRUPT (IRQ3, 67)
136 DEFAULT_INTERRUPT (IRQ4, 68)
137 DEFAULT_INTERRUPT (IRQ5, 69)
138 DEFAULT_INTERRUPT (IRQ6, 70)
139 DEFAULT_INTERRUPT (IRQ7, 71)
140 DEFAULT_INTERRUPT (DEI0, 72)
141 RESERVE_INTERRUPT ( 73)
142 DEFAULT_INTERRUPT (DEI1, 74)
143 RESERVE_INTERRUPT ( 75)
144 DEFAULT_INTERRUPT (DEI2, 76)
145 RESERVE_INTERRUPT ( 77)
146 DEFAULT_INTERRUPT (DEI3, 78)
147 RESERVE_INTERRUPT ( 79)
148 DEFAULT_INTERRUPT (IMIA0, 80)
149 DEFAULT_INTERRUPT (IMIB0, 81)
150 DEFAULT_INTERRUPT (OVI0, 82)
151 RESERVE_INTERRUPT ( 83)
152 DEFAULT_INTERRUPT (IMIA1, 84)
153 DEFAULT_INTERRUPT (IMIB1, 85)
154 DEFAULT_INTERRUPT (OVI1, 86)
155 RESERVE_INTERRUPT ( 87)
156 DEFAULT_INTERRUPT (IMIA2, 88)
157 DEFAULT_INTERRUPT (IMIB2, 89)
158 DEFAULT_INTERRUPT (OVI2, 90)
159 RESERVE_INTERRUPT ( 91)
160 DEFAULT_INTERRUPT (IMIA3, 92)
161 DEFAULT_INTERRUPT (IMIB3, 93)
162 DEFAULT_INTERRUPT (OVI3, 94)
163 RESERVE_INTERRUPT ( 95)
164 DEFAULT_INTERRUPT (IMIA4, 96)
165 DEFAULT_INTERRUPT (IMIB4, 97)
166 DEFAULT_INTERRUPT (OVI4, 98)
167 RESERVE_INTERRUPT ( 99)
168 DEFAULT_INTERRUPT (REI0, 100)
169 DEFAULT_INTERRUPT (RXI0, 101)
170 DEFAULT_INTERRUPT (TXI0, 102)
171 DEFAULT_INTERRUPT (TEI0, 103)
172 DEFAULT_INTERRUPT (REI1, 104)
173 DEFAULT_INTERRUPT (RXI1, 105)
174 DEFAULT_INTERRUPT (TXI1, 106)
175 DEFAULT_INTERRUPT (TEI1, 107)
176 RESERVE_INTERRUPT ( 108)
177 DEFAULT_INTERRUPT (ADITI, 109)
178
179/* UIE# block.
180 * Must go into the same section as the UIE() handler */
181
182 "\t.text\n"
183 "_UIE4:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
184 "_UIE5:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
185 "_UIE6:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
186 "_UIE7:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
187 "_UIE8:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
188 "_UIE9:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
189 "_UIE10:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
190 "_UIE11:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
191 "_UIE12:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
192 "_UIE13:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
193 "_UIE14:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
194 "_UIE15:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
195 "_UIE16:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
196 "_UIE17:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
197 "_UIE18:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
198 "_UIE19:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
199 "_UIE20:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
200 "_UIE21:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
201 "_UIE22:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
202 "_UIE23:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
203 "_UIE24:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
204 "_UIE25:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
205 "_UIE26:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
206 "_UIE27:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
207 "_UIE28:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
208 "_UIE29:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
209 "_UIE30:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
210 "_UIE31:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
211 "_UIE32:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
212 "_UIE33:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
213 "_UIE34:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
214 "_UIE35:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
215 "_UIE36:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
216 "_UIE37:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
217 "_UIE38:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
218 "_UIE39:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
219 "_UIE40:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
220 "_UIE41:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
221 "_UIE42:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
222 "_UIE43:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
223 "_UIE44:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
224 "_UIE45:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
225 "_UIE46:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
226 "_UIE47:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
227 "_UIE48:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
228 "_UIE49:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
229 "_UIE50:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
230 "_UIE51:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
231 "_UIE52:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
232 "_UIE53:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
233 "_UIE54:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
234 "_UIE55:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
235 "_UIE56:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
236 "_UIE57:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
237 "_UIE58:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
238 "_UIE59:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
239 "_UIE60:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
240 "_UIE61:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
241 "_UIE62:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
242 "_UIE63:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
243 "_UIE64:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
244 "_UIE65:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
245 "_UIE66:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
246 "_UIE67:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
247 "_UIE68:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
248 "_UIE69:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
249 "_UIE70:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
250 "_UIE71:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
251 "_UIE72:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
252 "_UIE73:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
253 "_UIE74:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
254 "_UIE75:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
255 "_UIE76:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
256 "_UIE77:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
257 "_UIE78:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
258 "_UIE79:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
259 "_UIE80:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
260 "_UIE81:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
261 "_UIE82:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
262 "_UIE83:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
263 "_UIE84:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
264 "_UIE85:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
265 "_UIE86:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
266 "_UIE87:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
267 "_UIE88:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
268 "_UIE89:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
269 "_UIE90:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
270 "_UIE91:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
271 "_UIE92:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
272 "_UIE93:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
273 "_UIE94:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
274 "_UIE95:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
275 "_UIE96:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
276 "_UIE97:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
277 "_UIE98:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
278 "_UIE99:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
279 "_UIE100:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
280 "_UIE101:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
281 "_UIE102:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
282 "_UIE103:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
283 "_UIE104:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
284 "_UIE105:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
285 "_UIE106:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
286 "_UIE107:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
287 "_UIE108:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
288 "_UIE109:\tbsr\t_UIE\n\tmov.l\t@r15+,r4\n"
289
290);
291
292extern void UIE4(void); /* needed for calculating the UIE number */
293
294void UIE (unsigned int pc) __attribute__((section(".text")));
295void UIE (unsigned int pc) /* Unexpected Interrupt or Exception */
296{
297 unsigned int n;
298
299 asm volatile ("sts\tpr,%0" : "=r"(n));
300
301 /* clear screen */
302#ifdef HAVE_LCD_BITMAP
303#if LCD_DEPTH > 1
304 lcd_set_backdrop(NULL);
305 lcd_set_drawmode(DRMODE_SOLID);
306 lcd_set_foreground(LCD_BLACK);
307 lcd_set_background(LCD_WHITE);
308#endif
309 lcd_setfont(FONT_SYSFIXED);
310 lcd_set_viewport(NULL);
311#endif
312
313 lcd_clear_display();
314 /* output exception */
315 n = (n - (unsigned)UIE4 + 12)>>2; /* get exception or interrupt number */
316 lcd_putsf(0, 0, "I%02x:%s", n, irqname[n]);
317 lcd_putsf(0, 1, "at %08x", pc);
318 lcd_update();
319
320 /* try to restart firmware if ON is pressed */
321 system_exception_wait();
322
323 /* enable the watchguard timer, but don't service it */
324 RSTCSR_W = 0x5a40; /* Reset enabled, power-on reset */
325 TCSR_W = 0xa560; /* Watchdog timer mode, timer enabled, sysclk/2 */
326 while (1);
327}
328
329void system_init(void)
330{
331 /* Disable all interrupts */
332 IPRA = 0;
333 IPRB = 0;
334 IPRC = 0;
335 IPRD = 0;
336 IPRE = 0;
337
338 /* NMI level low, falling edge on all interrupts */
339 ICR = 0;
340
341 /* Enable burst and RAS down mode on DRAM */
342 DCR |= 0x5000;
343
344 /* Activate Warp mode (simultaneous internal and external mem access) */
345 BCR |= 0x2000;
346
347 /* Bus state controller initializations. These are only necessary when
348 running from flash. */
349 WCR1 = 0x40FD; /* Long wait states for CS6 (ATA), short for the rest. */
350 WCR3 = 0x8000; /* WAIT is pulled up, 1 state inserted for CS6 */
351}
352
353void system_reboot (void)
354{
355 disable_irq();
356
357 asm volatile ("ldc\t%0,vbr" : : "r"(0));
358
359 PACR2 |= 0x4000; /* for coldstart detection */
360 IPRA = 0;
361 IPRB = 0;
362 IPRC = 0;
363 IPRD = 0;
364 IPRE = 0;
365 ICR = 0;
366
367 asm volatile ("jmp @%0; mov.l @%1,r15" : :
368 "r"(*(int*)0),"r"(4));
369}
370
371void system_exception_wait(void)
372{
373#if (CONFIG_LED == LED_REAL)
374 bool state = false;
375 int i = 0;
376#endif
377
378 while (1)
379 {
380#if (CONFIG_LED == LED_REAL)
381 if (--i <= 0)
382 {
383 state = !state;
384 led(state);
385 i = 240000;
386 }
387#endif
388
389#if CONFIG_KEYPAD == PLAYER_PAD
390 /* Player */
391 if (!(PADRL & 0x20))
392#elif CONFIG_KEYPAD == RECORDER_PAD
393 /* Recorder */
394#ifdef HAVE_FMADC
395 if (!(PCDR & 0x0008))
396#else
397 if (!(PBDRH & 0x01))
398#endif
399#elif CONFIG_KEYPAD == ONDIO_PAD
400 /* Ondio */
401 if (!(PCDR & 0x0008))
402#endif /* CONFIG_KEYPAD */
403 return;
404 }
405}
406
407/* Utilise the user break controller to catch invalid memory accesses. */
408int system_memory_guard(int newmode)
409{
410 static const struct {
411 unsigned long addr;
412 unsigned long mask;
413 unsigned short bbr;
414 } modes[MAXMEMGUARD] = {
415 /* catch nothing */
416 { 0x00000000, 0x00000000, 0x0000 },
417 /* catch writes to area 02 (flash ROM) */
418 { 0x02000000, 0x00FFFFFF, 0x00F8 },
419 /* catch all accesses to areas 00 (internal ROM) and 01 (free) */
420 { 0x00000000, 0x01FFFFFF, 0x00FC }
421 };
422
423 int oldmode = MEMGUARD_NONE;
424 int i;
425
426 /* figure out the old mode from what is in the UBC regs. If the register
427 values don't match any mode, assume MEMGUARD_NONE */
428 for (i = MEMGUARD_NONE; i < MAXMEMGUARD; i++)
429 {
430 if (BAR == modes[i].addr && BAMR == modes[i].mask &&
431 BBR == modes[i].bbr)
432 {
433 oldmode = i;
434 break;
435 }
436 }
437
438 if (newmode == MEMGUARD_KEEP)
439 newmode = oldmode;
440
441 BBR = 0; /* switch off everything first */
442
443 /* always set the UBC according to the mode, in case the old settings
444 didn't match any valid mode */
445 BAR = modes[newmode].addr;
446 BAMR = modes[newmode].mask;
447 BBR = modes[newmode].bbr;
448
449 return oldmode;
450}
diff --git a/firmware/target/sh/system-target.h b/firmware/target/sh/system-target.h
deleted file mode 100644
index a62a024823..0000000000
--- a/firmware/target/sh/system-target.h
+++ /dev/null
@@ -1,154 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Jens Arnold
11 * Based on the work of Alan Korr and others
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#ifndef SYSTEM_TARGET_H
23#define SYSTEM_TARGET_H
24
25#define or_b(mask, address) \
26 asm \
27 ("or.b %0,@(r0,gbr)" \
28 : \
29 : /* %0 */ I_CONSTRAINT((char)(mask)), \
30 /* %1 */ "z"(address-GBR))
31
32#define and_b(mask, address) \
33 asm \
34 ("and.b %0,@(r0,gbr)" \
35 : \
36 : /* %0 */ I_CONSTRAINT((char)(mask)), \
37 /* %1 */ "z"(address-GBR))
38
39#define xor_b(mask, address) \
40 asm \
41 ("xor.b %0,@(r0,gbr)" \
42 : \
43 : /* %0 */ I_CONSTRAINT((char)(mask)), \
44 /* %1 */ "z"(address-GBR))
45
46
47/****************************************************************************
48 * Interrupt level setting
49 * The level is left shifted 4 bits
50 ****************************************************************************/
51#define HIGHEST_IRQ_LEVEL (15<<4)
52
53static inline int set_irq_level(int level)
54{
55 int i;
56 /* Read the old level and set the new one */
57
58 /* Not volatile - will be optimized away if the return value isn't used */
59 asm ("stc sr, %0" : "=r" (i));
60 asm volatile ("ldc %0, sr" : : "r" (level));
61 return i;
62}
63
64static inline void enable_irq(void)
65{
66 int i;
67 asm volatile ("mov %1, %0 \n" /* Save a constant load from RAM */
68 "ldc %0, sr \n" : "=&r"(i) : "i"(0));
69}
70
71#define disable_irq() \
72 ((void)set_irq_level(HIGHEST_IRQ_LEVEL))
73
74#define disable_irq_save() \
75 set_irq_level(HIGHEST_IRQ_LEVEL)
76
77#define restore_irq(i) \
78 ((void)set_irq_level(i))
79
80static inline uint16_t swap16_hw(uint16_t value)
81 /*
82 result[15..8] = value[ 7..0];
83 result[ 7..0] = value[15..8];
84 */
85{
86 uint16_t result;
87 asm ("swap.b\t%1,%0" : "=r"(result) : "r"(value));
88 return result;
89}
90
91static inline uint32_t swaw32_hw(uint32_t value)
92 /*
93 result[31..16] = value[15.. 0];
94 result[15.. 0] = value[31..16];
95 */
96{
97 uint32_t result;
98 asm ("swap.w\t%1,%0" : "=r"(result) : "r"(value));
99 return result;
100}
101
102static inline uint32_t swap32_hw(uint32_t value)
103 /*
104 result[31..24] = value[ 7.. 0];
105 result[23..16] = value[15.. 8];
106 result[15.. 8] = value[23..16];
107 result[ 7.. 0] = value[31..24];
108 */
109{
110 asm ("swap.b\t%0,%0\n"
111 "swap.w\t%0,%0\n"
112 "swap.b\t%0,%0\n" : "+r"(value));
113 return value;
114}
115
116static inline uint32_t swap_odd_even32_hw(uint32_t value)
117{
118 /*
119 result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
120 result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
121 */
122 asm ("swap.b\t%0,%0\n"
123 "swap.w\t%0,%0\n"
124 "swap.b\t%0,%0\n"
125 "swap.w\t%0,%0\n" : "+r"(value));
126 return value;
127}
128
129extern const unsigned bit_n_table[32];
130#define BIT_N(n) ( \
131 __builtin_constant_p(n) \
132 ? (1U << (n)) \
133 : bit_n_table[n] \
134)
135
136static inline void commit_dcache(void) {}
137static inline void commit_discard_dcache(void) {}
138static inline void commit_discard_idcache(void) {}
139
140/*---------------------------------------------------------------------------
141 * Put core in a power-saving state.
142 *---------------------------------------------------------------------------
143 */
144static inline void core_sleep(void)
145{
146 asm volatile (
147 "and.b #0x7f, @(r0, gbr) \n" /* Clear SBY (bit 7) in SBYCR */
148 "mov #0, r1 \n" /* Enable interrupts */
149 "ldc r1, sr \n" /* Following instruction cannot be interrupted */
150 "sleep \n" /* Execute standby */
151 : : "z"(&SBYCR-GBR) : "r1");
152}
153
154#endif /* SYSTEM_TARGET_H */