Compare commits

...

3 Commits

Author SHA1 Message Date
Zane Kaminski 44bd31fe50 Now supporting Altera MAX II/V UFM and SPI flash 2023-08-16 05:19:15 -04:00
Zane Kaminski 0dc8b9b981 Fixed up Altera support 2023-08-16 03:53:59 -04:00
Zane Kaminski ac1d41f282 Revert "Add commands for RAM2GS with AGM CPLD"
This reverts commit c93999003d.
2023-08-13 01:49:47 -04:00
5 changed files with 180 additions and 227 deletions

Binary file not shown.

Binary file not shown.

198
ram2gs.c
View File

@ -9,14 +9,15 @@
#include "gwconio.h"
#include "ram2gs_asm.h"
// Commands common to Altera and AGM
static void ram2gs_set4mb() { ram2gs_cmd(0x10); }
static void ram2gs_set8mb() { ram2gs_cmd(0x11); }
static void ram2gs_set(char en8meg, char enled) {
char cmd = 0x10;
if (en8meg) { cmd |= 0x01; }
if (enled) { cmd |= 0x02; }
ram2gs_cmd(cmd);
}
// Commands for just altera
static void ram2gs_altera_erase() { ram2gs_cmd(0x28); }
static void ram2gs_altera_program() { ram2gs_cmd(0x24); }
static void ram2gs_altera_setnvm(char en8meg) {
static void ram2gs_max_erase() { ram2gs_cmd(0x28); }
static void ram2gs_max_set_nvm(char en8meg, char enled) {
char i;
// Clock in 0 to enable this setting entry
ram2gs_cmd(0x20);
@ -32,61 +33,97 @@ static void ram2gs_altera_setnvm(char en8meg) {
ram2gs_cmd(0x22);
}
// Clock in 14 dummy "1"s
for (i = 0; i < 14; i++) {
if (enled) {
// Clock in 0 to enable LED
ram2gs_cmd(0x20);
ram2gs_cmd(0x22);
} else {
// Clock in 1 to disable LED
ram2gs_cmd(0x21);
ram2gs_cmd(0x23);
}
ram2gs_altera_program();
// Clock in 13 dummy "1"s
for (i = 0; i < 13; i++) {
ram2gs_cmd(0x21);
ram2gs_cmd(0x23);
}
// Program
ram2gs_cmd(0x24);
}
// Commands for just AGM
static void ram2gs_agm_select() { ram2gs_cmd(0x34); }
static void ram2gs_agm_deselect() { ram2gs_cmd(0x30); }
static void ram2gs_agm_tx8(char data) {
static void ram2gs_spi_select() { ram2gs_cmd(0x34); }
static void ram2gs_spi_deselect() { ram2gs_cmd(0x30); }
static void ram2gs_spi_tx8(char data) {
char i;
for (i = 0; i < 8; i++) {
ram2gs_cmd(0x34 + ((data >> (7-i)) & 1));
ram2gs_cmd(0x36 + ((data >> (7-i)) & 1));
}
}
static void ram2gs_agm_write_en() {
ram2gs_agm_deselect();
ram2gs_agm_select();
ram2gs_agm_tx8(0x06); // 0x06 is write enable
ram2gs_agm_deselect();
static void ram2gs_spi_wren() {
ram2gs_spi_deselect();
ram2gs_spi_select();
ram2gs_spi_tx8(0x06); // 0x06 is write enable
ram2gs_spi_deselect();
}
static void ram2gs_agm_erase() {
ram2gs_agm_write_en();
ram2gs_agm_select();
ram2gs_agm_tx8(0x20); // 0x20 is sector erase (4 kB)
ram2gs_agm_tx8(0x00); // address[23:16]
ram2gs_agm_tx8(0x10); // address[15:8]
ram2gs_agm_tx8(0x00); // address[7:0]
ram2gs_agm_deselect();
static void ram2gs_spi_erase() {
ram2gs_spi_wren();
ram2gs_spi_select();
ram2gs_spi_tx8(0x20); // 0x20 is sector erase (4 kB)
ram2gs_spi_tx8(0x00); // address[23:16]
ram2gs_spi_tx8(0x10); // address[15:8]
ram2gs_spi_tx8(0x00); // address[7:0]
ram2gs_spi_deselect();
}
static void ram2gs_agm_write_nvm(char en8meg) {
ram2gs_agm_write_en();
ram2gs_agm_select();
ram2gs_agm_tx8(0x02); // 0x02 is page (byte) program
ram2gs_agm_tx8(0x00); // address[23:16]
ram2gs_agm_tx8(0x10); // address[15:8]
ram2gs_agm_tx8(0x00); // address[7:0]
if (en8meg) { ram2gs_agm_tx8(0xFF); } // data[7:0]
else { ram2gs_agm_tx8(0x00); } // data[7:0]
ram2gs_agm_deselect();
static void ram2gs_spi_set_nvm(char en8meg, char enled) {
ram2gs_spi_erase(); // First erase
spin(33, 8); // Wait for >= 500ms on even the fastest systems.
ram2gs_spi_wren();
ram2gs_spi_select();
ram2gs_spi_tx8(0x02); // 0x02 is page (byte) program
ram2gs_spi_tx8(0x00); // address[23:16]
ram2gs_spi_tx8(0x10); // address[15:8]
ram2gs_spi_tx8(0x00); // address[7:0]
// data[7:0]
if (!en8meg && !enled) { ram2gs_spi_tx8(0x7F); }
else if (!en8meg && enled) { ram2gs_spi_tx8(0x3F); }
else if ( en8meg && !enled) { ram2gs_spi_tx8(0xFF); }
else if ( en8meg && enled) { ram2gs_spi_tx8(0xBF); }
ram2gs_spi_deselect();
}
static void menu(void)
static void ram2gs_erase(char typecode) {
switch (typecode) {
case 0x00: ram2gs_max_erase(); break; // Altera MAX II / V
case 0x04: ram2gs_spi_erase(); break; // Lattice MachXO / iCE40 / AGM AG256
//case 0x08: ram2gs_erase_lcmxo2(); break; // Lattice MachXO2
}
}
static void ram2gs_set_nvm(char typecode, char en8meg, char enled) {
switch (typecode) {
case 0x00: ram2gs_max_set_nvm(en8meg, enled); break; // Altera MAX II / V
case 0x04: ram2gs_spi_set_nvm(en8meg, enled); break; // Lattice MachXO / iCE40 / AGM AG256
//case 0x08: ram2gs_set_nvm_lcmxo2(en8meg, enled); break; // Lattice MachXO2
}
}
static void menu_led(char enled) {
if (enled) {
gwcputsxy(1, 15, "LED enabled. Press [L] to disable LED.");
} else {
gwcputsxy(1, 15, "LED disabled. Press [L] to enable LED.");
}
}
static void menu()
{
uint8_t bankcount = ram2gs_getsize();
uint8_t bankcount;
clrscr(); // Clear screen
gwcputsxy(5, 1, "-- RAM2GS Capacity Settings --");
gotoxy(4, 3);
gwcputs("Current RAM2GS capacity: ");
printf("%d", bankcount * 64);
gwcputs(" kB");
gwcputsxy(4, 3, "Current RAM2GS capacity: ...");
gwcputsxy(1, 6, "Select desired memory capacity:");
@ -95,36 +132,56 @@ static void menu(void)
gwcputsxy(1, 18, "Capacity will be saved until power-off.");
gwcputsxy(1, 20, "To remember capacity setting in");
gwcputsxy(1, 20, "To remember capacity and LED setting in");
gwcputsxy(1, 21, "nonvolatile memory, press Apple+number.");
gwcputsxy(1, 23, "Press [Q] to quit without saving.");
bankcount = ram2gs_getsize();
gotoxy(29, 3);
printf("%d", bankcount * 64);
gwcputs(" kB");
}
static void loading_screen()
{
clrscr(); // Clear screen
gwcputsxy(8, 1, "Loading RAM2GS settings...");
}
int ram2gs_main(void)
{
char en8meg;
char nvm;
int reset_count;
char hasled = true;
char typecode = false;
char enled = false;
char en8meg = true;
char nvm = false;
int reset_count = false;
// Check for RAM2GS
#ifndef SKIP_RAM2GS_DETECT
if(!ram2gs_detect()) {
loading_screen();
if (ram2gs_detect(0x00)) {
typecode = 0x00;
hasled = !ram2gs_detect(0x04);
} else if (ram2gs_detect(0x04)) {
typecode = 0x04;
hasled = true;
} else {
#ifndef SKIP_RAM2GS_DETECT
// If no RAM2GS, show an error message and quit
gwcputsxy(0, 8, " No RAM2GS II detected.");
gwcputsxy(0, 10, " Press any key to quit.");
cgetc(); // Wait for key
clrscr(); // Clear screen before quitting
return EXIT_SUCCESS;
#endif
}
#endif
menu(); // Print menu
if (hasled) { enled = !ram2gs_detect(typecode | 0x02); }
menu();
if (hasled) { menu_led(enled); }
// Get user choice from menu
en8meg = 0;
nvm = 0;
reset_count = 0;
while (true) {
// Set capacity or quit according to keypress.
switch (toupper(cgetc() & 0x7F)) {
@ -132,9 +189,14 @@ int ram2gs_main(void)
clrscr();
return EXIT_SUCCESS;
}
case '1': en8meg = 0; ram2gs_set4mb(); break;
case '2': en8meg = 1; ram2gs_set8mb(); break;
case 'R': {
case '1': en8meg = false; ram2gs_set(en8meg, enled); break;
case '2': en8meg = true; ram2gs_set(en8meg, enled); break;
case 'L': {
enled = !enled;
ram2gs_set(en8meg, enled);
if (hasled) { menu_led(enled); };
continue;
} case 'R': {
reset_count++;
if (reset_count >= 25) {
// Show message about resetting.
@ -142,15 +204,16 @@ int ram2gs_main(void)
gwcputsxy(1, 8, "Resetting RAM2GS settings.");
gwcputsxy(1, 9, "Do not turn off your Apple.");
// Erase RAM2GS settings memory
ram2gs_altera_erase(); // Erase for Altera CPLD
ram2gs_agm_erase(); // Erase for AGM CPLD
spin(32, 8); // Wait for >= 500ms on even the fastest systems.
ram2gs_set8mb(); // Enable 8 megabytes now (default)
ram2gs_erase(typecode); // Erase RAM2GS settings memory
ram2gs_set(1, 0); // Enable 8 megabytes and disable LED
// Wait for >= 500ms on even the fastest systems.
spin(32, 8);
// Show success message and quit
clrscr(); // Clear screen
gwcputsxy(1, 8, "RAM2GS settings reset successfully.");
nvm = true;
goto end;
}
continue;
@ -170,10 +233,9 @@ int ram2gs_main(void)
gwcputsxy(1, 8, "Saving RAM2GS capacity setting.");
gwcputsxy(1, 9, "Do not turn off your Apple.");
// Save capacity in nonvolatile memory.
ram2gs_altera_setnvm(en8meg); // Save for Altera CPLD
ram2gs_agm_erase(); // Erase for AGM CPLD
spin(33, 8); // Wait for >= 500ms on even the fastest systems.
ram2gs_agm_write_nvm(en8meg); // Write for AGM CPLD
ram2gs_set_nvm(typecode, en8meg, enled);
// Wait for >= 500ms on even the fastest systems.
spin(33, 8);
// Print success message
clrscr(); // Clear screen
gwcputsxy(1, 8, "RAM2GS capacity saved successfully.");

View File

@ -1,8 +1,8 @@
#ifndef RAM2GS_ASM_H
#define RAM2GS_ASM_H
uint8_t __fastcall__ ram2gs_getsize(void);
uint8_t __fastcall__ ram2gs_detect(void);
uint8_t __fastcall__ ram2gs_cmd(char cmd);
uint8_t __fastcall__ ram2gs_detect(char typecode);
uint8_t __fastcall__ ram2gs_getsize(void);
#endif /* RAM2GS_ASM_H */

View File

@ -2,9 +2,9 @@
.autoimport on
.importzp sp
.export _ram2gs_cmd
.export _ram2gs_getsize
.export _ram2gs_detect
.export _ram2gs_cmd
.define GetTWConfig $BCFF3C
.define SetTWConfig $BCFF40
@ -44,7 +44,6 @@
.segment "CODE"
.proc _thrash: near
.A8
.I8
@ -125,12 +124,18 @@
rts
.endproc
.proc _unswap: near
.proc _ram2gs_cmd: near
.A8
.I8
; Save current bank and accumulator
phb
pha
; Preamble
php ; Push status
sei ; Disable interrupts
clc ; Clear carry
xce ; Clear emulation bit
php ; Push status again, reflecting emulation bit
phb ; Push bank
pha ; Push command in accumulator
AI8
; Switch to bank 0xFB
lda #$FB
pha
@ -141,36 +146,30 @@
lda #$AD
sta $FFFF
; Pull and submit command
lda #$00
sta $FFFD
; Restore accumulator and bank and return
pla
plb
sta $FFFD
; Postamble
plb ; Restore bank
plp ; Restore status
xce ; Restore emulation bit
plp ; Pull status again to pull I flag
rts
.endproc
.proc _unswap: near
.A8
.I8
tya
ora #$00
jmp _ram2gs_cmd
.endproc
.proc _swap: near
.A8
.I8
; Save current bank and accumulator
phb
pha
; Switch to bank 0xFB
lda #$FB
pha
plb
; Submit C1AD
lda #$C1
sta $FFFE
lda #$AD
sta $FFFF
; Pull and submit command
lda #$01
sta $FFFD
; Restore accumulator and bank and return
pla
plb
rts
tya
ora #$01
jmp _ram2gs_cmd
.endproc
.proc _ram2gs_getsize: near
@ -183,40 +182,8 @@
xce ; Clear emulation bit
php ; Push status again, reflecting emulation bit
phb ; Push bank
; Check for TranswarpGS
AI8
lda #0
pha ; Push "TWGS absent" flag
; AI16
; lda $BCFF00
; cmp #$5754 ; "WT"
; bne _ram2gs_getsize_notwgs1
; lda $BCFF02
; cmp #$5347 ; "SG"
; bne _ram2gs_getsize_notwgs1
;
; ; Get and push TWGS config
; jsl GetTWConfig
; pha
; ; Disable TWGS data cache
; jsl DisableDataCache ; Disable data cache
;
; ; Pull to restore TWGS settings into A
; pla
; ; Pull "TWGS absent" flag into x, and discard it
; AI8
; plx
; AI16
; ; Push TWGS settings
; pha
; ; Push "TWGS exists" flag
; AI8
; ldx #1
; phx
_ram2gs_getsize_notwgs1:
AI8
; Go to bank 3F
ldy #$3F
phy
@ -261,27 +228,13 @@
stx $3456
; Check result
ldx #$80
lda #$80
plp
beq _ram2gs_getsize_return
ldx #$40
; Restore TWGS config
_ram2gs_getsize_return:
pla ; Pull TWGS flag
phx ; Push to save return value
; beq _ram2gs_getsize_post ; Skip if no TWGS
; plx ; Get return value back
; AI16
; pla ; Pull TWGS config
; AI8
; phx
; AI16
; jsl SetTWConfig
; AI8
lda #$40
; Postamble
_ram2gs_getsize_post:
pla ; Pull return value
_ram2gs_getsize_return:
plb ; Restore bank
plp ; Restore status
xce ; Restore emulation bit
@ -289,50 +242,9 @@
rts
.endproc
.proc _ram2gs_detect: near
.proc _ram2gs_detect_internal: near
.A8
.I8
; Preamble
php ; Push status
sei ; Disable interrupts
clc ; Clear carry
xce ; Clear emulation bit
php ; Push status again, reflecting emulation bit
phb ; Push bank
; Check for TranswarpGS
AI8
lda #0
pha ; Push "TWGS absent" flag
; AI16
; lda $BCFF00
; cmp #$5754 ; "WT"
; bne _ram2gs_detect_notwgs1
; lda $BCFF02
; cmp #$5347 ; "SG"
; bne _ram2gs_detect_notwgs1
;
; ; Get and push TWGS config
; jsl GetTWConfig
; pha
; ; Disable TWGS data cache
; jsl DisableDataCache ; Disable data cache
;
; ; Pull to restore TWGS settings into A
; pla
; ; Pull "TWGS absent" flag into x, and discard it
; AI8
; plx
; AI16
; ; Push TWGS settings
; pha
; ; Push "TWGS exists" flag
; AI8
; ldx #1
; phx
_ram2gs_detect_notwgs1:
AI8
; Switch to bank 0x3F
lda #$3F
pha
@ -389,65 +301,44 @@
; Done, now put back clobbered bytes
_ram2gs_detect_done:
jsr _swap ; Swap
jsr _swap ; Swap
pla ; Get value to restore to swapped bank 3F
sta $8000 ; Restore
jsr _unswap ; Unswap
jsr _unswap ; Unswap
pla ; Get value to restore to unswapped bank 3F
sta $8000 ; Restore
; Restore TWGS config
_ram2gs_detect_return:
pla ; Pull TWGS flag
phx ; Push to save return value
; beq _ram2gs_detect_post ; Skip if no TWGS
; plx ; Get return value back
; AI16
; pla ; Pull TWGS config
; AI8
; phx
; AI16
; jsl SetTWConfig
; AI8
; Postamble
_ram2gs_detect_post:
pla ; Pull return value
plb ; Restore bank
plp ; Restore status
xce ; Restore emulation bit
plp ; Pull status again to pull I flag
; Return
rts
.endproc
.proc _ram2gs_cmd: near
.proc _ram2gs_detect: near
.A8
.I8
; Preamble
phx ; Push X
phy ; Push Y
php ; Push status
sei ; Disable interrupts
clc ; Clear carry
xce ; Clear emulation bit
php ; Push status again, reflecting emulation bit
phb ; Push bank
pha ; Push command in accumulator
AI8
; Switch to bank 0xFB
lda #$FB
pha
plb
; Submit C1AD
lda #$C1
sta $FFFE
lda #$AD
sta $FFFF
; Pull and submit command
pla
sta $FFFD
; Transfer typecode (shifted) to Y register
and #$0E
tay
jsr _ram2gs_detect_internal
; Postamble
txa ; Get return value
plb ; Restore bank
plp ; Restore status
xce ; Restore emulation bit
plp ; Pull status again to pull I flag
ply ; Pull X
plx ; Pull Y
rts
.endproc