Skip to content

Commit

Permalink
begin working on test programme for QSPI flash access. #153
Browse files Browse the repository at this point in the history
  • Loading branch information
gardners committed Jan 7, 2020
1 parent 4823264 commit dff6325
Show file tree
Hide file tree
Showing 2 changed files with 355 additions and 2 deletions.
346 changes: 346 additions & 0 deletions src/utilities/qspitest.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,346 @@
#include <stdio.h>
#define POKE(X,Y) (*(unsigned char*)(X))=Y
#define PEEK(X) (*(unsigned char*)(X))
void m65_io_enable(void);

unsigned char joy_x=100;
unsigned char joy_y=100;

struct dmagic_dmalist {
// Enhanced DMA options
unsigned char option_0b;
unsigned char option_80;
unsigned char source_mb;
unsigned char option_81;
unsigned char dest_mb;
unsigned char end_of_options;

// F018B format DMA request
unsigned char command;
unsigned int count;
unsigned int source_addr;
unsigned char source_bank;
unsigned int dest_addr;
unsigned char dest_bank;
unsigned char sub_cmd; // F018B subcmd
unsigned int modulo;
};

struct dmagic_dmalist dmalist;
unsigned char dma_byte;

void do_dma(void)
{
m65_io_enable();

// for(i=0;i<24;i++)
// screen_hex_byte(SCREEN_ADDRESS+i*3,PEEK(i+(unsigned int)&dmalist));

// Now run DMA job (to and from anywhere, and list is in low 1MB)
POKE(0xd702U,0);
POKE(0xd704U,0x00); // List is in $00xxxxx
POKE(0xd701U,((unsigned int)&dmalist)>>8);
POKE(0xd705U,((unsigned int)&dmalist)&0xff); // triggers enhanced DMA
}

unsigned char lpeek_toscreen(long address)
{
// Read the byte at <address> in 28-bit address space
// XXX - Optimise out repeated setup etc
// (separate DMA lists for peek, poke and copy should
// save space, since most fields can stay initialised).

dmalist.option_0b=0x0b;
dmalist.option_80=0x80;
dmalist.source_mb=(address>>20);
dmalist.option_81=0x81;
dmalist.dest_mb=0x00; // dma_byte lives in 1st MB
dmalist.end_of_options=0x00;
dmalist.sub_cmd=0x02; // Hold source address

dmalist.command=0x00; // copy
dmalist.count=1000;
dmalist.source_addr=address&0xffff;
dmalist.source_bank=((address>>16)&0x0f);
dmalist.dest_addr=0x0400;
dmalist.dest_bank=0;

do_dma();

return dma_byte;
}


unsigned char lpeek(long address)
{
// Read the byte at <address> in 28-bit address space
// XXX - Optimise out repeated setup etc
// (separate DMA lists for peek, poke and copy should
// save space, since most fields can stay initialised).

dmalist.option_0b=0x0b;
dmalist.option_80=0x80;
dmalist.source_mb=(address>>20);
dmalist.option_81=0x81;
dmalist.dest_mb=0x00; // dma_byte lives in 1st MB
dmalist.end_of_options=0x00;
dmalist.sub_cmd=0x00;

dmalist.command=0x00; // copy
dmalist.count=1;
dmalist.source_addr=address&0xffff;
dmalist.source_bank=(address>>16)&0x0f;
dmalist.dest_addr=(unsigned int)&dma_byte;
dmalist.dest_bank=0;

do_dma();

return dma_byte;
}

void lpoke(long address, unsigned char value)
{

dmalist.option_0b=0x0b;
dmalist.option_80=0x80;
dmalist.source_mb=0x00; // dma_byte lives in 1st MB
dmalist.option_81=0x81;
dmalist.dest_mb=(address>>20);
dmalist.end_of_options=0x00;

dma_byte=value;
dmalist.command=0x00; // copy
dmalist.count=1;
dmalist.source_addr=(unsigned int)&dma_byte;
dmalist.source_bank=0;
dmalist.dest_addr=address&0xffff;
dmalist.dest_bank=(address>>16)&0x0f;

do_dma();
return;
}

void lcopy(long source_address, long destination_address,
unsigned int count)
{
if (!count) return;
dmalist.option_0b=0x0b;
dmalist.option_80=0x80;
dmalist.source_mb=source_address>>20;
dmalist.option_81=0x81;
dmalist.dest_mb=(destination_address>>20);
dmalist.end_of_options=0x00;

dmalist.command=0x00; // copy
dmalist.count=count;
dmalist.sub_cmd=0;
dmalist.source_addr=source_address&0xffff;
dmalist.source_bank=(source_address>>16)&0x0f;
if (source_address>=0xd000 && source_address<0xe000)
dmalist.source_bank|=0x80;
dmalist.dest_addr=destination_address&0xffff;
dmalist.dest_bank=(destination_address>>16)&0x0f;
if (destination_address>=0xd000 && destination_address<0xe000)
dmalist.dest_bank|=0x80;

do_dma();
return;
}

void lfill(long destination_address, unsigned char value,
unsigned int count)
{
if (!count) return;
dmalist.option_0b=0x0b;
dmalist.option_80=0x80;
dmalist.source_mb=0x00;
dmalist.option_81=0x81;
dmalist.dest_mb=destination_address>>20;
dmalist.end_of_options=0x00;

dmalist.command=0x03; // fill
dmalist.sub_cmd=0;
dmalist.count=count;
dmalist.source_addr=value;
dmalist.dest_addr=destination_address&0xffff;
dmalist.dest_bank=(destination_address>>16)&0x0f;
if (destination_address>=0xd000 && destination_address<0xe000)
dmalist.dest_bank|=0x80;
do_dma();
return;
}

