LCDDriver_NXP_Arduino 0.7.6
Analog Front-End (AFE) device operation sample code for Arduino
Loading...
Searching...
No Matches
AFE_NXP.cpp
Go to the documentation of this file.
1
8
9#include "AFE_NXP.h"
10#include <math.h>
11
12double AFE_base::delay_accuracy = 1.1;
13
14/* AFE_base class ******************************************/
15
16AFE_base::AFE_base( int nINT, int DRDY, int SYN, int nRESET ) :
17 enabled_channels( 0 ), pin_nINT( nINT ), pin_DRDY( DRDY ), pin_SYN( SYN ), pin_nRESET( nRESET )
18{
19 pinMode( pin_nINT, INPUT );
20 pinMode( pin_DRDY, INPUT );
21 pinMode( pin_SYN, OUTPUT );
22 pinMode( pin_nRESET, OUTPUT );
23
24 digitalWrite( pin_SYN, 1 );
25 digitalWrite( pin_nRESET, 1 );
26
27 Serial.print("pin_nRESET = ");
28 Serial.println( pin_nRESET);
29}
30
34
35void AFE_base::begin( void )
36{
37 reset();
38 boot();
39}
40
41template<>
42int32_t AFE_base::read( int ch, float delay )
43{
44 if ( delay == INFINITY )
45 delay = ch_delay[ ch ] * delay_accuracy;
46
47 start_and_delay( ch, delay );
48 return adc_read( ch );
49};
50
51template<>
52double AFE_base::read( int ch, float delay )
53{
54 return read<int32_t>( ch, delay ) * coeff_uV[ ch ];
55};
56
57void AFE_base::start_and_delay( int ch, float delay_sec )
58{
59 if ( delay_sec >= 0.0 )
60 {
61 start( ch );
62 delay( delay_sec * 1000.0 );
63 }
64}
65
66int AFE_base::bit_count( uint32_t value )
67{
68 constexpr int bit_length = 32;
69 int count = 0;
70
71 for ( int i = 0; i < bit_length; i++ ) {
72 if ( value & (0x1 << i) )
73 count++;
74 }
75
76 return count;
77}
78
79
80/* NAFE13388_Base class ******************************************/
81
82NAFE13388_Base::NAFE13388_Base( int nINT, int DRDY, int SYN, int nRESET )
83 : AFE_base( nINT, DRDY, SYN, nRESET )
84{
85}
86
90
92{
94 delay( 1 );
95
97 delay( 1 );
98}
99
100void NAFE13388_Base::reset( bool hardware_reset )
101{
102 if ( hardware_reset )
103 {
104 digitalWrite( pin_nRESET, 0 );
105 delay( 1 );
106 digitalWrite( pin_nRESET, 1 );
107 }
108 else
109 {
110 command( CMD_RESET );
111 }
112
113 constexpr uint16_t CHIP_READY = 1 << 13;
114 constexpr auto RETRY = 10;
115
116 for ( auto i = 0; i < RETRY; i++ )
117 {
118 delay( 3 );
119 if ( reg( Register16::SYS_STATUS0 ) & CHIP_READY )
120 return;
121 }
122
123 Serial.println( "NAFE13388 couldn't get ready. Check power supply or pin conections\r\n" );
124
125 while ( true )
126 ;
127}
128
129void NAFE13388_Base::logical_ch_config( int ch, const uint16_t (&cc)[ 4 ] )
130{
131 constexpr double pga_gain[] = { 0.2, 0.4, 0.8, 1, 2, 4, 8, 16 };
132
133 command( ch );
134
135 for ( auto i = 0; i < 4; i++ )
136 reg( Register16::CH_CONFIG0 + i, cc[ i ] );
137
138 const uint16_t setbit = 0x1 << ch;
139 const uint16_t bits = bit_op( Register16::CH_CONFIG4, ~setbit, setbit );
140
141 enabled_channels = bit_count( bits );
142
143 if ( cc[ 0 ] & 0x0010 )
144 coeff_uV[ ch ] = ((10.0 / (double)(1L << 24)) / pga_gain[ (cc[ 0 ] >> 5) & 0x7 ]) * 1e6;
145 else
146 coeff_uV[ ch ] = (4.0 / (double)(1L << 24)) * 1e6;
147
148 ch_delay[ ch ] = calc_delay( ch );
149}
150
152{
153 constexpr static double data_rates[] = { 288000, 192000, 144000, 96000, 72000, 48000, 36000, 24000,
154 18000, 12000, 9000, 6000, 4500, 3000, 2250, 1125,
155 562.5, 400, 300, 200, 100, 60, 50, 30,
156 25, 20, 15, 10, 7.5, };
157 constexpr static uint16_t delays[] = { 0, 2, 4, 6, 8, 10, 12, 14,
158 16, 18, 20, 28, 38, 40, 42, 56,
159 64, 76, 90, 128, 154, 178, 204, 224,
160 256, 358, 512, 716,
161 1024, 1664, 3276, 7680, 19200, 23040, };
162
163 command( ch );
164
165 uint16_t ch_config1 = reg( Register16::CH_CONFIG1 );
166 uint16_t ch_config2 = reg( Register16::CH_CONFIG2 );
167
168 uint8_t adc_data_rate = (ch_config1 >> 3) & 0x001F;
169 uint8_t adc_sinc = (ch_config1 >> 0) & 0x0007;
170 uint8_t ch_delay = (ch_config2 >> 10) & 0x003F;
171 bool adc_normal_setting = (ch_config2 >> 9) & 0x0001;
172 bool ch_chop = (ch_config2 >> 7) & 0x0001;
173
174 double base_freq = data_rates[ adc_data_rate ];
175 double delay_setting = delays[ ch_delay ] / 4608000.00;
176
177 if ( (28 < adc_data_rate) || (4 < adc_sinc) || ((adc_data_rate < 12) && (adc_sinc)) )
178 return 0.00;
179
180 if ( !adc_normal_setting )
181 base_freq /= (adc_sinc + 1);
182
183 if ( ch_chop )
184 base_freq /= 2;
185
186#if 0
187 printf( "base_freq = %lf\r\n", base_freq );
188 printf( "delay_setting = %lf\r\n", delay_setting );
189 printf( "total delay = %lf\r\n", (1 / base_freq) + delay_setting );
190#endif
191
192 return (1 / base_freq) + delay_setting;
193}
194
195
196void NAFE13388_Base::logical_ch_config( int ch, uint16_t cc0, uint16_t cc1, uint16_t cc2, uint16_t cc3 )
197{
198 const ch_setting_t tmp_ch_config = { cc0, cc1, cc2, cc3 };
199 logical_ch_config( ch, tmp_ch_config );
200}
201
203{
204 const uint16_t clearingbit = 0x1 << ch;
205 const uint16_t bits = bit_op( Register16::CH_CONFIG4, ~clearingbit, ~clearingbit );
206
207 enabled_channels = bit_count( bits );
208}
209
211{
212 return reg( Register24::CH_DATA0 + ch );
213}
214
216{
217 command( ch );
218 command( CMD_SS );
219}
220
221void NAFE13388_Base::command( uint16_t com )
222{
223 write_r16( com );
224}
225
226void NAFE13388_Base::reg( Register16 r, uint16_t value )
227{
228 write_r16( static_cast<uint16_t>( r ), value );
229}
230
231void NAFE13388_Base::reg( Register24 r, uint32_t value )
232{
233 write_r24( static_cast<uint16_t>( r ), value );
234}
235
237{
238 return read_r16( static_cast<uint16_t>( r ) );
239}
240
242{
243 return read_r24( static_cast<uint16_t>( r ) );
244}
245
247{
248 return (static_cast<uint32_t>( reg( Register16::PN2 ) ) << 16) | reg( Register16::PN1 );
249}
250
252{
253 return reg( Register16::PN0 ) & 0xF;
254}
255
257{
258 uint64_t serial_number;
259
261 serial_number <<= 24;
263}
264
266{
267 return reg( Register16::DIE_TEMP ) / 64.0;
268}
269
271{
272 constexpr double pga1x_voltage = 5.0;
273 constexpr int adc_resolution = 24;
274 constexpr double pga_gain_setting = 0.2;
275
276 constexpr double fullscale_voltage = pga1x_voltage / pga_gain_setting;
277
278 double fullscale_data = pow( 2, (adc_resolution - 1) );
279 double ref_data_span = ref.high.data - ref.low.data;
280 double ref_voltage_span = ref.high.voltage - ref.low.voltage;
281
282 double dv_slope = ref_data_span / ref_voltage_span;
283 double custom_gain = dv_slope * (fullscale_voltage / fullscale_data);
284 double custom_offset = (dv_slope * ref.low.voltage - ref.low.data) / custom_gain;
285
286 int32_t gain_coeff_cal = reg( Register24::GAIN_COEFF0 + ref.cal_index );
287 int32_t offsset_coeff_cal = reg( Register24::OFFSET_COEFF0 + ref.cal_index );
288 int32_t gain_coeff_new = round( gain_coeff_cal * custom_gain );
289 int32_t offset_coeff_new = round( custom_offset - offsset_coeff_cal );
290
291#if 0
292 printf( "ref_point_high = %8ld @%6.3lf\r\n", ref.high.data, ref.high.voltage );
293 printf( "ref_point_low = %8ld @%6.3lf\r\n", ref.low.data, ref.low.voltage );
294 printf( "gain_coeff_new = %8ld\r\n", gain_coeff_new );
295 printf( "offset_coeff_new = %8ld\r\n", offset_coeff_new );
296#endif
297
298 reg( Register24::GAIN_COEFF0 + ref.coeff_index, gain_coeff_new );
299 reg( Register24::OFFSET_COEFF0 + ref.coeff_index, offset_coeff_new );
300}
301
302void NAFE13388_Base::recalibrate( int pga_gain_index, int channel_selection, int input_select, double reference_source_voltage, bool use_positive_side )
303{
304 constexpr auto low_gain_index = 4;
305 auto channel_in_use = false;
306 ch_setting_t tmp_ch_config;
307
308 if ( reg( Register16::CH_CONFIG4 ) & (0x1 << channel_selection) )
309 {
310 channel_in_use = true;
311
312 command( channel_selection );
313
314 for ( auto i = 0; i < 4; i++ )
315 tmp_ch_config[ i ] = reg( Register16::CH_CONFIG0 + i );
316 }
317
318 if ( !input_select )
319 {
320 if ( pga_gain_index <= low_gain_index )
321 {
322 input_select = 0x5; // REFH for low gain
323 reference_source_voltage = 2.30;
324 }
325 else
326 {
327 input_select = 0x6; // REFL for high gain
328 reference_source_voltage = 0.20;
329 }
330 }
331
332 const uint16_t REF_GND = 0x0011 | (pga_gain_index << 5);
333 const uint16_t REF_V = (input_select << (use_positive_side ? 12 : 8)) | REF_GND;
334 const uint16_t ch_config1 = (pga_gain_index << 12) | 0x00E4;
335 constexpr uint16_t ch_config2 = 0x8400;
336 constexpr uint16_t ch_config3 = 0x0000;
337
338 const ch_setting_t refh = { REF_V, ch_config1, ch_config2, ch_config3 };
339 const ch_setting_t refg = { REF_GND, ch_config1, ch_config2, ch_config3 };
340
341 logical_ch_config( channel_selection, refh );
342 raw_t data_REF = read<raw_t>( channel_selection );
343
344 logical_ch_config( channel_selection, refg );
345 raw_t data_GND = read<raw_t>( channel_selection );
346
347 constexpr double pga_gain[] = { 0.2, 0.4, 0.8, 1, 2, 4, 8, 16 };
348
349 const double fullscale_voltage = 5.00 / pga_gain[ pga_gain_index ];
350 const double calibrated_gain = pow( 2, 23 ) * (reference_source_voltage / fullscale_voltage) / (double)(data_REF - data_GND);
351
352#if 0
353 printf( "data_REF = %8ld\r\n", data_REF );
354 printf( "data_GND = %8ld\r\n", data_GND );
355 printf( "gain adjustment = %8lf (%lfdB)\r\n", calibrated_gain, 20 * log10( calibrated_gain ) );
356#endif
357
358 const double current_gain_coeff_value = (double)reg( Register24::GAIN_COEFF0 + pga_gain_index );
359 const uint32_t current_offset_coeff_value = reg( Register24::OFFSET_COEFF0 + pga_gain_index );
360
361 reg( Register24::GAIN_COEFF0 + pga_gain_index, (uint32_t)(current_gain_coeff_value * calibrated_gain) );
362 reg( Register24::OFFSET_COEFF0 + pga_gain_index, current_offset_coeff_value + data_GND );
363
364 if ( channel_in_use )
365 logical_ch_config( channel_selection, tmp_ch_config );
366 else
367 logical_ch_disable( channel_selection );
368}
369
371{
372}
373
374
375
376/* NAFE13388 class ******************************************/
377
378NAFE13388::NAFE13388( int nINT, int DRDY, int SYN, int nRESET )
379 : NAFE13388_Base( nINT, DRDY, SYN, nRESET )
380{
381}
382
386
387/* NAFE13388_UIM class ******************************************/
388
389NAFE13388_UIM::NAFE13388_UIM( int nINT, int DRDY, int SYN, int nRESET )
390 : NAFE13388_Base( nINT, DRDY, SYN, nRESET )
391{
392}
393
397
399{
400 uint16_t pattern[] = {
401 0x8000, 0x0040, 0x0100, 0x0080, 0x0200, 0x0400, 0x0800, 0x1000,
402 0x2000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0080,
403 0x0100, 0x0040,
404 };
405 reg( Register16::GPIO_CONFIG0, 0xFFC0 );
406 reg( Register16::GPIO_CONFIG1, 0xFFC0 );
407 reg( Register16::GPIO_CONFIG2, 0x0000 );
408
409 for ( auto j = 0; j < 2; j++ )
410 {
411 for ( auto i = 0U; i < sizeof( pattern ) / sizeof( uint16_t ); i++ )
412 {
413 reg( Register16::GPO_DATA, pattern[ i ] );
414 delay( 20 );
415 }
416 }
417
418 uint16_t pv = 0;
419
420 for ( auto j = 0; j < 4; j++ )
421 {
422 for ( auto i = 0; i < 10; i++ )
423 {
424 pv = (j % 2) ? pv & ~pattern[ i ] : pv | pattern[ i ];
425 reg( Register16::GPO_DATA, pv ); delay( 20 );
426 }
427 }
428}
429
430//double NAFE13388::coeff_uV[ 16 ];
int32_t raw_t
Definition AFE_NXP.h:22
virtual ~AFE_base()
Definition AFE_NXP.cpp:31
int pin_nINT
Definition AFE_NXP.h:115
virtual void begin(void)
Definition AFE_NXP.cpp:35
virtual void reset(bool hardware_reset=false)=0
int bit_count(uint32_t value)
Definition AFE_NXP.cpp:66
double coeff_uV[16]
Definition AFE_NXP.h:103
virtual void start(int ch)=0
void start_and_delay(int ch, float delay)
Definition AFE_NXP.cpp:57
AFE_base(int nINT, int DRDY, int SYN, int nRESET)
Definition AFE_NXP.cpp:16
int enabled_channels
Definition AFE_NXP.h:100
int pin_SYN
Definition AFE_NXP.h:117
static double delay_accuracy
Definition AFE_NXP.h:107
double ch_delay[16]
Definition AFE_NXP.h:106
T read(int ch, float delay=default_delay)
virtual void boot(void)=0
int pin_nRESET
Definition AFE_NXP.h:118
virtual int32_t adc_read(int ch)=0
int pin_DRDY
Definition AFE_NXP.h:116
virtual int32_t adc_read(int ch)
Definition AFE_NXP.cpp:210
virtual void boot(void)
Definition AFE_NXP.cpp:91
void gain_offset_coeff(const ref_points &ref)
Definition AFE_NXP.cpp:270
double calc_delay(int ch)
Definition AFE_NXP.cpp:151
virtual void command(uint16_t com)
Definition AFE_NXP.cpp:221
void blink_leds(void)
Definition AFE_NXP.cpp:370
uint32_t bit_op(T rg, uint32_t mask, uint32_t value)
Definition AFE_NXP.h:410
struct NAFE13388_Base::_ref_points ref_points
virtual void logical_ch_config(int ch, uint16_t cc0, uint16_t cc1, uint16_t cc2, uint16_t cc3)
Definition AFE_NXP.cpp:196
virtual void reg(Register16 r, uint16_t value)
Definition AFE_NXP.cpp:226
void recalibrate(int pga_gain_index, int channel_selection=15, int input_select=0, double reference_source_voltage=0, bool use_positive_side=true)
Definition AFE_NXP.cpp:302
uint8_t revision_number(void)
Definition AFE_NXP.cpp:251
NAFE13388_Base(int nINT, int DRDY, int SYN, int nRESET)
Definition AFE_NXP.cpp:82
uint64_t serial_number(void)
Definition AFE_NXP.cpp:256
virtual void logical_ch_disable(int ch)
Definition AFE_NXP.cpp:202
virtual ~NAFE13388_Base()
Definition AFE_NXP.cpp:87
virtual void reset(bool hardware_reset=false)
Definition AFE_NXP.cpp:100
uint32_t part_number(void)
Definition AFE_NXP.cpp:246
uint16_t[4] ch_setting_t
Definition AFE_NXP.h:131
float temperature(void)
Definition AFE_NXP.cpp:265
virtual void start(int ch)
Definition AFE_NXP.cpp:215
void blink_leds(void)
Definition AFE_NXP.cpp:398
virtual ~NAFE13388_UIM()
Definition AFE_NXP.cpp:394
NAFE13388_UIM(int nINT=3, int DRDY=4, int SYN=6, int nRESET=7)
Definition AFE_NXP.cpp:389
virtual ~NAFE13388()
Definition AFE_NXP.cpp:383
NAFE13388(int nINT=2, int DRDY=3, int SYN=5, int nRESET=6)
Definition AFE_NXP.cpp:378
int32_t read_r24(uint16_t reg)
void write_r24(uint16_t reg, uint32_t val)
uint16_t read_r16(uint16_t reg)
void write_r16(uint16_t reg)
reference_point high
Definition AFE_NXP.h:140
reference_point low
Definition AFE_NXP.h:141