CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

8-bit wav file player with Xmodem RS-232 for 16F873

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
yerpa



Joined: 19 Feb 2004
Posts: 58
Location: Wisconsin

View user's profile Send private message Visit poster's website

8-bit wav file player with Xmodem RS-232 for 16F873
PostPosted: Fri Jan 19, 2007 3:51 pm     Reply with quote

Here it is, offered strictly as-is. Please do not make fun of my nasty coding style! Note that this is a re-post - I forgot to disable HTML last time around.

Code:

/////////////////////////////////////////////////////////////////////////
////  T2K2v2.C  by RPL   15 OCT 2002                                 ////
////  Program for TONE2002 board, with audio playback, xmodem file   ////
////  transfers, and a simple file system.                           ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////

#include <16f873.h>
#fuses HS, NOWDT, PUT, NOBROWNOUT, NOPROTECT, NOWRT, NOLVP
#use fast_io(A)

/*  DEFINE EQUATES FOR PORTS */

#byte PORTA = 5
#byte PORTB = 6
#byte RTCC  = 1
#byte TMR0  = 0x01   //Timer 0.
#byte TMR1L = 0x0E   //Timer 1 LOW BYTE.

#define EEPROM_SELECT PIN_A2
#define EEPROM_DI     PIN_A0
#define EEPROM_DO     PIN_A4
#define EEPROM_CLK    PIN_A1

#define ACK 0x06
#define CAN 0x18
#define DLE 0x10
#define EOT 0x04
#define NAK 0x15
#define SOH 0x01
#define SYN 0x22
#define XOF 0x13
#define XON 0x11

#define EEPROM_ADDRESS byte
#define EEPROM_SIZE    256

#use delay(Clock=18432000, RESTART_WDT)
#use RS232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

void clr_all_ptrs();
void dir();
byte read_AT45_stat();
void write_AT45_stream128(long page, byte addr2);
void read_AT45_stream128(long page, byte addr2);
void read_AT45_stream64(long page, byte addr2);
byte xmodem();
void hexdump();

// Define static variables...

static byte toggle_lo;
static byte toggle_hi;
static byte softime;
static byte sample;
static byte sptr;
static byte pflag;
static byte sflag;
static byte filenum;
static long file_start;
static long file_end;
static byte rambuf1[64];
static byte rambuf2[64];


// Define constants...

