#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Пинове за връзка с 74HC165
const int latchPin = 4; // PL на 74HC165
const int clockPin = 3; // SH_CP на 74HC165
const int dataPin = 2; // Q7 на последния 74HC165
const int numRegisters = 5; // Имаме 5 последователно свързани регистъра
byte registerState[numRegisters]; // Място за съхранение на данните от регистрите
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Структура за съхранение на информация за всеки сегмент на скалата
struct ScaleSegment {
int x; // X координата на сегмента
int y; // Y координата на сегмента
int width; // Ширина на сегмента (за малки, средни и големи)
int height; // Височина на сегмента (за малки, средни и големи)
};
// Масив за всички сегменти на скалата в правилната последователност
const ScaleSegment scaleSegments[] = {
{19, 49, 3, 6}, {23, 53, 2, 2}, {26, 53, 2, 2}, {29, 53, 2, 2}, {32, 53, 2, 2},
{35, 51, 3, 4}, {39, 53, 2, 2}, {42, 53, 2, 2}, {45, 53, 2, 2}, {48, 53, 2, 2},
{51, 49, 3, 6}, {55, 53, 2, 2}, {58, 53, 2, 2}, {61, 53, 2, 2}, {64, 53, 2, 2},
{67, 51, 3, 4}, {71, 53, 2, 2}, {74, 53, 2, 2}, {77, 53, 2, 2}, {80, 53, 2, 2},
{83, 49, 3, 6}, {87, 53, 2, 2}, {90, 53, 2, 2}, {93, 53, 2, 2}, {96, 53, 2, 2},
{99, 51, 3, 4}, {103, 53, 2, 2}, {106, 53, 2, 2}, {109, 53, 2, 2}, {112, 53, 2, 2},
{115, 49, 3, 6}
};
const int numScaleSegments = sizeof(scaleSegments) / sizeof(scaleSegments[0]); // Брой сегменти
// Симулация на сигналите от регистрите (BG- до BG30)
int scaleValue = 0; // Текущо ниво на скалата (0 до максимум)
int scaleDirection = 1; // 1 = нагоре, -1 = надолу
const int maxScaleValue = numScaleSegments; // Максималната стойност е броят на сегментите
// Функция за симулация на сигналите от регистрите
void simulateShiftRegisterSignal() {
for (int i = 0; i < numRegisters; i++) {
registerState[i] = 0; // Всички регистри са нулирани
}
for (int i = 0; i < scaleValue; i++) {
int regIndex = i / 8;
int bitIndex = 7 - (i % 8);
registerState[regIndex] |= (1 << bitIndex);
}
scaleValue += scaleDirection;
if (scaleValue >= maxScaleValue || scaleValue <= 0) {
scaleDirection = -scaleDirection;
}
}
// Функция за рисуване на скалата
void drawScale(int x, int y) {
for (int i = 0; i < numScaleSegments; i++) {
int regIndex = i / 8;
int bitIndex = 7 - (i % 8);
if ((registerState[regIndex] >> bitIndex) & 1) {
display.fillRect(scaleSegments[i].x, scaleSegments[i].y, scaleSegments[i].width, scaleSegments[i].height, SSD1306_WHITE);
}
}
}
// Функция за рисуване на хоризонтален сегмент
void drawHorizontalSegment(int x, int y) {
display.drawPixel(x + 1, y, SSD1306_WHITE);
display.drawLine(x + 2, y, x + 10, y, SSD1306_WHITE);
display.drawPixel(x + 11, y, SSD1306_WHITE);
display.drawLine(x, y + 1, x + 12, y + 1, SSD1306_WHITE);
display.drawPixel(x + 1, y + 2, SSD1306_WHITE);
display.drawLine(x + 2, y + 2, x + 10, y + 2, SSD1306_WHITE);
display.drawPixel(x + 11, y + 2, SSD1306_WHITE);
}
// Функция за рисуване на вертикален сегмент
void drawVerticalSegment(int x, int y) {
display.drawPixel(x, y + 1, SSD1306_WHITE);
display.drawLine(x, y + 2, x, y + 8, SSD1306_WHITE);
display.drawPixel(x, y + 9, SSD1306_WHITE);
display.drawLine(x + 1, y, x + 1, y + 10, SSD1306_WHITE);
display.drawPixel(x + 2, y + 1, SSD1306_WHITE);
display.drawLine(x + 2, y + 2, x + 2, y + 8, SSD1306_WHITE);
display.drawPixel(x + 2, y + 9, SSD1306_WHITE);
}
// Функция за рисуване на минус (изглеждащ като горен сегмент)
void drawMinus(int x, int y) {
drawHorizontalSegment(x, y); // Минусът ще бъде на нивото на средния сегмент
}
// Функция за рисуване на Ом символ
void drawOhmSymbol(int x, int y) {
display.drawCircle(x + 2, y + 3, 3, SSD1306_WHITE);
display.drawLine(x - 1, y + 6, x + 1, y + 6, SSD1306_WHITE);
display.drawLine(x + 3, y + 6, x + 5, y + 6, SSD1306_WHITE);
display.drawLine(x + 1, y + 6, x + 3, y + 6, SSD1306_BLACK);
}
// Функция за рисуване на диод тест символ
void drawDiodeTestSymbol(int x, int y) {
display.drawCircle(x + 6, y + 6, 6, SSD1306_WHITE);
display.fillRect(x + 5, y + 5, 3, 3, SSD1306_WHITE);
}
// Функция за рисуване на цифра със 7 сегмента
void drawDigit(int digit, int x, int y) {
bool segments[7];
switch (digit) {
case 0: segments[0] = segments[1] = segments[2] = segments[3] = segments[4] = segments[5] = true; segments[6] = false; break;
case 1: segments[1] = segments[2] = true; segments[0] = segments[3] = segments[4] = segments[5] = segments[6] = false; break;
case 2: segments[0] = segments[1] = segments[6] = segments[4] = segments[3] = true; segments[2] = segments[5] = false; break;
case 3: segments[0] = segments[1] = segments[2] = segments[3] = segments[6] = true; segments[4] = segments[5] = false; break;
case 4: segments[5] = segments[1] = segments[6] = segments[2] = true; segments[0] = segments[3] = segments[4] = false; break;
case 5: segments[0] = segments[5] = segments[6] = segments[2] = segments[3] = true; segments[1] = segments[4] = false; break;
case 6: segments[0] = segments[5] = segments[6] = segments[2] = segments[3] = segments[4] = true; segments[1] = false; break;
case 7: segments[0] = segments[1] = segments[2] = true; segments[3] = segments[4] = segments[5] = segments[6] = false; break;
case 8: segments[0] = segments[1] = segments[2] = segments[3] = segments[4] = segments[5] = segments[6] = true; break;
case 9: segments[0] = segments[1] = segments[2] = segments[3] = segments[5] = segments[6] = true; segments[4] = false; break;
}
if (segments[0]) drawHorizontalSegment(x, y);
if (segments[1]) drawVerticalSegment(x + 12, y + 2);
if (segments[2]) drawVerticalSegment(x + 12, y + 14);
if (segments[3]) drawHorizontalSegment(x, y + 24);
if (segments[4]) drawVerticalSegment(x - 2, y + 14);
if (segments[5]) drawVerticalSegment(x - 2, y + 2);
if (segments[6]) drawHorizontalSegment(x, y + 12);
}
// Функция за рисуване на брояч от 0000 до 9999
void drawNumber(int number, int x, int y) {
drawDigit((number / 1000) % 10, x, y);
drawDigit((number / 100) % 10, x + 22, y);
drawDigit((number / 10) % 10, x + 44, y);
drawDigit(number % 10, x + 66, y);
}
// Променлива за брояча
int count = 0;
void drawInterfaceGraphics() {
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(2, 9);
display.println("MIN");
display.setCursor(108, 9);
display.println("MAX");
display.drawTriangle(120, 20, 115, 25, 125, 25, SSD1306_WHITE);
display.setCursor(107, 30);
display.println("nS");
display.setCursor(121, 30);
display.println("H");
display.setCursor(107, 39);
display.println("M");
display.setCursor(113, 39);
display.println("k");
drawOhmSymbol(120, 39);
drawDiodeTestSymbol(4, 39);
display.setCursor(39, 39);
display.println("3");
display.setCursor(58, 39);
display.println("30");
display.setCursor(77, 39);
display.println("300");
display.drawLine(4, 26, 8, 26, SSD1306_WHITE);
display.drawLine(12, 26, 16, 26, SSD1306_WHITE);
display.drawRect(2, 27, 17, 10, SSD1306_WHITE);
display.setCursor(4, 28);
display.println("-");
display.setCursor(12, 28);
display.println("+");
display.fillTriangle(121, 48, 121, 54, 124, 51, SSD1306_WHITE);
int SCALE_POS_X = 19;
int SCALE_POS_Y = 55;
drawScale(SCALE_POS_X, SCALE_POS_Y);
display.fillRect(SCALE_POS_X - 11, SCALE_POS_Y - 2, 5, 1, SSD1306_WHITE);
// Рисуване на минус отпред
drawMinus(4, 21); // Минусът ще е пред първата цифра
}
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, INPUT);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
}
void loop() {
simulateShiftRegisterSignal();
display.clearDisplay();
drawNumber(count, 24, 9);
drawInterfaceGraphics();
display.display();
count = (count + 1) % 10000;
delay(1);
}