Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
Bexin3 authored Jan 23, 2023
0 parents commit 2df752b
Show file tree
Hide file tree
Showing 18 changed files with 883 additions and 0 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Compatible with SAMC21, more description will be added soon, check examples to use the code. Its still in alpha.

This is to make SAMC21 functions faster same way as the SAMD21 speeduino, however it is not yet complete nor tested on a board as i am still waiting for one. Some features are also missing, while you can take advantage of two ADCs.


With centered analog read you can have relative ground on A0 which is half of supply voltage to compare against.

Function descriptions and time they take:
Simplified:

AnalogBegin(); - starts the ADC0 and attaches it to clock number 3. You can add one number inside to set resolution, deffault is 12 bit, possible are 8 10 and 12, then if you add one it will enable mode that centers values at half of the supply voltage, which now appears at pin A0, so you have negative and positive values, and after if you add 1 ADC will run in a freerun mode - it will keep taking reads again and again. Full form is AnalogBegin(Resolution, Centering, Freerun) ~ 30us

AnalogBegin0(); - starts ADC0

AnalogBegin1(); - starts ADC1

FastAnalogRead(pin); - Attaches the Analog pin and reads it, returns an integer. ~ 3us

AttachADC0(pin, centering) - Attaches to an analog pin and sets gain ~ 20us

AttachADC1(pin, centering) - Attaches to an analog pin and sets gain ~ 20us

Analog0Collect() - Reads and collects an analog value from last attached pin to ADC0 ~ 3us, but bit less than FastAnalogRead

Analog1Collect() - Reads and collects an analog value from last attached pin to ADC1 ~ 3us, but bit less than FastAnalogRead

PWMBegin(pin, frequency) - begins running a pin at a specified frequency while attaching it to clock 8, minimum is 1 hz - calls PWMSetup. ~ 87us

PWMDuty(pin, dutycycle) - Sets the duty cycle at a specified number, in fractions. ~ 7us

PWMFrequency(pin, frequency) - changes the frequency, minimum 1 hz, if the pin previously had lower frequency selected may cause issues. ~40us

PWMSetup(pin, frequency, clock, Interrupts) - enables PWM, at a specidied pin, frequency which can go down to 0.00281 but it changes clock divisions, use clock 3-8. Enabling interrupts will make it call to Tch(); where you return duty cycle so it changes every cycle. ~ 124us, ~ 80us with frequency above 1hz


56 changes: 56 additions & 0 deletions examples/Analog_to_PWM/Analog_to_PWM.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "Snowduino.h"


const int ADCpin = 2; //Pin for ADC, 0 cant be used in IDACRed mode as it has the DAC tied to it. AO can be used for ref GND for sound card with sound pin to ADCpin. On zero, 2 stands for A1
int PWMpin = 13; //PWM pin, 13 is usually connected to LED so you can see it working.

const float Frequency = 10.0f; //PWM frequency, higher the frequency lower resolution. Wont work below 0.00281 hz wont work
const int ADCDiv = 5; //Set up dividor of time for ADC, with high PWM frequencies high values may let the Duty period only to change every few cycles, while too low values may lead to less stable output. Up to 255.
const int Samples = 1; //Ammount of ADC samples, can be 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 or 1028
int gain = 1; //1, 2, 4, 8, 16, 32, multiplier of input, only goes up to 16 in ICADRef mode
const int res = 12; //Set up Resolution of the ADC, 8 or 10 or 12 bits

/* Calibration */
int16_t minv = -2048; //Minimum meassured value of the input signal, make sure the value doesnt go below
int16_t maxv = 2047; //Maximum meassured value og the input signal

/* DAC AREF */
const bool IDACRef = 1; //Use DAC as a reference instead of GND
const int BaseV = 512; //0-1024 base voltage, 512 works the best as VCC/2

const bool Interrupt = 1; //Enable PWM Interrupts

const int ADCClk = 3; //Selects ADC clock generator, both to be between 3-8
const int PWMClk = 4; //Selects PWM clock generator, they cant be the same.

//Not to be changed
int16_t Range; //Value dividor here Select between 3-8
int16_t Analog; //Analog read values go here
int Period; //Time period calculated here


void setup() {


Range = (maxv - minv);
Period = PWMSetup(PWMpin, Frequency, PWMClk, 1); //Sets up PWM
ADC0Setup(IDACRef, res, Samples, ADCClk, ADCDiv, BaseV, 0, 0);
AttachADC0(ADCpin, IDACRef);


}


//Shared TCC handler
int Tch() {
ADC0->INTFLAG.reg = ADC_INTFLAG_RESRDY; //Wait for new analog value to be ready
Analog = ADC0->RESULT.reg; //Write it down
ADC0->SWTRIG.bit.START = true; //Start reading again
return (Period * (Analog - minv) / Range); //Value to be set for next Period
}


/* Repeating code */
void loop() {
}

18 changes: 18 additions & 0 deletions examples/BasicPWM/BasicPWM.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "Snowduino.h"

int pin = 13;
float frequency = 2.0f;


