Go Down

Topic: (not solved) issues with the SPI bus music (full code provided) (Read 73 times) previous topic - next topic


the problem is kinda complicated ...

 the system consists of me reading raw music data from an SD-card then outputting that data to an R2R resistor ladder for output , now i did so this with an arduino-mega before and did get the music to play really well , now i am trying to do it with an UNO , the only diffrence is that i added an other component to the SPI bus , that is the 74HC595 , since before i was using a Mega port to output the sound bytes now i am using the spi bus to output serial data to the 74hc595 chip for it to then convert it to serial .
here is how the code goes

i send a sound to the DAC every 64us , that would be around 15660hz frequency , then i must read a sector from the sd card and that would take around 3ms i managed to read a byte at around a little less than one microsecond . now as you know reading a sector from an sd card goes in a loop that reads 512bytes , and since 3ms is too long , with the mega i did set a timer that counts untill the needed time to output a byte comes, then i would output a byte to the DAC from the the new sector that the system is reading . now before outputting a byte was just about outputting it to the port which had nothing to do with the spi-bus now though outputting a byte requires sending it via SPI .

so when i used the program without counting in the 3ms period the sound comes out fine , though when i added that part (it is really needed) the sound is distorted and there would be some noise in the SPI communication , here is the full code . and the part that causes the problem is marked

the SD card CS is at pin10
the 74HC595 CS is at pin9

i did test a very similar code with the mega but without the 74hc595 so i just set a port and it worked in a good way , now though it works but with noise if i keep that marked part , so i would guess this is an SPI issue

Code: [Select]

/********************** SPI SECTION BELOW **********************/

// SPI Variables
byte clr;     // dummy variable used to clear some of the SPI registers
byte spi_err; // SPI timeout flag, must be cleared manually
byte c_index;
volatile unsigned short g_i=0;
byte low=0;
short pos=0;
byte i2=1;

#define SPI_f(data)  SPDR=data; while (!(SPSR & 128));

  volatile long arg=262144;

