Skip to content

Commit

Permalink
Read timing adjustment, now getting 1216 KB/sec on LC III+.
Browse files Browse the repository at this point in the history
First pass at write speed optimization, now getting 825 KB/sec on LC III+.
Whitespace cleanup.
  • Loading branch information
mactcp authored and androda committed Apr 7, 2022
1 parent aa27be8 commit 10e3262
Showing 1 changed file with 67 additions and 53 deletions.
120 changes: 67 additions & 53 deletions F4_BlueSCSI/F4_BlueSCSI.ino
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,6 @@ inline byte readIO(void)
// Port input data register
uint32_t ret = GPIOB->regs->IDR;
byte bret = (byte)~(((ret >> 8) & 0b11110111) | ((ret & 0x00000004) << 1));

#if READ_PARITY_CHECK
if((db_bsrr[bret]^ret)&1) // TODO fix parity calculation
m_sts |= 0x01; // parity error
Expand Down Expand Up @@ -785,12 +784,12 @@ void writeDataPhase(int len, const byte* p)
writeHandshake(p[i]);
}
}

#if READ_SPEED_OPTIMIZE
/*
* This loop is tuned to repeat the following pattern:
* 1) Set REQ
* 2) 5 cycles of work/delay
* 2) 5-6 cycles of work/delay
* 3) Wait for ACK
* Cycle time tunings are for 72MHz STM32F103
*/
Expand All @@ -802,40 +801,40 @@ void writeDataLoop(uint32_t blocksize)
#define WAIT_ACK_ACTIVE() while(!SCSI_IN(vACK))
#define WAIT_ACK_INACTIVE() while(SCSI_IN(vACK))

register byte *srcptr= m_buf; // Source buffer
register byte *endptr= m_buf + blocksize; // End pointer

register const uint32_t *bsrr_tbl = db_bsrr; // Table to convert to BSRR
register uint32_t bsrr_val; // BSRR value to output (DB, DBP, REQ = ACTIVE)
register volatile uint32_t *db_dst = &(GPIOB->regs->BSRR); // Output port

// Start the first bus cycle.
FETCH_BSRR_DB();
REQ_OFF_DB_SET(bsrr_val);
REQ_ON();
FETCH_BSRR_DB();
WAIT_ACK_ACTIVE();
REQ_OFF_DB_SET(bsrr_val);
do{
WAIT_ACK_INACTIVE();
REQ_ON();
// 5 cycle delay before reading ACK.
// Two loads plus NOP is 5 cycles.
FETCH_BSRR_DB();
asm("NOP");
WAIT_ACK_ACTIVE();
REQ_OFF_DB_SET(bsrr_val);
// 5 cycle delay before reading ACK.
// Branch taken is 2-4, seems to be taking 3. A second write is 2 more cycles.
// cmp is being pipelined in to a store so doesn't add any time.
REQ_OFF_DB_SET(bsrr_val);
}while(srcptr < endptr);
WAIT_ACK_INACTIVE();
// Finish the last bus cycle, byte is already on DB.
REQ_ON();
WAIT_ACK_ACTIVE();
REQ_OFF_DB_SET(bsrr_val);
WAIT_ACK_INACTIVE();
register byte *srcptr= m_buf; // Source buffer
register byte *endptr= m_buf + blocksize; // End pointer

register const uint32_t *bsrr_tbl = db_bsrr; // Table to convert to BSRR
register uint32_t bsrr_val; // BSRR value to output (DB, DBP, REQ = ACTIVE)
register volatile uint32_t *db_dst = &(GPIOB->regs->BSRR); // Output port

