/* ST7789 240x240 IPS (without CS pin) connections (only 6 wires required): #01 GND -> GND #02 VCC -> VCC (3.3V only!) #03 SCL -> D13/SCK #04 SDA -> D11/MOSI #05 RES -> D8 #06 DC -> D10 #07 BLK -> NC */ #define TFT_DC 10 #define TFT_RST 8 #define SCR_WD 240 #define SCR_HT 240 #define CHANNEL0_TOP 20 #define CHANNEL_DISTANCE 50 #define CHANNEL_HEIGHT 30 #define BUFFER_SIZE 1500 #include #include #include Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST); volatile byte samples[BUFFER_SIZE]; void setup(void) { pinMode(TFT_DC, OUTPUT); pinMode(TFT_RST, OUTPUT); pinMode(A0, INPUT_PULLUP); pinMode(A1, INPUT_PULLUP); pinMode(A2, INPUT_PULLUP); tft.init(SCR_WD, SCR_HT); tft.fillScreen(BLACK); tft.setCursor(0, 80); tft.setTextColor(WHITE); tft.setTextSize(2); tft.println(" ABZ Encoder "); tft.setCursor(0, 100); tft.println(" Analyzer "); tft.setCursor(0, 140); tft.println(" Thomeeque (c) 2020 "); delay(1500); noInterrupts(); tft.fillScreen(BLACK); tft.setTextSize(2); } int derivePeriod() { int period = 0; while ((samples[period] & 1) && period < BUFFER_SIZE) { period++; } while (!(samples[period] & 1) && period < BUFFER_SIZE) { period++; } return period; } void drawChannel(int scale, int x, int channel) { int i = x * scale; byte mask = 1 << channel; bool curr = samples[i] & mask; int y1 = CHANNEL_DISTANCE * channel + CHANNEL0_TOP; int y0 = y1 + CHANNEL_HEIGHT - 1; if (x == 0) { tft.drawFastVLine(x, y1, CHANNEL_HEIGHT, channel > 0 ? BLACK : BLUE); } else { bool prev = samples[i - scale] & mask; tft.drawFastVLine(x, y1, CHANNEL_HEIGHT, prev == curr ? BLACK : BLUE); } tft.drawPixel(x, curr ? y1 : y0, BLUE); } void abzAnalysis(int period) { int sA1 = 0, sB1 = 0; int state = 0, states[4]; bool prevA = samples[0] & 1; bool prevB = samples[0] & 2; for (int i = 0; i < 4; i++) { states[i] = 0; } for (int i = 0; i < period; i++) { bool currA = samples[i] & 1; bool currB = samples[i] & 2; if (currA) { sA1++; } if (currB) { sB1++; } if (currA != prevA || currB != prevB) { state++; } if (state < 4) { states[state]++; } prevA = currA; prevB = currB; } float percentRatio = 100.0 / period; tft.setTextColor(period >= BUFFER_SIZE ? RED : GREEN, BLACK); tft.setCursor(0, 196); tft.print(period); tft.print(" "); tft.setTextColor(WHITE, BLACK); tft.print(percentRatio * sA1, 1); tft.print(" "); tft.print(percentRatio * sB1, 1); tft.print(" "); tft.setTextColor(state != 3 ? RED : GREEN, BLACK); tft.print(state + 1); tft.print(" "); tft.setCursor(0, 220); tft.setTextColor(WHITE, BLACK); for (int i = 0; i < 4; i++) { tft.print(percentRatio * states[i], 1); tft.print(" "); } tft.print(" "); } // hlavní smyčka (noInterrupts) void loop(void) { byte s0 = 0; // čekej na náběžnou hranu na prvním kanálu (plus první sample) while (PINC & 1) {} while (!(s0 & 1)) { s0 = PINC; } // nasampluj zbytek (cca 1.3 MSPS, max. BUFFER_SIZE cca 1800) for (int i = 1; i < BUFFER_SIZE; i++) { samples[i] = PINC; } samples[0] = s0; // vykresli a zanalyzuj int period = derivePeriod(); int scale = period / SCR_WD + 1; for (int x = 0; x < SCR_WD; x++) { drawChannel(scale, x, 0); drawChannel(scale, x, 1); drawChannel(scale, x, 2); } abzAnalysis(period); }