void setup() {
PWMBegin(pin, frequency);
}

void loop() {
PWMDuty(13, 0.2f); //second number is the duty cycle fraction
delay(10000);
PWMFrequency(13, 20.0f);
PWMDuty(13, 0.8f);
delay(10000);
PWMFrequency(13, 2.0f);
}
11 changes: 11 additions & 0 deletions examples/CenteredAnalogRead/CenteredAnalogRead.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "Snowduino.h"

void setup() {
Analog0Begin();
AttachADC0(2, 1);
Serial.begin(9600);
}

void loop() {
Serial.println(Analog0Collect());
}
18 changes: 18 additions & 0 deletions examples/FastAnalogRead/FastAnalogRead.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

#include "Snowduino.h"



void setup() {
AnalogBegin();
Serial.begin(115200);
}



/* Repeating code */
void loop() {
Serial.println(FastAnalogRead(0));
}


11 changes: 11 additions & 0 deletions library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name=Snowduino
version=0.0.1
author=Bexin Bexin#1128
maintainer=Bexin [email protected]
sentence=A library with faster commands for SAMC21
paragraph=Faster ADC and PWM
category=Optimalization
url=https://github.com/Bexin3/FastDuino
architectures=samd
includes=Snowduino.h

203 changes: 203 additions & 0 deletions src/ADCSetup.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
#include "ADCSetup.h"

bool mp = 0;
int16_t anv = 0;



void ADC0Setup(bool DacRef, int Res, int Samp, int ADCClk, int ADCDiv, int BaseV, bool Freerun, bool PreDiv) {

/* genericClockSetup(ADCClk, ADCDiv); //Sets up ADC clock and divides it
AttachClock(ADCClk, 0x1E);
if (DacRef) {
DACSetup(BaseV); //Setup DAC if needed
};
*/
ADC0->CALIB.reg = ADC_CALIB_BIASCOMP(0x7) | ADC_CALIB_BIASREFBUF(0x7);

ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val;



if (PreDiv) {
if (Res == 8) {
ADC0->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV2_Val;
ADC0->CTRLC.bit.RESSEL = ADC_CTRLC_RESSEL_8BIT_Val;
} else if (Res == 10) {
ADC0->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV2_Val;
ADC0->CTRLC.bit.RESSEL = ADC_CTRLC_RESSEL_10BIT_Val;
} else if (Res == 12) {
ADC0->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV2_Val;
ADC0->CTRLC.bit.RESSEL = ADC_CTRLC_RESSEL_12BIT_Val;
} else {
Serial.println("Unsupported resolution, change the value res to 8 10 or 12");
};
} else {
if (Res == 8) {
ADC0->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV2_Val;
ADC0->CTRLC.bit.RESSEL = ADC_CTRLC_RESSEL_8BIT_Val;
} else if (Res == 10) {
ADC0->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV2_Val;
ADC0->CTRLC.bit.RESSEL = ADC_CTRLC_RESSEL_10BIT_Val;
} else if (Res == 12) {
ADC0->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV8_Val;
ADC0->CTRLC.bit.RESSEL = ADC_CTRLC_RESSEL_12BIT_Val;
} else {
Serial.println("Unsupported resolution, change the value res to 8 10 or 12");
};
};

if (DacRef) {
ADC0->CTRLC.bit.DIFFMODE = 1;
};


ADC0->AVGCTRL.bit.SAMPLENUM = log2(Samp);

ADC0->CTRLC.bit.FREERUN = 0;

ADC0->CTRLA.bit.ENABLE = 1;


}


void AttachADC0(int ADCpin, bool IDACRefon) {

if (IDACRefon) {
ADC0->INPUTCTRL.bit.MUXNEG = 0;
ADC0->INPUTCTRL.bit.MUXPOS = ADCpin;
} else {
ADC0->INPUTCTRL.bit.MUXNEG = 0x18;
ADC0->INPUTCTRL.bit.MUXPOS = ADCpin;
};

}

void AnalogBegin(int resolution, bool midphase, bool Freerun) {
Analog0Begin(resolution, midphase, Freerun);
}
void Analog0Begin(int resolution, bool midphase, bool Freerun) {

ADC0Setup(midphase, resolution, 1, 3, 1, 512, Freerun, 1);
mp = midphase;

}


int Analog0Collect() {
ADC0->SWTRIG.bit.START = true; //Start reading again
while (ADC0->INTFLAG.reg == ADC_INTFLAG_RESRDY) {}; //Wait for new analog value to be ready
anv = ADC0->RESULT.reg;
return(anv);
}


int FastAnalogRead(int pin) {
if (mp) {
ADC0->INPUTCTRL.bit.MUXNEG = 0;
ADC0->INPUTCTRL.bit.MUXPOS = pin;
} else {
ADC0->INPUTCTRL.bit.MUXNEG = 0x18;
ADC0->INPUTCTRL.bit.MUXPOS = pin;
};
//while (ADC->STATUS.bit.SYNCBUSY) {};
ADC0->SWTRIG.bit.START = true; //Start reading again
while (ADC0->INTFLAG.reg == ADC_INTFLAG_RESRDY) {}; //Wait for new analog value to be ready
anv = ADC0->RESULT.reg;
return(anv); //Write it down
}






