small update, i made a github repo with all important files for this project, but i still need to update it since i changed some of the logic and the ROM code.
in terms of software i've been kinda fighting with a FAT32 file system for an SD Card (on an Arduino module) that is hooked up through the VIA Port A.
I've ported
FatFS, a highly portable fat32 C library. And after writing some bitbanging routines for the SPI Interface, it works perfectly fine. I can open/create files, and access their contents. but the 30kB program size is not idea for actual programs....
so i tried option 2:
fat32_x16 which is the FAT32 libary used in the Commander X16, written entirely in assembly (~5kB Program size). and all you really need to supply is your own byte transfer function, but i've not been able to get it running.
I know it's written for the 65c02, but i feel like it should still run perfectly fine on a 65816 with all registers set to 8-bit mode, and with the assembler knowing it should assemble for the 65816. using some debugging print statements i can see the code sending commands to the SD Card, but it never responds (always reads back $FF). adding the same print statements to the FatFS C program, the SD Card does respond:
Code:
C program:
Sending: 40, Receiving: FF <- Command $40
Sending: 00, Receiving: FF
Sending: 00, Receiving: FF
Sending: 00, Receiving: FF
Sending: 00, Receiving: FF <- 32-bit Operand, all 0
Sending: 95, Receiving: FF <- CRC checksum
Sending: FF, Receiving: FF
Sending: FF, Receiving: 01 <- SD Card responds
Sending: FF, Receiving: FF
Assembly program:
40>>FF <- Command $40
00>>FF
00>>FF
00>>FF
00>>FF <- 32-bit Operand, all 0
95>>FF <- CRC checksum
FF>>FF
FF>>FF
FF>>FF
... <- SD Card never responds
i thought one possibility could be that the CPU is just too fast for the SPI Interface, so that's why the slower C version works. so i slowed the CPU down using delay loops and by swapping the oscillator, but neither worked. plus SPI is designed to run at ~10-20MHz so the CPU speed shouldn't cause issues anyways. the VIA pins are also correctly initialized, exactly like in the C program.
so the only other thing i can think of is that something is wrong with my transfer code:
Code:
SPI_SCK = %00000001
SPI_MOSI = %00000010
SPI_MISO = %10000000
SPI_SCK_N = %11111110
SPI_MOSI_N = %11111101
SPI_MISO_N = %01111111
spi_read:
LDA #$FF
spi_transfer:
; debug $0A
; JSR PRINT_H8
; debug '>'
PHX
PHY ; Save X and Y
LDY #8
LDX #0 ; Clear the Output Byte
@1: ASL A ; Shift the MSB -> C
PHA ; Save the Input Byte
BCC @2 ; Check the Carry flag
LDA f:VIA_ORA
ORA #SPI_MOSI ; if it's 1 set the MOSI line high
STA f:VIA_ORA
BRA @3
@2: LDA f:VIA_ORA
AND #SPI_MOSI_N ; if it's 0 set the MOSI line low
STA f:VIA_ORA
@3: NOP
LDA f:VIA_ORA
ORA #SPI_SCK ; Set the Clock line high
STA f:VIA_ORA
LDA f:VIA_ORA
AND #SPI_MISO ; Get the MISO line
ASL A ; And put it into the Carry flag
TXA ; Get the Output Byte into A
ROL A ; Shift C -> LSB of the Output Byte
TAX ; And Save the Output Byte again
LDA f:VIA_ORA
AND #SPI_SCK_N ; Set the Clock line low again
STA f:VIA_ORA
PLA ; Restore the Input Byte for the next loop
DEY ; Decrement the Counter by 1
BNE @1 ; And Check if it reached 0
; debug '>'
LDA #SPI_IDLE
STA f:VIA_ORA
TXA ; If it did reach 0, get the Output Byte
; JSR PRINT_H8
PLY
PLX ; And restore X and Y
RTS
all the debug prints are commented out, also yes i did check that all of the symbols like VIA_ORA are correct. here the C version to compare:
Code:
uint8_t SPI_transfer(uint8_t value){
volatile uint8_t out = 0;
for (int8_t i = 7; i > -1; i--){
writeMOSI(bitread(value, i)); // Write the input bit to the MOSI line
writeSCK(1); // set the clock high
bitwrite(out, i, getMISO()); // read the MISO line and write the bit to the output
writeSCK(0); // set the clock low
}
// printf("Sending: %X, Receiving: %X\n", value, out);
return out;
}
writeMOSI and writeSCK just read the VIA_ORA Register, set/clear the specific bit and then write the value back. getMISO just reads the VIA_ORA Register and masks out all other bits. the ones in the assembly version should function basically the same, but without them being seperate functions.
maybe someone can see anything wrong with my assembly routine, or i'm missing something else. i think i'll just have to hook up my oscilloscope and see what exactly is happening on the SPI lines.
on another note, i've also been making plans for a VGA Card, 320x200 @ 256 colors. with 64kB of VRAM that are mapped from $FF0000 to $FFFFFF.
though the main problem is accessing the VRAM as the Card and CPU run at different clock speeds. i already have some ideas for write-only interfaces. for example:
the Video circuit only accesses VRAM every second cycle, so when writing to VRAM the write circuit would simply use the wait state signal to hold the CPU clock high until the next available VRAM cycle, then it would write the data to the specified address, and then let go of the CPU clock again. on average i think that would make a VRAM write ~3 cycles long. at 20MHz and using the MVN/MVP instructions would allow for 1 byte ever ~10 cycles, or a transfer speed of ~1.9MB/s. which sadly crushes my dreams of 60 FPS Video output, as that would require ~3.3MB/s of bandwidth. but it should still be good enough for basic drawings, demos, and GUIs.
.
anyways i just thought i'd do a little update to say what i've been doing with this thing for the past month or so.