byte const hexlist[16]={'0', '1', '2', '3', '4', '5', '6', '7',
                        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

   // INTERRUPT ROUTINE FOR RTCC...

#INT_RTCC
void time0_handler(void)
{
        #asm
sync:   btfss 1, 3               //Synchronize (de-jitter) the samples.
        goto  sync
        btfss 1, 0
        nop
        #endasm
       
   PORTB=sample;                 // Write sample to DAC.
   RTCC=0x4f;
   sptr++;
   if ((sptr & 0x40)!=0) sample = rambuf2[sptr & 0x3f];
   if ((sptr & 0x40)==0) sample = rambuf1[sptr & 0x3f];
   if ((sptr & 0x3f)==0) sflag=0;
   if (pflag==0) sample=0;
   toggle_lo++;
   if (toggle_lo==0)
   {
     toggle_hi++;
     softime++;
   }
     if (toggle_hi & 0x10)
     {
        output_low(PIN_A3);        // Toggle on-board LED.
     }
     if (!(toggle_hi & 0x10))
     {
        output_high(PIN_A3);
     }
   
}


main()
{
   byte ch, i, temp;
   byte ebyte;
   long page;
   filenum=0;
   SET_RTCC(0);   
   setup_timer_1(T1_INTERNAL);          //Free-running.
   setup_timer_2(T2_DIV_BY_1, 0x1F, 1); //Not really used.
   
   
   SETUP_CCP1(CCP_OFF);
   SETUP_CCP2(CCP_OFF);
//   SETUP_COUNTERS(RTCC_INTERNAL, WDT_18MS);
   SETUP_COUNTERS(RTCC_INTERNAL, RTCC_DIV_2);
   SETUP_PORT_A(NO_ANALOGS);
   SET_TRIS_A(0x10);                    //Port A0-A3, A5-A7=outputs,
                                        //Port A4=input.
   SET_TRIS_B(0x00);                    //Port B0-B7=outputs.
   ENABLE_INTERRUPTS(RTCC_ZERO);
//   ENABLE_INTERRUPTS(INT_TIMER1);
   SETUP_TIMER_1(T1_INTERNAL | T1_DIV_BY_8);
   SET_TIMER1(0x3F);
   ENABLE_INTERRUPTS(GLOBAL);
   PORTB=0;
   pflag=0;
   putc(XON);
   printf ("\r\n T2Kv2 \r\n");
top:
   printf ("\r\nS=Status, X=Xmodem transfer, H=Hexdump, P=Play.\r\n");
   printf ("C=Clear all, D=Directory.\r\n\r\n>");
   ch=getc();
   if ((ch=='S') || (ch=='s'))
   {
      printf ("\r\nreading Status...\r\n");
      ebyte = read_AT45_stat();     
      printf ("\r\nStatus=");
      if (ebyte & 0x80) putc (0x31);
      if (!(ebyte & 0x80)) putc (0x30);
      if (ebyte & 0x40) putc (0x31);
      if (!(ebyte & 0x40)) putc (0x30);
      if (ebyte & 0x20) putc (0x31);
      if (!(ebyte & 0x20)) putc (0x30);
      if (ebyte & 0x10) putc (0x31);
      if (!(ebyte & 0x10)) putc (0x30);
      putc (0x020);
      if (ebyte & 0x08) putc (0x31);
      if (!(ebyte & 0x08)) putc (0x30);
      if (ebyte & 0x04) putc (0x31);
      if (!(ebyte & 0x04)) putc (0x30);
      if (ebyte & 0x02) putc (0x31);
      if (!(ebyte & 0x02)) putc (0x30);
      if (ebyte & 0x01) putc (0x31);
      if (!(ebyte & 0x01)) putc (0x30);
   }

   if ((ch=='X') || (ch=='x'))
   { 
      ch=0;
      read_AT45_stream64(0, 0);
      output_high(EEPROM_SELECT);
      file_end=0;
      for (filenum=0; filenum < 7; filenum++)
      {
        i=filenum*4;
        file_start = rambuf1[i];
        file_start <<= 8;
        file_start |= rambuf1[i+1];
        if (file_start==0) break;
        file_end = rambuf1[i+2];
        file_end <<= 8;
        file_end |= rambuf1[i+3];
      }
      file_start = file_end + 1;
      if (filenum>=6) break;
      i = 4 * filenum;
      printf ("\r\nStart xmodem file %d transfer now...\r\n", filenum);
      ebyte=xmodem();
      if (ebyte==0)
      {
         delay_ms(25);
         read_AT45_stream64(0, 0);
         rambuf1[i]=(file_start >> 8);
         rambuf1[i+1]=(file_start & 0xFF);
         rambuf1[i+2]=(file_end >> 8);
         rambuf1[i+3]=(file_end & 0xFF);
         delay_ms(25);
         write_AT45_stream128(0, 0);
         output_high(EEPROM_SELECT);
         printf ("\r\nTransfer Complete!\r\n");
      }
      if (ebyte==1) printf ("\r\nTransfer Failed!\r\n");
   }

   if ((ch=='H') || (ch=='h')) hexdump();

   if ((ch=='C') || (ch=='c'))
   {
     clr_all_ptrs();
     printf ("\r\nDone.\r\n");
   }

   if ((ch=='D') || (ch=='d')) dir();

   if ((ch=='P') || (ch=='p'))             // PLAY loop is here.
   {
      ch=0;
      while ((ch < 0x30) || (ch > 0x35))
      {
        printf ("\r\nPick a file number to play (0-5):\r\n");
        ch=getc();
      }
      i=ch-0x30;
      i=4*i;
      disable_interrupts(global);
      read_AT45_stream64(0,0);        //Get directory.
      file_start=rambuf1[i];
      file_start <<= 8;
      file_start |= rambuf1[i+1];
      file_end=rambuf1[i+2];
      file_end <<= 8;
      file_end |= rambuf1[i+3];
      page=file_start;
      if (page==0) break;             //If no sample saved, quit.
      temp=0;
      sptr=0;
      read_AT45_stream64(page,temp);  //Pre-fill rambuf1[]
      temp=1;
      read_AT45_stream64(page,temp);  //Pre-fill rambuf2[]
      sflag=1;
      pflag=1;
      enable_interrupts(global);

      while ((kbhit()==FALSE) && (page <= file_end))
      {
         if (sflag==0)
         {
            temp++;
            temp &= 0x03;
            if ((temp & 0x03)==0) page++;
            read_AT45_stream64(page,temp); // Keep buffer loaded with samples.
            sflag=1;
         }
      }
      pflag=0;
   }
   output_low(PIN_A5);     //o-scope diagnostic
   output_high(PIN_A5);
   goto top;
}


// Read AT45DB041B status byte.  By RPL.

byte read_AT45_stat() {

   byte cmd;
   byte i,data;

   cmd=0xD7;

   output_low(EEPROM_SELECT);
   for(i=8;i>0;i--)
   {
      output_bit(EEPROM_DI, shift_left(&cmd,1,0));
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);
   }
   for(i=8;i>0;i--)
   {
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);       
      shift_left(&data,1,input(EEPROM_DO));
   }
   output_high(EEPROM_SELECT);
   return(data);
}

