execute all tests just once
[Arduino] / c2_ulx3s_test / adc.cpp
1 /*
2 */
3 #include <Arduino.h>
4
5 // constants won't change. Used here to set a pin number:
6 const int ledPin = 17; // the number of the LED pin
7 const int pin = 32+20; // first audio pin
8
9 const int SPI_MISO = 20;
10 const int SPI_MOSI = 8+18;
11 const int SPI_CLK = 8+17;
12 const int SPI_CSN = 8+16;
13
14 // additional gpio for GN lines (not integrated into arduino yet)
15 volatile uint32_t *gpio1_out = (uint32_t *) 0xfffff820;
16 volatile uint32_t *gpio1_ctl = (uint32_t *) 0xfffff824;
17 volatile uint32_t *gpio1_in  = (uint32_t *) 0xfffff838;
18 const uint32_t gpio1_bits = 0x3C000; // bits/pins 14,15,16,17
19
20 // constants won't change:
21 const long interval = 100; // min interval at which to blink (milliseconds)
22
23 const uint16_t config_setup =
24           (0x10 << 11) |  // CONFIG_SETUP
25           (1 << 10)    |  // REFSEL external single ended (vs REF-).
26           (0 << 9)     |  // AVGON averaging turned off.
27           (0 << 7)     |  // NAVG 1 conversion per result.
28           (0 << 5)     |  // NSCAN scans N and returns 4 results.
29           (0 << 3)     |  // SPM all circuitry powered all the time.
30           (1 << 2)     ;  // ECHO 1-enabled 0-disabled.
31
32 const uint16_t mode_control =
33           (0 << 15) |  // REG_CNTL select ADC mode control.
34           (3 << 11) |  // standard_int scan 0-N internal clock w/avg.
35           (7 << 7)  |  // CHSEL scan up to channel 7.
36           (0 << 5)  |  // RESET the FIFO only.
37           (0 << 3)  |  // PM power management normal.
38           (0 << 2)  |  // CHAN_ID set to 1 in ext mode to get chan id.
39           (1 << 1)  ;  // SWCNV 1 (rising edge of CS)
40
41 const uint16_t sample_set =
42           (B10110 << 11 ) |  // SMPL_SET select ADC sample set
43                (4 << 3)   ;  // SEQ length
44
45 uint16_t SPIRW(uint16_t d)
46 {
47   uint16_t r = 0, b = 1<<15;
48   uint8_t miso;
49   for(int i = 0; i < 16; i++)
50   {
51     digitalWrite(SPI_CLK, LOW);
52     //digitalWrite(9, LOW);
53     digitalWrite(SPI_MOSI, (d & b) != 0 ? HIGH : LOW);
54     //digitalWrite(10, (d & b) != 0 ? HIGH : LOW);
55     //delay(1);
56     digitalWrite(SPI_CLK, HIGH);
57     //digitalWrite(9, HIGH);
58     // read now
59     if(digitalRead(SPI_MISO))
60     {
61       r |= b;
62       //digitalWrite(11, HIGH);
63     }
64     else
65     {
66       //digitalWrite(11, LOW);
67     }
68     b >>= 1;
69     //delay(1);
70   }
71   return r;
72 }
73
74 uint16_t SPISend(const unsigned int adc_cbase, uint16_t d)
75 {
76   digitalWrite(SPI_CSN, LOW);
77   //digitalWrite(8, LOW);
78   uint16_t retval = SPIRW(d);
79   digitalWrite(SPI_CSN, HIGH);
80   //digitalWrite(8, HIGH);
81   return retval;
82 }
83
84 void SPIdriveCSN(int cs)
85 {
86   digitalWrite(SPI_CSN, cs);
87   //digitalWrite(8, cs);
88 }
89
90 void SPIstart()
91 {
92   // first clock with CSN HI
93   digitalWrite(SPI_CSN, HIGH); // make sure it's high
94   //delay(1);
95   digitalWrite(SPI_CLK, LOW);
96   //delay(1);
97   digitalWrite(SPI_CLK, HIGH);
98   //delay(1);
99   SPISend(0,mode_control); // to the rest 16 bit send normal mode control command
100 }
101
102 void configureMax1112x()
103 {
104   const int adc_cbase = 0;
105   // Config: Reset.
106   SPISend(adc_cbase, (2 << 5)); // RESET reset all registers to defaults.
107
108   // Config: ADC configuration.
109   SPISend(adc_cbase, config_setup);
110
111   // Config: Unipolar.
112   SPISend(adc_cbase, (0x12 << 11));  // All channels unipolar.
113   SPISend(adc_cbase, (0x11 << 11) |  // All channels unipolar.
114                         (1 << 2));      // Reference all channels to REF-.
115
116   // Config: ADC mode control.
117   SPISend(adc_cbase, mode_control);
118
119   // Defaults are good for:
120   // Config: Bipolar.
121   // Config: RANGE.
122   // Config: Custom scan 0.
123   // Config: Custom scan 1.
124   // Config: Sample set.
125 }
126
127
128 void adc_init()
129 {
130   for(int j = 0; j < 8; j++)
131   {
132     pinMode(8+j, OUTPUT);
133     digitalWrite(8+j, LOW);
134   }
135   // set the digital pin as output:
136   pinMode(ledPin, OUTPUT);
137   configureMax1112x();
138 }
139
140 int adc_read(char *a)
141 {
142   int ret = 0;
143   static uint8_t skip_eval = 5; // skip evaluation for first few readings
144   static uint16_t reading[10], prev_reading[10];
145   // alternating LED state will also alternate
146   // digital output pins shared with ADC
147   // ADC will read digital states
148   static int ledState = LOW;
149   {
150
151     // if the LED is off turn it on and vice-versa:
152     if (ledState == LOW) {
153       ledState = HIGH;
154     } else {
155       ledState = LOW;
156     }
157
158     // set the LED with the ledState of the variable:
159     digitalWrite(ledPin, ledState);
160
161     // copy previous reading for evaluation
162     for(int i = 0; i < 8; i++)
163       prev_reading[i] = reading[i];
164
165     SPIstart();
166     delay(1); // wait conversion
167     for(int i = 0; i < 9; i++)
168       reading[i] = SPISend(0,0);
169     // evaluation for ADC readings: OK/FAIL
170     static char *channel_eval[8];
171     for(uint16_t i = 0; i < 8; i++)
172     {
173       if(skip_eval)
174         channel_eval[i] = "WAIT";
175       else if(ledState)
176       {
177         if(i & 1)
178         {
179           if(reading[i] < ((i << 12) + 0x080) && prev_reading[i] > ((i << 12) + 0xF80) ) {
180             channel_eval[i] = " OK ";
181             ret++;
182           } else
183             channel_eval[i] = "FAIL";
184         }
185         else
186         {
187           if(prev_reading[i] < ((i << 12) + 0x080) && reading[i] > ((i << 12) + 0xF80) ) {
188             channel_eval[i] = " OK ";
189             ret++;
190           } else
191             channel_eval[i] = "FAIL";
192         }
193       }
194     }
195     // skip evaluation for first few readings
196     if(skip_eval)
197       skip_eval--;
198     sprintf(a, "%04x %04x %04x %04x %04x %04x %04x %04x\n%s %s %s %s %s %s %s %s\n",
199       reading[0],
200       reading[1],
201       reading[2],
202       reading[3],
203       reading[4],
204       reading[5],
205       reading[6],
206       reading[7],
207       channel_eval[0],
208       channel_eval[1],
209       channel_eval[2],
210       channel_eval[3],
211       channel_eval[4],
212       channel_eval[5],
213       channel_eval[6],
214       channel_eval[7]
215     );
216     // change GPIO logic levels 0/1, ADC is connected to GPIO
217     // and should convert logic levels
218     pinMode(32+14, OUTPUT);
219     digitalWrite(32+14, ledState);
220     pinMode(32+15, OUTPUT);
221     digitalWrite(32+15, ledState);
222     pinMode(32+16, OUTPUT);
223     digitalWrite(32+16, ledState);
224     pinMode(32+17, OUTPUT);
225     digitalWrite(32+17, ledState);
226     // same as above but with alternat phase for PN pins
227     // those are not implemented in arduino so we
228     // write directly to hardware registers
229     *gpio1_ctl |= gpio1_bits; // outputs
230     if(ledState)
231       *gpio1_out &= ~gpio1_bits;
232     else
233       *gpio1_out |= gpio1_bits;
234   }
235   return ret;
236 }