//###############################################################################################################
// ESP32 Multi point Audio streaming
// Created by Ricardo Mota
// Data: 04/05/2022
// Version: 0A
//
// Next steps:
// 1. Develope a simple hardware two adquire and generated simples sound wave in 1kHz. This test may be made in
// Wokwi simulator first. Use simples componentes in the simulator to test it.
// 2. Reserch for DAC and ADC for a good sound convertions.
// 3. Implement the hardware interrupts routines for precision time mesuament.
// 4. ?
//
// Bugs to fix:
//
//###############################################################################################################
#define GENERAL_DEBUG
//###############################################################################################################
// Constants declaration. Use UPPER CASE
//###############################################################################################################
// The total size most to be the X * Y coordenations -> 240 * 20
const int it_BUFFSIZE = 4800; // X=20 * Y=240
const int it_BUFFX = 20;
const int it_BUFFY = 240;
const int it_CTRLSIZE = 3;
const word wd_MSTID = 0xDEDE;
const word wd_GRPID = 0xDE01;
const unsigned long ulg_INTERVAL01 = 27;
const unsigned long ulg_INTERVAL02 = 260;
const unsigned long ulg_INTERVAL03 = 210;
const unsigned long ulg_INTERVAL04 = 27;
const unsigned long ulg_INTERVAL05 = 30;
//###############################################################################################################
// Variables declaration. Use loweer case
//###############################################################################################################
// Genereal variables
unsigned long ulg_millis_now, ulg_timer01, ulg_timer02, ulg_timer03, ulg_timer04, ulg_timer05;
float fl_analog_read;
float ft_rad = 0;
int it_ether_packet [it_BUFFY+it_CTRLSIZE];
// TX application variables
int it_tx_buff_free_space;
int it_tx_buff_in_position, it_tx_buff_out_position;
bool bl_tx_insert_permission, bl_tx_extract_permission;
word wd_tx_packet_number = 0;
int it_tx_buff [it_BUFFSIZE];
// RX application variables
int it_rx_buff_free_space;
int it_rx_buff_in_position, it_rx_buff_out_position;
bool bl_rx_insert_permission, bl_rx_extract_permission;
word wd_rx_packet_number = 0;
int it_rx_buff [it_BUFFSIZE];
//###############################################################################################################
// General functions declarations.
//###############################################################################################################
void VoidFunc(void) {}
//###############################################################################################################
// Setup routine.
//###############################################################################################################
void setup() {
// Setup routines are called in this program part
#ifdef GENERAL_DEBUG
Serial.begin(115200);
Serial.println("Hello, ESP32!");
#endif
delay(300);
}
//###############################################################################################################
// Main loop routine.
//###############################################################################################################
void loop() {
ulg_millis_now = millis();
//###############################################################################################################
// TX Buffer free space calculation
if(it_tx_buff_in_position >= it_tx_buff_out_position){
it_tx_buff_free_space = (it_BUFFSIZE - it_tx_buff_in_position) + it_tx_buff_out_position;
}
else {
it_tx_buff_free_space = (it_BUFFSIZE - it_tx_buff_in_position) - (it_BUFFSIZE - it_tx_buff_out_position);
}
// TX Buffer insertion permission
if(it_tx_buff_free_space > 1) bl_tx_insert_permission = true;
else bl_tx_insert_permission = false;
// TX Buffer extraction permission
if(((it_BUFFX*it_BUFFY) - it_tx_buff_free_space >= it_BUFFY) && it_ether_packet [0] == 0) bl_tx_extract_permission = true;
else bl_tx_extract_permission = false;
//###############################################################################################################
// RX Buffer free space calculation
if(it_rx_buff_in_position >= it_rx_buff_out_position){
it_rx_buff_free_space = (it_BUFFSIZE - it_rx_buff_in_position) + it_rx_buff_out_position;
}
else {
it_rx_buff_free_space = (it_BUFFSIZE - it_rx_buff_in_position) - (it_BUFFSIZE - it_rx_buff_out_position);
}
// RX Buffer insertion permission
if(it_rx_buff_free_space > it_BUFFY) bl_rx_insert_permission = true;
else bl_rx_insert_permission = false;
// RX Buffer extraction permission -------------- ''
if((it_BUFFX*it_BUFFY) - it_rx_buff_free_space >= 10) bl_rx_extract_permission = true;
else bl_rx_extract_permission = false;
//###############################################################################################################
// Verify if the elapsed time for timer01 was reached | Base time 3ms
// Inside this routine is generated the analog read value, simulating de analog input read
// The value is stored in fl_analog_read variable
//###############################################################################################################
if(ulg_millis_now - ulg_timer01 > ulg_INTERVAL01 ){
// Do something
fl_analog_read++; // = 32760 * sin(ft_rad);
ft_rad = ft_rad + (0.0174532925 * 10);
// Timer updater
ulg_timer01 = ulg_millis_now;
}
//###############################################################################################################
// Verify if the elapsed time for timer02 was reached | Base time 3ms
// Inside this routine it's executed de transfer of the analog read to TX Buffer, storing the values for future
// transfer
//###############################################################################################################
if((ulg_millis_now - ulg_timer02 > ulg_INTERVAL02) && bl_tx_insert_permission ){
// Do something
it_tx_buff[it_tx_buff_in_position] = (int)fl_analog_read;
it_tx_buff_in_position++;
/*
Serial.print("Insertion into TX Buffer[");
Serial.print((it_tx_buff_in_position-1), DEC);
Serial.print("]: ");
Serial.println(it_tx_buff[it_tx_buff_in_position-1]);
*/
if(it_tx_buff_in_position >= it_BUFFSIZE) it_tx_buff_in_position = 0;
// Timer update
ulg_timer02 = ulg_millis_now;
}
//###############################################################################################################
// Verify if the elapsed time for timer03 was reached | Base time 240 * 3ms
// Inside this routine it's executed the transfer of 240 byte from TX Buffer to RX Buffer simulating the
// communication routine
// The flow control information it's also added to de frame: Master ID, Group ID and Packet sequence number
//###############################################################################################################
if((ulg_millis_now - ulg_timer03 > ulg_INTERVAL03) && bl_tx_extract_permission){
// Data extraction from the TX Buffer
Serial.println(" ");
Serial.print("Extraction from TX Buffer[");
Serial.print((it_tx_buff_out_position), DEC);
Serial.print("]: ");
it_ether_packet [0] = wd_MSTID;
it_ether_packet [1] = wd_GRPID;
it_ether_packet [2] = wd_tx_packet_number;
wd_tx_packet_number++;
for(int i=0; i < it_BUFFY; i++){
//Serial.print(it_tx_buff[it_tx_buff_out_position]);
//Serial.print(", ");
it_ether_packet [i+it_CTRLSIZE] = it_tx_buff[it_tx_buff_out_position];
it_tx_buff_out_position++;
}
Serial.println("");
// Serial.print("Out Position: ");
// Serial.println(it_tx_buff_out_position, DEC);
if(it_tx_buff_out_position >= it_BUFFSIZE) it_tx_buff_out_position = 0;
// Timer update
ulg_timer03 = ulg_millis_now;
}
//###############################################################################################################
// Verify if the elapsed time for timer04 was reached | Base time 3ms
// Inside this routine it's executed de transfer of the received data to the RX Buffer
// If it_ether_packet[0] is diferente from zero, there is new data avaliable
//###############################################################################################################
if((ulg_millis_now - ulg_timer04 > ulg_INTERVAL04) && bl_rx_insert_permission && it_ether_packet [0] != 0 ){
// Transfer received data to RX Buffer
Serial.print("RX Packet sequence number: ");
Serial.println(it_ether_packet[2]);
// Verify if the IDs numbers and packet number match with the expected
if(it_ether_packet[0] == wd_MSTID && it_ether_packet[1] == wd_GRPID && it_ether_packet[2] == wd_rx_packet_number){
wd_rx_packet_number++;
for(int i=0; i < it_BUFFY; i++){
it_rx_buff[it_rx_buff_in_position] = it_ether_packet [i+it_CTRLSIZE];
it_rx_buff_in_position++;
}
Serial.print("Extraction from RX Buffer[");
Serial.print((it_rx_buff_in_position), DEC);
Serial.print("]: ");
Serial.println(it_rx_buff[it_rx_buff_in_position-1]);
if(it_rx_buff_in_position >= it_BUFFSIZE) it_rx_buff_in_position = 0;
}
it_ether_packet [0] = 0;
ulg_timer04 = ulg_millis_now;
}
//###############################################################################################################
// Verify if the elapsed time for timer05 was reached | Base time 3ms
// Inside this routine it's executed de transfer of the RX Buffer to the analog output, generating de audio wave
//###############################################################################################################
if((ulg_millis_now - ulg_timer05 > ulg_INTERVAL05) && bl_rx_extract_permission){
// Write the buffer value to the analog out put
Serial.print("Analog output ");
Serial.print((it_rx_buff_out_position), DEC);
Serial.print(" : ");
Serial.println(it_rx_buff[it_rx_buff_out_position]);
it_rx_buff_out_position++;
if(it_rx_buff_out_position >= it_BUFFSIZE) it_rx_buff_out_position = 0;
ulg_timer05 = ulg_millis_now;
}
}