// Main mem page 128-byte write thru buffer #1 on AT45DB041B chip. By RPL.
// Call with page address (=0-2047) and addr2 (=0 or 1).  If addr2==0,
// data is written from rambuf1[] & rambuf2[] to the 1st (128) bytes
// of selected page, but the chip select is not raised at the end, so
// the write operation is not completed.  When addr2==1, data is
// written to 2nd (128) bytes of selected page, followed by raising
// the chip select to finish the operation.  Warning: Don't do any other
// chip operations after a call with addr2==0.  That operation doesn't
// end until a call with addr2==1.

void write_AT45_stream128(long page, byte addr2)
{

   byte cmd;
   byte i, j;

   cmd=0x82;

   output_low(EEPROM_SELECT);
   
   if (addr2==0)
   {
     for(i=8;i>0;i--)            // Write command = 0x82 to mem chip.
     {
        output_bit(EEPROM_DI, shift_left(&cmd,1,0));
        output_high(EEPROM_CLK);
        output_low(EEPROM_CLK);
     }
     for(i=4;i>0;i--)            // Load (4) "0" (reserved) page bits.
     {
        output_bit(EEPROM_DI, 0);
        output_high(EEPROM_CLK);
        output_low(EEPROM_CLK);
     }
     for(i=5;i>0;i--)            // Line up page bit P10
     {
        shift_left(&page,2,0);
     }
     for(i=12;i>0;i--)           // Load page bits P10-P0 & byte addr
                                 // bit B8. Note B8=0.
     {
        output_bit(EEPROM_DI, shift_left(&page,2,0));
        output_high(EEPROM_CLK);
        output_low(EEPROM_CLK);
     }
     for(i=8;i>0;i--)              // Load byte addr bits B7-B0=0.
     {
        output_bit(EEPROM_DI, 0);
        output_high(EEPROM_CLK);
        output_low(EEPROM_CLK);   
     }
   }
   
   for(j=0;j<64;j++)       // Write 64 bytes of rambuf1[] to mem. chip.
   {
      cmd=rambuf1[j];
      for(i=8;i>0;i--)
      {
        output_bit(EEPROM_DI, shift_left(&cmd,1,0));
        output_high(EEPROM_CLK);
        output_low(EEPROM_CLK);
      }
   }
   for(j=0;j<64;j++)       // Write 64 bytes of rambuf2[] to mem. chip.
   {
      cmd=rambuf2[j];
      for(i=8;i>0;i--)
      {
        output_bit(EEPROM_DI, shift_left(&cmd,1,0));
        output_high(EEPROM_CLK);
        output_low(EEPROM_CLK);
      }
   }
   if (addr2 !=0) output_high(EEPROM_SELECT);
   return;
}
// Continuous 128-byte array read from AT45DB041B chip. By RPL.
// Call with page address (0-2047) and addr2 (0 or 1).  If addr2==0,
// data is read from the 1st (128) bytes of page and written into
// rambuff1[] & rambuff2[]. If addr2 != 0, data is read from 2nd (128)
// bytes of selected page...

