Add ADC10 application for sampling analog values.
authorscottlivingston <scottlivingston@12e2690d-a6be-4b82-a7b7-67c4a43b65c8>
Wed, 29 Sep 2010 05:15:16 +0000 (05:15 +0000)
committerscottlivingston <scottlivingston@12e2690d-a6be-4b82-a7b7-67c4a43b65c8>
Wed, 29 Sep 2010 05:15:16 +0000 (05:15 +0000)
Currently only supports x2274 chip, as on GoodFET31 board.
The sampled line is pin 5 of the JTAG header.

The new app ID is 0x74.
The corresponding client (Python script) is goodfet.adc

The ADC10 app is NOT included in the default build. See comments in
Makefile for what to add if you desire it.

git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@736 12e2690d-a6be-4b82-a7b7-67c4a43b65c8

firmware/Makefile
firmware/apps/adc/README.txt [new file with mode: 0644]
firmware/apps/adc/adc.c [new file with mode: 0644]
firmware/goodfet.c
firmware/include/adc.h [new file with mode: 0644]
firmware/include/apps.h
firmware/include/command.h

index eecfcef..81e87cf 100644 (file)
@@ -33,6 +33,7 @@ CC=msp430-gcc -Wall -Os -g -mmcu=$(mcu) -D$(mcu) -D$(platform) -Dplatform=$(plat
 moreapps?=apps/jtag/sbw.o apps/glitch/glitch.o apps/jtag/jtagarm7.o
 # should include apps/jtag/jtagarm7tdmi.o to build jtag for ARM7
 # should include apps/pic/dspic33f.o to build support for PIC24H/dsPIC33F
+# should include apps/adc/adc.o to build support for ADC10 app (still specific to x2274, GoodFET31).
 
 apps= $(moreapps) apps/chipcon/chipcon.o apps/radios/nrf.o apps/radios/ccspi.o apps/monitor/monitor.o apps/spi/spi.o   apps/jtag/jtag.o apps/jtag/jtag430.o apps/jtag/jtag430x2.o apps/avr/avr.o 
 
diff --git a/firmware/apps/adc/README.txt b/firmware/apps/adc/README.txt
new file mode 100644 (file)
index 0000000..46afadd
--- /dev/null
@@ -0,0 +1,9 @@
+GoodFET/ADC -- A/D Converter App
+
+Scott Livingston  <slivingston@caltech.edu>
+(written in Sep 2010.)
+
+
+The goal is to provide a convenient means for sampling an ADC-routed
+pin.  This is motivated because I needed a quick way to measure an
+analog signal with spectral content up to 100 kHz (at least).
diff --git a/firmware/apps/adc/adc.c b/firmware/apps/adc/adc.c
new file mode 100644 (file)
index 0000000..becf893
--- /dev/null
@@ -0,0 +1,136 @@
+/*! \file adc.c
+
+       \author Scott Livingston
+
+       \brief Simple A/D sampling of a GoodFET pin.  Currently assumes
+              x2274 chip, on a GoodFET31 board.
+
+       \date September 2010
+*/
+
+#include "apps.h"
+#include "platform.h"
+#include "command.h"
+
+#include "adc.h"
+
+
+void init_adc10()
+{
+       ADC10CTL0 = ADC10DISABLE;
+       ADC10CTL0 = REFON | REF2_5V | ADC10ON; // internal reference, at 2.5V
+       ADC10CTL1 = INCH_5 | ADC10SSEL_2; // input A5; using MCLK as clock source.
+       ADC10AE0 = 1<<5; // enable channel A5
+       ADC10SA = 0x200; // Start at bottom of RAM (i.e. lowest address).
+}
+
+void uninit_adc10()
+{
+       ADC10CTL0 = ADC10DISABLE;
+       ADC10CTL0 = ADC10CTL1 = 0x0000;
+}
+
+
+//! Handle an ADC10 command; currently assumes x2274, on a GoodFET31 board.
+void adchandle( unsigned char app, unsigned char verb, unsigned long len )
+{
+       u16 sample;
+       u16 actual_N;
+
+       switch (verb) {
+
+       case ADC10_INIT:
+               init_adc10();
+               txdata(app,verb,0);
+               break;
+
+       case ADC10_UNINIT:
+               uninit_adc10();
+               txdata(app,verb,0);
+               break;
+
+       case ADC10_1SAMPLE: //! Capture and return a single sample.
+               sample = sample_adc10();
+               *cmddata = sample & 0xff;
+               *(cmddata+1) = sample >> 8;
+               txdata(app,verb,2);
+               break;
+
+       case ADC10_NSAMPLE: //! Capture and return a sequence, with constanst Sps.
+               if (*cmddata == 0)
+                       *cmddata = 0xff; // Max length
+               /*if (len == 0) {
+                       actual_N = nsamples_adc10( 0xff, 3, 8 ); 
+               } else if (len == 1) {
+                       actual_N = nsamples_adc10( *cmddata, 3, 8 );
+                       } else {*/
+                       actual_N = nsamples_adc10( *cmddata, *(cmddata+1), *(cmddata+2) );
+//             }
+               txdata( app, verb, actual_N*2 );
+               break;
+
+       default:
+               debugstr( "Verb unimplemented in ADC10 application." );
+               txdata(app,NOK,0);
+               break;
+
+       }
+}
+
+
+u16 sample_adc10()
+{
+       // We assume the ADC10 module has already been initialized.
+       u16 result;
+       u16 ctl0_start = ADC10CTL0;
+
+       ADC10CTL0 |= ADC10SHT_3; /* Switch to longest sample-and-hold time
+                                                                                                                 (i.e. 64 ticks), to increase likelihood
+                                                                                                                 of success given we are only taking a
+                                                                                                                 single sample here. */
+       ADC10CTL0 |= 0x0003; // ENC | ADC10SC
+       while (!(ADC10CTL0 & ADC10IFG)) ;
+       result = ADC10MEM;
+       
+       ADC10CTL0 = ctl0_start; /* Return ADC10 control register to original
+                                                                                                          state, at calling of this function. */
+       return result;
+}
+
+
+u16 nsamples_adc10( u8 N_count, u8 t_sample, u8 clock_div )
+{
+       u16 ctl0_start;
+       u16 ctl1_start;
+
+       //while (ADC10BUSY) ; // Wait till any pending operation completes.
+
+       ctl0_start = ADC10CTL0;
+       ctl1_start = ADC10CTL1; // Save control registers states.
+       
+       if (N_count > (CMDDATALEN-4)/2) { // Bound number of samples to be obtained here.
+               N_count = (CMDDATALEN-4)/2;
+       }
+       clock_div--; // Place in form appropriate for control register
+
+       // Additional preparations of ADC10
+       ADC10CTL0 |= (t_sample&0x3)<<11 | MSC;
+       ADC10CTL1 |= (clock_div&0x7)<<5
+               | ADC10SSEL_2 // source from MCLK (should be 16 MHz),
+               | CONSEQ_2; // repeat-single-channel mode.
+
+       // Setup DTC (to make acquisition of block of samples easy/reliable)
+       ADC10DTC0 = 0x0000;
+       ADC10DTC1 = N_count;
+       ADC10SA = cmddata;
+
+       ADC10CTL0 |= 0x0003; // ENC | ADC10SC
+
+       while (!(ADC10CTL0 & ADC10IFG)) ;
+       
+       ADC10CTL0 = ctl0_start; // Restore control registers
+       ADC10CTL1 = ctl1_start;
+       ADC10DTC1 = 0x0000; // ...and disable DTC
+
+       return N_count;
+}
index b8d9e3d..a6ccae4 100644 (file)
@@ -53,7 +53,7 @@ void init(){
   //Setup clocks, unique to each '430.
   msp430_init_dco();
   msp430_init_uart();
-  
+
   //DAC should be at full voltage if it exists.
 #ifdef DAC12IR
   //glitchvoltages(0xfff,0xfff);
@@ -112,7 +112,9 @@ void handle(unsigned char app,
   case PIC:
     pichandle(app,verb,len);
     break;
-
+       case ADC10:
+               adchandle(app,verb,len);
+               break;
   case I2CAPP:
     i2chandle(app,verb,len);
     break;
diff --git a/firmware/include/adc.h b/firmware/include/adc.h
new file mode 100644 (file)
index 0000000..ad06a89
--- /dev/null
@@ -0,0 +1,71 @@
+/*! \file adc.h
+
+       \author Scott Livingston
+
+       \brief Prototypes for ADC application.  Note that this code was
+              written only with the x2274 chip and GoodFET31 in mind;
+              specifically, pin 5 of the (JTAG) header is sampled.
+              Supporting x2618, x1611/12 and other GoodFET boards remains!
+              For timing considerations, see at least Section 20.2.5
+              "Sample and Conversion Timing" (on page 589?) of msp430x2xx
+              family manual.
+
+       \date September 2010
+*/
+
+
+// Identical to that in command.h, but to avoid cyclic dependencies...
+#define u8 unsigned char
+#define u16 unsigned int
+#define u32 unsigned long
+
+
+//! Initialize ADC10 module (specific to 2xx chip family).
+void init_adc10();
+
+//! Uninit/stop ADC10 module (specific to 2xx chip family).
+void uninit_adc10();
+
+//! Return a single, instantaneous sample.
+u16 sample_adc10();
+
+//! Fill cmddata string; sampling repeatedly at a fixed rate.
+u16 nsamples_adc10( u8 N_count, //! Number samples to obtain (bounded w.r.t. cmddata)
+                                                                               u8 t_sample, /*! sample-and-hold time; this is
+                                                                                                                                    written directly to ADC10SHTx
+                                                                                                                                                field of ADC10CTL0 register;
+                                                                                                                                                possible values are
+                                                                                                                                                00   4 ADC10CLK ticks,
+                                                                                                                                                01   8 ADC10CLK ticks,
+                                                                                                                                                10  16 ADC10CLK ticks,
+                                                                                                                                                11  64 ADC10CLK ticks. */
+                                                                               u8 clock_div ); /*! Value by which to divide SMCLK
+                                                                                                                                                         (which is assumed to be 16
+                                                                                                                                                         MHz), then giving
+                                                                                                                                                         ADC10CLK.
+                                                                                                                                                               Possible values are 1..8
+                                                                                                                                                               Cf. Fig. 20-1 (on page 585?)
+                                                                                                                                                         of the msp430x2xxx family
+                                                                                                                                                         manual. */
+
+
+//! Command codes
+#define ADC10_INIT    0x81 //! Initialize ADC10 module (i.e., get ready for sampling).
+#define ADC10_UNINIT  0x82 //! Uninitialize (or "stop") ADC10.
+#define ADC10_1SAMPLE 0x83 //! Capture a single sample.
+
+/*! Capture a sequence of samples at a constant rate and write result
+    till requested number of samples is acquired or cmddata array is
+    filled, whichever is smaller. Hence, in the maximum length case,
+    (CMDDATALEN-4)/2 10-bit samples are obtained (128 total using
+    x2274 chip).
+
+    The command has several possible formats, switched according to
+    the length of received command data (from client). See above
+    comments about nsamples_adc10 function for meaning of ``t_samlpe''
+    and ``clock_div.''
+    
+    length 0  =>  max sample sequence length, t_sample = 3, clock_div = 8;
+           1  =>  user-specified sequence length, t_sample = 3, clock_div = 8;
+           3  =>  user-specified length, t_sample and clock_div. */
+#define ADC10_NSAMPLE 0x84 
index f0b9b08..82e6d1b 100644 (file)
@@ -31,6 +31,7 @@
 #define GLITCH 0x71
 #define PLUGIN 0x72
 #define SMARTCARD 0x73
+#define ADC10 0x74
 
 #define RESET 0x80     // not a real app -- causes firmware to reset
 
index d514e49..29f406f 100644 (file)
@@ -155,3 +155,5 @@ WEAKDEF int smartcardhandle(unsigned char app,
 WEAKDEF void pichandle( unsigned char app,
                        unsigned char verb,
                        unsigned long len );
+
+WEAKDEF void adchandle( unsigned char app, unsigned char verb, unsigned long len );