// send an SPI command, includes time out management
// returns spi_err: "0" is "no error"
byte spi_cmd(volatile char data) {       //send a command to the sd card
unsigned char r;
__asm__ __volatile__ (
"out %1,%2\n\t"
".rept 21\n\t" "nop\n\t" ".endr\n\t"
"in %0,%1\n\t"
:"=r" (r):"i" (_SFR_IO_ADDR(SPDR)),"r" (data):); 
return r;

// initialize SPI port
void spi_initialize(void) {
  SPCR = (1<<SPE) | (1<<MSTR); // spi enabled, master mode
  clr = SPSR; // dummy read registers to clear previous results
  clr = SPDR;

/********************** SD CARD SECTION BELOW **********************/

// SD Card variables
#define blockSize 512          // block size (default 512 bytes)
byte vBlock[blockSize];        // set vector containing data that will be recorded on SD Card
byte vBuffer[16];

#define GO_IDLE_STATE 0x00     // resets the SD card
#define SEND_CSD 0x09          // sends card-specific data
#define SEND_CID 0x0A          // sends card identification
#define READ_SINGLE_BLOCK 0x11 // reads a block at byte address
#define WRITE_BLOCK 0x18       // writes a block at byte address
#define SEND_OP_COND 0x29      // starts card initialization
#define APP_CMD 0x37           // prefix for application command

// Send a SD command, num is the actual index, NOT OR'ed with 0x40.
// arg is all four bytes of the argument
byte sdc_cmd(byte commandIndex, long arg) {
  spi_cmd(0xFF);           // dummy byte
  commandIndex |= 0x40;    // command token OR'ed with 0x40
  spi_cmd(commandIndex);   // send command
  for (int i=3; i>=0; i--) {
    spi_cmd(arg>>(i*8));   // send argument in little endian form (MSB first)
  spi_cmd(0x95);           // checksum valid for GO_IDLE_STATE, not needed thereafter, so we can hardcode this value
  spi_cmd(0xFF);           // dummy byte gives card time to process
  byte res = spi_cmd(0xFF);
  return (res);  // query return value from card

// initialize SD card
// retuns 1 if successful
byte sdc_initialize(void) {
  // set slow clock: 1/128 base frequency (125Khz in this case)
  SPCR |=  (1<<SPR1) | (1<<SPR0); // set slow clock: 1/128 base frequency (125Khz in this case)
  SPSR &= ~(1<<SPI2X);            // No doubled clock frequency
  // wake up SD card
  for(byte i=0; i<10; i++) {
    spi_cmd(0xFF);                // send 10 times 8 pulses for a warmup (74 minimum)
  // set idle mode
  byte retries=0;
  while(sdc_cmd(GO_IDLE_STATE, 0) != 0x01) { // while SD card is not in iddle state
    if (retries >= 0xFF) {
      return(NULL); // timed out!
  // at this stage, the card is in idle mode and ready for start up
  retries = 0;
  sdc_cmd(APP_CMD, 0); // startup sequence for SD cards 55/41
  while (sdc_cmd(SEND_OP_COND, 0) != 0x00) {
    if (retries >= 0xFF) {
      return(NULL); // timed out!
    sdc_cmd(APP_CMD, 0);
  // set fast clock, 1/4 CPU clock frequency (4Mhz in this case)
  SPCR &= 0b11111100; // Clock Frequency: f_OSC / 4
  SPSR |=  (1<<SPI2X);              // Doubled Clock Frequency: f_OSC / 2
  return (0x01); // returned value (success)

// read block on SD card and copy data in block vector
// retuns 1 if successful
void sdc_readBlock(long blockIndex) {
  if(sdc_cmd(READ_SINGLE_BLOCK,  (blockIndex * blockSize))!=0x00) while(spi_cmd(0xFF)!=0x00);
  while (spi_cmd(0xFF) != 0xFE);
  for (int i=0; i<blockSize; i++)
    vBlock[i] = spi_cmd(0xFF); // read data
                          if(TCNT2>=498)  { sound_byte(vBlock[g_i]); /*<-- this is the command that causes the issue
                                                                            without it the system works but kinda slow because of that 3ms thing
                                                                             its supposed to work and it works but it causes major noise in the spi bus */
                                                        g_i++;  TCNT1=0;}
  // read CRC (lost results in blue sky)
  spi_cmd(0xFF); // LSB
  spi_cmd(0xFF); // MSB

/********************** MAIN ROUTINES SECTION  BELOW **********************/

unsigned char buff[8];                                       

volatile unsigned int pos_index=512;                       

void sound_byte(unsigned char _byte){
digitalWrite(10,HIGH);            //get the SD card to ignore the command
digitalWrite(9,LOW);              //get the 74hc595 to get the commant
digitalWrite(9,HIGH);             //restore
digitalWrite(10,LOW);             //restore

void setup() {
  // Set ports
  // Data in
  unsigned char i=0;
  // Initialize serial communication
  unsigned short l=0;

TCCR1A = 0;
TCCR1B = 0;

OCR1A = 500;         //this is supposed to work at around 31200 frequency but it works at 15660 for some reason
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS10);

TCCR2A = 0;
TCCR2B = 0;

OCR2A = 1000;         //second counter timer
TCCR2B |= (1 << WGM12);
TCCR2B |= (1 << CS10);

TIMSK1 |= (1 << OCIE1A);  //interrupt setting

unsigned short l=0;


sound_byte(vBlock[g_i]); //send a byte to the 74HC595 (this part works fine)
if(g_i==512) {g_i=0; /* --->  */ sdc_readBlock(pos_index);  /* <---- problem   */ pos_index++; if(pos_index==33400) pos_index=512;}

void loop() {}


Probably related to both the SD card and the 74HC595 being on the same SPI bus. It may not be possible to do through a shift register for that reason...
ATtiny core for 841+1634+828 and x4/x5/x61/x7/x8 series Board Manager:
ATtiny 841/1634/828/88/861/167 breakouts, mosfets, touch sensors and prototyping board in my store http://tindie.com/stores/DrAzzy


i dont get it though ...
i managed to send bytes to the shift register without the SD card being affected
and i managed to send bytes to the sd card without the sd card being affected
but in the reading loop of the sd card , that's when it get's messy


Yeah, because you're sending data to the shift register in the middle of a read... Actually, could it be corrupting data, since there's only one SPI data register...?
ATtiny core for 841+1634+828 and x4/x5/x61/x7/x8 series Board Manager:
ATtiny 841/1634/828/88/861/167 breakouts, mosfets, touch sensors and prototyping board in my store http://tindie.com/stores/DrAzzy


i am not sending it during a read ,
the reading loop of the sd card consists of many data transmissions , sending the sound byte is outside the data transmissions but inside the reading loop , you can see that in code .
the data register is the same but i dont think it has anything to do with the issue


the noise in the music is like going in parallel with it , you can hear the music , but you can hear the noise to

Go Up