#ifndef nanoTronic065.h #define nanoTronic065.h int ip[10] = {0, A7,A6,8,7, A3,A2,A1,A0,13}; // Arduino pins, default int i[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int r[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int f[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0, i7 = 0, i8 = 0, i9 = 0; int r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0, r7 = 0, r8 = 0, r9 = 0; int f1 = 0, f2 = 0, f3 = 0, f4 = 0, f5 = 0, f6 = 0, f7 = 0, f8 = 0, f9 = 0; unsigned long ms[5] = {0, 0, 0, 0, 0}; int c[5] = {0, 0, 0, 0, 0}; int op[10] = {0, 12,11,10,9, 6,5,4,3,2}; // Arduino pins, default int o[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int oe[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int o1 = 0, o2 = 0, o3 = 0, o4 = 0, o5 = 0, o6 = 0, o7 = 0, o8 = 0, o9 = 0; //String iOut = "", oOut = ""; char iOut[15], oOut[15]; #define USE_SCREEN 1 // 1 = kasuta ekraani, 0 = Ära kasuta #if USE_SCREEN == 1 #include #include // I2C liidese jaoks, mis on juba teie projektis olemas U8G2_SSD1306_128X64_NONAME_2_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); #define SMX_ROW_SIZE 22 // Maatriksi rea pikkus #define SMX_ROWS 4 // Ridade arv (4) char sMx[SMX_ROWS][SMX_ROW_SIZE]; // Teie maatriks char ep_temp_buffer[SMX_ROW_SIZE]; size_t ep_buffer_index; void shift_history() { // Alustame altpoolt (viimasest reast, mis nihkub välja) ja liigume üles // Eesmärk: sMx[i] = sMx[i-1] for (int i = SMX_ROWS - 1; i > 0; i--) { // Kopeeri rida (i-1) rida (i) peale. // Strncpy on siin ohutu ja kiire. strncpy(sMx[i], sMx[i-1], SMX_ROW_SIZE); } } // 2A. Lisab char[] (C-stiilis sõne) void ep_append(const char* str) { // Loo TURVALINE versioon strncat abil: size_t remaining = SMX_ROW_SIZE - ep_buffer_index - 1; // 1 koht \0 jaoks if (remaining > 0) { // Kui ruumi on jäänud // strncat on ALATI ohutu ja kopeerib KUNI 'remaining' tähemärki strncat(ep_temp_buffer, str, remaining); // VÄGA OLULINE: Värskendame indeksi pikkusega pärast lisamist. // Kuna me alustasime tühjast puhvrist, peaks see olema ok. ep_buffer_index = strlen(ep_temp_buffer); } } // 2B. Lisab int (Täisarv) void ep_append(int val) { char temp[12]; // Ajutine puhver int väärtuse hoidmiseks size_t len = snprintf(temp, sizeof(temp), "%d", val); // %d = täisarv // Turvalisuskontroll ja lisamine if (ep_buffer_index + len < SMX_ROW_SIZE) { strcat(ep_temp_buffer, temp); ep_buffer_index += len; } } // 2C. Lisab float (Ujukomaarv) void ep_append(float val) { char temp[12]; // %.1f = ujukomaarv 1 komakohaga. Kasutage %.2f, kui vaja 2 kohta. size_t len = snprintf(temp, sizeof(temp), "%.1f", val); if (ep_buffer_index + len < SMX_ROW_SIZE) { strcat(ep_temp_buffer, temp); ep_buffer_index += len; } } void ep_append() { // Lõpetab stringi ajutises puhvris if (ep_buffer_index < SMX_ROW_SIZE) { ep_temp_buffer[ep_buffer_index] = '\0'; // Õige koht } else { ep_temp_buffer[SMX_ROW_SIZE - 1] = '\0'; // Kui ületäitus, siis lõpeta } } template void ep_append(T first, Args... rest) { ep_append(first); // Kutsub vastava ülelaaditud abifunktsiooni (nt int või const char*) ep_append(rest...); // Jätkab rekursiooniga, kutsudes ennast uuesti } // UUS PÕHIFUNKTSIOON: ep(arg1, arg2, ...) template void ep(T first, Args... rest) { // 1. Nihuta ajalugu... shift_history(); // 2. Lähtesta puhver... ep_temp_buffer[0] = '\0'; ep_buffer_index = 0; // 3. Alusta rekursiooni... ep_append(first, rest...); // AITAB SILUDA: KONTROLLI PUHVRIT SERIALIS KOHE PÄRAST KOGUMIST Serial.print(F("Ajutine Puhver (ep_temp_buffer) Sisu: [")); Serial.print(ep_temp_buffer); Serial.println(F("]")); // ... Serial.flush(); kui vaja ... // 4. Kopeeri tulemus esimesse ritta (indeks 0) // strncpy kopeerib KUNI 22 tähemärki strncpy(sMx[0], ep_temp_buffer, SMX_ROW_SIZE); // 5. Nullterminaatori Garanteerimine (Parandus!) // Sõltumata sellest, kas strncpy kopeeris 22 märki või vähem, // on see kood tagab, et maatriksi rida lõppeb kindlasti. sMx[0][SMX_ROW_SIZE - 1] = '\0'; // SMX_ROW_SIZE - 1 on indeks 21 } void ekraaniPrint(){ u8g2.firstPage(); do { u8g2.setFont(u8g2_font_6x10_tf); // Valige font u8g2.setCursor(0, 8); // x, y (U8g2 puhul on y fontide suurusega seotud) u8g2.print(iOut); u8g2.setCursor(0, 18); u8g2.print(oOut); for (int a = 0; a < 4; a++){ // 3 - 6 rida y positsioon 28 - 58 px u8g2.setCursor(0, a * 10 + 28); u8g2.print(sMx[a]); } // end for tsükkel } while (u8g2.nextPage()); } // end ekraaniprint #else template void ep(T first, Args... rest) { // Ära tee midagi } void ekraaniPrint(){ // Ära tee midagi } #endif int deBounceMs = 50; unsigned long dBt[10] = {0,0,0,0,0, 0,0,0,0,0}; bool fHistCheck(int a){ if (dBt[a] < millis()){ return false; } else { return true; } } void fHistorySave(int a){ dBt[a] = millis() + deBounceMs; } void setPinM(){ // set Pin Modes // Configure pin numbers differently int pinConfig = 0; // 0 - default, 1 - legacy if (pinConfig){ ip[1] = 14; ip[2] = 13; ip[3] = 17; ip[4] = 10; // GPIO number, legacy ip[5] = 20; ip[6] = 3; ip[7] = 2; ip[8] = 1; ip[9] = 48; op[1] = 47; op[2] = 38; op[3] = 21; op[4] = 18; op[5] = 9; op[6] = 8; op[7] = 7; op[8] = 6; op[9] = 5; pinMode(ip[5], INPUT); } pinMode(ip[5], INPUT); for (int a = 1; a < 10; a++) { pinMode(op[a], OUTPUT); digitalWrite(op[a], LOW); } } void stOne(){ setPinM(); Serial.begin(115200); #if USE_SCREEN == 1 u8g2.begin(); u8g2.enableUTF8Print(); #endif } // end bool timePass(int timeIn = 1){ if (ms[timeIn] > 0 && millis() > ms[timeIn]){ ms[timeIn] = 0; return true; } else { return false; } } // end timePass func void timeStart(int millisIn, int timeIn = 1){ ms[timeIn] = millis() + millisIn; } // end timeStart func void countStart(int htimes, int cIn = 1){ c[cIn] = htimes; } // end count bool countEnded(int cIn = 1){ if (!c[cIn]){ return true; } else { c[cIn]--; return false; } } // end cEnded void inRe(){ //////// input Reading set i variables /////// iOut[0] = '\0'; char tempChar[3]; // Ajutine puhver (2 märki + \0) for (int a = 1; a < 3; a++) { if (analogRead(ip[a]) > 600){ if (i[a] == 0 & !fHistCheck(a)){ r[a] = 1; } else { r[a] = 0; } i[a] = 1; f[a] = 0; } else if (analogRead(ip[a]) < 400){ if (i[a] == 1){ f[a] = 1; fHistorySave(a); } else { f[a] = 0; } i[a] = 0; r[a] = 0; } snprintf(tempChar, sizeof(tempChar), "%d", i[a]); strcat(iOut, tempChar); } // end for loop for (int a = 3; a < 10; a++) { if (digitalRead(ip[a]) == HIGH){ if (i[a] == 0 & !fHistCheck(a)){ r[a] = 1; } else { r[a] = 0; } i[a] = 1; f[a] = 0; } else if (digitalRead(ip[a]) == LOW){ if (i[a] == 1){ f[a] = 1; fHistorySave(a); } else { f[a] = 0; } i[a] = 0; r[a] = 0; } if (a == 5){ strcat(iOut, " "); // Lisab tühiku } snprintf(tempChar, sizeof(tempChar), "%d", i[a]); strcat(iOut, tempChar); } // end for loop strcat(iOut, " i"); i1 = i[1]; i2 = i[2]; i3 = i[3]; i4 = i[4]; i5 = i[5]; i6 = i[6]; i7 = i[7]; i8 = i[8]; i9 = i[9]; r1 = r[1]; r2 = r[2]; r3 = r[3]; r4 = r[4]; r5 = r[5]; r6 = r[6]; r7 = r[7]; r8 = r[8]; r9 = r[9]; f1 = f[1]; f2 = f[2]; f3 = f[3]; f4 = f[4]; f5 = f[5]; f6 = f[6]; f7 = f[7]; f8 = f[8]; f9 = f[9]; } // end inMo String str(int inputInt){ return String(inputInt); } void pr(){ // Lõpetav funktsioon (prindib uue rea) Serial.println(); } template void pr(T first, Args... rest){ // Rekursiivne printimine Serial.print(first); pr(rest...); } void print(){ // Lõpetav alias pr(); } template void print(T first, Args... rest){ // Rekursiivne alias pr(first, rest...); } void pio(){ pr(iOut); // Prindib iOut ja teeb uue rea pr(oOut); // Prindib oOut ja teeb uue rea } String sm = ""; void seRe(){ if (Serial.available()){ char incomingChar = Serial.read(); if (incomingChar != '\n'){ sm += String(incomingChar); } else { if (sm == "op"){ print(oOut); } if (sm == "ip"){ print(iOut); } if (sm == "p"){ pio(); } sm = ""; } } } // end seRe #ifdef __arm__ // ARM kiipidel on keerulisem määrata, jätame selle lihtsustatud // versiooni ATmega-le, mida kasutab Nano/Uno. #error "See funktsioon on mõeldud ATmega kiipidele (Nano/Uno/Mega)." #else extern char *__brkval; // Viit heap'i lõpule (kui on kasutatud) int getFreeSRAM() { char top; // See on muutuja virnas (stack'is) return (int)&top - (__brkval == 0 ? (int)&top : (int)__brkval); } #endif int cOp(int eelm, int oarr, int ovb){ // compare outputs if (oarr == eelm && ovb != eelm){ return(ovb); } else { return(oarr); } } // end cOp void doOut(){ oOut[0] = '\0'; char tempChar[3]; o[1] = cOp(oe[1], o[1], o1); o[2] = cOp(oe[2], o[2], o2); o[3] = cOp(oe[3], o[3], o3); o[4] = cOp(oe[4], o[4], o4); o[5] = cOp(oe[5], o[5], o5); o[6] = cOp(oe[6], o[6], o6); o[7] = cOp(oe[7], o[7], o7); o[8] = cOp(oe[8], o[8], o8); o[9] = cOp(oe[9], o[9], o9); for (int a = 1; a < 10; a++) { oe[a] = o[a]; if (o[a] == 1){ digitalWrite(op[a], HIGH); } else if (o[a] == 0) { digitalWrite(op[a], LOW); } if (a == 5){ strcat(oOut, " "); } snprintf(tempChar, sizeof(tempChar), "%d", o[a]); strcat(oOut, tempChar); } // end for loop o1 = o[1]; o2 = o[2]; o3 = o[3]; o4 = o[4]; o5 = o[5]; o6 = o[6]; o7 = o[7]; o8 = o[8]; o9 = o[9]; strcat(oOut, " o"); ekraaniPrint(); // kirjuta ekraanile (kui on define USE_SCREEN 1) } // end doOut #endif