mohan-bee/mini-mp3-player

Portable, battery-powered MP3 player hardware with USB charging, microSD storage, an MCU, VS10xx audio decoder, headphone output, status controls, and regulated power rails.

Version
1.2.0
License
unset
Stars
0

firmware/tests/test_sd.c

#include "board.h"
#include "ff.h"
#include "diskio.h"
#include <assert.h>
#include <stdio.h>
static bool selected,sdhc=true,removed,fast;
static uint32_t clock_ms,read_argument;
static uint8_t packet[6],response[520];
static unsigned packet_size,response_size,response_position,initial_clocks,reads;
uint32_t millis(void) { return clock_ms++; }
void delay_ms(uint32_t ms) { clock_ms+=ms; }
void sd_speed(bool value) { fast=value; }
void sd_select(bool value) {
    selected=value;
    if (!value) { packet_size=0; response_size=response_position=0; }
}
static void reply(void) {
    uint8_t command=packet[0]&63;
    uint32_t argument=((uint32_t)packet[1]<<24)|((uint32_t)packet[2]<<16)|((uint32_t)packet[3]<<8)|packet[4];
    response_position=0; response_size=1; response[0]=0;
    switch(command) {
    case 0: assert(packet[5]==0x95 && !fast && initial_clocks>=10); response[0]=1; break;
    case 8:
        assert(packet[5]==0x87 && argument==0x1aa);
        response[0]=1; response[1]=response[2]=0; response[3]=1; response[4]=0xaa;
        response_size=5; break;
    case 55: response[0]=1; break;
    case 41: assert(argument==0x40000000); break;
    case 58:
        response[1]=sdhc?0xc0:0x80; response[2]=0xff; response[3]=0x80; response[4]=0;
        response_size=5; break;
    case 16: assert(!sdhc && argument==512); break;
    case 17:
        assert(fast); read_argument=argument; reads++;
        response[1]=0xfe;
        for (unsigned i=0;i<512;i++) response[2+i]=(uint8_t)i;
        response[514]=response[515]=0xff; response_size=516; break;
    default: assert(!"unexpected SD command");
    }
}
bool sd_byte(uint8_t tx,uint8_t *rx) {
    *rx=0xff;
    if (removed) return false;
    if (!selected) { initial_clocks++; return true; }
    if (response_position<response_size) { *rx=response[response_position++]; return true; }
    if (packet_size || (tx&0xc0)==0x40) {
        packet[packet_size++]=tx;
        if (packet_size==6) { packet_size=0; reply(); }
    }
    return true;
}
int main(void) {
    BYTE data[1024];
    for(unsigned mode=0;mode<2;mode++) {
        sdhc=mode==0;
        assert(disk_initialize(0)==0 && fast && !selected);
        assert(disk_read(0,data,7,2)==RES_OK);
        assert(read_argument==(sdhc?8:8*512));
        for(unsigned i=0;i<sizeof data;i++) assert(data[i]==(BYTE)i);
        assert(!selected);
    }
    assert(reads==4);
    removed=true;
    assert(disk_read(0,data,9,1)==RES_ERROR && !selected);
    assert(disk_status(0)&STA_NOINIT);
    assert(disk_read(0,data,9,1)==RES_NOTRDY);
    assert(disk_initialize(0)&STA_NOINIT);
    assert(disk_read(0,data,9,0)==RES_PARERR);
    puts("PASS: SDHC/SDSC initialization, CRC command bytes, sector/byte addressing, multiblock read, removal");
}