VIRTUAL 2315 CARTRIDGE FACILITY USES SPI LINK BETWEEN PICO AND FPGA
The heart of the Virtual 2315 Cartridge Facility (V2315CF) is a unit that houses a Lattice Field Programmable Gate Array (FPGA), enough RAM memory to hold one disk's worth of data, and a Raspberry Pi PICO. The PICO mainly manages the user interface while the FPGA mainly implements the disk drive emulation and controls the RAM.
The PICO implements a Serial Peripheral Interface (SPI) link to the FPGA, with the PICO acting as the master. The PICO exchanges two bytes with the FPGA as a transaction, the first byte having the command from the PICO and the second byte recieves one byte from the FPGA based on that command.
For example, a transaction code of x88 is a request for the FPGA to return one byte of data from the RAM. The address for memory access was previously transmitted by the PICO as a set of three x05 commands that set the 24 bit RAM address. When the PICO is writing back the contents of a virtual 2315 disk cartridge to the microSD card file that stores the data, it sets the RAM address for each of the 1,624 sectors, reads 642 bytes sequentially from the FPGA and then writes the sector's 321 words of data to the file.
PICO LIBRARY PROVIDES ROUTINES TO CONTROL THE SPI LINK
Exchanging data over an SPI link is done with a few library calls provided for the PICO. The caller first starts the transaction by asserting the SPI chip select line, then calls the spi_write_read_blocking function giving it the address of the buffer holding the outbound data to send to the FPGA, the address of a buffer to receive the data coming back from the FPGA, and a count of how many bytes to send. The caller then deasserts the chip select signal.
The transfer proceeds with the SCLK signal being alternated for the number of bits being transmitted - in this case, that is 16. The MOSI signal sends the bits serially from the PICO to the FPGA. The MISO signal comes from the FPGA and provides the inbound data that is returned to the caller. Thus, an SPI transaction is an exchange.
The routines that I inherited from the RK-05 Emulator had defined the outbound and inbound buffers as arrays of uint8_t, an eight bit unsigned value (byte). The length of each was 2, since the intent is to exchanges two bytes between master and slave in a transaction. There was also a 2 byte array of uint8_t declared in the routine but never used.
EXPERIENCED ERRATIC RESULTS AND LOOKED CLOSELY AT THE FUNCTION CALLS
When my logic tried to write back the contents of RAM to the microSD card in the virtual 2315 cartridge, I would get some correct results and some corrupt data returned. I looked for every possible cause and investigated, but wasn't getting anywhere.
The routines that I inherited from the RK-05 Emulator had defined the outbound (OUTBUF) and inbound (INBUF) buffers as arrays of uint8_t, an eight bit unsigned value (byte). The length of each was 2, since the intent is to exchanges two bytes between master and slave in a transaction. There was also a 2 byte array BUF of uint8_t declared in the routine but never used.
After adding code to verify that the last bits had been exchanged before deasserting the chip select, yet seeing no improvement, I was considering slowing the SPI clock just in case I was getting errors due to hardware signal issues. However, this didn't make sense because at startup the same link transferred 1,624 sectors of data down from the microSD card file to the RAM without a single failure.
I happened to remove the unused variable BUF from the routines but when I next tested, the corruption rate increased to almost 100%. That was unexpected.
MY ASSUMPTION WAS THAT THE FUNCTION WAS RETURNING TOO MANY BYTES
Perhaps the issue was the function, which might be overrunning the buffers I passed it. The count was a hard coded integer 2, which should be what controls this completely, but perhaps it was instead returning integers, a longer data type than the uint8_t bytes in the arrays.
I increased the size of OUTBUF and INBUF to four from two and tried again. The code worked flawlessly. Somehow it was stepping on the stack and causing issues until I added extra room in teh buffers. The code is below.
uint8_t read_write_spi_register(uint8_t reg, uint8_t data)
{
uint8_t out_buf [BUF_LEN+2], in_buf [BUF_LEN+2];
uint8_t buf[2];
out_buf[0] = reg;
out_buf[1] = data;
cs_select();
spi_write_read_blocking (spi_default, out_buf, in_buf, 2);
cs_deselect();
return(in_buf[1]);
}