void read_AT45_stream128(long page, byte addr2)
{
   byte cmd;
   byte i, j;

   cmd=0x68;

   output_low(EEPROM_SELECT);
   for(i=8;i!=0;i--)            // Send command to mem chip.
   {
      output_bit(EEPROM_DI, shift_left(&cmd,1,0));
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);
   }
   cmd=0;
   for(i=4;i!=0;i--)            // Load (4) "0" (reserved) page bits.
   {
      output_bit(EEPROM_DI, 0);
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);
   }
   for(i=5;i!=0;i--)            // Line up page bit P10
   {
      shift_left(&page,2,0);
   }
   for(i=12;i!=0;i--)            // Load page bits P10-P0 & byte addr
                                // bit B8. Note B8=0.
   {
      output_bit(EEPROM_DI, shift_left(&page,2,0));
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);
   }
   cmd=0;
   if (addr2 !=0) cmd = 0x80;
   for(i=8;i!=0;i--)              // Load byte addr bits B7-B0.
   {
      output_bit(EEPROM_DI, shift_left(&cmd,1,0));
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);   
   }
   cmd=0;
   for(i=32;i!=0;i--)              // Load (32) "don't care" bits.
   {
      output_bit(EEPROM_DI, 0);
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);   
   }
   for(j=0;j<64;j++)             // Read 64 bytes into rambuf1[].
   {
      for(i=8;i!=0;i--)
      {
        output_high(EEPROM_CLK);
        output_low(EEPROM_CLK);       
        shift_left(&rambuf1[j],1,input(EEPROM_DO));
      }
   }
   for(j=0;j<64;j++)             // Read 64 bytes into rambuf2[].
   {
      for(i=8;i!=0;i--)
      {
        output_high(EEPROM_CLK);
        output_low(EEPROM_CLK);       
        shift_left(&rambuf2[j],1,input(EEPROM_DO));
      }
   }
   output_high(EEPROM_SELECT);
   return;
}

// Continuous 64-byte array read from AT45DB041B chip. By RPL.
// Call with page address (0-2047) and addr2.  If if lo nibble of
// addr2==0, data is read from the 1st (64) bytes of page into rambuf1[].
// If lo nib of addr2==1, data is read from 2nd (64) bytes of page into
// rambuf2[]. If lo nib==2, data read from 3rd (64) bytes of page into
// rambuf1[].  If lo nib==3, data from 4th (64) bytes of page into
// rambuf2[]. If addr2 has hi bit set, data is read into rambuf2[]...

void read_AT45_stream64(long page, byte addr2)
{
   byte cmd;
   byte i, j;

   cmd=0x68;

   output_low(EEPROM_SELECT);
   for(i=8;i!=0;i--)            // Send command to mem chip.
   {
      output_bit(EEPROM_DI, shift_left(&cmd,1,0));
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);
   }
   output_bit(EEPROM_DI, 0);   
   for(i=4;i!=0;i--)            // Load (4) "0" (reserved) page bits.
   {
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);
   }
   for(i=5;i!=0;i--)            // Line up page bit P10
   {
      shift_left(&page,2,0);
   }
   for(i=12;i!=0;i--)            // Load page bits P10-P0 & byte addr
                                // bit B8. Note B8=0.
   {
      output_bit(EEPROM_DI, shift_left(&page,2,0));
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);
   }

   if ((addr2 & 0x0f)==0) cmd=0;
   if ((addr2 & 0x0f)==1) cmd=0x40;
   if ((addr2 & 0x0f)==2) cmd=0x80;
   if ((addr2 & 0x0f)==3) cmd=0xC0;

   for(i=8;i!=0;i--)              // Load byte addr bits B7-B0.
   {
      output_bit(EEPROM_DI, shift_left(&cmd,1,0));
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);   
   }
   output_bit(EEPROM_DI, 0);
   for(i=32;i!=0;i--)              // Load (32) "don't care" bits.
   {
      output_high(EEPROM_CLK);
      output_low(EEPROM_CLK);   
   }
   if ((addr2==0)||(addr2==2))     // Use rambuf1[]?
   {
     for(j=0;j<64;j++)             // Read 64 bytes into rambuf1[].
     {
        for(i=8;i!=0;i--)
        {
          output_high(EEPROM_CLK);
          output_low(EEPROM_CLK);       
          shift_left(&rambuf1[j],1,input(EEPROM_DO));
        }
     }
   }
   if ((addr2==1)||(addr2==3))     // Use rambuf2[]?
   {
     for(j=0;j<64;j++)             // Read 64 bytes into rambuf2[].
     {
        for(i=8;i!=0;i--)
        {
          output_high(EEPROM_CLK);
          output_low(EEPROM_CLK);       
          shift_left(&rambuf2[j],1,input(EEPROM_DO));
        }
     }
   }
   output_high(EEPROM_SELECT);
}



// This subroutine runs the upload (receive) part of the xmodem protocol...