void ADC1Setup(bool DacRef, int Res, int Samp, int ADCClk, int ADCDiv, int BaseV, bool Freerun, bool PreDiv) {

/* genericClockSetup(ADCClk, ADCDiv); //Sets up ADC clock and divides it
AttachClock(ADCClk, 0x1E);
if (DacRef) {
DACSetup(BaseV); //Setup DAC if needed
};
*/
ADC1->CALIB.reg = ADC_CALIB_BIASCOMP(0x7) | ADC_CALIB_BIASREFBUF(0x7);

ADC1->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val;



if (PreDiv) {
if (Res == 8) {
ADC1->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV2_Val;
ADC1->CTRLC.bit.RESSEL = ADC_CTRLC_RESSEL_8BIT_Val;
} else if (Res == 10) {
ADC1->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV2_Val;
ADC1->CTRLC.bit.RESSEL = ADC_CTRLC_RESSEL_10BIT_Val;
} else if (Res == 12) {
ADC1->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV2_Val;
ADC1->CTRLC.bit.RESSEL = ADC_CTRLC_RESSEL_12BIT_Val;
} else {
Serial.println("Unsupported resolution, change the value res to 8 10 or 12");
};
} else {
if (Res == 8) {
ADC1->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV2_Val;
ADC1->CTRLC.bit.RESSEL = ADC_CTRLC_RESSEL_8BIT_Val;
} else if (Res == 10) {
ADC1->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV2_Val;
ADC1->CTRLC.bit.RESSEL = ADC_CTRLC_RESSEL_10BIT_Val;
} else if (Res == 12) {
ADC1->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV8_Val;
ADC1->CTRLC.bit.RESSEL = ADC_CTRLC_RESSEL_12BIT_Val;
} else {
Serial.println("Unsupported resolution, change the value res to 8 10 or 12");
};
};

if (DacRef) {
ADC1->CTRLC.bit.DIFFMODE = 1;
};


ADC1->AVGCTRL.bit.SAMPLENUM = log2(Samp);

ADC1->CTRLC.bit.FREERUN = 0;

ADC1->CTRLA.bit.ENABLE = 1;


}


void AttachADC1(int ADCpin, bool IDACRefon) {

if (IDACRefon) {
ADC1->INPUTCTRL.bit.MUXNEG = 0;
ADC1->INPUTCTRL.bit.MUXPOS = ADCpin;
} else {
ADC1->INPUTCTRL.bit.MUXNEG = 0x18;
ADC1->INPUTCTRL.bit.MUXPOS = ADCpin;
};

}


void Analog1Begin(int resolution, bool midphase, bool Freerun) {

ADC1Setup(midphase, resolution, 1, 3, 1, 512, Freerun, 1);
mp = midphase;

}


int Analog1Collect() {
ADC1->SWTRIG.bit.START = true; //Start reading again
while (ADC1->INTFLAG.reg == ADC_INTFLAG_RESRDY) {}; //Wait for new analog value to be ready
anv = ADC1->RESULT.reg;
return(anv);
}


20 changes: 20 additions & 0 deletions src/ADCSetup.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef ADCSetup_h
#define ADCSetup_h

#include <Arduino.h>

void ADC0Setup(bool DacRef, int Res, int Samp, int ADCClk, int ADCDiv, int BaseV, bool Freerun, bool PreDiv);
void ADC1Setup(bool DacRef, int Res, int Samp, int ADCClk, int ADCDiv, int BaseV, bool Freerun, bool PreDiv);
void genericClockSetup(int clk, int dFactor);
void AttachClock(int clk, int clkid);
void AttachADC0(int ADCpin = 0, bool IDACRefon = 0);
void AttachADC1(int ADCpin = 0, bool IDACRefon = 0);
void DACSetup(int BaseV);
void AnalogBegin(int resolution = 12, bool midphase = 0, bool Freerun = 0);
void Analog0Begin(int resolution = 12, bool midphase = 0, bool Freerun = 0);
void Analog1Begin(int resolution = 12, bool midphase = 0, bool Freerun = 0);
int FastAnalogRead(int pin);
int Analog0Collect();
int Analog1Collect();

#endif
18 changes: 18 additions & 0 deletions src/ClockSetup.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "ClockSetup.h"

void genericClockSetup(int clk, int dFactor) {


GCLK->GENCTRL[clk].bit.IDC;
GCLK->GENCTRL[clk].bit.DIV = dFactor;
GCLK->GENCTRL[clk].bit.GENEN;
GCLK->GENCTRL[clk].bit.SRC = GCLK_GENCTRL_SRC_OSC48M_Val;


}



void AttachClock(int clk, int clkid) {
GCLK->PCHCTRL[clkid].bit.GEN = clk;
}
Loading

0 comments on commit 2df752b

Please sign in to comment.