Code: Select all
// Include section -------------------------------------------
#include "soc/sens_reg.h"
// Define section---------------------------------------------
#define adcRes 12
#define dacPin 25 // DAC Channel 1 | GPIO25 | DAC_CHANNEL_1
// Structs section---------------------------------------------
// Library parameters ---------------------------------------------
// FreeRTOS
TaskHandle_t th_Task0, th_Task1, th_TaskS;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
volatile SemaphoreHandle_t task0Semaphore, task1Semaphore;
// ESP32-IDF
hw_timer_t *timer = NULL;
volatile uint32_t time_scale = 1814;
volatile uint32_t time_count = 1;
// Variables section---------------------------------------------
// Variables
volatile uint32_t isrCounter = 0, tsk0count = 0, tsk1count = 0;
volatile uint32_t lastIsrAt = 0;
volatile uint32_t isrCount = 0, isrTime = 0;
// ADC & DAC
volatile int16_t adcData;
volatile int16_t adcData0;
volatile uint8_t dacData = 127;
uint16_t dacInd = 0;
uint16_t sine[100]; // 440 Hz
// ****************************************************************
// Prototypes
// ****************************************************************
void IRAM_ATTR onTimer()
{
portENTER_CRITICAL_ISR(&timerMux);
adcData = sine[dacInd];
dacInd++;
if (dacInd == 100) dacInd = 0;
dacData = adcData0;
dacFastWrite25(dacData); // 3
isrCounter++;
portEXIT_CRITICAL_ISR(&timerMux);
//xSemaphoreGiveFromISR(task0Semaphore, NULL);
xSemaphoreGiveFromISR(task1Semaphore, NULL);
}
// ****************************************************************
void Task1(void* _par)
{
while(1)
{
if (xSemaphoreTake(task1Semaphore, 0) == pdTRUE)
{
isrTime = micros();
tsk1count++;
portENTER_CRITICAL(&timerMux);
adcData0 = adcData;
portEXIT_CRITICAL(&timerMux);
lastIsrAt += micros() - isrTime;
}
}
vTaskDelete(NULL);
}
// ****************************************************************
void Task0(void* _par)
{
while(1)
{
if (xSemaphoreTake(task0Semaphore, 0) == pdTRUE)
{
tsk0count++;
portENTER_CRITICAL(&timerMux);
adcData0 = adcData;
portEXIT_CRITICAL(&timerMux);
}
}
vTaskDelete(NULL);
}
// ****************************************************************
void startTimer()
{
timer = timerBegin(0, time_scale, true); // 1814 = 44100 kHz = 80000000/44100
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, time_count, true);
timerAlarmEnable(timer);
return;
}
// ****************************************************************
void setup()
{
BaseType_t bt_Task0, bt_Task1, bt_TaskS;
Serial.begin(115200);
adcData = 0;
for (int i = 0; i < 100; i++)
{
sine[i] = 127*sin((float)i*3.141516/50) + 127;
}
// Create semaphore to inform us when the timer has fired
task0Semaphore = xSemaphoreCreateBinary();
task1Semaphore = xSemaphoreCreateBinary();
bt_Task0 = xTaskCreatePinnedToCore(Task0, "Task0", 1024, NULL, 1,
&th_Task0, 0);
bt_Task1 = xTaskCreatePinnedToCore(Task1, "Task1", 1024, NULL, 1,
&th_Task1, 1);
startTimer();
dacAttachPin(dacPin);
// Disable Watch Dog Timer on Core 0, otherwise it keeps reseting ESP32
disableCore0WDT();
}
// ****************************************************************
void loop()
{
if (isrCounter > 44100)
{
portENTER_CRITICAL_ISR(&timerMux);
Serial.print("ISR duty cycle (%):");
Serial.print(lastIsrAt*100./1000000.);
Serial.print(" at ");
Serial.print(millis()/1000.);
Serial.print(" ");
Serial.print(tsk0count);
Serial.print(" ");
Serial.print(tsk1count);
Serial.println();
lastIsrAt = 0;
isrCounter = 0;
tsk0count = 0;
tsk1count = 0;
portEXIT_CRITICAL_ISR(&timerMux);
}
}
void dacAttachPin(uint8_t pin)
{
if(pin < 25 || pin > 26)
{
return;
}
pinMode(pin, ANALOG);
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_SW_TONE_EN);
if(pin == 25)
{
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN1_M);
SET_PERI_REG_BITS(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_DAC, 0, RTC_IO_PDAC1_DAC_S);
SET_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);
}
else
{
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN2_M);
SET_PERI_REG_BITS(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_DAC, 0, RTC_IO_PDAC2_DAC_S);
SET_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE);
}
}
void dacFastWrite25(uint8_t value)
{
SET_PERI_REG_BITS(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_DAC, value, RTC_IO_PDAC1_DAC_S);
}
void dacFastWrite26(uint8_t value)
{
SET_PERI_REG_BITS(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_DAC, value, RTC_IO_PDAC2_DAC_S);
}