Stap 4: Het maken van de firmware voor Marioman
De bijgevoegde tar-bestand heeft het bronbestand evenals gecompileerde firmware voor download.
Drie arrays in de c code werden gebruikt voor het genereren van de muziek
- freq [] - frequenties van elke noot
- lengte [] - lengte van elke noot
- vertraging [] - pauze tussen elke noot
De frequentie-array beschikt niet over de werkelijke frequenties maar eerder de waarde in het register van de TTCROB voor het genereren van de blokgolf uit de PB0 pin te plaatsen.
Hier is een korte samenvatting van de berekeningen en pin-configuratie voor blokgolf generatie:
- De attiny13A heeft een interne oscillator ingesteld op 9.6MHz
- De interne klok voor IO is de gedeeld door 8 of 1.2 MHz oscillator
- Een interne timer is ingesteld in een 8-bit register te tellen elke klokcyclus met prescale van 8.
- Dit resulteert in een teek gelijk is aan 1 / (1.2 MHz / 8) =.006667ms
- De attiny13A is geconfigureerd voor vergelijken wat er in de 8-bit TCCR0B register met de timer en een PIN-code in-/ uitschakelen wanneer zij overeenkomen.
- Als u bijvoorbeeld om het genereren van een blokgolf op 524 Hz (een octaaf boven midden C) die beschikt over een periode van 1.908ms.
1.908ms = 286 klok teken (1.908/.0067)
Verdelen van 286 door 2 om te wisselen van de pin aan de t/2 (286/2 = 143)
143 in het register van de TTCR0B voor het genereren van deze opmerking plaatsen
Dit is de code die nodig is voor het instellen van de timer, doen de vergelijken en output van een blokgolf:
TCCR0A |= (1<<WGM01); // configure timer 1 for CTC mode TCCR0A |= (1<<COM0A0); // toggle OC0A on compare match TCCR0B |= (1<<CS01); // clk/8 prescale TTCR0B = 143; // generate a square wave at 524Hz
Als u wilt vertragen de tonen en de pauzes tussen hen was een eenvoudige vertraging-functie gebruikt:
void sleep(int ms) { int cnt; for (cnt=0; cnt<(ms); cnt++) { int i = 150; while(i--) { __asm("NOP"); } }}
Dit telt af vanaf 150 waar elke NOP-cyclus ongeveer.006667ms is.
Het laatste wat dat de code doet is de arrays doorlopen, genereren de muziek en de twee LED's knipperen.
Dit gebeurt in een continue lus met de volgende code:
const uint8_t freq[] PROGMEM = { ... data };const uint8_t length[] PROGMEM = { ... data };const uint8_t delay[] PROGMEM = { ... data };...while (1) { for (cnt=0; cnt<156; cnt++) { OCR0A=pgm_read_byte(&freq[cnt]); output_toggle(PORTB,PB3); output_toggle(PORTB,PB4); sleep( pgm_read_byte(&length[cnt]) ); output_toggle(PORTB,PB3); output_toggle(PORTB,PB4); // stop timer TCCR0B = 0; sleep ( pgm_read_word(&delay[cnt]) ); // start timer TCCR0B |= (1<<CS01); // clk/8 prescale }}
Er zijn 156 elementen in de frequenties/lengte/vertraging arrays, deze lus doorloopt hen. PIN-PB3 en PB4 zijn elk van een knevel gevoorzid zodat zij zullen worden afgewisseld met elke noot de eerste slaap is de lengte van de opmerking die we spelen na het opzetten van het OCR0A-register op de juiste waarde. De tweede slaap is de pauze tussen de noten die we spelen.
In de bovenstaande code hebt u aankondiging van de twee functies pgm_read_byte() en pgm_read_word(), evenals het sleutelwoord PROGMEM.
Met een ingebouwde chip als de attiny is de hoeveelheid SRAM zeer beperkt, in dit geval enige 64bytes. De arrays die we voor alle frequentie/vertraging/lengte gegevens gebruiken zijn veel groter dan 64bytes en daarom kunnen niet worden geladen in het geheugen. Met behulp van de speciale PROGMEM avr-gcc richtlijn die deze grote gegevensmatrices wordt verhinderd laden in het geheugen, zijn in plaats daarvan ze lezen van flash.