// Start the first bus cycle.
FETCH_BSRR_DB();
REQ_OFF_DB_SET(bsrr_val);
REQ_ON();
FETCH_BSRR_DB();
WAIT_ACK_ACTIVE();
REQ_OFF_DB_SET(bsrr_val);
do{
WAIT_ACK_INACTIVE();
REQ_ON();
// 6 cycle delay before reading ACK.
// Store plus 2 loads is 6 cycles.
REQ_ON();
FETCH_BSRR_DB();
WAIT_ACK_ACTIVE();
REQ_OFF_DB_SET(bsrr_val);
// 5 cycle delay before reading ACK.
// Branch taken is 2-4, seems to be taking 3. A second write is 2 more cycles.
// cmp is being pipelined in to a store so doesn't add any time.
REQ_OFF_DB_SET(bsrr_val);
}while(srcptr < endptr);
WAIT_ACK_INACTIVE();
// Finish the last bus cycle, byte is already on DB.
REQ_ON();
WAIT_ACK_ACTIVE();
REQ_OFF_DB_SET(bsrr_val);
WAIT_ACK_INACTIVE();
}
#endif

Expand All @@ -853,22 +852,22 @@ void writeDataPhaseSD(uint32_t adds, uint32_t len)
SCSI_OUT(vCD ,inactive) // gpio_write(CD, low);
SCSI_OUT(vIO , active) // gpio_write(IO, high);

SCSI_DB_OUTPUT()
SCSI_DB_OUTPUT()
for(uint32_t i = 0; i < len; i++) {
// Asynchronous reads will make it faster ...
m_resetJmp = false;
m_img->m_file.read(m_buf, m_img->m_blocksize);
enableResetJmp();

#if READ_SPEED_OPTIMIZE
writeDataLoop(m_img->m_blocksize);
writeDataLoop(m_img->m_blocksize);
#else
for(int j = 0; j < m_img->m_blocksize; j++) {
writeHandshake(m_buf[j]);
}
#endif
}
SCSI_DB_INPUT()
SCSI_DB_INPUT()
}

/*
Expand All @@ -885,6 +884,33 @@ void readDataPhase(int len, byte* p)
p[i] = readHandshake();
}

void readDataLoop(uint32_t blockSize)
{
register byte *dstptr= m_buf;
register byte *endptr= m_buf + blockSize - 1;

#define REQ_ON() (port_b->BSRR = BITMASK(vREQ)<<16);
#define REQ_OFF() (port_b->BSRR = BITMASK(vREQ));
#define WAIT_ACK_ACTIVE() while((*ack_src>>(vACK&15)&1))
#define WAIT_ACK_INACTIVE() while(!(*ack_src>>(vACK&15)&1))
register gpio_reg_map *port_b = PBREG;
register volatile uint32_t *ack_src = &(GPIOA->regs->IDR);
REQ_ON();
do {
WAIT_ACK_ACTIVE();
uint32_t ret = GPIOB->regs->IDR;
REQ_OFF();
*dstptr++ = ~(ret >> 8);
WAIT_ACK_INACTIVE();
REQ_ON();
} while(dstptr<endptr);
WAIT_ACK_ACTIVE();
uint32_t ret = GPIOB->regs->IDR;
REQ_OFF();
*dstptr++ = ~(ret >> 8);
WAIT_ACK_INACTIVE();
}

/*
* Data out phase.
* Write to SD card while reading len block.
Expand All @@ -900,19 +926,7 @@ void readDataPhaseSD(uint32_t adds, uint32_t len)
for(uint32_t i = 0; i < len; i++) {
m_resetJmp = true;
#if WRITE_SPEED_OPTIMIZE
register byte *dstptr= m_buf;
register byte *endptr= m_buf + m_img->m_blocksize;

for(dstptr=m_buf;dstptr<endptr;dstptr+=8) {
dstptr[0] = readHandshake();
dstptr[1] = readHandshake();
dstptr[2] = readHandshake();
dstptr[3] = readHandshake();
dstptr[4] = readHandshake();
dstptr[5] = readHandshake();
dstptr[6] = readHandshake();
dstptr[7] = readHandshake();
}
readDataLoop(m_img->m_blocksize);
#else
for(int j = 0; j < m_img->m_blocksize; j++) {
m_buf[j] = readHandshake();
Expand Down

0 comments on commit 10e3262

Please sign in to comment.