AFE_NXP_Arduino 2.0.4
Analog Front-End (AFE) device operation sample code for Arduino
Loading...
Searching...
No Matches
NAFE33352.cpp
Go to the documentation of this file.
1
8
9#include "NAFE33352.h"
10#include <Arduino.h>
11#include <math.h>
12
16
21
22void NAFE33352_Base::LogicalChannel::configure( const uint16_t (&cc)[ 3 ] )
23{
24 const uint16_t tmp_ch_config[ 4 ] = { cc[ 0 ], cc[ 1 ], cc[ 2 ], 0 };
25 afe_ptr->open_logical_channel( ch_number, tmp_ch_config );
26}
27
28void NAFE33352_Base::LogicalChannel::configure( uint16_t cc0, uint16_t cc1, uint16_t cc2 )
29{
30 const uint16_t tmp_ch_config[ 4 ] = { cc0, cc1, cc2, 0 };
31 afe_ptr->open_logical_channel( ch_number, tmp_ch_config );
32}
33
37
41
42void NAFE33352_Base::DAC::configure( uint16_t cc0, uint16_t cc1, uint16_t cc2, uint16_t cc3, uint16_t cc4, uint16_t cc5 )
43{
44 const uint16_t tmp_ch_config[ 6 ] = { cc0, cc1, cc2, cc3, cc4, cc5 };
45 afe_ptr->open_dac_output( tmp_ch_config );
46}
47
48void NAFE33352_Base::DAC::configure( const uint16_t (&cc)[ 6 ] )
49{
50 afe_ptr->open_dac_output( cc );
51}
52
53void NAFE33352_Base::DAC::configure( ModeSelect mode, double full_scale_range )
54{
55 uint16_t default_dac_setting[ 6 ] = { 0x0000, 0x1000, 0x87FF, 0x0000, 0xE7FF, 0x0C00 };
56
57 output_mode = mode;
58
59 switch ( output_mode )
60 {
62 full_scale = 12.50;
63 default_dac_setting[ 0 ] |= 0x0002;
64 break;
66 full_scale = 12.50;
67 default_dac_setting[ 0 ] |= 0x6040;
68 break;
70 full_scale = 0.025 / 0.95;
71 default_dac_setting[ 0 ] |= 0x6061;
72 default_dac_setting[ 1 ] |= 0x1000;
73 break;
75 full_scale = 0.025;
76 default_dac_setting[ 0 ] |= 0x6061;
77 default_dac_setting[ 1 ] |= 0x1000;
78 break;
80 full_scale = 0.025;
81 default_dac_setting[ 0 ] |= 0x6000;
82 break;
84 full_scale = 0.025;
85 default_dac_setting[ 0 ] |= 0x7000;
86 break;
87 }
88
89 if ( 0.0 < full_scale_range ) // overwrite fullscale range if it is specified
90 full_scale = full_scale_range;
91
92 configure( default_dac_setting );
93}
94
95void NAFE33352_Base::DAC::configure( double full_scale_range )
96{
97 full_scale = full_scale_range;
98}
99
100void NAFE33352_Base::DAC::output( double value )
101{
102 afe_ptr->dac_out( value, full_scale, 18 );
103}
104
106{
107 output( value );
108 return *this;
109}
110
111
112
113/* NAFE33352_Base class ******************************************/
114
115NAFE33352_Base::NAFE33352_Base( bool spi_addr, bool hsv, int nINT, int DRDY, int SYN, int nRESET, int DRDY_input, int SYNCDAC )
116 : AFE_base( spi_addr, hsv, nINT, DRDY, SYN, nRESET, DRDY_input, SYNCDAC )
117{
118 for ( auto i = 0; i < 16; i++ )
119 {
120 logical_channel[ i ].afe_ptr = this;
121 logical_channel[ i ].ch_number = i;
122 }
123
124 dac.afe_ptr = this;
125}
126
130
131void NAFE33352_Base::txrx( uint8_t *data, int size, int cd_delay )
132{
133 SPI.beginTransaction( SPISettings( frequency, MSBFIRST, SPI_MODE1 ) );
134 digitalWrite( SS, LOW );
135 SPI.transfer( data, size );
136 delayMicroseconds( cd_delay );
137 digitalWrite( SS, HIGH );
138}
139
140void NAFE33352_Base::write_r24( uint16_t reg, uint32_t val )
141{
142 int cs_delay = (static_cast<uint16_t>(NAFE33352_Base::Register24::AO_DATA) == reg) ? 4 : 0;
143
144 reg <<= 1;
145
146 uint8_t v[] = { (uint8_t)(reg >> 8), (uint8_t)(reg & 0xFF), (uint8_t)(val >> 16), (uint8_t)(val >> 8), (uint8_t)val };
147 txrx( v, sizeof( v ), cs_delay );
148}
149
165
166void NAFE33352_Base::reset( bool hardware_reset )
167{
168 if ( hardware_reset )
169 Serial.println( "warning: UIOM doesn't have hardware RESET pin on the board. This reset will be ignored\r\n" );
170
172
173 constexpr uint16_t CHIP_READY = 1 << 13;
174 constexpr auto RETRY = 10;
175
176 for ( auto i = 0; i < RETRY; i++ )
177 {
178 delay( 1 );
179 if ( reg( NAFE33352_Base::Register16::SYS_STATUS ) & CHIP_READY )
180 return;
181 }
182
183 Serial.println( "NAFE33352 couldn't get ready. Check power supply or pin conections\r\n" );
184
185 while ( true )
186 ;
187
188}
189
190void NAFE33352_Base::open_dac_output( const uint16_t (&cc)[ 6 ] )
191{
192 for ( auto i = 0; i < 6; i++ )
194}
195
196
197void NAFE33352_Base::open_logical_channel( int ch, const uint16_t (&cc)[ 4 ] )
198{
199 static bool pga_enabled = false;
200 constexpr double pow2_24 = (double)(1L << 24);
201 double coeff = 0.00;
202 bool pga_on = false;
203
204 mux_setting[ ch ] = (cc[ 0 ] >> 3) & 0x1F;
205
207
208 switch ( mux_setting[ ch ] )
209 {
210 case VCM_VCM:
211 case GPIO0_GPIO1:
212 coeff = (20.00 * 2.50) / (12.5 * pow2_24);
213 break;
214 case AIP_AIN:
215 coeff = (20.00 * 2.50) / ((cc[ 0 ] & 0x0100 ? 16.00 : 1.00) * pow2_24);
216 pga_on = true;
217 break;
218 case AIP_VSNS:
219 case VSNS:
220 coeff = (20.00 * 2.50) / pow2_24;
221 pga_on = true;
222 break;
223 case AIP:
224 case AIN:
225 coeff = (20.00 * 2.50) / ((cc[ 0 ] & 0x0100 ? 16.00 : 1.00) * pow2_24);
226 pga_on = true;
227 break;
228 case ISNS:
229 coeff = (20.00 * 2.50) / (3.7989 * pow2_24);
230 break;
231 case TIA:
232 coeff = (20.00 * 2.50) / (2.50 * pow2_24);
233 break;
234 case GPIO0_VCM:
235 case VCM_GPIO1:
236 case REF_BYP__VCM:
237 case LDO:
238 case DAC_REF:
239 coeff = (20.00 * 2.50) / (12.5 * pow2_24) + 1.50;
240 break;
241 case VCM__REF_BYP:
242 coeff = (20.00 * 2.50) / (12.5 * pow2_24) - 1.50;
243 break;
244 case BG:
245 //coeff = (20.00 * 2.50) / (12.5 * pow2_24) - 1.50;
246 break;
247 case VADD:
248 coeff = (2.00 * 20.00 * 2.50) / (12.5 * pow2_24) - 1.50;
249 break;
250 case VHDD:
251 case VHSS:
252 coeff = (40.00 * 20.00 * 2.50) / (12.5 * pow2_24);
253 break;
254 }
255
256 coeff_V[ ch ] = coeff;
257
258 if ( pga_on && !pga_enabled )
259 {
261 pga_enabled = true;
262 }
263
264 for ( auto i = 0; i < 3; i++ )
266
268
269 ch_delay[ ch ] = calc_delay( ch );
270
271#if 0
272 Serial.print("lc[ ");
273 Serial.print(ch);
274 Serial.print("] : ");
275 Serial.println( ch_delay[ ch ], 10 );
276#endif
277}
278
280{
281 constexpr auto bit_length = 16;
283 total_delay = 0.00;
284
285 memset( sequence_order, 0, 16 );
286
287 for ( auto i = 0; i < bit_length; i++ )
288 {
289 if ( value & (0x1 << i) )
290 {
293 total_delay += ch_delay[ i ];
294 }
295 }
296
297#if 0
298 for ( auto i = 0; i < bit_length; i++ )
299 printf( " %x", sequence_order[ i ] );
300 printf( "\r\n" );
301#endif
302}
303
305{
306 constexpr double system_clock = 4608000.00;
307
308 constexpr static double data_rates[] = { 288000, 192000, 144000, 96000, 72000, 48000, 36000, 24000,
309 18000, 12000, 9000, 6000, 4500, 3000, 2250, 1125,
310 562.5, 400, 300, 200, 100, 60, 50, 30,
311 25, 20, 15, 10, 7.5, };
312 constexpr static uint16_t delays[] = { 0, 2, 4, 6, 8, 10, 12, 14,
313 16, 18, 20, 28, 38, 40, 42, 56,
314 64, 76, 90, 128, 154, 178, 204, 224,
315 256, 358, 512, 716,
316 1024, 1664, 3276, 7680, 19200, 23040, };
317
319
320 uint16_t ch_config1 = reg( NAFE33352_Base::Register16::AI_CONFIG1 );
321 uint16_t ch_config2 = reg( NAFE33352_Base::Register16::AI_CONFIG2 );
322
323 uint8_t adc_data_rate = (ch_config1 >> 3) & 0x001F;
324 uint8_t adc_sinc = (ch_config1 >> 0) & 0x0007;
325 uint8_t ch_delay = (ch_config2 >> 10) & 0x003F;
326 bool adc_normal_setting = (ch_config2 >> 9) & 0x0001;
327 bool ch_chop = (ch_config2 >> 7) & 0x0001;
328 double base_freq = data_rates[ adc_data_rate ];
329 double delay_setting = ((double)delays[ ch_delay ]) / system_clock;
330
331 if ( highspeed_variant )
332 {
333 base_freq *= 2.00;
334 delay_setting /= 2.00;
335 }
336
337 if ( (28 < adc_data_rate) || (4 < adc_sinc) || ((adc_data_rate < 12) && (adc_sinc)) )
338 return 0.00;
339
340 if ( !adc_normal_setting )
341 base_freq /= (adc_sinc + 1);
342
343 if ( ch_chop )
344 base_freq /= 2;
345
346#if 0
347 Serial.print( "adc_data_rate =" );
348 Serial.println( adc_data_rate );
349 Serial.print( "base_freq = " );
350 Serial.println( base_freq );
351 Serial.print( "delay_setting = " );
352 Serial.println( delay_setting, 10 );
353 Serial.print( "channel delay = " );
354 Serial.println( (1 / base_freq) + delay_setting, 10 );
355#endif
356
357 return (1 / base_freq) + delay_setting;
358}
359
360#pragma GCC diagnostic ignored "-Wunused-parameter"
361void NAFE33352_Base::open_logical_channel( int ch, uint16_t cc0, uint16_t cc1, uint16_t cc2, uint16_t dummy )
362{
363 const ch_setting_t tmp_ch_config = { cc0, cc1, cc2 };
364 open_logical_channel( ch, tmp_ch_config );
365}
366#pragma GCC diagnostic pop
367
369{
370 const uint16_t setbit = 0x1 << (ch + 8);
371 const uint16_t bits = bit_op( NAFE33352_Base::Register16::AI_MULTI_CH_EN, ~setbit, setbit );
372
373 channel_info_update( bits >> 8 );
374}
375
377{
378 const uint16_t clearingbit = 0x1 << (ch + 8);
379 const uint16_t bits = bit_op( NAFE33352_Base::Register16::AI_MULTI_CH_EN, ~clearingbit, ~clearingbit );
380
381 channel_info_update( bits >> 8 );
382}
383
389
395
400
405
407{
408 bit_op( NAFE33352_Base::Register16::AI_SYSCFG, ~0x0100, flag ? 0x0100 : 0x0000 );
409}
410
411int32_t NAFE33352_Base::read( int ch )
412{
414}
415
417{
418 burst( (uint32_t *)data, enabled_channels );
419}
420
422{
423 raw_t raw_data[ 16 ];
424
425 read( raw_data );
426
427 for ( auto i = 0; i < enabled_channels; i++ )
428 data[ i ] = raw2uv( sequence_order[ i ], raw_data[ i ] );
429}
430
431void NAFE33352_Base::dac_out( double vi, double full_scale, uint8_t bit_length )
432{
433 reg( NAFE33352_Base::Register24::AO_DATA, dac_code( vi, full_scale, bit_length ) );
434}
435
436int32_t NAFE33352_Base::dac_code( double a, double full_scale, uint8_t bit_length )
437{
438 int32_t fsv = (1L << (bit_length - 1));
439
440 int32_t v = (int32_t)((double)fsv * -a / full_scale);
441
442 v = v < -fsv ? -fsv : v;
443 v = v > (fsv - 1) ? (fsv - 1) : v;
444
445 return v << (24 - bit_length);
446}
447
448void NAFE33352_Base::command( uint16_t com )
449{
450 write_r16( com );
451}
452
453void NAFE33352_Base::reg( Register16 r, uint16_t value )
454{
455 write_r16( static_cast<uint16_t>( r ), value );
456}
457
458void NAFE33352_Base::reg( Register24 r, uint32_t value )
459{
460 write_r24( static_cast<uint16_t>( r ), value );
461}
462
464{
465 return read_r16( static_cast<uint16_t>( r ) );
466}
467
469{
470 return read_r24( static_cast<uint16_t>( r ) );
471}
472
474{
475 return (static_cast<uint64_t>( reg( NAFE33352_Base::Register16::PN2 ) ) << (16 + 8)) | static_cast<uint64_t>( reg( NAFE33352_Base::Register16::PN1 ) ) << 8 | reg( NAFE33352_Base::Register16::PN0_REV ) >> 8;
476}
477
479{
481}
482
491
493{
494 return ((int16_t)reg( NAFE33352_Base::Register16::DIE_TEMP )) / 64.0;
495}
496
497/* NAFE33352 class ******************************************/
498
499NAFE33352::NAFE33352( bool spi_addr, bool hsv, int nINT, int DRDY, int SYN, int nRESET, int DRDY_input, int SYNCDAC )
500 : NAFE33352_Base( spi_addr, hsv, nINT, DRDY, SYN, nRESET, DRDY_input, SYNCDAC )
501{
502}
503
507
508/* NAFE33352 class ******************************************/
509
510NAFE33352_UIOM::NAFE33352_UIOM( bool spi_addr, bool hsv, int nINT, int DRDY, int SYN, int nRESET, int DRDY_input, int SYNCDAC )
511 : NAFE33352_Base( spi_addr, hsv, nINT, DRDY, SYN, nRESET, DRDY_input, SYNCDAC )
512{
513}
514
int32_t raw_t
Definition AFE_NXP.h:22
double volt_t
Definition AFE_NXP.h:23
bool highspeed_variant
Definition AFE_NXP.h:224
double raw2uv(int ch, raw_t value)
Definition AFE_NXP.h:172
double coeff_V[16]
Definition AFE_NXP.h:247
int enabled_channels
Definition AFE_NXP.h:241
uint8_t sequence_order[16]
Definition AFE_NXP.h:244
AFE_base(bool spi_addr, bool highspeed_variant, int nINT, int DRDY, int SYN, int nRESET, int DRDY_input, int SYNCDAC)
Definition AFE_NXP.cpp:70
double ch_delay[16]
Definition AFE_NXP.h:253
int mux_setting[16]
Definition AFE_NXP.h:250
double total_delay
Definition AFE_NXP.h:254
AFE_base * afe_ptr
Definition AFE_NXP.h:314
void disable(void)
Definition AFE_NXP.cpp:19
NAFE33352_Base * afe_ptr
Definition NAFE33352.h:154
DAC & operator=(double value)
ModeSelect output_mode
Definition NAFE33352.h:156
void output(double value)
void configure(const uint16_t(&cc)[6])
Definition NAFE33352.cpp:48
void configure(const uint16_t(&cc)[3])
Definition NAFE33352.cpp:22
uint32_t bit_op(T rg, uint32_t mask, uint32_t value)
Definition NAFE33352.h:472
uint64_t part_number(void)
uint8_t revision_number(void)
virtual raw_t read(int ch)
void enable_logical_channel(int ch)
virtual void boot(void)
virtual void open_logical_channel(int ch, uint16_t cc0, uint16_t cc1, uint16_t cc2, uint16_t dummy)
virtual void write_r24(uint16_t reg, uint32_t val)
virtual void close_logical_channel(void)
void open_dac_output(const uint16_t(&cc)[6])
virtual void reset(bool hardware_reset=false)
virtual void command(uint16_t com)
virtual void start(void)
virtual ~NAFE33352_Base()
void channel_info_update(uint16_t value)
uint64_t serial_number(void)
int32_t dac_code(double a, double full_scale, uint8_t bit_length)
NAFE33352_Base(bool spi_addr, bool highspeed_variant, int nINT, int DRDY, int SYN, int nRESET, int DRDY_input, int SYNCDAC)
double calc_delay(int ch)
virtual void start_continuous_conversion()
uint16_t[4] ch_setting_t
Definition NAFE33352.h:19
virtual void dac_out(double vi, double full_scale, uint8_t bit_length)
virtual void DRDY_by_sequencer_done(bool flag=true)
virtual void txrx(uint8_t *data, int size, int cs_delay=0)
float temperature(void)
LogicalChannel logical_channel[16]
Definition NAFE33352.h:91
virtual void reg(Register16 r, uint16_t value)
virtual ~NAFE33352_UIOM()
NAFE33352_UIOM(bool spi_addr=0, bool highspeed_variant=false, int nINT=7, int DRDY=4, int SYN=14, int nRESET=14, int DRDY_input=2, int SYNCDAC=14)
NAFE33352(bool spi_addr=0, bool highspeed_variant=false, int nINT=7, int DRDY=4, int SYN=14, int nRESET=14, int DRDY_input=2, int SYNCDAC=14)
virtual ~NAFE33352()
virtual int32_t read_r24(uint16_t reg)
virtual uint16_t read_r16(uint16_t reg)
virtual void burst(uint32_t *data, int length, int width=3)
uint32_t frequency
Definition SPI_for_AFE.h:83
virtual void write_r16(uint16_t reg)