Skip to content

Instantly share code, notes, and snippets.

@svofski
Created November 2, 2021 10:56
Show Gist options
  • Save svofski/385aae72494482adac9488efbc4d8c32 to your computer and use it in GitHub Desktop.
Save svofski/385aae72494482adac9488efbc4d8c32 to your computer and use it in GitHub Desktop.
ESP8266 Oscilloscope
/*
a basic esp8266 audioscope
*/
#include <Arduino.h>
#include <U8g2lib.h>
#include <ESP8266WiFi.h>
#define FPM_SLEEP_MAX_TIME 0xFFFFFFF
#define DISPLAY_WIDTH 128
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
#define OLED_MOSI 13
#define OLED_CLK 14
#define OLED_DC 5
#define xOLED_CS 15
#define OLED_RESET 4
U8G2_SH1106_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R2, xOLED_CS, OLED_DC, OLED_RESET);
ADC_MODE(ADC_TOUT);
// https://arduino.stackexchange.com/questions/43376/can-the-wifi-on-esp8266-be-disabled
void WiFiOn() {
wifi_fpm_do_wakeup();
wifi_fpm_close();
//Serial.println("Reconnecting");
wifi_set_opmode(STATION_MODE);
wifi_station_connect();
}
void WiFiOff() {
//Serial.println("diconnecting client and wifi");
//client.disconnect();
wifi_station_disconnect();
wifi_set_opmode(NULL_MODE);
wifi_set_sleep_type(MODEM_SLEEP_T);
wifi_fpm_open();
wifi_fpm_do_sleep(FPM_SLEEP_MAX_TIME);
}
void drawDLine(u8g2_uint_t x1, u8g2_uint_t y1, u8g2_uint_t x2, u8g2_uint_t y2, u8g2_int_t d)
{
u8g2_uint_t tmp;
u8g2_uint_t x, y;
u8g2_uint_t dx, dy;
u8g2_int_t err;
u8g2_int_t ystep;
uint8_t swapxy = 0;
/* no intersection check at the moment, should be added... */
if ( x1 > x2 ) dx = x1 - x2; else dx = x2 - x1;
if ( y1 > y2 ) dy = y1 - y2; else dy = y2 - y1;
if ( dy > dx )
{
swapxy = 1;
tmp = dx; dx = dy; dy = tmp;
tmp = x1; x1 = y1; y1 = tmp;
tmp = x2; x2 = y2; y2 = tmp;
}
if ( x1 > x2 )
{
tmp = x1; x1 = x2; x2 = tmp;
tmp = y1; y1 = y2; y2 = tmp;
}
err = dx >> 1;
if ( y2 > y1 ) ystep = 1; else ystep = -1;
y = y1;
#ifndef U8G2_16BIT
if ( x2 == 255 )
x2--;
#else
if ( x2 == 0xffff )
x2--;
#endif
for ( x = x1; x <= x2; x++ )
{
if ( swapxy == 0 )
{
if (d == 0) {
/* solid line */
u8g2.drawPixel(x, y);
} else if (d == 1) {
/* dotted line */
if (x % 2 == 0) u8g2.drawPixel(x, y);
} else if (d > 1) {
/* dashed line */
if ((x / d) % 2 == 0) u8g2.drawPixel(x, y);
} else if (d < 0) {
/* dashed line inverted */
if ((x / -d) % 2 != 0) u8g2.drawPixel(x, y);
}
}
else
{
if (d == 0) {
/* solid line */
u8g2.drawPixel(y, x);
} else if (d == 1) {
/* dotted line */
if (x % 2 == 0) u8g2.drawPixel(y, x);
} else if (d > 1) {
/* dashed line */
if ((x / d) % 2 == 0) u8g2.drawPixel(y, x);
} else if (d < 0) {
/* dashed line inverted */
if ((x / -d) % 2 != 0) u8g2.drawPixel(y, x);
}
}
err -= (uint8_t)dy;
if ( err < 0 )
{
y += (u8g2_uint_t)ystep;
err += (u8g2_uint_t)dx;
}
}
}
void u8g2_prepare(void) {
u8g2.setFont(u8g2_font_6x10_tf);
u8g2.setFontRefHeightExtendedText();
u8g2.setDrawColor(1);
u8g2.setFontPosTop();
u8g2.setFontDirection(0);
}
void setup(void) {
WiFiOff();
Serial.begin(115200);
u8g2.begin();
}
int scope_step = 8;
const uint8_t adc_clk_div = 16;
const int adc_num_samples = 2048+1024;//4096;
int16_t adc_value = 0;
uint16_t adc_buf[adc_num_samples];
unsigned adc_sample_buf()
{
unsigned long start, end;
system_soft_wdt_stop();
ets_intr_lock( );
noInterrupts();
start = micros();
system_adc_read_fast(adc_buf, /*min(scope_step*128, adc_num_samples)*/adc_num_samples, adc_clk_div);
end = micros();
interrupts();
ets_intr_unlock();
system_soft_wdt_restart();
return end - start;
}
const int deadzone = 8;
void find_minmax(int begin, int end, int& amin, int& amax)
{
amin = adc_buf[begin];
amax = adc_buf[begin];
for (int i = begin + 1; i < end; ++i) {
if (adc_buf[i] < amin) amin = adc_buf[i];
if (adc_buf[i] > amax) amax = adc_buf[i];
}
}
void find_trigger(int holdoff, int& best)
{
int i = holdoff;
int end = adc_num_samples - DISPLAY_WIDTH * scope_step - holdoff;
int minus = adc_buf[holdoff] < (512 - deadzone);
for (i = holdoff + 1; i < end && !minus; ++i) {
minus = adc_buf[i] < (512 - deadzone);
}
for (; i < end && minus; ++i) {
minus = adc_buf[i] < (512 + deadzone);
}
// step back
i -= holdoff;
best = i;
// see if there's something better
int cur_len = 0, best_len = 0;
int cur_start = best, best_start = best;
minus = adc_buf[i] < 512;
for (i = best+1; i < end; ++i) {
int minus2 = adc_buf[i] < 512;
//if (minus2 == minus) {
if (minus2 == 0) { // only positive halfwave
++cur_len;
}
else {
if (cur_len > best_len) {
best_len = cur_len;
best_start = cur_start;
}
minus = minus2;
cur_len = 0;
cur_start = i;
}
}
if (i == end) {
if (cur_len > best_len) {
best_len = cur_len;
best_start = cur_start;
}
}
best = best_start;
}
void draw_osc_frame()
{
u8g2_prepare();
// 1024 samples @ 8us each: 8192us, period = 122Hz, 4096 samples
// step == 1: 128px = ~1ms/1khz
// step == 4: 4ms/244hz
// step == 8: 8ms/125hz
// step == 16: 16/62hz
// step == 32: 32/31.25hz (max with buffer size 4096)
int holdoff = scope_step * 8;
int i;
find_trigger(holdoff, i);
float scale = 60.0 / 1024;
// auto gain
#if 1
int w_min, w_max;
find_minmax(i, i + scope_step * DISPLAY_WIDTH, w_min, w_max);
w_min = 512 - w_min;
w_max = w_max - 512;
w_max = max(w_min, w_max);
if (w_max < 40) w_max = 40;
scale = 60.0 / (2*w_max);
#endif
int y = round(scale*((int)adc_buf[i] - 512) + 31);
for (int x = 1; x < DISPLAY_WIDTH; ++x) {
int y2 = round(scale*((int)adc_buf[i] - 512) + 31);
u8g2.drawLine(x - 1, 64 - y, x, 64 - y2);
y = y2;
i += scope_step;
}
y = 33;
drawDLine(0, y, DISPLAY_WIDTH, y, 1);
}
unsigned long average_sample_time = 0;
int frame_count = 0;
void loop(void) {
average_sample_time = (average_sample_time + adc_sample_buf()) / 2;
#ifdef TUNING
if (++frame_count == 64) {
frame_count = 0;
Serial.print("buf sample time="); Serial.print(average_sample_time); Serial.print(" ");
Serial.print("tsamp="); Serial.print(average_sample_time / (float)adc_num_samples);
Serial.print("us : ");
for (int i = 0; i < adc_num_samples / 32; ++i) {
Serial.print(adc_buf[i * 32]); Serial.print(" ");
}
Serial.println();
}
#endif
// picture loop
u8g2.clearBuffer();
draw_osc_frame();
u8g2.sendBuffer();
}
@cepiburhanudin
Copy link

Hello sir where the connection board

@svofski
Copy link
Author

svofski commented May 29, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment