First addition of dsPIC33F/PIC24H chip family programmer!
[goodfet] / firmware / lib / command.c
index f585e4c..1de6f0a 100644 (file)
+/*! \file command.c
+  \author Travis Goodspeed
+  \brief These functions manage command interpretation.
+*/
+
 #include "command.h"
 #include "platform.h"
 #include <string.h>
 
-//! Different command handling functions.
-
-unsigned char cmddata[256];
+unsigned char cmddata[CMDDATALEN];
+unsigned char silent=0;
 
 //! Transmit a string.
 void txstring(unsigned char app,
              unsigned char verb,
              const char *str){
-  unsigned char len=strlen(str);
-  serial_tx(app);
-  serial_tx(verb);
-  serial_tx(len);
+  unsigned long len=strlen(str);
+  txhead(app,verb,len);
   while(len--)
     serial_tx(*(str++));
 }
 
+/*! \brief Transmit a debug string.
+  
+  Transmits a debugging string that is to be printed
+  out of line by the client.  This is just for record-keeping;
+  it is not considered a proper reply to a query.
+ */
+void debugstr(const char *str){
+  txstring(0xFF,0xFF,str);
+}
+
+//! brief Debug a hex word string.
+void debughex(u16 v) {
+  unsigned char a[7];
+  a[0]='0'; a[1]='x';
+    
+  a[2]=0xf&(v>>12);
+  a[2]+=(a[2]>9)?('a'-10):'0';
+
+  a[3]=0xf&(v>>8);
+  a[3]+=(a[3]>9)?('a'-10):'0';
+
+  a[4]=0xf&(v>>4);
+  a[4]+=(a[4]>9)?('a'-10):'0';
+
+  a[5]=0xf&(v>>0);
+  a[5]+=(a[5]>9)?('a'-10):'0';
+
+  a[6]=0;
+
+  txstring(0xFF,0xFF,a);
+}
+
+/*! \brief Transmit debug bytes.
+  
+  Transmits bytes for debugging.
+*/
+void debugbytes(const char *bytes, unsigned int len){
+  u16 i;
+  txhead(0xFF,0xFE,len);
+  for(i=0;i<len;i++)
+    serial_tx(bytes[i]);
+}
+
+
+//! Transmit a header.
+void txhead(unsigned char app,
+           unsigned char verb,
+           unsigned long len){
+  serial_tx(app);
+  serial_tx(verb);
+  //serial_tx(len); //old protocol
+  txword(len);
+}
+
 //! Transmit data.
 void txdata(unsigned char app,
            unsigned char verb,
-           unsigned char len){
+           unsigned long len){
   unsigned int i=0;
-  serial_tx(app);
-  serial_tx(verb);
-  serial_tx(len);
+  if(silent)
+    return;
+  txhead(app,verb,len);
   for(i=0;i<len;i++){
     serial_tx(cmddata[i]);
   }
 }
 
+//! Receive a long.
+unsigned long rxlong(){
+  unsigned long toret=0;
+  toret=serial_rx();
+  toret|=(((long)serial_rx())<<8);
+  toret|=(((long)serial_rx())<<16);
+  toret|=(((long)serial_rx())<<24);
+  return toret;
+}
+//! Receive a word.
+unsigned int rxword(){
+  unsigned long toret=0;
+  toret=serial_rx();
+  toret|=(((long)serial_rx())<<8);
+  return toret;
+}
+//! Transmit a long.
+void txlong(unsigned long l){
+  serial_tx(l&0xFF);
+  l>>=8;
+  serial_tx(l&0xFF);
+  l>>=8;
+  serial_tx(l&0xFF);
+  l>>=8;
+  serial_tx(l&0xFF);
+  l>>=8;
+}
+//! Transmit a word.
+void txword(unsigned int l){
+  serial_tx(l&0xFF);
+  l>>=8;
+  serial_tx(l&0xFF);
+  l>>=8;
+}
+
+//Be very careful changing delay().
+//It was chosen poorly by trial and error.
+
 //! Delay for a count.
 void delay(unsigned int count){
   volatile unsigned int i=count;
@@ -46,3 +140,57 @@ void msdelay(unsigned int ms){
   }
   //Using TimerA might be cleaner.
 }
+
+
+/* To better satisfy the somewhat odd timing requirements for
+   dsPIC33F/PIC24H ICSP programming, and for better control of GoodFET
+   timing more generally, here are a few delay routines that use Timer A.
+
+   Note that I wrote these referring only to the MSP430x2xx family
+   manual. Beware on MSP430x1xx chips. Further note that, assuming
+   some minor errors will be made, I try to err on the side of
+   delaying slightly longer than requested. */
+void prep_timer()
+{
+       BCSCTL2 = 0x00; /* In particular, use DCOCLK as SMCLK source with
+                                          divider 1. Hence, Timer A ticks with system
+                                          clock at 16 MHz. */
+
+       TACTL = 0x0204; /* Driven by SMCLK; disable Timer A interrupts;
+                                          reset timer in case it was previously in use */
+}
+
+//! Delay for specified number of milliseconds (given 16 MHz clock)
+void delay_ms( unsigned int ms )
+{
+       // 16000 ticks = 1 ms
+       TACTL |= 0x20; // Start timer!
+       while (ms--) {
+               while (TAR < 16000)
+                       asm( "nop" );
+               TACTL = 0x0224;
+       }
+       TACTL = 0x0204; // Reset Timer A, till next time
+}
+
+//! Delay for specified number of microseconds (given 16 MHz clock)
+void delay_us( unsigned int us )
+{
+       // 16 ticks = 1 us
+       TACTL |= 0x20; // Start timer!
+       while (us--) {
+               while (TAR < 16)
+                       asm( "nop" );
+               TACTL = 0x0224;
+       }
+       TACTL = 0x0204; // Reset Timer A, till next time
+}
+
+//! Delay for specified number of clock ticks (16 MHz clock implies 62.5 ns per tick).
+void delay_ticks( unsigned int num_ticks )
+{
+       TACTL |= 0x20; // Start timer
+       while (TAR < num_ticks)
+               asm( "nop" );
+       TACTL = 0x0204; // Reset Timer A, till next time
+}