void setup_screen() {
// Initialise the TFT registers
tft.init();
tft.setRotation(1);
// Optionally set colour depth to 8 or 16 bits, default is 16 if not specified
spr.setColorDepth(8);
// Create a sprite of defined size (320x240)
spr.createSprite(320, 240);
// Clear the TFT screen to black
tft.fillScreen(TFT_BLACK);
}
int data[320] = { 0 }; // Updated array size to match new width
float to_scale(float reading) {
float voltage = (reading - 20480.0) / 4095.0 * 3.3; // Convert ADC reading to voltage
float temp = 120 - ( // Center 0V at 120 pixels
(((voltage + offset) * 3300 / (v_div * 6))) * (120 - 1) // Scale within half of the screen height
);
return temp;
}
float to_voltage(float reading) {
return (reading - 20480.0) / 4095.0 * 3.3;
}
uint32_t from_voltage(float voltage) {
return uint32_t(voltage / 3.3 * 4095 + 20480.0);
}
void update_screen(uint16_t *i2s_buff, float sample_rate) {
float mean = 0;
float max_v, min_v;
peak_mean(i2s_buff, BUFF_SIZE, &max_v, &min_v, &mean);
float freq = 0;
float period = 0;
uint32_t trigger0 = 0;
uint32_t trigger1 = 0;
// If analog mode OR auto mode and wave recognized as analog
bool digital_data = false;
if (digital_wave_option == 1) {
trigger_freq_analog(i2s_buff, sample_rate, mean, max_v, min_v, &freq, &period, &trigger0, &trigger1);
} else if (digital_wave_option == 0) {
digital_data = digital_analog(i2s_buff, max_v, min_v);
if (!digital_data) {
trigger_freq_analog(i2s_buff, sample_rate, mean, max_v, min_v, &freq, &period, &trigger0, &trigger1);
} else {
trigger_freq_digital(i2s_buff, sample_rate, mean, max_v, min_v, &freq, &period, &trigger0);
}
} else {
trigger_freq_digital(i2s_buff, sample_rate, mean, max_v, min_v, &freq, &period, &trigger0);
}
draw_sprite(freq, period, mean, max_v, min_v, trigger0, sample_rate, digital_data, true);
}
void draw_sprite(float freq,
float period,
float mean,
float max_v,
float min_v,
uint32_t trigger,
float sample_rate,
bool digital_data,
bool new_data) {
max_v = to_voltage(max_v);
min_v = to_voltage(min_v);
String frequency = "";
if (freq < 1000)
frequency = String(freq) + "Hz";
else if (freq < 100000)
frequency = String(freq / 1000) + "kHz";
else
frequency = "----";
String s_mean = "";
if (mean > 1.0)
s_mean = "Avg: " + String(mean) + "V";
else
s_mean = "Avg: " + String(mean * 1000.0) + "mV";
String str_filter = "";
if (current_filter == 0)
str_filter = "None";
else if (current_filter == 1)
str_filter = "Pixel";
else if (current_filter == 2)
str_filter = "Mean-5";
else if (current_filter == 3)
str_filter = "Lpass9";
String str_stop = "";
if (!stop)
str_stop = "RUNNING";
else
str_stop = "STOPPED";
String wave_option = "";
if (digital_wave_option == 0)
if (digital_data)
wave_option = "AUTO:Dig./data";
else
wave_option = "AUTO:Analog";
else if (digital_wave_option == 1)
wave_option = "MODE:Analog";
else
wave_option = "MODE:Dig./data";
if (new_data) {
// Fill the whole sprite with black (Sprite is in memory so not visible yet)
spr.fillSprite(TFT_BLACK);
draw_grid();
if (auto_scale) {
auto_scale = false;
v_div = 1000.0 * max_v / 1.5;
s_div = period / 3.5;
if (s_div > 7000 || s_div <= 0)
s_div = 7000;
if (v_div <= 0)
v_div = 550;
}
// Only draw digital data if a trigger was in the data
if (!(digital_wave_option == 2 && trigger == 0))
draw_channel1(trigger, 0, i2s_buff, sample_rate);
}
int shift = 150;
if (menu) {
for (int x = 0; x < 320; x += 10) { // Spaced vertical dots for reference line
spr.drawLine(x, 118, x, 122, TFT_WHITE); // Short vertical segments
}
// Display menu options
spr.fillRect(shift, 0, 102, 110, TFT_BLACK);
spr.drawRect(shift, 0, 102, 110, TFT_WHITE);
spr.fillRect(shift + 1, 3 + 10 * (opt - 1), 100, 11, TFT_RED);
spr.drawString("AUTOSCALE", shift + 5, 5);
spr.drawString(String(int(v_div)) + "mV/div", shift + 5, 15);
spr.drawString(String(int(s_div)) + "uS/div", shift + 5, 25);
spr.drawString("Offset: " + String(offset) + "V", shift + 5, 35);
spr.drawString("T-Off: " + String((uint32_t)toffset) + "uS", shift + 5, 45);
spr.drawString("Filter: " + str_filter, shift + 5, 55);
spr.drawString(str_stop, shift + 5, 65);
spr.drawString(wave_option, shift + 5, 75);
spr.drawString("Single " + String(single_trigger ? "ON" : "OFF"), shift + 5, 85);
//spr.drawLine(shift, 103, shift + 100, 103, TFT_WHITE);
// Display Frequency at the top-left corner
int y_top = 5; // Position at the top of the screen
int x_start = 10; // Starting X position
spr.drawString("Freq: " + frequency, x_start, y_top);
// Display Vmax, Vmin, and Vpp at the bottom of the screen
int y_bottom = 220; // Position at the bottom of the screen (240 - 20 for text height)
int x_bottom = 10; // Starting X position
// Calculate text widths to avoid overlapping
String vmax_text = "Vmax: " + String(max_v) + "V";
String vmin_text = "Vmin: " + String(min_v) + "V";
String vpp_text = "Vpp: " + String(max_v - min_v) + "V";
int vmax_width = spr.textWidth(vmax_text);
int vmin_width = spr.textWidth(vmin_text);
int vpp_width = spr.textWidth(vpp_text);
// Draw text with proper spacing
spr.drawString(vmax_text, x_bottom, y_bottom);
spr.drawString(vmin_text, x_bottom + vmax_width + 20, y_bottom); // Add 20 pixels spacing
spr.drawString(vpp_text, x_bottom + vmax_width + vmin_width + 40, y_bottom); // Add 40 pixels spacing
} else if (info) {
for (int x = 0; x < 320; x += 10) { // Spaced vertical dots for reference line
spr.drawLine(x, 118, x, 122, TFT_WHITE); // Short vertical segments
}
// Display Voltage per Division, Time per Division, and Frequency at the top of the screen
int y_top = 5; // Position at the top of the screen
int x_start = 10; // Starting X position
// Voltage per Division
String v_div_text = "V/div: " + String(int(v_div)) + "mV";
spr.drawString(v_div_text, x_start, y_top);
// Time per Division
String s_div_text = "Time/div: " + String(int(s_div)) + "uS";
spr.drawString(s_div_text, x_start + spr.textWidth(v_div_text) + 20, y_top); // Add 20 pixels spacing
// Frequency
String freq_text = "Freq: " + frequency;
spr.drawString(freq_text, x_start + spr.textWidth(v_div_text) + spr.textWidth(s_div_text) + 40, y_top); // Add 40 pixels spacing
// Display Vmax, Vmin, and Vpp at the bottom of the screen
int y_bottom = 220; // Position at the bottom of the screen (240 - 20 for text height)
// Calculate text widths to avoid overlapping
String vmax_text = "Vmax: " + String(max_v) + "V";
String vmin_text = "Vmin: " + String(min_v) + "V";
String vpp_text = "Vpp: " + String(max_v - min_v) + "V";
int vmax_width = spr.textWidth(vmax_text);
int vmin_width = spr.textWidth(vmin_text);
int vpp_width = spr.textWidth(vpp_text);
// Draw text with proper spacing
spr.drawString(vmax_text, x_start, y_bottom);
spr.drawString(vmin_text, x_start + vmax_width + 20, y_bottom); // Add 20 pixels spacing
spr.drawString(vpp_text, x_start + vmax_width + vmin_width + 40, y_bottom); // Add 40 pixels spacing
}
// Push the drawn sprite to the screen
spr.pushSprite(0, 0);
yield(); // Stop watchdog reset
}
void draw_zero_reference() {
int zero_y = to_scale(from_voltage(offset)); // Calculate zero level
// Vertical dotted reference line at zero level
for (int x = 0; x < 320; x += 10) {
spr.drawPixel(x, zero_y, TFT_WHITE);
}
// Right-pointing green arrow
spr.drawLine(5, zero_y, 15, 120, TFT_GREEN); // Horizontal arrow line
spr.drawLine(15, zero_y, 10, zero_y - 5, TFT_GREEN); // Upward arrowhead
spr.drawLine(15, zero_y, 10, zero_y + 5, TFT_GREEN); // Downward arrowhead
// Ground symbol (⏚) below arrow
spr.drawLine(5, zero_y + 5, 5, zero_y + 10, TFT_GREEN);
spr.drawLine(2, zero_y + 10, 8, zero_y + 10, TFT_GREEN);
spr.drawLine(3, zero_y + 12, 7, zero_y + 12, TFT_GREEN);
spr.drawLine(4, zero_y + 14, 6, zero_y + 14, TFT_GREEN);
}
void draw_grid() {
for (int i = 0; i < 32; i++) { // Updated to 32 for 320 pixels
spr.drawPixel(i * 10, 40, TFT_WHITE);
spr.drawPixel(i * 10, 80, TFT_WHITE);
spr.drawPixel(i * 10, 120, TFT_WHITE);
spr.drawPixel(i * 10, 160, TFT_WHITE);
spr.drawPixel(i * 10, 200, TFT_WHITE);
}
for (int i = 0; i < 240; i += 10) {
for (int j = 0; j < 320; j += 40) { // Updated to 320 pixels
spr.drawPixel(j, i, TFT_WHITE);
}
}
}
void draw_channel1(uint32_t trigger0, uint32_t trigger1, uint16_t *i2s_buff, float sample_rate) {
// Screen wave drawing
data[0] = to_scale(i2s_buff[trigger0]);
low_pass filter(0.99);
mean_filter mfilter(5);
mfilter.init(i2s_buff[trigger0]);
filter._value = i2s_buff[trigger0];
float data_per_pixel = (s_div / 40.0) / (sample_rate / 1000);
uint32_t index_offset = (uint32_t)(toffset / data_per_pixel);
trigger0 += index_offset;
uint32_t old_index = trigger0;
float n_data = 0, o_data = to_scale(i2s_buff[trigger0]);
for (uint32_t i = 1; i < 320; i++) { // Updated to 320 pixels
uint32_t index = trigger0 + (uint32_t)((i + 1) * data_per_pixel);
if (index < BUFF_SIZE) {
if (full_pix && s_div > 40 && current_filter == 0) {
uint32_t max_val = i2s_buff[old_index];
uint32_t min_val = i2s_buff[old_index];
for (int j = old_index; j < index; j++) {
// Draw lines for all this data points on pixel i
if (i2s_buff[j] > max_val)
max_val = i2s_buff[j];
else if (i2s_buff[j] < min_val)
min_val = i2s_buff[j];
}
spr.drawLine(i, to_scale(min_val), i, to_scale(max_val), TFT_GREEN);
} else {
if (current_filter == 2)
n_data = to_scale(mfilter.filter((float)i2s_buff[index]));
else if (current_filter == 3)
n_data = to_scale(filter.filter((float)i2s_buff[index]));
else
n_data = to_scale(i2s_buff[index]);
spr.drawLine(i - 1, o_data, i, n_data, TFT_GREEN);
o_data = n_data;
}
} else {
break;
}
old_index = index;
}
}
void configure_i2s(int rate) {
/*keep in mind:
dma_buf_len * dma_buf_count * bits_per_sample/8 > 4096
*/
i2s_config_t i2s_config =
{
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN), // I2S receive mode with ADC
.sample_rate = rate, // sample rate
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // 16 bit I2S
.channel_format = I2S_CHANNEL_FMT_ALL_LEFT, // only the left channel
.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB), // I2S format
.intr_alloc_flags = 1, // none
.dma_buf_count = 2, // number of DMA buffers
.dma_buf_len = NUM_SAMPLES, // number of samples
.use_apll = 0, // no Audio PLL
};
adc1_config_channel_atten(ADC_CHANNEL, ADC_ATTEN_11db);
adc1_config_width(ADC_WIDTH_12Bit);
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_adc_mode(ADC_UNIT_1, ADC_CHANNEL);
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL2_REG, SYSCON_SARADC_SAR1_INV);
i2s_adc_enable(I2S_NUM_0);
}
void ADC_Sampling(uint16_t *i2s_buff){
for (int i = 0; i < B_MULT; i++) {
//TODO i2s_read_bytes is deprecated, replace with new function
i2s_read_bytes(I2S_NUM_0, (char*)&i2s_buff[i * NUM_SAMPLES], NUM_SAMPLES * sizeof(uint16_t), portMAX_DELAY);
}
}
void set_sample_rate(uint32_t rate) {
i2s_driver_uninstall(I2S_NUM_0);
configure_i2s(rate);
}
The program is multifile please tell me which file should I provide
I am using a 100k and 10k voltage divider with the 10k connected to 1.65volts and 100k connected to the input and esp32 is connected to a TFT display
Please help me as I am in some urgent to submit my project
Thanks for reply