void m65_io_enable(void)
{
// Gate C65 IO enable
POKE(0xd02fU,0x47);
POKE(0xd02fU,0x53);
// Force to full speed
POKE(0,65);
}

void wait_10ms(void)
{
// 16 x ~64usec raster lines = ~1ms
int c=160;
unsigned char b;
while(c--) {
b=PEEK(0xD012U);
while (b==PEEK(0xD012U))
continue;
}
}

unsigned char sprite_data[63]={
0xff,0,0,
0xe0,0,0,
0xb0,0,0,
0x98,0,0,
0x8c,0,0,
0x86,0,0,
0x83,0,0,
0x81,0x80,0,

0,0xc0,0,
0,0x60,0,
0,0x30,0,
0,0x18,0,
0,0,0,
0,0,0,
0,0,0,
0,0,0,

0,0,0,
0,0,0,
0,0,0,
0,0,0,
0,0,0
};

void main(void)
{

unsigned char seconds = 0;
unsigned char minutes = 0;
unsigned char hours = 0;

short x,y,z;
short a1,a2,a3;
unsigned char n=0;

m65_io_enable();

// Sprite 0 on
lpoke(0xFFD3015L,0x01);
// Sprite data at $03c0
*(unsigned char *)2040 = 0x3c0/0x40;

for(n=0;n<64;n++)
*(unsigned char*)(0x3c0+n)=
sprite_data[n];

// Disable OSK
lpoke(0xFFD3615L,0x7F);

// Clear screen
printf("%c",0x93);



}

/*
$D6CC.7 = data bits DDR (all 4 bits at once)
$D6CC.6 = CS#
$D6CC.5 = clock
$D6CC.4 = tri-state SI only (to enable single bit SPI communications)
$D6CC.0 = data bit 0 / SI (serial input)
$D6CC.1 = data bit 1 / SO (serial output)
$D6CC.2 = data bit 2 / WP# (write protect)
$D6CC.3 = data bit 3 / HOLD#
*/

void spi_clock_low(void)
{
POKE(0xD6CCU,PEEK(0xD6CCU)&(0xFF-0x20));
}

void spi_clock_high(void)
{
POKE(0xD6CCU,PEEK(0xD6CCU)|0x20);
}

void spi_cs_low(void)
{
POKE(0xD6CCU,PEEK(0xD6CCU)&(0xFF-0x40));
}

void spi_cs_high(void)
{
POKE(0xD6CCU,PEEK(0xD6CCU)|0x40);
}


void spi_tx_bit(unsigned char bit)
{
spi_clock_low();
spi_so_set(bit);
spi_clk_high();
}

void spi_tx_byte(unsigned char b)
{
unsigned char i;

for(i=0;i<8;i++) {
spi_tx_bit(b&1);
b=b>>1;
}
}

unsigned char spi_rx_byte()
{
unsigned char b=0;
unsigned char i;

spi_tristate_si();
for(i=0;i<8;i++) {
spi_clk_low();
b=b>>1;
if (spi_sample_si()) b|=0x80;
spi_clk_high();
}
}

unsigned char manufacturer;
unsigned short device_id;
unsigned short cfi_data[512];

void fetch_rdid(void)
{
/* Run command 0x9F and fetch CFI etc data.
(Section 9.2.2)
*/

unsigned short i;

spi_cs_high();
spi_cs_low();
spi_tx_byte(0x9f);

// Data format according to section 11.2

// Start with 3 byte manufacturer + device ID
manufacturer=spi_rx_byte();
device_id=spi_rx_byte()<<8;
devide_id|=spi_rx_byte();

// Now get the CFI data block
for(i=0;i<512;i++) cfi_data[i]=0x00;
cfi_length=spi_rx_byte();
if (cfi_length==0) cfi_length = 512;
for(i=0;i<cfi_length;i++)
cfi_data[i]=spi_rx_byte;

}

11 changes: 9 additions & 2 deletions src/vhdl/sdcardio.vhdl
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ architecture behavioural of sdcardio is
signal qspi_clock_int : std_logic := '1';
signal qspi_csn_int : std_logic := '1';
signal qspi_dbddr : std_logic := '0';
signal qspi_tristate_d0 : std_logic := '0';
signal qspidb_in : unsigned(3 downto 0);

signal aclMOSIinternal : std_logic := '0';
Expand Down Expand Up @@ -1107,7 +1108,7 @@ begin -- behavioural
fastio_rdata(7) <= qspi_dbddr;
fastio_rdata(6) <= qspi_csn_int;
fastio_rdata(5) <= qspi_clock_int;
fastio_rdata(4) <= '0';
fastio_rdata(4) <= qspi_tristate_d0;
fastio_rdata(3 downto 0) <= qspidb;
when x"D0" =>
-- @IO:GS $D6D0 - I2C bus select (bus 0 = temp sensor on Nexys4 boardS)
Expand Down Expand Up @@ -2225,8 +2226,14 @@ begin -- behavioural
qspi_csn_int <= fastio_wdata(6);
qspi_clock <= fastio_wdata(5);
qspi_clock_int <= fastio_wdata(5);
qspi_tristate_d0 <= fastio_wdata(4);
if fastio_wdata(7)='1' then
qspidb <= fastio_wdata(3 downto 0);
if fastio_wdata(4)='0' then
qspidb <= fastio_wdata(3 downto 0);
else
qspidb(3 downto 1) <= fastio_wdata(3 downto 1);
qspidb(0) <= 'Z';
end if;
else
qspidb <= "ZZZZ";
end if;
Expand Down

0 comments on commit dff6325

Please sign in to comment.