byte xmodem()
{
   byte i, j, k, seq, csum;
   long page;
   seq=0;
   k=0;
   csum=0;
   softime=0;
   page=file_start;
   putc(NAK);               //Initiate communication by sending NAKs.
   while (kbhit()==FALSE)
   {
     if (softime >= 0xf0)
     {
       softime=0;
       putc(NAK);
     }
   }
   while(1)
   {
      i=getc();
      while (i!=SOH)
      {
         i=getc();
         if (i==EOT)
         {
            putc(ACK);       //ACK the EOT. Transfer complete.
            putc(ACK);
            output_high(EEPROM_SELECT); // In case last packet was even #.
            file_end=page;
            return(0);
         }
         if (i==CAN) return(1);
      }
      seq=getc(); //Get packet sequence #.
      seq=getc(); //Get complemented packet sequence #.
      for (i=0;i<128;i++)
      {
         j=getc();
         if (i<64)  rambuf1[i]=j;
         if (i>=64) rambuf2[i-64]=j;
      }
      csum=getc();     //Get checksum.
      write_AT45_stream128(page, k);
      delay_ms(25);
      k++;
      k &= 0x01;     
      if (k==0) page++;
      putc(ACK);       //ACK the packet.
   }
   return(1);
}


void hexdump()
{
   long page;
   byte addr2, i, j, k, m, ch;
   page=0;
   addr2=0;
   putc(0x0d);
   putc(0x0a);
   k=0;
   ch=0;
   while ((ch != 'Q') && (ch != 'q'))
   {
     read_AT45_stream128(page, addr2);
     j=0;
     while (j < 8)
     {
       m=k;
       if (addr2 != 0) m=k+0x80;
       printf ("%4lx-%2x", page, m);   
       putc(':');
       for(i=0;i<16;i++)  // Display in hex.
       {
          ch=rambuf1[k];
          if (j >=4) ch=rambuf2[k-64];
          ch >>= 4;
          ch &= 0x0f;
          putc(hexlist[ch]);
          ch=rambuf1[k];
          if (j >=4) ch=rambuf2[k-64];
          ch &= 0x0f;
          putc(hexlist[ch]);
          putc(0x20);
          if (i==7) putc(0x20);
          k++;
       }
       for(i=0;i<5;i++) putc(0x20);
       k-=16;
       for(i=0;i<16;i++)   // Display in ASCII.
       {
          ch=rambuf1[k];
          if (j >=4) ch=rambuf2[k-64];
          if (ch < 0x20) ch='.';
          if (ch > 0x7e) ch='.';
          putc(ch);
          k++;
       }
       putc(0x0d);
       putc(0x0a);
       j++;
     }
     printf ("\n\r\M=More, N=skip 100 pages, S=Skip 10 pages, Q=Quit:\r\n");
     ch=getc();
     k=0;
     addr2++;
     addr2 &= 0x01;
     if (addr2==0) page++;
     if ((ch=='N') || (ch=='n'))
     {
        page+=100;
        addr2=0;
     }
     if ((ch=='S') || (ch=='s'))
     {
        page+=10;
        addr2=0;
     }
   }
}

// This subroutine clears the 1st page of the AT45DB041B chip.
// The 1st page is used in this app to hold file pointers & file info.

void clr_all_ptrs()
{
   byte i;
   long j;
   for (i=0; i < 64; i++)
   {
     rambuf1[i]=0;
     rambuf2[i]=0;
   }
   write_AT45_stream128(0, 0);   // Clear page 0 (the directory).
   write_AT45_stream128(0, 1);
   delay_ms(25);

//   for (j=0; j<2048; j++)
//   {
//     write_AT45_stream128(j, 0);
//     write_AT45_stream128(j, 1);
//     delay_ms(25);
//   }

}


// This function displays a simple directory listing.

void dir()
{
   byte i, k;
   read_AT45_stream128(0, 0);
   for (i=0; i<6; i++)
   {
     k=4*i;
     printf ("\r\nFile %d: Start page %2x%2x", i, rambuf1[k], rambuf1[k+1]);
     printf ("   End page %2x%2x", rambuf1[k+2], rambuf1[k+3]);
   }
}


Last edited by yerpa on Sun Jan 21, 2007 12:34 pm; edited 1 time in total
Jackson.Calixto



Joined: 11 May 2007
Posts: 1

View user's profile Send private message

TONE2002 board
PostPosted: Fri May 11, 2007 6:25 am     Reply with quote

Do you have the schema for this board?

Thank's
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group