/* * * 1/ Aufgabenstellug: * =================== * Es soll ein elektronischer Würfel mit 7 LEDs realisiert werden. * Als Zähler soll ein 7492 oder 74LS97 o.ä. eingesetzt werden. * Die LEDs sollen an einen zweckentfremdeten 7-Segment-Decoder/Treiber * 7447 oder 74LS47 angeschlossen werden (Ausgangsstrom: 40 bzw. 24 mA). * * 2/ Nomenklatur: * =============== * M = LED in der Mitte des Würfels (für die Würfelbilder 1, 3 und 5) * L = LED-Paar von links unten nach rechts oben (für die 2, 3, 4, 5, 6) * R = LED-Paar von rechts unten nach links oben (für die 4, 5, 6) * Q = LED-Paar quer (für die 6) * a, b, c, d, e, f, g = Ausgänge des Decoder/Treibers 7447/74LS47 * A, B, C, D = Eingänge des Decoder/Treibers * U, V, W = der Eindeutigkeit halber umbenannte Ausgänge * des Zählers 7492/74LS92 (eigentlich: QB, QC, QD) * X = Festpotenzial, wahlweise low(0) oder high(1) * * 3/ Lösungsansatz * ================ * a/ Die LED-Anschlüsse M,L,R,Q können auf unterschiedliche Weise mit * den Decoder/Treiber-Ausgängen a,b,c,d,e,f,g verbunden werden. * b/ Die Eingänge des Decoder/Treibers können auf unterschiedliche Weise mit * den Zählerausgängen U,V,W (s.o.) und dem Festpotenzial X verbunden werden. * Das Festpotenzial X kann 0 oder 1 sein. * c/ Für jede der Kombinationen aus /a/ und /b/ ist zu prüfen, ob damit dann * die 6 Zustände des Zählers: 0, 1, 2, 4, 5, 6 * die 6 gewünschten Würfelbilder ergeben, wobei die Reihenfolge einerlei ist; * es muss nur die Häufigkeit des Auftretens gezählt werden. * * 4/ Lösung * ========= * Drei ineinander verschchtelte Prozeduren, darin jeweils einige ineinander * verschachtelte Schleifen simulieren die o.g. Kombinationen /a/ und /b/. * In der innersten Prozedur /c/ wird das Durchlaufen des Zähler simuliert * und geprüft, ob jedes der gewünschten Würfelbilder mindestens einmal auftritt. * Falls ja, wird das Ergebns über die Serial ausgegeben. * Während der Entwicklung waren weitere Ausgaben über die Serial hilfreich. * Diese können mit der Variable 'debugLevel' freigeschaltet oder unterdrückt werden. * * 5/ Ergebnis * =========== * Die nachfolgenden Prozeduren wurden auf einer Node-MCU V.3 / ESP-12E implementiert: * 1.451.520 verschachtelte Schleifen benötigten 1604 ms und ergaben 8 Lösungen. * Einzelheiten siehe RESULTATE im Kommentar am Ende dieses Sketches. * Eine der 8 Lösungen wurde für den Stromlaufplan übernommen. * * */ #include // i'm lazy #include #include // ********** Deklarationen ********** // static void SchleifeEingangsBeschaltung(); static void SchleifeAusgangsBeschaltung(); static void SchleifeWuerfelBilderUeberZaehlerStaende(); // ---------- Konstanten ------------- // #define countof(a) (sizeof(a) / sizeof(a[0])) const unsigned int debugLevelA = 9 ; // auf Ebene: SchleifeEINgangsBeschaltung() const unsigned int debugLevelB = 8 ; // auf Ebene: SchleifeAUSgangsBeschaltung() const unsigned int debugLevelC = 7 ; // auf Ebene: SchleifeWuerfelBilderUeberZaehlerStaende() const unsigned int debugLevel = 7 ; // freigeben bzw. unterdrücken der Debug-Ausgaben via Serial const char cntOut[] = "UVWX" ; // SN7492: R=QB, S=QC, T=QD, X=Dauer-0 oder Dauer-1 const char decInp[] = "ABCD" ; const char decOut[] = "abcdefg"; const char Decoder[17][8] = { "1111110", // 0 - Abbild des 7-Segment-Decoders: SN7447/SN74LS47 //abcdefg// hier gilt: 0=OFF, 1=ON (und nicht: 0=low, 1=high) "0110000", // 1 "1101101", // 2 "1111001", // 3 "1001100", // 4 "1011011", // 5 "0011111", // 6 "1110000", // 7 "1111111", // 8 "1110011", // 9 "0001101", // 10 "0011001", // 11 "0100011", // 12 "1001011", // 13 "0001111", // 14 "0000000"}; // 15 const char Wuerfel[7][5] = { "????", // pseudo-0 // QLRM // "0001", // 1 "0010", // 2 "0011", // 3 "0110", // 4 "0111", // 5 "1110"}; // 6 // Ausgangssignale des SN7492 an den Pins QB=0, QC=1, QD=2, bit-pos 3=FestPotenzial const int cntSteps[2][6][4] = {{{ 0,0,0,0 }, // 0 - ab hier Dauer-LOW // Bit-Position 0,1,2,3 // - LSB ist hier links ! { 1,0,0,0 }, // 1 { 0,1,0,0 }, // 2 { 0,0,1,0 }, // 4 { 1,0,1,0 }, // 5 { 0,1,1,0 }}, // 6 {{ 0,0,0,1 }, // 0 - ab hier Dauer-HIGH { 1,0,0,1 }, // 1 { 0,1,0,1 }, // 2 { 0,0,1,1 }, // 4 { 1,0,1,1 }, // 5 { 0,1,1,1 }}}; // 6 // ---------- Variablen -------------- // char PrintString[100]; // im ESP ist Platz genug... int successCount[7]; // 1(!) ... 6(!), zur Überprüfung, ob jedes Würfelbild mindestens einmal auftritt int hurra = 0; // Erfolgszähler für passende Beschaltungs-Kombinationen int M, L, R, Q ; // legt die Eingänge des Würfels auf 0..6, das sind die 7 Ausgänge a..g des Decoders int A, B, C, D ; // legt die Eingänge des Decoders auf 0..3, das sind die 3+1 Ausgänge B,C,D + Hi or Lo des Zählers int FP; // FestPotenzial: 0 oder 1 für low oder high int DecInpVal ; // Decoder-Input-Value in Abhängigkeit von der Eingangsbeschaltung und dem Zählerstand int CntOutNum ; // Zählerstand 0..5, obgleich der Zähler anders zählt: 0,1,2,4,5,6 plus FestPotential long int rowCnt =0 ; // numeriert die Zeilen für die Debug-Ausgaben via Serial long int LoopCnt=0 ; // zählt die ineinander verschachtelten Schleifen // ***** ***** IMPLEMENTIERUNG ***** ***** // // ----- ----- Haupt-Routinen ----- ----- // int main() { printf("\n"); printf("Elektronischer Wuerfel mit 2 ICs: Suchlauf fuer Eingangs- und Ausgangs-Matrix\n"); printf("SN7492(012456) --> E-Matrix --> SN7447 --> A-Matrix --> Wuerfel(MLRQ)\n"); printf("***** START *****\n"); printf("\n"); auto start = std::chrono::high_resolution_clock::now(); SchleifeEingangsBeschaltung(); auto dur = std::chrono::high_resolution_clock::now() - start; printf("\n"); snprintf( PrintString, countof( PrintString ), // %I64d would better be %lld but intellisense does not like it "*** fertig! *** %d verschachtelte Schleifen benoetigten %lld ms und ergaben %d Loesungen\n", LoopCnt, std::chrono::duration_cast(dur).count(), hurra ); printf(PrintString); return 0; } // ----- ----- Unter-Routinen ----- ----- // void SerialPrintInputOutput(){ snprintf( PrintString, countof( PrintString ), // "%5d Eingang: A=%c B=%c C=%c D=%c X=%d / Ausgang: M=%c L=%c R=%c Q=%c", // rowCnt, cntOut[A], cntOut[B], cntOut[C], cntOut[D], FP, decOut[M], decOut[L], decOut[R], decOut[Q] ); "Eingang: A=%c B=%c C=%c D=%c X=%d / Ausgang: M=%c L=%c R=%c Q=%c\n", cntOut[A], cntOut[B], cntOut[C], cntOut[D], FP, decOut[M], decOut[L], decOut[R], decOut[Q] ); printf(PrintString); } void SchleifeEingangsBeschaltung(){ // Die 4 EingangsPins A,B,C,D des Decoders werden in allen möglichen Kombinationen ... // ... auf die 3 AusgangsPins B,C,D des Zählers SN7492 sowie ein FestPotenzial gelegt. // Die AusgangsPins B,C,D sind auf die BitPositionen 0,1,2 gemappt, das FestPotenzial auf Pos.3 // cntSteps[2][6][4] for( FP=0; FP<=1; FP++ ){ for( A=0; A<4; A++ ){ for( B=0; B<4; B++ ){ for( C=0; C<4; C++ ){ for( D=0; D<4; D++ ){ if( A!=B && A!=C && A!=D && B!=C && B!=D && C!=D ){ if( debugLevel >= debugLevelA ){ snprintf( PrintString, countof( PrintString ), "Eingang: A=%d B=%d C=%d D=%d FP=%d --> \n", A, B, C, D, FP ); printf(PrintString); } // end of debugLevel >= debugLevelA SchleifeAusgangsBeschaltung() ; } // end of keine Doppel } // D } // C } // B } // A } // FP } // end of loopLevelA void SchleifeAusgangsBeschaltung(){ // Die 4 EingangsPins M,L,R,Q des Decoders werden in allen möglichen Kombinationen ... // ... auf die 7 AusgangsPins a,b,c,d,e,f,g des Decoders SN7447 gelegt. for( M=0; M<7; M++ ){ for( L=0; L<7; L++ ){ for( R=0; R<7; R++ ){ for( Q=0; Q<7; Q++ ){ if( M!=L && M!=R && M!=Q && L!=R && L!=Q && R!=Q ){ rowCnt++; if( debugLevel >= debugLevelB ){ SerialPrintInputOutput(); } SchleifeWuerfelBilderUeberZaehlerStaende(); // prüft, ob hierbei die gewünschten Würfel-Kombinationen auftreten } // end of keine Duplikate } // Q } // R } // L } // M } // end of SchleifeAusgangsBeschaltung() void SchleifeWuerfelBilderUeberZaehlerStaende(){ // Mittels Variable CntOutNum werden die 6 Zustände 0..5 des Zählers simuliert // Der Zähler selbst zählt: 0,1,2,4,5,6 plus Dauer-Low oder -High // Was davon am Decoder-Eingang ankommt (DecInpVal), bestimmt die SchleifeEingangsBeschaltung() // cntSteps[2][6][4] for( int i=1; i<=6; i++ ){ successCount[i] = 0; } // ErgebnisSpeicher löschen/initialisieren for( CntOutNum=0; CntOutNum<=5; CntOutNum++ ){ // Schleife über die 6 ZählerStände DecInpVal = cntSteps[ FP ][ CntOutNum ][ A ] + cntSteps[ FP ][ CntOutNum ][ B ] * 2 + cntSteps[ FP ][ CntOutNum ][ C ] * 4 + cntSteps[ FP ][ CntOutNum ][ D ] * 8 ; int found=0 ; char vector[ 10 ]; vector[0] = Decoder[ DecInpVal ][ Q ] ; // war: [ M ] ; vector[1] = Decoder[ DecInpVal ][ R ] ; // war: [ L ] ; vector[2] = Decoder[ DecInpVal ][ L ] ; // war: [ R ] ; vector[3] = Decoder[ DecInpVal ][ M ] ; // war: [ Q ] ; vector[4] = 0 ; for( int j=1; j<=6; j++ ){ // Würfel zählt von 1 bis 6 LoopCnt++ ; if( strcmp( vector, Wuerfel[j]) == 0 ){ // ist der Vector ein Würfelbild? found=j; successCount[j]++; } // end of Vector ist ein Würfelbild } // end of loop over j=1 to 6 } // end of Durchlaufen der 6 Zählerstände bool help=true; for( int i=1; i<=6; i++ ){ // kam in der Schleife oben jedes Würfelbild einmal vor if( successCount[i] < 1 ){ help=false; } // war !=1 } // end of Untersuchung der 6 Häufigkeiten if( help ){ hurra++; if( debugLevel >= debugLevelC ){ SerialPrintInputOutput(); } } // end of if help=true } // end of SchleifeWuerfelBilderUeberZaehlerStaende()