Firmware for Nucleo boards for the SLab system Description at http://r6500.blogspot.com.es/2018/02/slab-first-release.html All associated files at https://github.com/R6500/SLab

Dependencies:   mbed

Revision:
0:39a545e08ccd
Child:
1:d81bef65eece
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Feb 10 09:43:16 2018 +0000
@@ -0,0 +1,2244 @@
+/*******************************************************
+
+  SLab - Python 
+  
+  MBED Firmware for Nucleo Boards
+  Alternate version for profiling
+  
+  Program to operate a nucleo board from a PC
+  in order to perform measurements.
+  
+  Desgined for the Nucleo64 F303RE Board
+
+  Commands implemented in version 1
+  
+  Global
+  
+  F     : Obtain a string that describes the firmware
+  M     : Obtain 4 byte magic code
+  I     : Board capabilities identification
+  L     : Pin list
+  E     : Soft Reset
+  
+  DC
+  
+  A + 1 : Read one ADC channel
+  D + 3 : Write one DAC channel
+  N + 2 : Set number of reads to average
+
+  
+  Transient
+  
+  R + 2 : Set sample time
+  S + 4 : Set storage configuration
+  Y     : Async read
+  G + 3 : Triggered read
+  P + 2 : Step response
+  
+  Wavetable
+  
+  W + n : Load a wavetable
+  w + n : Load a secondary wavetable
+  V + 2 : Wave response
+  v + 2 : Dual wave response
+  X + 3 : Single Wave Response
+  Q + 2 : Wave Play
+  q + 2 : Dual Wave Play
+    
+  Digital I/O
+  
+  H + 2 : dio mode
+  J + 2 : dio write
+  K + 1 : dio read  
+     
+Incidences:
+
+  06/04/2017 : Open Drain does not work as expected
+               It is currently disabled    
+               
+  25/10/2017 : v1.1
+               Hardware profile lines added
+               Improved timings. Minimum sample times:
+                 Asyn Read: 1CH (13us) 2CH (33us)  3CH (43us) 4CH (54us)
+                 Trig Read: 1CH (13us) 2CH (33us)  3CH (44us) 4CH (54us)
+                 Step Resp: 1CH (13us) 2CH (36us)  3CH (46us) 4CH (56us)
+                 Wave Resp: 1CH (13us) 2CH (38us)  3CH (47us) 4CH (58us)
+                 Dual Wave: 1CH (13us) 2CH (40us)  3CH (50us) 4CH (61us)
+                 Sing Wave: 1CH Only (13us)   
+                 Wave play: No ADC (11us)  
+                 Dual wave play: No ADC (11us)      
+     
+********************************************************/
+
+#include "mbed.h"
+
+/***************** MAIN DEFINES *************************************/
+
+// Version string
+#define VSTRING " v1.1"
+
+// Major number version changes when new commands are added
+#define VERSION 1
+
+// Uncomment to use hardware profiling during tests
+// It should be commented for release versions
+//#define USE_PROFILING 1
+
+// Information about the board
+#include "Nucleo64-F303RE.h"  // Board 1
+//#include "Nucleo32-F303K8.h"  // Board 2
+//#include "Nucleo64-L152RE.h"  // Board 3
+
+/******************* OTHER CONSTANTS ******************************/
+
+// Max value in unsigned 16bit as float number
+#define MAX16F 65536.0f 
+
+// Special serial codes
+#define ACK  181
+#define NACK 226
+#define ECRC 37
+
+// Codes for transient responses
+#define TRAN_OK       0  // Ok
+#define TRAN_OVERRUN  1  // Sample overrun
+#define TRAN_TIMEOUT  2  // Triggered timeout
+
+// Magic data is different for each firmware
+#define MAGIC_SIZE 4
+const uint8_t magic[MAGIC_SIZE]={56,41,18,1};
+
+/***************** VARIABLES AND OBJECTS *************************/
+
+Serial pc(SERIAL_TX, SERIAL_RX, 38400);   // Serial link with PC
+
+AnalogIn   ain1(AD1);
+AnalogIn   ain2(AD2);
+AnalogIn   ain3(AD3);
+AnalogIn   ain4(AD4);
+
+AnalogIn   *ainList[NADCS];
+
+AnalogOut  aout1(DA1);   // DAC1
+AnalogOut  aout2(DA2);   // DAC2 
+#ifdef EXIST_DAC3
+AnalogOut  aout3(DA3);   // DAC3 if exists
+#endif 
+
+#ifdef EXIST_DIO  // For now, it requires 8 DIO
+DigitalInOut dio1(DIO1);
+DigitalInOut dio2(DIO2);
+DigitalInOut dio3(DIO3);
+DigitalInOut dio4(DIO4);
+DigitalInOut dio5(DIO5);
+DigitalInOut dio6(DIO6);
+DigitalInOut dio7(DIO7);
+DigitalInOut dio8(DIO8);
+
+DigitalInOut *dioList[NDIO];
+#endif
+
+// Sample time period defaults to 1ms
+float stime = 0.001;
+
+// Buffer for storage of inputs (in U16)
+//uint16_t inBuff[IN_BSIZE];
+
+// Wavetable buffer (in U16)
+//uint16_t waveBuff[WSIZE];
+
+// Unified memory buffer
+uint16_t buff[BSIZE];
+
+// Start of all buffer sections
+uint16_t *wave2buff = NULL;
+uint16_t *tranBuff  = NULL;
+
+// DC analog read number of readings
+int nread = 10;
+
+// Input configuration
+int n_ai = 1;     // Number of analog inputs
+int n_di = 0;     // Number of digital inputs (always zero)
+int n_s  = 1000;  // Number of samples
+
+// Ticker for readings
+Ticker ticR;
+
+// Sample information for ticker
+int samples = 0;    // Number of processed samples
+int inBuffPos = 0;  // Current buffer position
+
+int presamples;     // Number of samples before trigger
+int postsamples;    // Number of samples after trigger
+int triggerSample;  // Sample number at trigger point
+int samplePhase;    // Sample phase
+int currentBsize;   // Current buffer size
+int trigger;        // Trigger value
+int triggerMode;    // Trigger mode (0 Rise 1 Fall)
+int stepValue;      // Value for step analysis
+
+int checkTimeOut;   // Indicates if we check timeout
+uint32_t timeOut;   // Timeout for triggered capture
+
+// Global to communicate with ISR ticker
+volatile int endTicker = 0;
+
+// Global to check overruns
+volatile int overrun = 0;
+volatile int overrun_error = 0;
+volatile int timeout_error = 0;
+
+int w_s = 0;             // Wavetable size (in samples)
+volatile int w_n = 10;   // Number of waves before measurement
+volatile int w_pos = 0;  // Current wave position
+
+int w_s2 = 0;            // Secondary wavetable size (in samples)
+volatile int w_pos2 = 0; // Current secondary wave position
+
+// Globals for CRC
+int crcTx,crcRx;
+
+// Selected ADC for transient
+AnalogIn *ain_tran;
+
+// Indicate that board status is at reset condition
+int resetState=1;
+
+/****************** HARDWARE PROFILING *********************************/
+// Uses GPIO lines to show system activity
+
+#ifdef USE_PROFILING
+
+// Profiling outputs
+DigitalOut pro1(PRO1_PIN);
+DigitalOut pro2(PRO2_PIN);
+
+#else
+
+#define PRO1_SET    /* No code */
+#define PRO1_CLEAR  /* No code */
+#define PRO2_SET    /* No code */
+#define PRO2_CLEAR  /* No code */ 
+
+#endif //USE_PROFILING
+
+/*********************** SERIAL CODE **********************************/
+
+// Start Tx
+// Clears the tx crc
+void startTx()
+ {
+ crcTx = 0;
+ }
+ 
+// Send Tx CRC
+// Usually that ends transmission
+void sendCRC()
+ {
+ pc.putc(crcTx);
+ }     
+ 
+// Send one byte and computes crc
+void sendByte(int value)
+ {
+ pc.putc(value);
+ crcTx = crcTx ^ value;    
+ }    
+ 
+// Send one uint16 and computes crc
+void sendU16(int value)
+ {
+ int low,high;    
+ 
+ high = value / 256;
+ low  = value % 256;
+      
+ sendByte(low);
+ sendByte(high);    
+ }    
+      
+// Send float as mantisa and exponent
+void sendMantExp(int mantissa, int exponent)
+ {
+ sendByte(exponent+128);
+ sendU16(mantissa+20000);    
+ }     
+      
+// Send one string and computes crc
+void sendString(char *str)
+ {
+ while (*str)
+    {
+    sendByte(*str); 
+    str++;
+    }
+ }          
+
+// Start of a Rx reception
+void startRx()
+ { 
+ crcRx = 0;
+ }    
+ 
+ 
+// Get CRC anc check it
+// It usually ends the Rx reception
+// Returns 1 if CRC is ok, 0 if not
+int getAndCheckCRC()
+ {
+ int crc;
+ 
+ crc = pc.getc();
+ if (crc != crcRx) return 0;
+ return 1;
+ }
+ 
+// Get and check CRC and sends ECRC in case of error
+// If no error, don't respond anything
+// Returns 1 if CRC is ok, 0 if not
+int crcResponse()
+ {
+ // Check if CRC is ok    
+ if (getAndCheckCRC()) return 1;
+ 
+ // If CRC is not ok
+ sendByte(ECRC);  
+ // End transmission
+ sendCRC();
+ return 0;    
+ }    
+
+   
+// Get one byte and computes crc
+int getByte()
+ {
+ int byte;
+ 
+ byte = pc.getc();
+ crcRx = crcRx ^byte;
+ return byte;   
+ }
+
+    
+// Get one uint16 and computes crc
+int getU16()
+ {
+ int low, high, value;
+ 
+ low  = getByte();
+ high = getByte();
+ value = (256 * high) + low;
+ 
+ return value;   
+ }   
+
+
+// Get one float value and computes crc
+float getFloat()
+ {
+ int exp,mant;
+ float value; 
+ 
+ exp = getByte() - 128;
+ mant = getU16() - 20000;
+ 
+ value = ((float)mant) * pow((float)10.0,(float)exp);
+ 
+ return value;    
+ }
+   
+/*********************** DC CODE ********************************/
+
+// Reads one analog line 1...
+// Discards the first reading
+// Uses the indicated number of readings
+static int analogRead(int line)
+ {
+ int i,value;    
+ uint32_t sum;
+ 
+ sum = 0;
+ for(i=0;i<=nread;i++) 
+    {
+    value=ainList[line-1]->read_u16();
+    if (i) sum+=value;
+    }    
+    
+ value = sum/nread;   
+      
+ return value;     
+ }    
+ 
+/********************* TRANSIENT CODE ***************************/ 
+ 
+// Calculates available transize
+static inline uint16_t tranBuffSize()
+ {
+ uint16_t size;
+ 
+ size = BSIZE - w_s - w_s2;   
+ return size;  
+ }  
+ 
+// Calculates available wave 2 buff size
+static inline uint16_t wave2buffSize()
+ {
+ uint16_t size;
+ 
+ size = BSIZE - w_s;   
+ return size;  
+ }   
+ 
+// Implements command 'R'
+// Sets the sample period time
+void setSampleTime()
+ {
+ //Get sample time
+ stime = getFloat();
+ 
+ // End of message, check CRC
+ if (!crcResponse()) return;
+ 
+ // Check limits
+ if ((stime < MIN_STIME) || (stime > MAX_STIME))
+      sendByte(NACK);
+      else
+      sendByte(ACK);
+      
+ // End of message
+ sendCRC();     
+ }    
+
+// Implements command 'S'
+// Configure storage
+void setStorage()
+ {
+ int sample_size,size; 
+ int error = 0;   
+          
+ // Get number of analog inputs
+ n_ai = getByte();
+ if (n_ai > 4) error = 1;
+ 
+ // Get number of digital inputs
+ // Not implemented yet
+ n_di = getByte();
+ if (n_di != 0) error = 1;
+ 
+ // Get the number of samples
+ n_s = getU16();
+ 
+ // End of message, check CRC
+ if (!crcResponse()) return; 
+ 
+ // Check if it fits the buffer
+ if (n_di)
+    sample_size = n_ai+1;
+    else
+    sample_size = n_ai;
+    
+ size = n_s*sample_size;
+ if (size > tranBuffSize()) error = 1;
+ 
+ // Response depending on errors
+ if (error)
+      sendByte(NACK);
+      else
+      sendByte(ACK);
+      
+ // End of message
+ sendCRC();          
+ }    
+
+// Store analog inputs in circular buffer
+static inline int storeAnalog()
+ {
+ int a1; 
+     
+ a1 = ain1.read_u16();  
+  
+ if (n_ai >= 1) tranBuff[inBuffPos++]=a1; 
+ if (n_ai >= 2) tranBuff[inBuffPos++]=ain2.read_u16();
+ if (n_ai >= 3) tranBuff[inBuffPos++]=ain3.read_u16();
+ if (n_ai >= 4) tranBuff[inBuffPos++]=ain4.read_u16();
+ 
+ if (inBuffPos == currentBsize) inBuffPos = 0;
+ 
+ return a1;
+ }    
+
+// Dumps the input buffer on serial
+void dumpInBuffer()
+  {
+  int ia,is;    
+      
+  // Response code
+  if (overrun_error)
+        {
+        sendByte(TRAN_OVERRUN);
+        return;
+        }
+        else
+        sendByte(TRAN_OK);    
+      
+  sendByte(n_ai);  // Number of analog    
+  sendByte(n_di);  // Number of digital (always zero)
+  sendU16(n_s);  // Number of samples
+  
+  for(ia=0;ia<n_ai;ia++)                // For every analog input
+       for(is=0;is<n_s;is++)            // For every sample
+       sendU16(tranBuff[is*n_ai+ia]);     // Send it
+  }   
+  
+// Dumps the input buffer on serial
+// Overrides the nimber of analog channels and sets it to 1
+void dumpInSingleBuffer()
+  {
+  int is;    
+      
+  // Response code
+  if (overrun_error)
+        {
+        sendByte(TRAN_OVERRUN);
+        return;
+        }
+        else
+        sendByte(TRAN_OK);    
+      
+  sendByte(1);  // Number of analog is 1   
+  sendByte(n_di);  // Number of digital (always zero)
+  sendU16(n_s);  // Number of samples
+  
+  for(is=0;is<n_s;is++)         // For every sample
+       sendU16(tranBuff[is]);     // Send it
+  }      
+
+/********************* ASYNC READ ***************************/ 
+
+// Hardware profiling operation (if enabled)
+//   PRO1 line high during ISR
+//   PRO2 line mimics overrun variable
+
+// ISR for the asyncRead function
+void asyncReadISR()
+ {
+ PRO1_SET // Profiling        
+
+ // Store analog data    
+ storeAnalog();    
+ 
+ // Increase sample
+ samples++;
+     
+ // Check if we should end
+ if (samples >= n_s)
+    {
+    // Disable ticker
+    ticR.detach();     
+    // Signal end
+    endTicker = 1;
+    PRO1_CLEAR // Profiling   
+    return;
+    }   
+    
+ // Check for overrun
+ if (overrun)
+    {
+    overrun_error = 1;
+    }
+    
+ overrun = 1;  
+ 
+ PRO2_SET    // Profiling
+ PRO1_CLEAR            
+ }    
+ 
+// ISR for the asyncRead function
+// Optimized timing when only reading one input
+// Used only for one input and stime < 25us
+void asyncReadSingleISR()
+ {
+ PRO1_SET // Profiling    
+  
+ // Direct access to ADC registers 
+ ADC1->CR |= ADC_CR_ADSTART;           
+ while (!(ADC1->ISR & ADC_ISR_EOC));
+ tranBuff[inBuffPos++] = (ADC1->DR)<<4;         
+ 
+ if (inBuffPos == currentBsize) inBuffPos = 0;
+ 
+ // Increase sample
+ samples++;
+     
+ // Check if we should end
+ if (samples >= n_s)
+    {
+    // Disable ticker
+    ticR.detach();     
+    // Signal end
+    endTicker = 1;
+    PRO1_CLEAR // Profiling   
+    return;
+    }   
+    
+ // Check for overrun
+ if (overrun)
+    {
+    overrun_error = 1;
+    }
+ overrun = 1;    
+ 
+ PRO2_SET    // Profiling
+ PRO1_CLEAR         
+ }   
+
+// Implements command 'Y'
+// Async read
+ // This command don't get any parameter
+void asyncRead()
+ {    
+ PRO1_CLEAR  // Reset profiling lines
+ PRO2_CLEAR
+ 
+ // Check of CRC
+ if (!crcResponse()) return; 
+ 
+ // Send ACK to command
+ sendByte(ACK);
+ 
+ // Configure ticker ISR    
+ samples = 0;    // Number of processed samples
+ inBuffPos = 0;  // Current buffer position
+ endTicker = 0;  // Ticker has not ended
+ 
+ currentBsize = n_ai * n_s;        // Current size for buffer
+     
+ // Clear overrun variables
+ overrun_error = 0;
+ overrun = 0;   
+ PRO2_CLEAR   // Profiling     
+     
+ // Check if we only read one channel and stime is less than 41us
+ if ((n_ai==1)&&(stime<25e-6f))
+    {
+    // Perform a dummy read
+    ain1.read_u16();     
+    // Programs the ticker for one input optimized ISR version
+    ticR.attach(&asyncReadSingleISR,stime);   
+    }
+   else     
+    { 
+    // Programs the ticker for several inputs
+    ticR.attach(&asyncReadISR,stime);
+    }
+ 
+ // Wait till end
+ while (!endTicker) { overrun = 0; PRO2_CLEAR }
+ 
+ // Return data
+ dumpInBuffer();  // Dump data
+ 
+ sendCRC(); // End of Tx 
+ }
+ 
+/********************* TRIGGERED READ ***************************/ 
+ 
+// Hardware profiling operation (if enabled)
+//   PRO1 line high during ISR
+//   PRO2 line mimics overrun variable 
+ 
+// Dumps the input buffer on serial for triggered caputure
+void dumpTriggeredInBuffer()
+  {
+  int ia,is,pos,sample,first;    
+      
+  presamples = n_s/2;               // Number of samples before trigger
+  postsamples = n_s - presamples;   // Number of samples after trigger    
+  
+  // Response code
+  if (overrun_error)
+        {
+        sendByte(TRAN_OVERRUN);
+        return;
+        }
+  
+  if (timeout_error)
+        {
+        sendByte(TRAN_TIMEOUT);    
+        return;    
+        }
+  
+  sendByte(TRAN_OK);    
+      
+  sendByte(n_ai);  // Number of analog    
+  sendByte(n_di);  // Number of digital (always zero)
+  sendU16(n_s);    // Number of samples
+  
+  // First sample to send
+  first = (triggerSample - presamples + n_s)%n_s;
+  
+  for(ia=0;ia<n_ai;ia++)                    // For every analog input
+       for(is=0;is<n_s;is++)                // For every sample
+          {
+          sample = (first+is)%n_s;          // Calculate sample
+          pos = sample*n_ai+ia;             // Calculate buff position
+          sendU16(tranBuff[pos]);            // Send it
+          }
+  }     
+ 
+// ISR for the triggeredRead function
+void triggeredReadISR()
+ {
+ int a1;    
+ 
+ PRO1_SET
+     
+ // Store analog data    
+ a1 = storeAnalog();    
+ 
+ // Increase sample
+ samples++;
+ if (samples == n_s) samples = 0;
+ 
+ // Decrease timeout
+ timeOut--;
+ 
+ // Check phase
+ switch(samplePhase)
+    {
+    case 0: // Prefill of the buffer
+      presamples--;
+      if (!presamples) samplePhase = 1;
+      if (!timeOut)
+        {
+        // Set error
+        timeout_error = 1;
+        // Disable ticker
+        ticR.detach();     
+        // Signal end
+        endTicker = 1;
+        }
+      break;
+    case 1: // Wait for trigger precondition
+      if (triggerMode == 0) // Rise
+         if (a1 < trigger) samplePhase = 2;
+      if (triggerMode == 1) // Fall
+         if (a1 > trigger) samplePhase = 2;    
+      if (!timeOut)
+        {
+        // Set error
+        timeout_error = 1;
+        // Disable ticker
+        ticR.detach();     
+        // Signal end
+        endTicker = 1;
+        }   
+      break;  
+    case 2: // Wait for trigger postcondition
+      if (triggerMode == 0) // Rise
+         if (a1 > trigger)
+                     {
+                     samplePhase = 3;
+                     triggerSample = samples;
+                     }
+      if (triggerMode == 1) // Fall
+         if (a1 < trigger)
+                     {
+                     samplePhase = 3;
+                     triggerSample = samples;
+                     }
+      if (!timeOut)
+        {
+        // Set error
+        timeout_error = 1;
+        // Disable ticker
+        ticR.detach();     
+        // Signal end
+        endTicker = 1;
+        }               
+      break;
+    case 3: // Capture after trigger
+      postsamples--;  
+      if (!postsamples) 
+            {
+            // Disable ticker
+            ticR.detach();     
+            // Signal end
+            endTicker = 1;        
+            }
+      break;    
+    } 
+    
+ // Check for overrun
+ if (overrun)
+    overrun_error = 1;
+    
+ overrun = 1;   
+ 
+ PRO2_SET
+ PRO1_CLEAR       
+ }    
+ 
+// ISR for the triggeredRead function
+// Version optimized for only one channel
+// Only used for single channel and stime < 30us
+void triggeredReadSingleISR()
+ {
+ int a1;    
+ 
+ PRO1_SET
+     
+ // Direct access to ADC registers 
+ ADC1->CR |= ADC_CR_ADSTART;           
+ while (!(ADC1->ISR & ADC_ISR_EOC));
+ a1=(ADC1->DR)<<4;
+ tranBuff[inBuffPos++]=a1;  
+ 
+ if (inBuffPos == currentBsize) inBuffPos = 0;   
+ 
+ // Increase sample
+ samples++;
+ if (samples == n_s) samples = 0;
+ 
+ // Decrease timeout
+ timeOut--;
+ 
+ // Check phase
+ switch(samplePhase)
+    {
+    case 0: // Prefill of the buffer
+      presamples--;
+      if (!presamples) samplePhase = 1;
+      if (!timeOut)
+        {
+        // Set error
+        timeout_error = 1;
+        // Disable ticker
+        ticR.detach();     
+        // Signal end
+        endTicker = 1;
+        }
+      break;
+    case 1: // Wait for trigger precondition
+      if (triggerMode == 0) // Rise
+         if (a1 < trigger) samplePhase = 2;
+      if (triggerMode == 1) // Fall
+         if (a1 > trigger) samplePhase = 2;    
+      if (!timeOut)
+        {
+        // Set error
+        timeout_error = 1;
+        // Disable ticker
+        ticR.detach();     
+        // Signal end
+        endTicker = 1;
+        }   
+      break;  
+    case 2: // Wait for trigger postcondition
+      if (triggerMode == 0) // Rise
+         if (a1 > trigger)
+                     {
+                     samplePhase = 3;
+                     triggerSample = samples;
+                     }
+      if (triggerMode == 1) // Fall
+         if (a1 < trigger)
+                     {
+                     samplePhase = 3;
+                     triggerSample = samples;
+                     }
+      if (!timeOut)
+        {
+        // Set error
+        timeout_error = 1;
+        // Disable ticker
+        ticR.detach();     
+        // Signal end
+        endTicker = 1;
+        }               
+      break;
+    case 3: // Capture after trigger
+      postsamples--;  
+      if (!postsamples) 
+            {
+            // Disable ticker
+            ticR.detach();     
+            // Signal end
+            endTicker = 1;        
+            }
+      break;    
+    } 
+    
+ // Check for overrun
+ if (overrun)
+    overrun_error = 1;
+    
+ overrun = 1;   
+ 
+ PRO2_SET
+ PRO1_CLEAR       
+ }   
+ 
+// Implements command 'G'
+// Triggered read
+void triggeredRead()
+ {    
+ PRO1_CLEAR  // Reset profiling lines
+ PRO2_CLEAR
+ 
+ // Get trigger point
+ trigger = getU16();
+ // Get trigger mode
+ triggerMode = getByte();
+ // Get timeout in seconds
+ timeOut = getByte();
+ 
+ if (timeOut)
+    {
+    checkTimeOut=1;
+    // Convert to samples
+    timeOut=int(1.0*timeOut/stime);
+    }
+    else
+    checkTimeOut = 0;
+ 
+ // Erase timeout error
+ timeout_error = 0;
+ 
+ // Check of CRC
+ if (!crcResponse()) return; 
+ 
+ // Check mode
+ if ( (triggerMode != 0) && (triggerMode != 1) )
+    {
+    sendByte(NACK);
+    sendCRC();
+    return;
+    }
+    
+ // All ok
+ sendByte(ACK);   
+ 
+ // Configure ticker ISR    
+ samples = 0;    // Number of processed samples
+ inBuffPos = 0;  // Current buffer position
+ endTicker = 0;  // Ticker has not ended
+ 
+ presamples = n_s/2;               // Number of samples before trigger
+ postsamples = n_s - presamples;   // Number of samples after trigger
+ currentBsize = n_ai * n_s;        // Current size for buffer
+ 
+ samplePhase = 0; // First phase: buffer prefill
+ 
+ // Clear overrun variables
+ overrun_error = 0;
+ overrun = 0;  
+
+ // Check if we only read one channel
+ if ((n_ai==1)&&(stime<30e-6f))
+    {
+    // Perform a dummy read
+    ain1.read_u16();     
+    // Programs the ticker for one input optimized ISR version
+    ticR.attach(&triggeredReadSingleISR,stime);   
+    }
+   else     
+    { 
+    // Programs the ticker for several inputs
+    ticR.attach(&triggeredReadISR,stime);
+    }
+  
+ // Wait till end
+ while (!endTicker) { overrun = 0; PRO2_CLEAR }
+ 
+ // Return data
+ dumpTriggeredInBuffer();  // Dump data
+ 
+ // Send CRC to end Tx
+ sendCRC();
+ }
+
+/********************* STEP RESPONSE ***************************/
+
+// Hardware profiling operation (if enabled)
+//   Not implemented yet
+
+// ISR for the stepResponse function
+void stepResponseISR()
+ {
+ // Store analog data    
+ storeAnalog();    
+ 
+ // Increase sample
+ samples++;
+     
+ // Check trigger position
+ if (samples == triggerSample) aout1 = stepValue / MAX16F;
+     
+ // Check if we should end
+ if (samples >= n_s)
+    {
+    // Disable ticker
+    ticR.detach();     
+    // Signal end
+    endTicker = 1;    
+    }        
+    
+ // Check for overrun
+ if (overrun)
+    overrun_error = 1;
+    
+ overrun = 1;   
+ }    
+
+// ISR for the stepResponse function
+// Time optimized version
+// Only used for one channel and stime < 30us
+void stepResponseSingleISR()
+ {
+ // Direct access to ADC registers 
+ ADC1->CR |= ADC_CR_ADSTART;           
+ while (!(ADC1->ISR & ADC_ISR_EOC));
+ tranBuff[inBuffPos++]=(ADC1->DR)<<4;  
+ 
+ if (inBuffPos == currentBsize) inBuffPos = 0;     
+ 
+ // Increase sample
+ samples++;
+     
+ // Check trigger position
+ if (samples == triggerSample)
+       DAC->DHR12R1 = (stepValue>>4);
+     
+ // Check if we should end
+ if (samples >= n_s)
+    {
+    // Disable ticker
+    ticR.detach();     
+    // Signal end
+    endTicker = 1;    
+    }        
+    
+ // Check for overrun
+ if (overrun)
+    overrun_error = 1;
+    
+ overrun = 1;   
+ }    
+
+// Implements command 'P'
+// Step response
+void stepResponse()
+ {    
+ // Read step value
+ stepValue = getU16();
+ 
+ // Check of CRC
+ if (!crcResponse()) return; 
+ 
+ sendByte(ACK); // All Ok
+ 
+ // Configure ticker ISR    
+ samples = 0;               // Number of processed samples
+ inBuffPos = 0;             // Current buffer position
+ endTicker = 0;            // Ticker has not ended
+ 
+ triggerSample = n_s/5;
+ 
+ currentBsize = n_ai * n_s;        // Current size for buffer
+     
+ // Clear overrun variables
+ overrun_error = 0;
+ overrun = 0;    
+     
+ // Check if we only read one channel
+ if ((n_ai==1)&&(stime<30e-6f))
+    {
+    // Perform a dummy read
+    ain1.read_u16();    
+    // Programs the ticker
+    ticR.attach(&stepResponseSingleISR,stime);
+    }
+    else
+    {     
+    // Programs the ticker
+    ticR.attach(&stepResponseISR,stime);
+    }
+ 
+ // Wait till end
+ while (!endTicker) overrun = 0;
+ 
+ // Return data
+ dumpInBuffer();  // Dump data
+ 
+ // Send CRC to end Tx
+ sendCRC();
+ }
+
+/********************* WAVETABLE CODE ***************************/ 
+
+// Load a wavetable
+void loadWaveTable()
+ {
+ int i;    
+     
+ // Eliminate secondary wavetable
+ w_s2 = 0;    
+     
+ // Get size
+ w_s = getU16();
+ 
+ // Check size
+ if (w_s > BSIZE) 
+    {
+    w_s = 0; // Eliminate table
+    
+    // Calculate new memory configuration
+    wave2buff=&buff[w_s];
+    tranBuff =&buff[w_s];
+ 
+    sendByte(NACK);
+    sendCRC();
+    return;    
+    }
+     
+ // Calculate new memory configuration
+ wave2buff=&buff[w_s];
+ tranBuff =&buff[w_s];
+ 
+ if (w_s > 0) 
+   {
+   // Load samples
+   for(i=0;i<w_s;i++)
+      buff[i] = getU16();
+   }   
+
+ // Check of CRC
+ if (!crcResponse()) return; 
+ 
+ sendByte(ACK);
+    
+ sendCRC();   
+ }
+ 
+// Load a secondary wavetable
+void loadSecondaryWaveTable()
+ {
+ int i;    
+     
+ // Get size
+ w_s2 = getU16();
+ 
+ // Check size and primary wavetable
+ if (w_s2 > wave2buffSize()) 
+    {
+    w_s2 = 0;
+    // Calculate new memory configuration
+    tranBuff =&buff[w_s+w_s2];
+    
+    sendByte(NACK);
+    sendCRC();
+    return;    
+    }
+ 
+ // Calculate new memory configuration
+ tranBuff =&buff[w_s+w_s2];
+ 
+ for(i=0;i<w_s2;i++)
+    wave2buff[i] = getU16();
+
+ // Check of CRC
+ if (!crcResponse()) return; 
+ 
+ sendByte(ACK);
+    
+ sendCRC();   
+ }
+ 
+
+/****************** WAVE RESPONSE CODE *************************/ 
+
+// Hardware profiling operation (if enabled)
+//    Not implemented
+
+// ISR for the waveResponse function
+void waveResponseISR()
+ {
+ // Write DAC
+ aout1 = buff[w_pos++] / MAX16F;    
+     
+ // Store analog data    
+ if (!w_n)
+      {
+      storeAnalog();    
+     
+      // Increase sample
+      samples++;
+     
+      // Check if we should end
+      if (samples >= n_s)
+           {
+           // Disable ticker
+           ticR.detach();     
+           // Signal end
+           endTicker = 1;    
+           } 
+      
+      // Check wave rollover
+      if (w_pos == w_s) w_pos = 0;        
+      }
+     else
+      {
+      // Check wave rollover    
+      if (w_pos == w_s)
+            {
+            w_pos = 0;    
+            w_n--;
+            }
+      }                     
+                 
+ // Check wave rollover
+ // if (w_pos == w_s) w_pos = 0;
+        
+ // Check for overrun
+ if (overrun)
+    overrun_error = 1;
+    
+ overrun = 1;   
+ }    
+
+// ISR for the waveResponse function
+// Time optimized version
+// Only used for single ADC and stime < 30us
+void waveResponseSingleISR()
+ {
+ // Write DAC
+ DAC->DHR12R1 = (buff[w_pos++]>>4);
+     
+ // Store analog data    
+ if (!w_n)
+      {
+      // Direct access to ADC registers 
+      ADC1->CR |= ADC_CR_ADSTART;           
+      while (!(ADC1->ISR & ADC_ISR_EOC));
+      tranBuff[inBuffPos++]=(ADC1->DR)<<4;  
+ 
+      if (inBuffPos == currentBsize) inBuffPos = 0;    
+     
+      // Increase sample
+      samples++;
+     
+      // Check if we should end
+      if (samples >= n_s)
+           {
+           // Disable ticker
+           ticR.detach();     
+           // Signal end
+           endTicker = 1;    
+           } 
+      
+      // Check wave rollover
+      if (w_pos == w_s) w_pos = 0;        
+      }
+     else
+      {
+      // Check wave rollover    
+      if (w_pos == w_s)
+            {
+            w_pos = 0;    
+            w_n--;
+            }
+      }                     
+                 
+ // Check wave rollover
+ // if (w_pos == w_s) w_pos = 0;
+        
+ // Check for overrun
+ if (overrun)
+    overrun_error = 1;
+    
+ overrun = 1;   
+ }    
+
+// Wave response
+void waveResponse()
+ {
+ // Read number of waves before mesurement    
+ w_n = getU16();   
+
+ // Check of CRC
+ if (!crcResponse()) return; 
+ 
+ sendByte(ACK);
+
+ // Configure ticker ISR    
+ samples = 0;               // Number of processed samples
+ inBuffPos = 0;             // Current buffer position
+ endTicker = 0;             // Ticker has not ended
+ w_pos = 0;                 // Current wave position 
+
+ currentBsize = n_ai * n_s;        // Current size for buffer
+ 
+ // Clear overrun variables
+ overrun_error = 0;
+ overrun = 0;
+ 
+ // Check if we only read one channel
+ if ((n_ai==1)&&(stime<30e-6f))
+    {
+    // Perform a dummy read
+    ain1.read_u16();    
+    // Programs the ticker
+    ticR.attach(&waveResponseSingleISR,stime);
+    }
+    else
+    {    
+    // Programs the ticker
+    ticR.attach(&waveResponseISR,stime);
+    }
+   
+ // Wait till end
+ while (!endTicker) overrun = 0;
+ 
+ // Return data
+ dumpInBuffer();  // Dump data  
+ 
+ // End sending CRC
+ sendCRC(); 
+ }    
+
+/*************** DUAL WAVE RESPONSE CODE *************************/ 
+
+// ISR for the dualWaveResponse function
+void dualWaveResponseISR()
+ {
+ // Write DACs
+ aout1 = buff[w_pos++] / MAX16F;    
+ aout2 = wave2buff[w_pos2++] / MAX16F;
+      
+ // Store analog data    
+ if (!w_n)
+      {
+      storeAnalog();    
+     
+      // Increase sample
+      samples++;
+     
+      // Check if we should end
+      if (samples >= n_s)
+           {
+           // Disable ticker
+           ticR.detach();     
+           // Signal end
+           endTicker = 1;    
+           } 
+      
+      // Check wave rollover
+      if (w_pos == w_s)   w_pos = 0;
+      if (w_pos2 == w_s2) w_pos2 = 0;
+      }
+     else
+      {
+      // Check wave rollover    
+      if (w_pos == w_s)
+            {
+            w_pos = 0;    
+            w_n--;
+            }
+      if (w_pos2 == w_s2) w_pos2 = 0;      
+      }                     
+                 
+ // Check wave rollover
+ //if (w_pos == w_s) w_pos = 0;
+           
+ // Check for overrun
+ if (overrun)
+    overrun_error = 1;
+    
+ overrun = 1;   
+ }  
+ 
+// ISR for the dualWaveResponse function
+// Time optimized version
+// Use only for single ADC read and stime < 35us
+void dualWaveResponseSingleISR()
+ {
+ // Write DACs
+ DAC->DHR12R1 = (buff[w_pos++]>>4);
+ DAC->DHR12R2 = (wave2buff[w_pos2++]>>4);
+     
+ // Store analog data    
+ if (!w_n)
+      {
+      // Direct access to ADC registers 
+      ADC1->CR |= ADC_CR_ADSTART;           
+      while (!(ADC1->ISR & ADC_ISR_EOC));
+      tranBuff[inBuffPos++]=(ADC1->DR)<<4;  
+ 
+      if (inBuffPos == currentBsize) inBuffPos = 0;     
+     
+      // Increase sample
+      samples++;
+     
+      // Check if we should end
+      if (samples >= n_s)
+           {
+           // Disable ticker
+           ticR.detach();     
+           // Signal end
+           endTicker = 1;    
+           } 
+      
+      // Check wave rollover
+      if (w_pos == w_s)   w_pos = 0;
+      if (w_pos2 == w_s2) w_pos2 = 0;
+      }
+     else
+      {
+      // Check wave rollover    
+      if (w_pos == w_s)
+            {
+            w_pos = 0;    
+            w_n--;
+            }
+      if (w_pos2 == w_s2) w_pos2 = 0;      
+      }                     
+                 
+ // Check wave rollover
+ //if (w_pos == w_s) w_pos = 0;
+           
+ // Check for overrun
+ if (overrun)
+    overrun_error = 1;
+    
+ overrun = 1;   
+ }     
+
+// Dual wave response
+void dualWaveResponse()
+ {
+ // Read number of primary waves before mesurement    
+ w_n = getU16();   
+
+ // Check of CRC
+ if (!crcResponse()) return; 
+ 
+ sendByte(ACK);
+
+ // Configure ticker ISR    
+ samples = 0;               // Number of processed samples
+ inBuffPos = 0;             // Current buffer position
+ endTicker = 0;             // Ticker has not ended
+ w_pos = 0;                 // Current wave position 
+ w_pos2 = 0;                // Secondary wave position
+
+ currentBsize = n_ai * n_s;        // Current size for buffer
+ 
+ // Clear overrun variables
+ overrun_error = 0;
+ overrun = 0;    
+ 
+ // Check if we only read one channel
+ if ((n_ai==1)&&(stime<35e-6f))
+    {
+    // Perform a dummy read
+    ain1.read_u16();   
+    // Programs the ticker
+    ticR.attach(&dualWaveResponseSingleISR,stime); 
+    }
+    else
+    {
+    // Programs the ticker
+    ticR.attach(&dualWaveResponseISR,stime);
+    }
+   
+ // Wait till end
+ while (!endTicker) overrun = 0;
+ 
+ // Return data
+ dumpInBuffer();  // Dump data  
+ 
+ // End sending CRC
+ sendCRC(); 
+ }    
+
+/*************** SINGLE WAVE RESPONSE CODE **********************/ 
+// Hardware profiling operation (if enabled)
+//   PRO1 line high during ISR
+//   PRO2 line mimics overrun variable 
+
+// ISR for the singleWaveResponse function
+void singleWaveResponseISR()
+ {
+ int a1;    
+     
+ PRO1_SET    
+    
+ // Write DAC1
+ aout1 = buff[w_pos++] / MAX16F;   
+     
+ // Store analog data    
+ if (!w_n)
+      {
+      // Store data  
+      // Store data  
+      a1 = ain_tran->read_u16();    
+      tranBuff[inBuffPos++]=a1;    
+     
+      // Increase sample
+      samples++;
+     
+      // Check if we should end
+      if (samples >= n_s)
+           {
+           // Disable ticker
+           ticR.detach();     
+           // Signal end
+           endTicker = 1;    
+           } 
+      
+      // Check wave rollover
+      if (w_pos == w_s) w_pos = 0;        
+      }
+     else
+      {
+      // Check wave rollover    
+      if (w_pos == w_s)
+            {
+            w_pos = 0;    
+            w_n--;
+            }
+      }                     
+                 
+ // Check wave rollover
+ if (w_pos == w_s) w_pos = 0;
+        
+ // Check for overrun
+ if (overrun)
+    overrun_error = 1;
+    
+ overrun = 1;  
+ 
+ PRO2_SET
+ PRO1_CLEAR
+ }   
+
+// ISR for the singleWaveResponse function
+// Time optimized version
+// Only used for stime < 30us
+void singleWaveResponseFastISR()
+ {
+ int a1;    
+     
+ PRO1_SET    
+    
+ // Write DAC1
+ DAC->DHR12R1 = (buff[w_pos++]>>4);  /* New faster code */
+     
+ // Store analog data    
+ if (!w_n)
+      {
+      // Store data  
+      // Direct access to registers
+      ADC1->CR |= ADC_CR_ADSTART;           
+      while (!(ADC1->ISR & ADC_ISR_EOC));
+      a1 = ADC1->DR;
+      tranBuff[inBuffPos++]=a1<<4;    
+     
+      // Increase sample
+      samples++;
+     
+      // Check if we should end
+      if (samples >= n_s)
+           {
+           // Disable ticker
+           ticR.detach();     
+           // Signal end
+           endTicker = 1;    
+           } 
+      
+      // Check wave rollover
+      if (w_pos == w_s) w_pos = 0;        
+      }
+     else
+      {
+      // Check wave rollover    
+      if (w_pos == w_s)
+            {
+            w_pos = 0;    
+            w_n--;
+            }
+      }                     
+                 
+ // Check wave rollover
+ if (w_pos == w_s) w_pos = 0;
+        
+ // Check for overrun
+ if (overrun)
+    overrun_error = 1;
+    
+ overrun = 1;  
+ 
+ PRO2_SET
+ PRO1_CLEAR
+ }  
+
+// Select analog channel
+// In case of error, closes the communication and returns 0
+// If all is ok, returns 1
+int selectTranChannel(int channel)
+ {
+ if ((channel<0) || (channel>4))
+          {
+          sendByte(NACK);
+          sendCRC();
+          return 0;
+          } 
+          
+ switch(channel)         
+    {
+    case 1:
+        ain_tran=&ain1;
+        break;
+    case 2:
+        ain_tran=&ain2;
+        break;
+    case 3:
+        ain_tran=&ain3;
+        break;
+    case 4:
+        ain_tran=&ain4;
+        break;                        
+    }
+    
+ return 1;   
+ }    
+
+// Single Wave response
+void singleWaveResponse()
+ {
+ int channel;  
+ 
+ PRO1_CLEAR // Reset profile lines
+ PRO2_CLEAR  
+     
+ // Read channel to read    
+ channel = getByte();   
+          
+ // Read number of waves before mesurement    
+ w_n = getU16();   
+
+ // Check of CRC
+ if (!crcResponse()) return; 
+ 
+ // Configure the input channel
+ if (!selectTranChannel(channel)) return;
+ 
+ // Dummy read
+ ain_tran->read_u16();
+
+ // Send ACK
+ sendByte(ACK);
+
+ // Configure ticker ISR    
+ samples = 0;               // Number of processed samples
+ inBuffPos = 0;             // Current buffer position
+ endTicker = 0;             // Ticker has not ended
+ w_pos = 0;                 // Current wave position 
+
+ currentBsize = n_s;        // Current size for buffer
+ 
+ // Clear overrun variables
+ overrun_error = 0;
+ overrun = 0;    
+ 
+ if (stime < 30e-6f)
+     {
+     // Programs the ticker with fast version
+     ticR.attach(&singleWaveResponseFastISR,stime);
+     }
+     else
+     {    
+     // Programs the ticker with normal version
+     ticR.attach(&singleWaveResponseISR,stime);
+     }
+   
+ // Wait till end
+ while (!endTicker) { overrun = 0; PRO2_CLEAR }
+ 
+ // Return data
+ dumpInSingleBuffer();  // Dump data  
+ 
+ // End sending CRC
+ sendCRC(); 
+ }    
+
+/****************** WAVE PLAY CODE *************************/ 
+
+// ISR for the wavePlay function
+void wavePlayISR()
+ {
+ // Write DAC (Old code)
+ // aout1 = buff[w_pos++] / MAX16F;    
+ 
+  // Write DACs (New faster code)
+ DAC->DHR12R1 = (buff[w_pos++]>>4);
+              
+ // Check wave rollover    
+ if (w_pos == w_s)
+     {
+     w_pos = 0;    
+     w_n--;
+     if (w_n <= 0)
+           {
+           // Disable ticker
+           ticR.detach();     
+           // Signal end
+           endTicker = 1;     
+           return;
+           }
+     }
+        
+ // Check for overrun
+ if (overrun)
+    overrun_error = 1;
+    
+ overrun = 1;   
+ }    
+
+// Wave Play
+void wavePlay()
+ {
+ PRO1_SET
+ // Read number of waves to send    
+ w_n = getU16();   
+
+ // Check of CRC
+ if (!crcResponse()) return; 
+ 
+ sendByte(ACK);
+
+ // Configure ticker ISR    
+ endTicker = 0;             // Ticker has not ended
+ w_pos = 0;                 // Current wave position 
+
+ // Clear overrun variables
+ overrun_error = 0;
+ overrun = 0;    
+ 
+ // Programs the ticker
+ ticR.attach(&wavePlayISR,stime);
+   
+ // Wait till end
+ while (!endTicker) overrun = 0;
+ 
+ PRO1_CLEAR
+ 
+ // Response code
+ if (overrun_error)
+        sendByte(TRAN_OVERRUN);
+        else
+        sendByte(TRAN_OK);  
+ 
+ // End sending CRC
+ sendCRC(); 
+ }    
+
+/****************** DUAL WAVE PLAY CODE *************************/ 
+
+// ISR for the dualWavePlay function
+void dualWavePlayISR()
+ {
+ // Write DAC (Old code)
+ //aout1 = buff[w_pos++] / MAX16F; 
+ //aout2 = wave2buff[w_pos2++] / MAX16F; 
+ 
+ // Write DACs (New faster code)
+ DAC->DHR12R1 = (buff[w_pos++]>>4);
+ DAC->DHR12R2 = (wave2buff[w_pos2++]>>4);
+              
+ // Check primary wave rollover    
+ if (w_pos == w_s)
+     {
+     w_pos = 0;    
+     w_n--;
+     if (w_n <= 0)
+           {
+           // Disable ticker
+           ticR.detach();     
+           // Signal end
+           endTicker = 1;     
+           }
+     }
+     
+ // Check for secondary wave rollover
+ if (w_pos2 == w_s2) w_pos2 = 0;   
+        
+ // Check for overrun
+ if (overrun)
+    overrun_error = 1;
+    
+ overrun = 1;   
+ }    
+
+// Dual Wave Play
+void dualWavePlay()
+ {
+ // Read number of primary waves to send    
+ w_n = getU16();   
+
+ // Check of CRC
+ if (!crcResponse()) return; 
+ 
+ sendByte(ACK);
+
+ // Configure ticker ISR    
+ endTicker = 0;             // Ticker has not ended
+ w_pos =  0;                // Current primary wave position 
+ w_pos2 = 0;                // Current secondary wave position
+
+ // Clear overrun variables
+ overrun_error = 0;
+ overrun = 0;    
+ 
+ // Programs the ticker
+ ticR.attach(&dualWavePlayISR,stime);
+   
+ // Wait till end
+ while (!endTicker) overrun = 0;
+ 
+ // Response code
+ if (overrun_error)
+        sendByte(TRAN_OVERRUN);
+        else
+        sendByte(TRAN_OK);  
+ 
+ // End sending CRC
+ sendCRC(); 
+ }    
+
+/***************** DC DIGITAL IO *********************************/
+
+// Digital IO mode
+void dioMode()
+ {
+ int line,mode,error; 
+  
+ // Read line to configure 
+ line = getByte(); 
+     
+ // Read mode to set
+ mode = getByte();
+ 
+ // Check of CRC
+ if (!crcResponse()) return; 
+ 
+ // No error for now
+ error = 0;
+ 
+ // Check line number
+ if ((line <= 0)||(line > NDIO)) error = 1;
+ 
+ // Set dio mode
+ if (!error)
+    switch(mode)
+        {
+        case 10: 
+           dioList[line-1]->input();
+           dioList[line-1]->mode(PullNone);
+           break;
+        case 11: 
+           dioList[line-1]->input();        
+           dioList[line-1]->mode(PullUp);
+           break;  
+        case 12: 
+           dioList[line-1]->input();
+           dioList[line-1]->mode(PullDown);
+           break;                        
+        case 20: 
+           dioList[line-1]->mode(PullNone);        
+           dioList[line-1]->output();        
+           break;  
+//        case 21: 
+//           dioList[line-1]->mode(OpenDrain);        
+//           dioList[line-1]->output();        
+//           break; 
+        default:
+           error = 1;
+           break;                             
+        }
+        
+ if (error)
+    sendByte(NACK);
+    else
+    sendByte(ACK);     
+ 
+ // End sending CRC
+ sendCRC(); 
+ }
+ 
+// Digital Write
+void dioWrite()
+ {
+ int line,value; 
+  
+ // Read line to write 
+ line = getByte(); 
+     
+ // Value to set
+ value = getByte();
+ 
+ // Check of CRC
+ if (!crcResponse()) return; 
+ 
+ // Check line number
+ if ((line <= 0)||(line > NDIO)) 
+     {
+     sendByte(NACK);
+     sendCRC();
+     return;
+     }
+ 
+ // Set dio value
+ dioList[line-1]->write(value);
+
+ // Send ACK and CRC
+ sendByte(ACK);     
+ sendCRC(); 
+ } 
+ 
+// Digital Read
+void dioRead()
+ {
+ int line,value; 
+  
+ // Read line to read
+ line = getByte(); 
+ 
+ // Check of CRC
+ if (!crcResponse()) return; 
+ 
+ // Check line number
+ if ((line <= 0)||(line > NDIO)) 
+     {
+     sendByte(NACK);
+     sendCRC();
+     return;
+     }
+ 
+ // Send ACK
+ sendByte(ACK);
+ 
+ // Read and send dio value
+ value=dioList[line-1]->read();
+ if (value)
+    sendByte(1);
+    else
+    sendByte(0);
+ 
+ // Send CRC     
+ sendCRC(); 
+ }  
+
+/***************** MAIN LOOP CODE ********************************/
+
+// Soft reset
+// Put the system in default reset state
+void softReset(void)
+ {
+ int i;    
+     
+ // Sample time period defaults to 1ms
+ stime = 0.001;
+ 
+ // Set number of DC readings to 10
+ nread = 10;
+ 
+ // Input configuration
+ n_ai = 1;     // Number of analog inputs
+ n_di = 0;     // Number of digital inputs (always zero)
+ n_s  = 1000;  // Number of samples
+ 
+ // Eliminate wavetables
+ w_s =  0;  
+ w_s2 = 0;
+ 
+ // Initialize unified memory
+ wave2buff = buff;
+ tranBuff  = buff;  
+ 
+ // Set DACs to zero
+ aout1 = 0.0;
+ aout2 = 0.0; 
+ 
+ // Fill ain list
+ ainList[0]=&ain1;
+ ainList[1]=&ain2;
+ ainList[2]=&ain3;
+ ainList[3]=&ain4;
+ 
+ // Configure DIO
+ #ifdef EXIST_DIO
+ // Setup dioList
+ dioList[0]=&dio1;
+ dioList[1]=&dio2;
+ dioList[2]=&dio3;
+ dioList[3]=&dio4;
+ dioList[4]=&dio5;
+ dioList[5]=&dio6;
+ dioList[6]=&dio7;
+ dioList[7]=&dio8;
+ // Default configuration
+ for(i=0;i<NDIO;i++)
+    {
+    dioList[i]->mode(PullNone);
+    dioList[i]->input();    
+    }    
+ #endif
+ }
+
+// Process one character received from the PC
+void process(int car)
+ {
+ int i;
+ uint16_t value;
+  
+ // Initialize Tx CRC
+ startTx();
+    
+ switch(car)
+    {
+    case 'F': // Get firmware string
+        sendString(BSTRING);
+        sendString(VSTRING);
+        sendString("\n\r");
+        break;
+    case 'M': // Get magic
+        // Check CRC of command. Returns 1 if Ok
+        // On error Sends ECRC + CRC and return 0
+        if (!crcResponse()) return;
+        sendByte(ACK);
+        // Send magic
+        for(i=0;i<MAGIC_SIZE;i++)
+            sendByte(magic[i]);
+        // Send CRC
+        sendCRC();
+        break; 
+    case 'I': // Get board capabilities
+        // Check CRC of command. Returns 1 if Ok
+        // On error Sends ECRC + CRC and return 0
+        if (!crcResponse()) return;
+        sendByte(ACK);
+            
+        sendByte(NDACS);                //  1
+        sendByte(NADCS);                //  2
+        sendU16(BSIZE);                 //  4 Buffer
+        sendMantExp(MAX_S_M,MAX_S_E);   //  7
+        sendMantExp(MIN_S_M,MIN_S_E);   // 10
+        sendMantExp(VDD_M,VDD_E);       // 13
+        sendMantExp(MAX_SF_M,MAX_SF_E); // 16
+        sendMantExp(VREF_M,VREF_E);     // 29
+        sendByte(DAC_BITS);             // 20
+        sendByte(ADC_BITS);             // 21
+        sendByte(NDIO);                 // 22
+        sendByte(resetState);           // 23
+        
+        // Send CRC
+        sendCRC();
+        break;
+    case 'L' : // Send pin list
+        // Check CRC of command. Returns 1 if Ok
+        // On error Sends ECRC + CRC and return 0
+        if (!crcResponse()) return;
+        sendByte(ACK);
+        
+        sendString(PIN_LIST);
+        
+        // Send CRC
+        sendCRC();        
+        break;
+        
+    
+    case 'A' : // ADC Read
+        i = getByte();   // Channel to read
+        // Check CRC of command. Returns 1 if Ok
+        // On error Sends ECRC + CRC and return 0
+        if (!crcResponse()) return;   
+             
+        /*     
+        switch(i)
+            {
+            case 1:
+               value = ain1.read_u16();  // Two reads
+               value = ain1.read_u16(); 
+               break;  
+            case 2:
+               value = ain2.read_u16();  // Two reads
+               value = ain2.read_u16(); 
+               break; 
+            case 3:
+               value = ain3.read_u16();  // Two reads
+               value = ain3.read_u16(); 
+               break; 
+            case 4:
+               value = ain4.read_u16();  // Two reads
+               value = ain4.read_u16(); 
+               break;  
+            default:
+               sendByte(NACK);
+               sendCRC();
+               return;                                              
+            }  
+        */
+        if ((i<1)||(i>NADCS))
+            {
+            sendByte(NACK);
+            sendCRC();
+            return;     
+            }
+            
+        value = analogRead(i);    
+               
+        sendByte(ACK);    
+        sendU16(value);
+        sendCRC();
+        break;        
+    
+    case 'D' : // DAC Write
+        i = getByte();          // Channel to write
+        value = getU16();       // Read value to set
+        // Check CRC of command. Returns 1 if Ok
+        // On error Sends ECRC + CRC and return 0
+        if (!crcResponse()) return;          
+        switch(i)
+            {
+            case 1: 
+               aout1 = value / MAX16F;   // Scale to float and send
+               break;
+            case 2:
+               aout2 = value / MAX16F;   // Scale to float and send
+               break;
+            #ifdef EXIST_DAC3   
+            case 3:
+               aout3 = value / MAX16F;   // Scale to float and send
+               break;          
+            #endif   
+            default:
+               sendByte(NACK);
+               sendCRC();
+               return;                
+            }  
+        sendByte(ACK);    
+        sendCRC();     
+        resetState=0;  // State change         
+        break;    
+                          
+    case 'R': // Set sample period time
+        setSampleTime();
+        resetState=0;  // State change
+        break;  
+    case 'S': // Set Storage
+        setStorage();
+        resetState=0;  // State change
+        break;      
+    case 'Y': // Async Read
+        asyncRead();
+        break;
+    case 'G': // Triggered Read
+        triggeredRead();
+        break;        
+    case 'P': // Step response
+        stepResponse();
+        break;    
+        
+    case 'W': // Load wavetable
+        loadWaveTable();
+        resetState=0;  // State change
+        break;  
+    case 'w': // Load secondary wavetable
+        loadSecondaryWaveTable();
+        resetState=0;  // State change
+        break;         
+    case 'V': // Wave response
+        waveResponse();
+        break;  
+    case 'v': // Dual wave response
+        dualWaveResponse();
+        break;          
+    case 'X': // Single Wave response
+        singleWaveResponse();
+        break; 
+    case 'Q': // Wave Play
+        wavePlay();
+        break;  
+    case 'q': // Wave Play
+        dualWavePlay();
+        break;                 
+        
+    case 'E': // Soft Reset
+        if (!crcResponse()) return;
+        
+        softReset();
+        resetState=1;  // Return to reset state
+    
+        sendByte(ACK);    
+        sendCRC();
+        break;   
+        
+    case 'H': // DIO mode
+        dioMode();
+        resetState=0;  // State change
+        break;  
+    case 'J': // DIO Write
+        dioWrite();
+        resetState=0;  // State change
+        break;    
+    case 'K': // DIO Read
+        dioRead();
+        break;   
+        
+    case 'N': // Number of reads in DC
+        value = getU16();             // Read value to set
+        if (!crcResponse()) return;   // Check CRC
+        if (value==0) value=1;        // At least it shall be one
+        nread = value;
+        sendByte(ACK);                // Send ACK and CRC
+        sendCRC();    
+        resetState=0;  // State change          
+        break;                          
+    
+    default:
+        // Unknown command
+        sendByte(NACK);
+        sendCRC();    
+        break;             
+    }     
+ }    
+
+int main() 
+ {
+ int car;
+ 
+ // Generate soft reset
+ softReset();
+ 
+ pc.printf("%s%s\n\r",BSTRING,VSTRING);
+
+ // Reset profile lines (if enabled)
+ PRO1_CLEAR
+ PRO2_CLEAR
+ 
+ // New ADC code
+ //adc_init();
+
+ // Loop that processes each received char
+ while(1) 
+    {
+    startRx();        // Init Rx CRC
+    car = getByte();  // Get command
+    process(car);     // Process command
+    }
+ }
+
+