Stap 22: Firmware
De volgende firmware uploaden naar de Raad van bestuur:www.Monome.org www.Monome.org www.Monome.org www.Monome.org * * / / / PIN en poort toewijzingen / / als u hardware dan het unsped schild, zult u willen gaan door dit gedeelte van de code, / / en wijzig de pincodes en atmega 168-poorten die u gebruikt. Gebruiken we hier, pin/PORT assignments / / niet de pin nummer regeling uit de arduino bord uitgangen (bijvoorbeeld arduino digitale pin 8 = PORTB pin 1) / / echter in de commentaren hieronder, ik geef de equivalenten tussen arduino digitale pin-codes en de / / atmega168 de poort/bit nummering. BELANGRIJK - u zult moeten om ervoor te zorgen dat u de gegevens op basis van twee richting register variabelen aan uw / / pin toewijzingen. byte PORTD_Data_Direction = 0x02; //all ingangen behalve pin 1 (TX) byte PORTB_Data_Direction = 0xFF; //all uitgangen byte PORTC_Data_Direction = 0xFC; //A2-A5 zijn uitgangen, A0, A1 ingangen //Connections tot 595 shift register //dataPin = A4 = PORTC, bit 4 //clockPin = A2 = PORTC, bit 2 //latchPin = A3 = PORTC, bit 3 #define DATA_PORT_595 (PORTC) byte dataPin595 = 4; byte dataPin595MaskHigh = 1 << dataPin595; byte dataPin595MaskLow = ~ dataPin595MaskHigh; #define CLOCK_PORT_595 (PORTC) byte clockPin595 = 2; byte clockPin595MaskHigh = 1 << clockPin595; byte clockPin595MaskLow = ~ clockPin595MaskHigh; #define LATCH_PORT_595 (PORTC) byte latchPin595 = 3; byte latchPin595MaskHigh = 1 << latchPin595; byte latchPin595MaskLow = ~ latchPin595MaskHigh; Verbindingen met de Max7219 (stations LEDS) / / dataIn = arduino pin A5 = PORTC, bit 5 / / laden = arduino pin 11 = PORTB bits 4 / / klok = arduino pin 12 = PORTB, bit 5 #define LED_DATA_PORT (PORTC) byte MaxDataPin = 5; byte DataMaskHigh = 1 << MaxDataPin; byte DataMaskLow = ~ DataMaskHigh; #define LED_CLOCK_PORT (PORTB) byte MaxClockPin = 5; byte ClockMaskHigh = 1 << MaxClockPin; byte ClockMaskLow = ~ ClockMaskHigh; #define LED_LOAD_PORT (PORTB) byte MaxLoadPin = 4; byte LoadMaskHigh = 1 << MaxLoadPin; byte LoadMaskLow = ~ LoadMaskHigh; end-verbindingen aan de 165 verschuiving te registreren //use dit bevestigen mirroring van Boole mirrorXLEDs = waar; Boole mirrorYLEDs = false; Boole mirrorXButtons = false; Boole mirrorYButtons = false; EINDE pin en poorttoewijzingen / /---/ / globale variabelen byte byte0, byte1; opslag voor inkomende seriële gegevensbyte WaitingForAddress = 1; 1 wanneer wij verwachten het volgende seriële byte een waarde van het adres, adres 0 anders bytes = 0x00; vuilnis byte om te houden van adres functie byte Indiase deelstaat = 0x00; vuilnis te houden staat waarde byte byte x = 0x00; vuilnis byte te houden x positie byte y = 0x00; vuilnis byte te houden y positie byte z = 0x00; vuilnis byte itereert over knoppen / / de volgende variabelen worden gebruikt voor het opslaan van vlaggen die aangeven of we een bepaald bericht hebben ontvangen / / de waarde van de gegevens in dat bericht. bijvoorbeeld IntensityChange = 0 == geen intensiteit verandering bericht ontvangen, / / IntensityChange = 1 == een intensiteit verandering bericht is ontvangen, en zijn waarde zal in IntensityVal / / de code die uiteindelijk bij het inkomende bericht fungeert zal de variabele 'Change' reset naar 0 keer de / / bericht is afgehandeld. byte IntensityChange = 0; byte IntensityVal = 0; byte DisplayTestChange = 0; byte DisplayTestVal = 0; byte ShutdownModeChange = 0; byte ShutdownModeVal = 0; Deze variabelen worden gebruikt om de berichten van de ADC, en winkel welke poorten momenteel zijn ingeschakeld, / / en welke niet. byte ADCnum; byte ADCstate; byte ADCEnableState [4]; byte ledmem [8]; geheugen voor LED Staten - 64 bits. byte j = 0; tijdelijke variabele voor knop looping int i = 0; tijdelijke variabele voor looping etc. int id = 0; tijdelijke opslaglocatie voor binnenkomende bericht ID byte firstRun = 1; 1 wanneer we nog te ontvangen van een LED-opdracht, 0 daarna. gebruikt om ervoor te zorgen dat onze led staat geheugen correct is geïnitialiseerd wanneer we de eerste LED bericht int kButtonUpDefaultDebounceCount ontvangen = 12; Gebruikt in debouncing int kButtonNewEvent knop = 1; Gebruikt voor de opslag of de toestand van een knop is veranderd of niet. byte t = 0; tijdelijke variabele gebruikt bij de verwerking van de knop / * knop ARRAY variabelen voor 1/0 knoptoestanden, 8 bytes (64 bits) voor knop ontdendering counter, gebruik van 8 x 8 matrix * / byte button_current [8]; byte button_last [8]; byte button_state [8]; byte button_debounce_count [8] [8]; byte button_event [8]; / * EINDE van knop ARRAY variabelen * / / * MAX 7219 instructie adressen * / byte max7219_reg_noop = 0x00; define max7219 registers (Lees de tech doc voor explaination) byte max7219_reg_digit0 = 0x01; byte max7219_reg_digit1 = 0x02; byte max7219_reg_digit2 = 0x03; byte max7219_reg_digit3 = 0x04; byte max7219_reg_digit4 = 0x05; byte max7219_reg_digit5 = 0x06; byte max7219_reg_digit6 = 0x07; byte max7219_reg_digit7 = 0x08; byte max7219_reg_decodeMode = 0x09; byte max7219_reg_intensity = 0x0a; byte max7219_reg_scanLimit = 0x0b; byte max7219_reg_shutdown = 0x0c; byte max7219_reg_displayTest = 0x0f; / * EINDE van MAX 7219 instructie adressen * / / / putByte - helper functie die één byte naar de MAX stuurt chip void putByte (bytegegevens) {byte ik = 8; byte mask; while(i > 0) {masker 0x01 = << (i - 1); / / get bitmasker als (data & masker) / / controleren en sturen van de waarde van dit stukje {LED_DATA_PORT | = DataMaskHigh;} anders {LED_DATA_PORT & = DataMaskLow;} / / Pulse de MAX klok LED_CLOCK_PORT & = ClockMaskLow; / / digitalWrite (klok LAAG); "Tik" prepeare voor beetje input LED_CLOCK_PORT | = ClockMaskHigh; / / digitalWrite (klok, hoge); "tock" invoer bit--i; verhuizing naar minder bits}} //maxSingle is de "gemakkelijke" functie om te gebruiken voor een enkele max7219-//dig is de oproep van de rij, en seg is de kolom oproep graven en seg verwijzen naar pin namen van tech doc void maxSingle (byte graven, byte seg) {LED_LOAD_PORT & = LoadMaskLow; / / digitalWrite ("load", laag); / / beginnen putByte(dig); / / Geef register putByte(seg); / / ((data & 0x01) * 256) + data >> 1); gegevens LED_LOAD_PORT | = LoadMaskHigh; digitalWrite(load,HIGH); } / / buttonInit - helper functie die de knop nullen Staten nietig buttonInit(void) {byte ik; voor (ik = 0; ik < 8; i ++) {button_current [i] = 0x00; button_last [i] = 0x00; button_state [i] = 0x00; button_event [i] = 0x00;}} / / buttonCheck - controleert de status van een bepaalde knop. VOID buttonCheck (byte rij, byte index) {als (((button_current [rij] ^ button_last[row]) & (1 << index)) & & / / als de huidige status van de fysieke knop van verschilt de ((button_current [rij] ^ button_state[row]) & (1 << index))) {/ / laatste fysieke knop staat en de huidige debounced staat als (button_current [rij] & (1 << index)) {/ / als de huidige status van de fysieke knoop depressief button_event [rij is] = kButtonNewEvent << index; / / queue van de gebeurtenis van een nieuwe knop onmiddellijk [rij] button_state | = (1 << index); en stel de debounced staat naar beneden. } else {button_debounce_count [rij] [index] = kButtonUpDefaultDebounceCount;} / / anders de knop werd eerder depressief en nu / / is vrijgegeven, zodat we onze ontdendering teller instellen. } anders als (((button_current [rij] ^ button_last[row]) & (1 << index)) == 0 & & / / als de huidige status van de fysieke knop hetzelfde als is (button_current [rij] ^ button_state[row]) & (1 << index)) {/ / de laatste fysieke knop staat maar de huidige fysieke / / knoptoestand verschilt van de huidige ontdendering / / staat... als (button_debounce_count [rij] [index] > 0 & &--button_debounce_count [rij] [index] == 0) {/ / als de de ontdendering teller / / is verlaagd naar 0 (betekenis de / / de knop is al up / / kButtonUpDefaultDebounceCount / / iteraties / / / button_event [rij] = kButtonNewEvent << index; / / queue up een knop staat wijzigingsgebeurtenis als (button_current [rij] & (1 << index)) {/ / en de knoppen ontdendering staat. button_state [rij] in-/ uitschakelen | = (1 << index);} anders {button_state [rij] & = ~ (1 << index);}}} } void buttonpress () {voor (ik = 0; ik < 8; i ++) {LATCH_PORT_595 & = latchPin595MaskLow; / / klink pin laag ingesteld, zodat de resultaten niet wijzigen tijdens het verzenden in bits voor (j = 0; j < 8; j ++) {CLOCK_PORT_595 & clockPin595MaskLow;//digitalWrite(clockPin,LOW); = als (j == ik) {//if index gelijk stroom ik hecht waarde aan, instellen van lage DATA_PORT_595 & = dataPin595MaskLow;//digitalWrite(A4,LOW);} anders {//set de rest van de pinnen hoge DATA_PORT_595 | = dataPin595MaskHigh; //digitalWrite (A4 HOGE); } CLOCK_PORT_595 | = clockPin595MaskHigh;//digitalWrite(clockPin,HIGH); } //set klink pin high-deze gegevens worden verzonden uitgangen LATCH_PORT_595 | = latchPin595MaskHigh; //digitalWrite (latchPin, hoge); Vertraging is zetten hier een beetje om tijd te verspillen terwijl we op de staat van de productie wachten / / pinnen om te regelen. Zonder deze tijd verspillen lus, één enkele knooppers zou verschijnen als / / twee persen (de knop en het buurland) vluchtige int vertraging = 0; terwijl (vertraging < 15) {vertraging ++;} button_last [i] = button_current [i]; voor (id = 0; id < 8; id ++) {schakelaar (id) {geval 0: t = digitalRead(A0); break; case 1: t = digitalRead(A1); break; case 2: t = digitalRead(2); break; case 3: t = digitalRead(3); break; case 4: t = digitalRead(4); break; case 5: t = digitalRead(5); break; case 6: t = digitalRead(6); break; case 7: t = digitalRead(7); break;} t = (t == 0); //invert t if(t) {button_current [i] | = (1 << id);} else {button_current [i] & = ~ (1 << id);} buttonCheck (i, id); Als (button_event [i] & (1 << id)) {button_event [i] & = ~ (1 << id); //zero knop gebeurtenis als (button_state [i] & (1 << id)) {Serial.write(1);} else {Serial.write(byte(0));} als (mirrorXButtons) {id = 7-id;} als (mirrorYButtons) {ik = 7-i;} Serial.write(((id) << 4) | (i)); }}} //set alle pinnen van 595 hoge LATCH_PORT_595 & = latchPin595MaskLow; / / klink pin laag ingesteld, zodat de resultaten niet wijzigen tijdens het verzenden in bits voor (j = 0; j < 8; j ++) {CLOCK_PORT_595 & = clockPin595MaskLow;//digitalWrite(clockPin,LOW); DATA_PORT_595 | = dataPin595MaskHigh;//digitalWrite(A4,HIGH); CLOCK_PORT_595 | = clockPin595MaskHigh;//digitalWrite(clockPin,HIGH); } //set klink pin high-deze gegevens worden verzonden uitgangen LATCH_PORT_595 | = latchPin595MaskHigh; //digitalWrite (latchPin, hoge); } ISR(TIMER2_COMPA_vect) {doen {als (Serial.available()) {als (WaitingForAddress == 1) {byte0 = Serial.read(); adres = byte0 >> 4; WaitingForAddress = 0; } / / end als (WaitingForAddress == 1); Als (Serial.available()) {WaitingForAddress = 1; byte1 = Serial.read(); switch(address) {geval 2: staat = byte0 & 15; x = byte1 >> 4, y = byte1 & 15; als (staat == 0) {ledmem [7-y] & = ~ (1 << x);} anders {ledmem [7-y] | = (1 << x);} break; case 3: IntensityChange = 1; IntensityVal = byte1 & 15; breken; geval 4: DisplayTestChange = 1; DisplayTestVal = byte1 & 15; breken; geval 5: staat = byte1 & 0x0F; ADCEnableState [(byte1 >> 4) & 0x03] = staat; breken; kast 6: ShutdownModeChange = 1; ShutdownModeVal = byte1 & 15; breken; geval 7: als (firstRun == 1) {voor (x = 0 x < 8; x ++) {ledmem [x] = 0;} firstRun = 0;} x = ((byte0 & 15) & 0x7); maskeren deze waarde zodat we niet naar een ongeldig adres schrijven. y = byte1; Als (mirrorYLEDs) {y = 7-y;} als (mirrorXLEDs) {x=flipByte(x);} ledmem [x] = y; breken; geval 8: als (firstRun == 1) {voor (x = 0 x < 8; x ++) {ledmem [x] = 0;} firstRun = 0;} x = ((byte0 & 15) & 0x7); y = byte1; Als (mirrorYLEDs) {x = 7-x;} als (mirrorXLEDs) {y=flipByte(y);} voor (z = 0; z < 8; z ++) {als (y & (1 << z)) {ledmem [z] | = 1 << x;} else {ledmem [z] & = ~ (1 << x);}} breken; } / / end switch(address)} / / end als (Serial.available()} / / end als (Serial.available();} / / end doen terwijl (Serial.available() > 16); } ongeldig whoosh(void) {/ / overflow interrupt voor activeren / / timer 1 - dat het nodig is door delay(...) TIMSK0 | = (1 << TOIE0); voor (int j = 0; j < 9; j ++) {voor (int i = 0; ik < 8; i ++) {maxSingle (i + 1, 1 << j);} delay(125);} / / en de interrupt uit te schakelen. TIMSK0 & = ~ (1 << TOIE0); } void setup () {DDRD = PORTD_Data_Direction; DDRB = PORTB_Data_Direction; DDRC = PORTC_Data_Direction; Serial.begin(57600); buttonInit(); Inleiding van de max 7219 maxSingle (max7219_reg_scanLimit, 0x07); maxSingle(max7219_reg_intensity,0x0F); maxSingle (max7219_reg_shutdown, 0x01); niet in afsluiten modus maxSingle (max7219_reg_displayTest, 0x00); lege registers, zet alle LEDs uit h voor (ik = 1; ik < = 8; i ++) {maxSingle(i,0), ledmem [i-1] = 0;} cli (); //stop interrupts //set timer2 onderbreken elke 128us TCCR2A = 0; / / set hele TCCR2A register op 0 TCCR2B = 0; / / zelfde voor TCCR2B TCNT2 = 0; //initialize waarde van de teller op 0 / / set vergelijk wedstrijd aanmelden voor 7,8 khz stappen OCR2A = 255; / / = (16 * 10 ^ 6) / (7812.5 * 8) - 1 (moet < 256) / / CTC modus TCCR2A inschakelen | = (1 << WGM21); Set CS11-bit in voor 8 prescaler TCCR2B | = (1 << CS11); inschakelen van de timer vergelijk interrupt TIMSK2 | = (1 << OCIE2A); Sei (); //allow interrupts / / / / 8-bit teller 2 ingesteld, uitvoer vergelijk uitgeschakeld, / / / / normale golfvorm generatie (wat dat zou kunnen betekenen) / / TCCR2A = 0; / / set strijd te worden geklokt op 16Mhz/8 = 2 Mhz / / TCCR2B = 1 << CS21; / / / / set de interrupt masker zodat we een interrupt krijgen / / / / op timer 2 overflow, d.w.z. na 256 klokcycli. / / De timer 2 interrupt routine zal uitvoeren elke / / / / 128 ons. TIMSK2 = 1 << TOIE2; / / / / Opmerking: In mijn inspanningen om te proberen om dit te krijgen / / / / code om te werken betrouwbaar op 115200 baud / / / / ik ging over het uitschakelen van ongebruikte timers die / / / / zijn ingesteld door het kader van de Arduino. / / Het kader stelt beide timer 2 en / / / / timer 1. We gebruiken timer 2 naar station de / / / / serieel lezen onderbreken, zodat we kunnen alleen / / / / timer1 en de interrupt uitschakelen. / / / / ECHT belangrijke opmerking: als u wilt gebruik / / / / ANALOGWRITE / / / / / / uitschakelen timer 1 zal uitschakelen van de timer / / / / gebruikt voor PWM, die ten grondslag ligt aan de analogWrite. / / Als u gebruik wilt maken analogWrite, remove / / / / het voorbeeld hieronder. / / / / DISABLE PWM teller / / TIMSK0 & = ~ (1 << TOIE0); / / TCCR1B & = ~ (1 << CS12); TCCR1B & = ~ (1 << CS11); TCCR1B & = ~ (1 << CS10); / / EINDE uitschakelen PWM teller / / / / / / Schakel ook de interrupts op timer 0 / / / / echt belangrijke opmerking als u wilt te gebruiken / / / / vertraging / / / / Verwijder deze regel, en ook kijken naar / / / / 'whoosh', die en vervolgens uitschakelt / / / / de intterupt timer 0. U zult willen / / / / te ontdoen van die lijnen ook. TIMSK0 & = ~ (1 << TOIE0); vrij patroon te verzekeren me dat het de firmware / / geüpload naar behoren. whoosh(); Zorg ervoor dat de lichten uit te schakelen. for (int i = 0; ik < 8; i ++) {maxSingle(i+1,0);}} VOID sendADC (int poort, int value) {/ / Serial.write ((1 << 4) | ((poort << 2) & 0x0C) | ((waarde >> 8) & 0x03)); Serial.write (waarde & 0xFF); } / / //int huidige [4]; int vorige [4]; int tolerantie = 7; VOID checkADCs() {/ / / / voor (int adcCounter = 0; adcCounter < 4; adcCounter ++) / / {/ / / / als (ADCEnableState [adcCounter]! = 0) / / {/ / huidige [adcCounter] = analogRead(adcCounter); / / / / als (abs(previous[adcCounter]-current[adcCounter]) > tolerantie) / / {/ / vorige [adcCounter] = huidige [adcCounter]; / / sendADC(adcCounter,current[adcCounter]); / /} / / / /} / / / /} / /} byte flipByte (byte numToFlip) {byte spiegel = 0; voor (int j = 0; j < 8; j ++) {byte kopie = numToFlip; spiegel | = (kopie >> j) & 1; als (j < 7) {spiegel = spiegel << 1;}} retour spiegel;} ongeldig lus () {/ / verzending van de LED-Staten naar de LED-matrix. voor (int ik = 0; ik < 8; i ++) {byte ledmemMirror = 0; als (mirrorXLEDs) {ledmemMirror=flipByte(ledmem[i])}; anders {ledmemMirror = ledmem [i];} int y; als (mirrorYLEDs) {y =(7-i) + 1;} else {y = i + 1;} maxSingle(y,ledmemMirror);} als (IntensityChange == 1) {IntensityChange = 0; maxSingle (max7219_reg_intensity, IntensityVal & 15);} als (DisplayTestChange == 1) {DisplayTestChange = 0; maxSingle (max7219_reg_displayTest, DisplayTestVal & 15);} als (ShutdownModeChange == 1) {ShutdownModeChange = 0; maxSingle (max7219_reg_shutdown ShutdownModeVal & 15); } / / check voor knop buttonpress() indrukt; / / de status van de ADCs controleren / / checkADCs(); }
U moeten zien uw leds oplichten één kolom een tijd en blader door het display nadat de firmware is voltooid uploaden:
Als uw leds zijn niet bekabeld correct, vast hen nu voordat u naar de volgende stap.