#include #include "sta013.h" void wait(int reps) { int x; for(x=0; x> 7); BI2C_WAIT; SCL_OUT(HIGH); // bit 7 captured BI2C_WAIT; SCL_OUT(LOW); BI2C_WAIT; SDA_OUT(c >> 6); BI2C_WAIT; SCL_OUT(HIGH); // bit 6 captured BI2C_WAIT; SCL_OUT(LOW); BI2C_WAIT; SDA_OUT(c >> 5); BI2C_WAIT; SCL_OUT(HIGH); // bit 5 captured BI2C_WAIT; SCL_OUT(LOW); BI2C_WAIT; SDA_OUT(c >> 4); BI2C_WAIT; SCL_OUT(HIGH); // bit 4 captured BI2C_WAIT; SCL_OUT(LOW); BI2C_WAIT; SDA_OUT(c >> 3); BI2C_WAIT; SCL_OUT(HIGH); // bit 3 captured BI2C_WAIT; SCL_OUT(LOW); BI2C_WAIT; SDA_OUT(c >> 2); BI2C_WAIT; SCL_OUT(HIGH); // bit 2 captured BI2C_WAIT; SCL_OUT(LOW); BI2C_WAIT; SDA_OUT(c >> 1); BI2C_WAIT; SCL_OUT(HIGH); // bit 1 captured BI2C_WAIT; SCL_OUT(LOW); BI2C_WAIT; SDA_OUT(c); BI2C_WAIT; SCL_OUT(HIGH); // bit 0 captured BI2C_WAIT; SCL_OUT(LOW); BI2C_WAIT; // ACK sequence begins here SDA_MODE_IN; // SDA direction -> input BI2C_WAIT; SCL_OUT(HIGH); // clock ACK BI2C_DELAY to regain bus control BI2C_WAIT; ACK = !(SDA_IN); // detect ACK response *** should be waiting for ACK, not just detecting BI2C_WAIT; SCL_OUT(LOW); BI2C_WAIT; SDA_MODE_OUT; // SDA direction -> output BI2C_WAIT; } char bi2c_read() { char res,x; res = 0; SDA_MODE_IN; // SDA direction -> input BI2C_WAIT; for(x=0; x<8; x++) { SCL_OUT(HIGH); BI2C_WAIT; res = (res << 1) | ((SDA_IN) & 1); BI2C_WAIT; SCL_OUT(LOW); BI2C_WAIT; } SDA_OUT(HIGH); BI2C_WAIT; // ACK starts here SDA_MODE_OUT; BI2C_WAIT; return res; } char bi2c_get(char addr) { char res; bi2c_start(); bi2c_write(0x86); bi2c_write(addr); bi2c_start(); bi2c_write(0x87); res = bi2c_read(); bi2c_stop(); return res; } void bi2c_put(char addr, char data) { bi2c_start(); bi2c_write(0x86); bi2c_write(addr); bi2c_write(data); bi2c_stop(); } void setVolume(char vol) { char val; val = (10-vol)*3; // 90dB attenuation at min volume, 0dB attenuation at max bi2c_put(DLA,val); // equal left-right volumes bi2c_put(DRA,val); if (!ACK) { #ifdef DEBUG printf("\n\rERROR setting volume\n\r"); #endif lcd_line2("ERROR: STA013 volume set w/o ACK"); while(1) {} } } void incVolume() { if (volume < 10) volume++; setVolume(volume); } void decVolume() { if (volume > 0) volume--; setVolume(volume); } // MP3 streaming functions #pragma warn- //don't get warning about data not used void play(char data) { #asm ld r26,Y rol r26 brcs play_one1 cbi __sdi_port, __sdi_port_sub rjmp play_next1 play_one1: sbi __sdi_port, __sdi_port_sub play_next1: sbi __sckr_port, __sckr_port_sub rol r26 cbi __sckr_port, __sckr_port_sub brcs play_one2 cbi __sdi_port, __sdi_port_sub rjmp play_next2 play_one2: sbi __sdi_port, __sdi_port_sub play_next2: sbi __sckr_port, __sckr_port_sub rol r26 cbi __sckr_port, __sckr_port_sub brcs play_one3 cbi __sdi_port, __sdi_port_sub rjmp play_next3 play_one3: sbi __sdi_port, __sdi_port_sub play_next3: sbi __sckr_port, __sckr_port_sub rol r26 cbi __sckr_port, __sckr_port_sub brcs play_one4 cbi __sdi_port, __sdi_port_sub rjmp play_next4 play_one4: sbi __sdi_port, __sdi_port_sub play_next4: sbi __sckr_port, __sckr_port_sub rol r26 cbi __sckr_port, __sckr_port_sub brcs play_one5 cbi __sdi_port, __sdi_port_sub rjmp play_next5 play_one5: sbi __sdi_port, __sdi_port_sub play_next5: sbi __sckr_port, __sckr_port_sub rol r26 cbi __sckr_port, __sckr_port_sub brcs play_one6 cbi __sdi_port, __sdi_port_sub rjmp play_next6 play_one6: sbi __sdi_port, __sdi_port_sub play_next6: sbi __sckr_port, __sckr_port_sub rol r26 cbi __sckr_port, __sckr_port_sub brcs play_one7 cbi __sdi_port, __sdi_port_sub rjmp play_next7 play_one7: sbi __sdi_port, __sdi_port_sub play_next7: sbi __sckr_port, __sckr_port_sub rol r26 cbi __sckr_port, __sckr_port_sub brcs play_one8 cbi __sdi_port, __sdi_port_sub rjmp play_next8 play_one8: sbi __sdi_port, __sdi_port_sub play_next8: sbi __sckr_port, __sckr_port_sub nop cbi __sckr_port, __sckr_port_sub #endasm } #pragma warn+ /* void play(char data) { SDI_OUT(data >> 7); SCKR_OUT(HIGH); SCKR_OUT(LOW); SDI_OUT(data >> 6); SCKR_OUT(HIGH); SCKR_OUT(LOW); SDI_OUT(data >> 5); SCKR_OUT(HIGH); SCKR_OUT(LOW); SDI_OUT(data >> 4); SCKR_OUT(HIGH); SCKR_OUT(LOW); SDI_OUT(data >> 3); SCKR_OUT(HIGH); SCKR_OUT(LOW); SDI_OUT(data >> 2); SCKR_OUT(HIGH); SCKR_OUT(LOW); SDI_OUT(data >> 1); SCKR_OUT(HIGH); SCKR_OUT(LOW); SDI_OUT(data >> 0); SCKR_OUT(HIGH); SCKR_OUT(LOW); } */ void sta013init() { #ifdef INIT_FLASH_ADDR char flash * idata = INIT_FLASH_ADDR; #endif #ifdef INIT_EEPROM_ADDR char eeprom * idata = INIT_EEPROM_ADDR; #endif char val; int x; char addr; char data; // initialize ports SDA_DIR = 0; SDA = 1; SCL_DIR = 1; SDI_DIR = 1; SCKR_DIR = 1; RESET_DIR = 1; // DATAREQ_DIR = 0; // DATAREQ = 0; SDA_OUT(HIGH); SCL_OUT(LOW); SCKR_OUT(LOW); // provide reset signal lcd_line2("STA013 INIT: RESET"); #ifdef DEBUG printf("STA013 INIT: RESET"); #endif RESET_OUT(LOW); wait(RESET_DELAY_0); RESET_OUT(HIGH); wait(RESET_DELAY_1); // initialize I2C, detect STA013 lcd_line2("STA013 INIT: DETECT"); #ifdef DEBUG printf(" DETECT"); #endif val = 0; x = 0; while(((val != 0xAC) || (!ACK)) && (x < DETECT_RETRY)) { bi2c_init(); // send a re-initialization sequence // check present status val = bi2c_get(0x01); x++; } if (x == DETECT_RETRY) { #ifdef DEBUG printf("\n\rERROR: device not detected, code %02X should have been 0xAC, ack was %02X\n\r",val,ACK); #endif lcd_line2("ERROR: STA013 not detected"); while(1) {}; } // send configuration to STA013 (include init of MP3 playback) #ifdef DEBUG printf(" INIT"); #endif lcd_line2("STA013 INIT: INIT"); for(x=0; 1;) { addr = idata[x++]; data = idata[x++]; if ((addr == 0) && (data == 0)) break; bi2c_put(addr,data); if (!ACK) { #ifdef DEBUG printf("\n\rERROR: no ACK!!! index=%04X addr=%02X data=%02X\n\r",x,addr,data); #endif lcd_line2("ERROR: STA013 initialization sequence with no ACK"); while (1) {}; } if (addr == 16) wait(RESET_DELAY_1); } #ifdef DEBUG printf("(%04X cmds)",x >> 1); #endif /* // informational stuff data = bi2c_get(DLA); printf("read DLA = %02X\n\r",data); data = bi2c_get(DLB); printf("read DLB = %02X\n\r",data); data = bi2c_get(DRA); printf("read DRA = %02X\n\r",data); data = bi2c_get(DRB); printf("read DRB = %02X\n\r",data); data = bi2c_get(MFSFDF_411); printf("read MFSDF_411 = %02X\n\r",data); data = bi2c_get(PLLFRAC_411_L); printf("read PLLFRAC_411_L = %02X\n\r",data); data = bi2c_get(PLLFRAC_411_R); printf("read PLLFRAC_411_R = %02X\n\r",data); data = bi2c_get(PCMDIVIDER); printf("read PCMDIVIDER = %02X\n\r",data); data = bi2c_get(PCMCONF); printf("read PCMCONF = %02X\n\r",data); data = bi2c_get(MSFDF_X); printf("read MSFDF_X = %02X\n\r",data); data = bi2c_get(DAC_CLK_MODE); printf("read DAC_CLK_MODE = %02X\n\r",data); data = bi2c_get(PLLFRAC_L); printf("read PLLFRAC_L = %02X\n\r",data); data = bi2c_get(PLLFRAC_H); printf("read PLLFRAC_H = %02X\n\r",data); data = bi2c_get(PLLCTRL); printf("read PLLCTRL = %02X\n\r",data); data = bi2c_get(REG0x06); printf("read REG0x06 = %02X\n\r",data); data = bi2c_get(REG0x0B); printf("read REG0x0B = %02X\n\r",data); */ // set volume and run/play enable #ifdef DEBUG printf(" PARAMS"); #endif lcd_line2("STA013 INIT: PARAMS"); volume = 10; //setVolume(volume); bi2c_put(0x72,0x01); // RUN enable if (!ACK) { #ifdef DEBUG printf("\n\rERROR: no ACK on RUN\n\r"); #endif lcd_line2("ERROR: STA013 no ACK on RUN"); while(1) {}; } bi2c_put(0x13,0x01); // PLAY enable if (!ACK) { #ifdef DEBUG printf("\n\rERROR: no ACK on PLAY\n\r"); #endif lcd_line2("ERROR: STA013 no ACK on PLAY"); while(1) {}; } #ifdef DEBUG printf(" DONE\n\r"); #endif lcd_line2("STA013 INIT: DONE"); }