//*************************************************************************
//* Hybrid program from: *
//* Tni, Greiman, Yannick and Leon *
//* *
//* for analog measurements and datalogging *
//*************************************************************************
#include <ADC.h>
#include <DMAChannel.h>
#include <array>
#include "SdFat.h"
#include <TimeLib.h>
/*PRÄ-------------------------------------------------------------*/
uint32_t BUF_DIM = 32768 ;
uint32_t FILE_SIZE = 0 , last = 0;
volatile size_t write_pos = 0;
volatile uint16_t adc_val = 0;
File file;
uint32_t duration = 0;
uint32_t bytes = 0;
float preceil = 0;
float scale = 0;
/*----------------------------------------------------------------*/
/*PINS------------------------------------------------------------*/
const uint8_t adc_pin = A9; // digital pin 23 for singleended
const uint8_t diff_pin1 = A10; // digital pin A10 for differential
const uint8_t diff_pin2 = A11; // digital pin A11 for differential
const uint8_t out_pin = 2; // PWM output
/*----------------------------------------------------------------*/
/*DECLARATIONS----------------------------------------------------*/
SdFatSdioEX sd ; // used to declare the sd.### object (Sdfat)
ADC adc; // used to declare the adc.### object
DMAChannel dma; // used to declare the dma.### object
std::array<volatile uint16_t, (uint32_t)128*512> buffer __attribute__ ((aligned (32*1024)));
char str[128] ;
typeof(*dma.TCD) tcd_mem[4] __attribute__ ((aligned (32))) ;
/*----------------------------------------------------------------*/
void setup()
{
Serial.begin(250000);
while(!Serial);
/*TimeSetup-------------------------------------------------------*/
setSyncProvider(getTeensy3Time);
if (timeStatus()!= timeSet) {
Serial.println("Unable to sync with the RTC");
} else {
Serial.println("Begin Setup\n");
}
/*----------------------------------------------------------------*/
/*ModeSetup-------------------------------------------------------*/
Serial.println("Please choose a measure-mode");
Serial.println("Singleended(1) or differential(2)");
delay(100);
while(Serial.available() == 0){
}
char c = Serial.read();
if (c != '1' && c != '2') {
Serial.println("Invalid input");
return;
}
if (c=='1'){
Serial.println("Singleended");
adc.adc0->analogRead(adc_pin);
} else{
Serial.println("Differential");
adc.adc0->startSingleDifferential(diff_pin1,diff_pin2);
}
delay(100);
/*----------------------------------------------------------------*/
/*SamplingRate----------------------------------------------------*/
Serial.println("Please choose a sampling rate[Hz]");
delay(100);
while(Serial.available() == 0){
}
const uint32_t pdbfreq = Serial.parseInt();
if (pdbfreq> 300000){
Serial.println("Sampling rate to high must be 10-300000[Hz)");
} else {
Serial.println("OK the sampling rate[Hz] is:");
Serial.println(pdbfreq);
}
delay(100);
/*----------------------------------------------------------------*/
/*FileSetup-------------------------------------------------------*/
Serial.println("Please choose a file name");
delay(100);
while(Serial.available() == 0){
}
String Date = String(year())+"."+String(month())+"."+String(day())+"-"+String(hour())+"."+String(minute());
String Name;
Name = Serial.readString();
String filename = Name + "_" + Date + ".bin";
char fname[30];
filename.toCharArray(fname,30);
if (! sd.begin()) { sd.initErrorHalt("SdFatSdio begin() failed"); } sd.chvol();
if (!file.open(fname, O_RDWR | O_CREAT)) { sd.errorHalt("open failed"); }
delay(100);
/*----------------------------------------------------------------*/
/*DurationSetup---------------------------------------------------*/
Serial.println("Please choose the duration[s] of the measurement");
delay(100);
while(Serial.available() == 0){
}
duration = Serial.parseInt();
bytes = ((duration*1000000)/(1000000/pdbfreq))* 2; //(duration/(1/pdbfreq))*(resolution/8)
preceil = bytes/BUF_DIM;
scale = ceil(preceil);
FILE_SIZE = (scale+2) * BUF_DIM;
delay(100);
/*----------------------------------------------------------------*/
Serial.println("Setup is done, enter any key to start");
while(Serial.available() == 0){
}
delay(1000);
/*----------------------------------------------------------------*/
/*HardcodedSetup-could be made variable---------------------------*/
pinMode ( LED_BUILTIN, OUTPUT );
pinMode ( adc_pin, INPUT );
pinMode ( diff_pin1, INPUT );
pinMode ( diff_pin2, INPUT );
adc.setAveraging ( 1 );
adc.setResolution ( 16,0 );
adc.setConversionSpeed ( ADC_CONVERSION_SPEED::HIGH_SPEED);
adc.setSamplingSpeed ( ADC_SAMPLING_SPEED::HIGH_SPEED );
//adc.enableCompare(1.0/3.3*adc.getMaxValue(ADC_0), 0, ADC_0);
//adc.enableCompareRange(1.0*adc.getMaxValue(ADC_0)/3.3, 2.0*adc.getMaxValue(ADC_0)/3.3, 0, 1, ADC_0); // ready if value lies out of [1.0,2.0] V
adc.setReference(ADC_REFERENCE::REF_3V3, ADC_0);
if(adc.adc0->fail_flag) { Serial.print("ADC error: "); Serial.println(adc.adc0->fail_flag, HEX); }
dma.source ( ADC0_RA);
dma.transferSize ( 2);
dma.triggerAtHardwareEvent (DMAMUX_SOURCE_ADC0);
/*----------------------------------------------------------------*/
// ********* y.j.**********
dma.TCD->CITER = 32*1024/2 ; dma.TCD->BITER = 32*1024/2 ; dma.TCD->DOFF = 2 ; dma.TCD->CSR = 0x10;
dma.TCD->DADDR = (volatile void*) &buffer [ 0*512] ; //Serial.println((uint32_t) &tcd_mem[0]);
dma.TCD->DLASTSGA = ( int32_t ) &tcd_mem[ 1] ; //print_config (&dma);
memcpy ( &tcd_mem[0], dma.TCD , 32 ) ;
dma.TCD->DADDR = (volatile void*) &buffer [32*512] ; //Serial.println((uint32_t) &tcd_mem[1]);
dma.TCD->DLASTSGA = ( int32_t ) &tcd_mem[ 2] ; //print_config (&dma);
memcpy ( &tcd_mem[1], dma.TCD , 32 ) ;
dma.TCD->DADDR = (volatile void*) &buffer [64*512] ; //Serial.println((uint32_t) &tcd_mem[2]);
dma.TCD->DLASTSGA = ( int32_t ) &tcd_mem[ 3] ; //print_config (&dma);
memcpy ( &tcd_mem[2], dma.TCD , 32 ) ;
dma.TCD->DADDR = (volatile void*) &buffer [96*512] ; //Serial.println((uint32_t) &tcd_mem[3]);
dma.TCD->DLASTSGA = ( int32_t ) &tcd_mem[ 0] ; //print_config (&dma);
memcpy ( &tcd_mem[3], dma.TCD , 32 ) ;
memcpy ( dma.TCD , &tcd_mem[0], 32 ) ; //Serial.println(" tcd0 back"); //print_config (&dma);
// *************
dma.enable();
adc.enableDMA(ADC_0);
adc.adc0->stopPDB();
adc.adc0->startPDB(pdbfreq);
NVIC_DISABLE_IRQ(IRQ_PDB); // we don't want or need the PDB interrupt
// analogWriteFrequency(out_pin, 1000); // PWM output on out_pin for testing purposes.
// analogWrite(out_pin, 127);
}
void loop()
{
while ( ((128*1024-1) & ( (int)dma.TCD->DADDR - last )) > BUF_DIM )
{
if (BUF_DIM != (uint32_t)file.write( (char*)&buffer[((last/2)&(64*1024-1))], BUF_DIM) ) { sd.errorHalt("write failed"); } ;
Serial.println("."); last += BUF_DIM ;
}
if ( last >= FILE_SIZE )
{
file.close(); Serial.println ("\n Done");
while(1) { digitalWriteFast(LED_BUILTIN, HIGH) ; delay(100) ; digitalWriteFast(LED_BUILTIN, LOW) ; delay(1000) ; }
} ;
delayMicroseconds(1); // can be decreased or suppressed (was just to play, try...)
}
void pdb_isr(void) { PDB0_SC &=~PDB_SC_PDBIF ; Serial.println("."); };
void print_config(DMAChannel* dma) {
Serial.print("channel \t"); Serial.println(dma->channel);
Serial.print("SADDR \t"); sprintf(str, "%8x", (unsigned int)dma->TCD->SADDR); Serial.println(str);
Serial.print("SOFF \t"); Serial.println((uint32_t)dma->TCD->SOFF);
Serial.print("ATTR \t"); Serial.println((uint32_t)dma->TCD->ATTR);
Serial.print("NBYTES \t"); Serial.println((uint32_t)dma->TCD->NBYTES);
Serial.print("SLAST \t"); Serial.println((uint32_t)dma->TCD->SLAST);
Serial.print("DADDR \t"); sprintf(str, "%8x", (unsigned int)dma->TCD->DADDR); Serial.println(str);
Serial.print("DOFF \t"); Serial.println((uint32_t)dma->TCD->DOFF);
Serial.print("CITER \t"); Serial.println((uint32_t)dma->TCD->CITER);
Serial.print("DLASTSGA\t"); Serial.println(( int32_t)dma->TCD->DLASTSGA);
Serial.print("CSR \t"); Serial.println((uint32_t)dma->TCD->CSR);
Serial.print("BITER \t"); Serial.println((uint32_t)dma->TCD->BITER);
Serial.println();
}
time_t getTeensy3Time()
{
return Teensy3Clock.get();
}