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
--- /dev/null
+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).
--- /dev/null
+/*! \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;
+}
//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);
case PIC:
pichandle(app,verb,len);
break;
-
+ case ADC10:
+ adchandle(app,verb,len);
+ break;
case I2CAPP:
i2chandle(app,verb,len);
break;
--- /dev/null
+/*! \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
#define GLITCH 0x71
#define PLUGIN 0x72
#define SMARTCARD 0x73
+#define ADC10 0x74
#define RESET 0x80 // not a real app -- causes firmware to reset
WEAKDEF void pichandle( unsigned char app,
unsigned char verb,
unsigned long len );
+
+WEAKDEF void adchandle( unsigned char app, unsigned char verb, unsigned long len );