diff --git a/examples/Platforms/UnoR4/ADCtoDAC_UnoR4/ADCtoDAC_UnoR4.ino b/examples/Platforms/UnoR4/ADCtoDAC_UnoR4/ADCtoDAC_UnoR4.ino new file mode 100644 index 0000000..e00efc3 --- /dev/null +++ b/examples/Platforms/UnoR4/ADCtoDAC_UnoR4/ADCtoDAC_UnoR4.ino @@ -0,0 +1,36 @@ + +#include +AutoAnalog aaAudio; + +#define bufferSize 256 + +void setup() { + Serial.begin(115200); + Serial.println("Analog Audio Begin"); + + //Set pins low for MAX9814 microphone AR and GAIN pins + pinMode(7,OUTPUT); + digitalWrite(7,LOW); + + pinMode(8,OUTPUT); + digitalWrite(8,LOW); + + + aaAudio.begin(3, 3); //Setup aaAudio using DAC and ADC + aaAudio.dacBitsPerSample = 16; + aaAudio.adcBitsPerSample = 16; + aaAudio.setSampleRate(44100); + +} + +void loop() { + + aaAudio.getADC(bufferSize); + + // Copy our 14-bit ADC data to the DAC buffer which is only 12-bit + // The dac input expects signed 16-bit samples, and the ADC will output signed 16-bit samples + for(int i=0; i +#include + +AutoAnalog aaAudio; +RF24 radio(7,8); + +uint8_t address[6] = { "1Node" }; +#define bufferSize 16 + +void setup() { + Serial.begin(115200); + while(!Serial){} + Serial.println("Analog Audio Begin"); + + radio.begin(); + radio.setChannel(23); + radio.setPayloadSize(32); + radio.setAutoAck(0); + radio.openReadingPipe(1, address); + radio.startListening(); + + aaAudio.begin(0, 3); //Setup aaAudio using DAC and ADC + aaAudio.dacBitsPerSample = 16; + aaAudio.adcBitsPerSample = 16; + aaAudio.setSampleRate(44100); + +} + +uint32_t timer = millis(); + +void loop() { + + if(radio.available()){ + if(millis() - timer > 1000){ + Serial.println("Data received"); + timer = millis(); + } + radio.read(aaAudio.dacBuffer16, bufferSize * 2); // Each 16-bit sample takes up 2 bytes + aaAudio.feedDAC(0,bufferSize); + } +} diff --git a/examples/Platforms/UnoR4/RadioTX_UnoR4/RadioTX_UnoR4.ino b/examples/Platforms/UnoR4/RadioTX_UnoR4/RadioTX_UnoR4.ino new file mode 100644 index 0000000..23b5bba --- /dev/null +++ b/examples/Platforms/UnoR4/RadioTX_UnoR4/RadioTX_UnoR4.ino @@ -0,0 +1,42 @@ + +#include +#include + +AutoAnalog aaAudio; +RF24 radio(7,8); + +uint8_t address[6] = { "1Node" }; + +#define bufferSize 16 + +void setup() { + Serial.begin(115200); + Serial.println("Analog Audio Begin"); + + //Set pins low for MAX9814 microphone AR and GAIN pins + pinMode(5,OUTPUT); + digitalWrite(5,LOW); + + pinMode(6,OUTPUT); + digitalWrite(6,LOW); + + radio.begin(); + radio.setChannel(23); + radio.setPayloadSize(32); + radio.setAutoAck(0); + radio.openWritingPipe(address); + radio.stopListening(); + + aaAudio.begin(3, 0); //Setup aaAudio using DAC and ADC + aaAudio.dacBitsPerSample = 16; + aaAudio.adcBitsPerSample = 16; + aaAudio.setSampleRate(44100); + radio.printDetails(); +} + +void loop() { + + aaAudio.getADC(bufferSize); // Get buffersize of 16-bit samples + radio.writeFast(aaAudio.adcBuffer16, bufferSize * 2); // Each 16-bit sample takes up 2 bytes + +} diff --git a/examples/Platforms/UnoR4/SD_Playback_DAC_Auto_UnoR4/SD_Playback_DAC_Auto_UnoR4.ino b/examples/Platforms/UnoR4/SD_Playback_DAC_Auto_UnoR4/SD_Playback_DAC_Auto_UnoR4.ino new file mode 100644 index 0000000..8efc562 --- /dev/null +++ b/examples/Platforms/UnoR4/SD_Playback_DAC_Auto_UnoR4/SD_Playback_DAC_Auto_UnoR4.ino @@ -0,0 +1,127 @@ +/* + AutoAnalogAudio streaming via DAC & ADC by TMRh20 + Copyright (C) 2016 TMRh20 - tmrh20@gmail.com, github.com/TMRh20 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Auto Analog Audio (Automatic DAC, ADC & Timer) library + + Auto Analog Audio Library Information: + http://github.com/TMRh20 + http://tmrh20.blogspot.com + + This example automatically determines the format of WAV files & + attempts to play them. +*/ + +#include +#include +#include + +AutoAnalog aaAudio; + + +float volumeControl = 0.2; +#define BUFFER_SIZE 256 + +void setup() { + + Serial.begin(115200); + + Serial.print("Init SD card..."); + if (!SD.begin(2)) { + Serial.println("init failed!"); + return; + } + Serial.println("init ok"); + Serial.println("Analog Audio Begin"); + aaAudio.begin(0, 3); //Setup aaAudio using DAC and I2S + + pinMode(6, OUTPUT); //Connected to SD pin of MAX98357A + digitalWrite(6, HIGH); + + playAudio("brick/brick24.wav"); // 24kHz @ 16-bits is about the maximum when reading from SD card + +} + +void loop() { + + loadBuffer(); + + + if (Serial.available()) { + char c = Serial.read(); + if (c == '=') { + volumeControl += 0.1; + } else if (c == '-') { + volumeControl -= 0.1; + volumeControl = max(0.0, volumeControl); + } else if (c == 'p') { + playAudio("libra/lb16b44k.wav"); + } + Serial.println(volumeControl); + } +} + +/*********************************************************/ +/* A simple function to handle playing audio files +/*********************************************************/ + +File myFile; + +void playAudio(char *audioFile) { + + if (myFile) { + myFile.close(); + } + //Open the designated file + myFile = SD.open(audioFile); + + myFile.seek(22); + uint16_t var; + uint32_t var2; + myFile.read(&var, 2); // Get channels (Stereo or Mono) + myFile.read(&var2, 4); // Get Sample Rate + aaAudio.setSampleRate(var2, var - 1); + myFile.seek(34); + myFile.read(&var, 2); // Get Bits Per Sample + aaAudio.dacBitsPerSample = var; + + myFile.seek(44); //Skip past the WAV header +} + +void loadBuffer() { + + if (myFile.available()) { + + if (aaAudio.dacBitsPerSample == 8) { + myFile.read(aaAudio.dacBuffer, BUFFER_SIZE); // Change this to dacBuffer16 for 16-bit samples + for (uint32_t i = 0; i < BUFFER_SIZE; i++) { + aaAudio.dacBuffer[i] *= volumeControl; + } + aaAudio.feedDAC(0, BUFFER_SIZE); // change this to 3200 for 16-bit samples + } else { + myFile.read(aaAudio.dacBuffer16, BUFFER_SIZE); // Change this to dacBuffer16 for 16-bit samples + for (uint32_t i = 0; i < BUFFER_SIZE / 2; i++) { + int16_t sample = aaAudio.dacBuffer16[i]; + sample *= volumeControl; + aaAudio.dacBuffer16[i] = (uint16_t)sample; + } + aaAudio.feedDAC(0, BUFFER_SIZE / 2); // change this to 3200 for 16-bit samples + } + + } else { + myFile.seek(44); + } +} diff --git a/examples/Platforms/UnoR4/WiFi_TX_UnoR4/WiFi_TX_UnoR4.ino b/examples/Platforms/UnoR4/WiFi_TX_UnoR4/WiFi_TX_UnoR4.ino new file mode 100644 index 0000000..11c60bb --- /dev/null +++ b/examples/Platforms/UnoR4/WiFi_TX_UnoR4/WiFi_TX_UnoR4.ino @@ -0,0 +1,151 @@ +#include +#include "WiFiS3.h" +#include +#include "secrets.h" + +char ssid[] = SECRET_SSID; +char pass[] = SECRET_PASS; +int status = WL_IDLE_STATUS; + +/*********************** USER CONFIG ****************************/ +const char* myName = "Arduino-R4"; +const char* targetIP = "10.10.1.174"; +const uint16_t targetPort = 5004; + +// Set the above targetIP to the IP of your VLC machine +// In VLC open a Network Stream at rtp://@:5004 + +/********************************************************/ + +// RTP Configuration - 8-bit PCM at 8kHz +const uint8_t RTP_PAYLOAD_TYPE = 0; // PCMU (will work for raw PCM too) +const uint16_t SAMPLE_RATE = 8000; +const uint16_t SAMPLES_PER_PACKET = 512; + +uint16_t rtp_sequence = 0; +uint32_t rtp_timestamp = 0; +uint32_t rtp_ssrc = 0x12345678; + +AutoAnalog aaAudio; +WiFiUDP udp; + +#define bufferSize 512 + +void setup() { + Serial.begin(115200); + + modem.begin(); + WiFi.setHostname(myName); + + String fv = WiFi.firmwareVersion(); + if (fv < WIFI_FIRMWARE_LATEST_VERSION) { + Serial.println("Please upgrade the firmware"); + } + + while (status != WL_CONNECTED) { + Serial.print("Attempting to connect to WPA SSID: "); + Serial.println(ssid); + status = WiFi.begin(ssid, pass); + delay(10000); + } + Serial.print("IP Address: "); + Serial.println(WiFi.localIP()); + + Serial.println("Analog Audio Begin"); + pinMode(5, OUTPUT); + digitalWrite(5, LOW); + pinMode(6, OUTPUT); + digitalWrite(6, LOW); + + aaAudio.begin(3, 0); + aaAudio.dacBitsPerSample = 16; + aaAudio.adcBitsPerSample = 16; + aaAudio.setSampleRate(8000); + + udp.begin(4444); +} + +uint32_t timer = millis(); +uint32_t packetCount = 0; + + +void loop() { + aaAudio.getADC(bufferSize); + + + uint8_t finalBuf[bufferSize]; + for(int i=0; i 1000){ + timer = millis(); + Serial.print("Packets/sec: "); + Serial.print(packetCount); + Serial.print(" | Seq: "); + Serial.print(rtp_sequence); + Serial.print(" | TS: "); + Serial.println(rtp_timestamp); + packetCount = 0; + } +} + +void sendRTPPacket(uint8_t* payload, int payload_len) { + uint8_t rtpPacket[12 + payload_len]; + + rtpPacket[0] = 0x80; + rtpPacket[1] = (0 << 7) | RTP_PAYLOAD_TYPE; + + rtpPacket[2] = (rtp_sequence >> 8) & 0xFF; + rtpPacket[3] = rtp_sequence & 0xFF; + rtp_sequence++; + + rtpPacket[4] = (rtp_timestamp >> 24) & 0xFF; + rtpPacket[5] = (rtp_timestamp >> 16) & 0xFF; + rtpPacket[6] = (rtp_timestamp >> 8) & 0xFF; + rtpPacket[7] = rtp_timestamp & 0xFF; + rtp_timestamp += SAMPLES_PER_PACKET; + + rtpPacket[8] = (rtp_ssrc >> 24) & 0xFF; + rtpPacket[9] = (rtp_ssrc >> 16) & 0xFF; + rtpPacket[10] = (rtp_ssrc >> 8) & 0xFF; + rtpPacket[11] = rtp_ssrc & 0xFF; + + memcpy(&rtpPacket[12], payload, payload_len); + + udp.beginPacket(targetIP, targetPort); + udp.write(rtpPacket, 12 + payload_len); + udp.endPacket(); +} + +uint8_t encodePcm16ToPcmu(int16_t sample) { + // 1. Extract sign bit (0x80 for negative, 0x00 for positive) + uint8_t sign = (sample < 0) ? 0x80 : 0x00; + if (sample < 0) { + // Convert to absolute value safely handling INT16_MIN + sample = (sample == INT16_MIN) ? INT16_MAX : -sample; + } + + // 2 & 3. Add G.711 bias and clip to max 15-bit value + sample += 33; + if (sample > 32767) { + sample = 32767; + } + + // 4. Determine exponent (chord) + // Find the position of the highest set bit + int16_t exponent = 7; + for (int16_t mask = 0x4000; (sample & mask) == 0 && exponent > 0; mask >>= 1) { + exponent--; + } + + // 5. Extract mantissa (step) - 4 bits following the leading 1 + uint8_t mantissa = (sample >> (exponent + 3)) & 0x0F; + + // 6. Combine and flip all bits (G.711 standard requirement) + return ~(sign | (exponent << 4) | mantissa); +} diff --git a/examples/Platforms/UnoR4/WiFi_TX_UnoR4/secrets.h b/examples/Platforms/UnoR4/WiFi_TX_UnoR4/secrets.h new file mode 100644 index 0000000..edaf36a --- /dev/null +++ b/examples/Platforms/UnoR4/WiFi_TX_UnoR4/secrets.h @@ -0,0 +1,2 @@ +#define SECRET_SSID "mySSID" +#define SECRET_PASS "myPassword" diff --git a/library.json b/library.json index 68fe80a..5f9e505 100644 --- a/library.json +++ b/library.json @@ -21,7 +21,8 @@ "atmelavr", "atmelsam", "espressifesp32", - "nordicnrf52" + "nordicnrf52", + "renesas-ra" ], "export": { "exclude": "examples/*/*.wav" diff --git a/library.properties b/library.properties index a6d518b..adb30f3 100644 --- a/library.properties +++ b/library.properties @@ -6,4 +6,4 @@ sentence=Automated analog reads and analog output (streaming) using Arduino DAC( paragraph=Simplified API for Arduino DAC, ADC, Timers & DMA, designed with radio & wireless communication in mind. Easily create a wide variety of audio related applications. category=Signal Input/Output url=https://github.com/TMRh20/AutoAnalogAudio -architectures=avr,sam,esp32,nrf52 +architectures=avr,sam,esp32,nrf52,renesas diff --git a/src/AutoAnalogAudio.h b/src/AutoAnalogAudio.h index 8f69930..c39bf39 100644 --- a/src/AutoAnalogAudio.h +++ b/src/AutoAnalogAudio.h @@ -91,14 +91,17 @@ class AutoAnalog * 8-bit user samples are loaded directly into this buffer before calling feedDAC()
* @see dacBitsPerSample */ + #if !defined ARDUINO_ARCH_RENESAS uint8_t dacBuffer[MAX_BUFFER_SIZE]; - + #else + static uint8_t dacBuffer[MAX_BUFFER_SIZE]; + #endif /** ADC Data buffer for 8-bit samples * * 8-bit samples are read directly from this buffer after calling getADC()
* @see adcBitsPerSample */ - #if !defined(ARDUINO_ARCH_NRF52840) && !defined(ARDUINO_ARCH_NRF52) && !defined ARDUINO_NRF52840_FEATHER && !defined ARDUINO_NRF54L15 + #if !defined(ARDUINO_ARCH_NRF52840) && !defined(ARDUINO_ARCH_NRF52) && !defined ARDUINO_NRF52840_FEATHER && !defined ARDUINO_NRF54L15 && !defined ARDUINO_ARCH_RENESAS uint8_t adcBuffer[MAX_BUFFER_SIZE]; #elif defined __MBED__ inline static uint8_t adcBuffer[MAX_BUFFER_SIZE]; @@ -118,7 +121,7 @@ class AutoAnalog * 10 or 12-bit samples are read directly from this buffer after calling getADC()
* @see adcBitsPerSample */ - #if !defined(ARDUINO_ARCH_NRF52840) && !defined(ARDUINO_ARCH_NRF52) && !defined ARDUINO_NRF52840_FEATHER && !defined ARDUINO_NRF54L15 + #if !defined(ARDUINO_ARCH_NRF52840) && !defined(ARDUINO_ARCH_NRF52) && !defined ARDUINO_NRF52840_FEATHER && !defined ARDUINO_NRF54L15 && !defined ARDUINO_ARCH_RENESAS uint16_t adcBuffer16[MAX_BUFFER_SIZE]; #elif defined __MBED__ inline static uint16_t adcBuffer16[MAX_BUFFER_SIZE]; @@ -149,7 +152,7 @@ class AutoAnalog * adcBuffer[] is an 8-bit buffer used solely for your 8-bit samples
* adcBuffer16[] is a 16-bit buffer used solely for placing your 10 and 12-bit samples
**/ - #if !defined(ARDUINO_ARCH_NRF52840) && !defined(ARDUINO_ARCH_NRF52) && !defined ARDUINO_NRF52840_FEATHER && !defined ARDUINO_NRF54L15 + #if !defined(ARDUINO_ARCH_NRF52840) && !defined(ARDUINO_ARCH_NRF52) && !defined ARDUINO_NRF52840_FEATHER && !defined ARDUINO_NRF54L15 && !defined ARDUINO_ARCH_RENESAS uint8_t adcBitsPerSample; #elif defined __MBED__ inline static uint8_t adcBitsPerSample; @@ -245,9 +248,29 @@ class AutoAnalog uint8_t enableDAC; bool whichBuf; static bool adcWhichBuf; + + #elif defined ARDUINO_ARCH_RENESAS + static volatile uint16_t* dacBuf0; + static volatile uint16_t* dacBuf1; + volatile static uint8_t aCtr; + static volatile uint32_t aSize; + static uint16_t* adcBuf0; + static uint16_t* adcBuf1; + static void (*_onReceive)(uint16_t* buf, uint32_t buf_len); + static void adcCallback(uint16_t* buf, uint32_t buf_len); + void set_callback(void (*function)(uint16_t* buf, uint32_t buf_len)); + static volatile bool adcReady; + static volatile uint32_t sampleCounter; + uint8_t enableADC; + uint8_t enableDAC; + bool whichBuf; + static volatile bool adcWhichBuf; + static volatile uint32_t sCounter; + bool dacDisabled; + static volatile uint8_t analogChannel; #endif - #if defined(ARDUINO_ARCH_NRF52840) || defined(ARDUINO_ARCH_NRF52) || defined ARDUINO_NRF54L15 || defined(DOXYGEN_FORCED) + #if defined(ARDUINO_ARCH_NRF52840) || defined(ARDUINO_ARCH_NRF52) || defined ARDUINO_NRF54L15 || defined ARDUINO_ARCH_RENESAS || defined(DOXYGEN_FORCED) /**@}*/ /** * @name Section for nRF52 Devices Only diff --git a/src/AutoAnalog_config.h b/src/AutoAnalog_config.h index 9af245e..ed2e7c6 100644 --- a/src/AutoAnalog_config.h +++ b/src/AutoAnalog_config.h @@ -22,6 +22,10 @@ #define MAX_BUFFER_SIZE 256 + #elif defined (ARDUINO_ARCH_RENESAS) + + #define MAX_BUFFER_SIZE 512 + #elif defined ESP32 || defined ARDUINO_ARCH_NRF52840 || defined (ARDUINO_ARCH_NRF52) || defined ARDUINO_NRF52840_FEATHER || defined ARDUINO_NRF54L15 #define MAX_BUFFER_SIZE 6400 diff --git a/src/RA41M/AutoAnalogAudio.cpp b/src/RA41M/AutoAnalogAudio.cpp new file mode 100644 index 0000000..bce8ec1 --- /dev/null +++ b/src/RA41M/AutoAnalogAudio.cpp @@ -0,0 +1,501 @@ +/* +AutoAnalogAudio streaming via DAC & ADC by TMRh20 +Copyright (C) 2016 TMRh20 - tmrh20@gmail.com, github.com/TMRh20 + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/****************************************************************************/ + +#if defined(ARDUINO_ARCH_RENESAS) + + #include "../AutoAnalogAudio.h" + #include "FspTimer.h" + #include "r_timer_api.h" + #include "r_adc.h" + #if defined ARDUINO_UNOR4_WIFI + #include "WiFiS3.h" + #endif +FspTimer high_speed_timer; +FspTimer adc_timer; +uint8_t high_speed_timer_index; +uint8_t adc_timer_index; + +extern "C" void my_adc_isr(timer_callback_args_t* p_args); +volatile uint8_t AutoAnalog::analogChannel = 0; + +uint16_t AutoAnalog::adcBuffer16[MAX_BUFFER_SIZE]; +uint8_t AutoAnalog::adcBuffer[MAX_BUFFER_SIZE]; +volatile bool AutoAnalog::adcReady; +volatile uint32_t AutoAnalog::sampleCounter; +volatile bool AutoAnalog::adcWhichBuf; +uint8_t AutoAnalog::adcBitsPerSample; +volatile uint32_t AutoAnalog::aSize; +volatile uint8_t AutoAnalog::aCtr; +uint16_t* AutoAnalog::adcBuf0; +uint16_t* AutoAnalog::adcBuf1; +volatile uint16_t* AutoAnalog::dacBuf0; +volatile uint16_t* AutoAnalog::dacBuf1; +void (*AutoAnalog::_onReceive)(uint16_t* buf, uint32_t buf_len); +uint8_t AutoAnalog::dacBuffer[MAX_BUFFER_SIZE]; +volatile uint32_t AutoAnalog::sCounter = 0; +void dac_callback(timer_callback_args_t* p_args); + +/****************************************************************************/ +/* Public Functions */ +/****************************************************************************/ + +AutoAnalog::AutoAnalog() +{ + + adcReady = false; + adcBitsPerSample = 8; + dacBitsPerSample = 8; + autoAdjust = true; + for (int i = 0; i < MAX_BUFFER_SIZE; i++) { + dacBuffer[i] = 0; + } + + aSize = MAX_BUFFER_SIZE; + aCtr = 0; + sampleCounter = 0; + maxBufferSize = 0; + dacBuffersAllocated = false; + manualI2S = false; +} + +void AutoAnalog::begin(uint8_t enADC, uint8_t enDAC, uint8_t _useI2S) +{ + + maxBufferSize = maxBufferSize > 0 ? maxBufferSize : MAX_BUFFER_SIZE; + + // Fix for backward compatiblity with badly thought out changes + if (_useI2S == 1) { + enDAC = 2; + } + else if (_useI2S == 2) { + enADC = 2; + } + else if (_useI2S == 3) { + enADC = 2; + enDAC = 2; + } + else if (_useI2S == 4 || _useI2S == 5) { + enADC = 3; + } + else if (_useI2S == 6) { + enADC = 3; + enDAC = 2; + } + + enableADC = enADC; + enableDAC = enDAC; + + if (enADC) { + if (!adcBuffersAllocated) { + adcBuffersAllocated = true; + adcBuf0 = reinterpret_cast(malloc(maxBufferSize * 2)); + memset(adcBuf0, 0, maxBufferSize * 2); + adcBuf1 = reinterpret_cast(malloc(maxBufferSize * 2)); + memset(adcBuf1, 0, maxBufferSize * 2); + } + adcSetup(); + } + + if (enDAC) { + if (!dacBuffersAllocated) { + dacBuffersAllocated = true; + dacBuf0 = reinterpret_cast(malloc(maxBufferSize * 2)); + memset(const_cast(reinterpret_cast(dacBuf0)), 0, maxBufferSize * 2); + dacBuf1 = reinterpret_cast(malloc(maxBufferSize * 2)); + memset(const_cast(reinterpret_cast(dacBuf1)), 0, maxBufferSize * 2); + } + dacSetup(); + } +} + +/****************************************************************************/ + +void AutoAnalog::setSampleRate(uint32_t sampRate, bool stereo) +{ + + if (enableDAC == 3) { + high_speed_timer.stop(); + + uint8_t timer_type = GPT_TIMER; + + high_speed_timer.begin( + TIMER_MODE_PERIODIC, // Fire continuously at the specified interval + timer_type, // Use the General PWM Timer peripheral block + high_speed_timer_index, // Selected hardware channel channel + sampRate * (stereo + 1), // Target Frequency in Hz (16 kHz) + 0.0, // Duty cycle (unused for generic interrupts, keep 0.0) + dac_callback // Name of your ISR function to execute + ); + + high_speed_timer.setup_overflow_irq(); + high_speed_timer.open(); + high_speed_timer.start(); + } + if (enableADC == 3) { + adc_timer.stop(); + + uint8_t timerType = GPT_TIMER; + + adc_timer.begin(TIMER_MODE_PERIODIC, timerType, adc_timer_index, sampRate * (stereo + 1), 0.0f, my_adc_isr); + adc_timer.setup_overflow_irq(); + adc_timer.open(); + adc_timer.start(); + } +} + +/****************************************************************************/ + +void AutoAnalog::triggerADC() +{ +} + +/****************************************************************************/ + +void AutoAnalog::enableAdcChannel(uint8_t pinAx) +{ + adc_timer.stop(); + + pinMode(pinAx + 15, INPUT); + analogRead(pinAx + 15); + + R_ADC0->ADCSR_b.ADST = 0; + while (R_ADC0->ADCSR_b.ADST) { + } + + R_ADC0->ADANSA[0] = 1 << pinAx; + + analogChannel = pinAx; + + adc_timer.start(); +} + +/****************************************************************************/ + +void AutoAnalog::disableAdcChannel(uint8_t pinAx) +{ + + adc_timer.stop(); + + R_ADC0->ADCSR_b.ADST = 0; + while (R_ADC0->ADCSR_b.ADST) { + } + + R_ADC0->ADANSA[0] = 0; +} + +/****************************************************************************/ + +void AutoAnalog::getADC(uint32_t samples) +{ + + while (!adcReady) { + #if defined ARDUINO_UNOR4_WIFI + WiFi.status(); + delayMicroseconds(100); + #else + yield(); + #endif + } + + adcReady = false; + aSize = samples; +} + +/****************************************************************************/ + +void AutoAnalog::feedDAC(uint8_t dacChannel, uint32_t samples, bool startInterrupts) +{ + + if (enableDAC == 3) { + + if (dacDisabled) { + R_DAC->DACR = 0x5F; + high_speed_timer.start(); + dacDisabled = false; + } + + if (aCtr == 1) { + if (dacBitsPerSample == 8) { + for (int i = 0; i < samples; i++) { + dacBuf0[i] = dacBuffer[i] << 4; + } + } + else if (dacBitsPerSample == 16) { + for (int i = 0; i < samples; i++) { + dacBuf0[i] = (dacBuffer16[i] >> 4) + 2048; + } + } + } + else { + if (dacBitsPerSample == 8) { + for (int i = 0; i < samples; i++) { + dacBuf1[i] = dacBuffer[i] << 4; + } + } + else if (dacBitsPerSample == 16) { + for (int i = 0; i < samples; i++) { + dacBuf1[i] = (dacBuffer16[i] >> 4) + 2048; + } + } + } + while (sCounter < samples) { + } + aCtr = (aCtr + 1) % 2; + aSize = samples; + sCounter = 0; + } +} + +/****************************************************************************/ +/* Private Functions */ +/****************************************************************************/ + +void AutoAnalog::dacBufferStereo(uint8_t dacChannel) +{ +} + +/****************************************************************************/ + +uint32_t AutoAnalog::frequencyToTimerCount(uint32_t frequency) +{ + + return 1; +} + +/****************************************************************************/ + +void AutoAnalog::startPwmI2sTimers() +{ +} + + /****************************************************************************/ + +void AutoAnalog::adcSetup(void) +{ + + if (enableADC == 3) { + + analogReadResolution(14); + pinMode(15 + analogChannel, INPUT); + analogRead(15 + analogChannel); + //analogReference(AR_INTERNAL); + + R_MSTP->MSTPCRD &= ~(1UL << 16); // MSTPD16 = 0 -> ADC140 enabled + __asm volatile("nop"); + __asm volatile("nop"); + + R_ADC0->ADCSR_b.ADST = 0; + while (R_ADC0->ADCSR_b.ADST) { + } + + R_ADC0->ADCSR = 0x8000; + R_ADC0->ADANSA[0] = 1 << analogChannel; + + R_ADC0->ADSSTR[analogChannel] = 12; + + uint8_t timerType = GPT_TIMER; + adc_timer_index = FspTimer::get_available_timer(timerType); + if (adc_timer_index < 0) { + FspTimer::force_use_of_pwm_reserved_timer(); + timerType = GPT_TIMER; + adc_timer_index = FspTimer::get_available_timer(timerType); + } + adc_timer.begin(TIMER_MODE_PERIODIC, timerType, adc_timer_index, 16000, 0.0f, my_adc_isr); + adc_timer.setup_overflow_irq(); + adc_timer.open(); + adc_timer.start(); + } +} + +/****************************************************************************/ + +void AutoAnalog::adcInterrupts(bool enabled) +{ +} + +/****************************************************************************/ + +void AutoAnalog::dacSetup(void) +{ + + if (enableDAC == 3) { + + analogWriteResolution(12); + analogWrite(A0, 0); + + R_DAC->DACR = 0x5F; // enable + R_DAC->DADPR = 0; // Right justified + R_DAC->DAADSCR = 1 << 7; // Sync ADC14 and DAC12 + //R_DAC->DAVREFCR = 1 << 3 | 1 << 2; // VREFH/VREFL + + uint8_t timer_type = GPT_TIMER; + high_speed_timer_index = FspTimer::get_available_timer(timer_type); + if (high_speed_timer_index < 0) { + FspTimer::force_use_of_pwm_reserved_timer(); + timer_type = GPT_TIMER; + high_speed_timer_index = FspTimer::get_available_timer(timer_type); + } + + high_speed_timer.begin( + TIMER_MODE_PERIODIC, // Fire continuously at the specified interval + timer_type, // Use the General PWM Timer peripheral block + high_speed_timer_index, // Selected hardware channel channel + 16000.0, // Target Frequency in Hz (16 kHz) + 0.0, // Duty cycle (unused for generic interrupts, keep 0.0) + dac_callback // Name of your ISR function to execute + ); + + high_speed_timer.setup_overflow_irq(); + high_speed_timer.open(); + high_speed_timer.start(); + } +} + +/****************************************************************************/ + +void AutoAnalog::disableDAC(bool withinTask) +{ + if (enableDAC == 3) { + high_speed_timer.stop(); + R_DAC->DACR = 0x4F; + dacDisabled = true; + } + else if (enableDAC == 2) { + /*NRF_I2S->TASKS_STOP = 1; + NRF_I2S->ENABLE = 0;*/ + } + else if (enableDAC == 1) { + //NRF_PWM0->TASKS_STOP = 1; + } +} + +/****************************************************************************/ + +void AutoAnalog::dacHandler(void) +{ +} + +/****************************************************************************/ + +void AutoAnalog::tcSetup(uint32_t sampRate) +{ +} + +/****************************************************************************/ + +void AutoAnalog::tc2Setup(uint32_t sampRate) +{ +} +extern "C" { +__attribute__((__used__)) void I2S_IRQHandler_v(void) +{ +} +} + +extern "C" { +__attribute__((__used__)) void SAADC_IRQHandler(void) +{ +} +} + +/****************************************************************************/ + +void dac_callback(timer_callback_args_t* p_args) +{ + + if (AutoAnalog::sCounter < AutoAnalog::aSize) { + + if (AutoAnalog::aCtr == 0) { + R_DAC->DADR[0] = AutoAnalog::dacBuf0[AutoAnalog::sCounter]; + } + else { + R_DAC->DADR[0] = AutoAnalog::dacBuf1[AutoAnalog::sCounter]; + } + } + AutoAnalog::sCounter++; +} + +extern "C" void my_adc_isr(timer_callback_args_t* p_args) +{ + + (void)p_args; + + if (AutoAnalog::adcWhichBuf == 0) { + AutoAnalog::adcBuf0[AutoAnalog::sampleCounter] = R_ADC0->ADDR[AutoAnalog::analogChannel]; + } + else { + AutoAnalog::adcBuf1[AutoAnalog::sampleCounter] = R_ADC0->ADDR[AutoAnalog::analogChannel]; + } + + AutoAnalog::sampleCounter++; + + if (AutoAnalog::sampleCounter >= AutoAnalog::aSize && AutoAnalog::adcReady == false) { + if (AutoAnalog::adcWhichBuf == 0) { + if (AutoAnalog::adcBitsPerSample == 8) { + for (uint32_t i = 0; i < AutoAnalog::aSize; i++) { + AutoAnalog::adcBuffer[i] = AutoAnalog::adcBuf0[i] >> 6; + } + } + else { + for (uint32_t i = 0; i < AutoAnalog::aSize; i++) { + int16_t sample = AutoAnalog::adcBuf0[i] - 8192; + AutoAnalog::adcBuffer16[i] = sample << 2; + } + } + } + else { + if (AutoAnalog::adcBitsPerSample == 8) { + for (uint32_t i = 0; i < AutoAnalog::aSize; i++) { + AutoAnalog::adcBuffer[i] = AutoAnalog::adcBuf1[i] >> 6; + } + } + else { + for (uint32_t i = 0; i < AutoAnalog::aSize; i++) { + int16_t sample = AutoAnalog::adcBuf1[i] - 8192; + AutoAnalog::adcBuffer16[i] = sample << 2; + } + } + } + AutoAnalog::adcReady = true; + AutoAnalog::sampleCounter = 0; + AutoAnalog::adcWhichBuf = !AutoAnalog::adcWhichBuf; + }else + if (AutoAnalog::sampleCounter >= AutoAnalog::aSize){ + AutoAnalog::sampleCounter = 0; + AutoAnalog::adcWhichBuf = !AutoAnalog::adcWhichBuf; + } + + + R_ADC0->ADCSR_b.ADST = 1; +} + +void AutoAnalog::set_callback(void (*function)(uint16_t* buf, uint32_t buf_len)) +{ + _onReceive = function; +} + +void AutoAnalog::adcCallback(uint16_t* buf, uint32_t buf_len) +{ + + memcpy(adcBuffer16, buf, buf_len * 2); + adcReady = true; +} + +#endif //#if defined (ARDUINO_ARCH_SAM) \ No newline at end of file