ArSid - Arduino Sid Synthesizer

Thu 12-Dec-19
23:06:08




Decoder

Datum: Fri 01 July 2016
Samenvatting: De Decoder zorgt voor het decoderen van de Adresbus naar de Sid's en de Latches-registers (deze is compleet getest na een onderbreking van bijna anderhalf jaar).
 Soort Artikel: Electro
Status: Afgerond



[Tekst] [Afbeeldingen] [Aansluitingen] [Broncodes]
decoder_01-schema.jpg
1/21: decoder_01-schema.jpg.
decoder_02-printontwerp.jpg
2/21: decoder_02-printontwerp.jpg.
decoder_03-printcut.jpg
3/21: decoder_03-printcut.jpg.
decoder_04-oscillator.jpg
4/21: decoder_04-oscillator.jpg.
decoder_05-osc1mhz.jpg
5/21: decoder_05-osc1mhz.jpg.
decoder_06-oscteller.jpg
6/21: decoder_06-oscteller.jpg.
Meer
[Tekst] [Afbeeldingen] [Aansluitingen] [Broncodes]

Om vanuit de Adres-bus de data naar de juiste Sid, of de juiste register van de Latches te laten gaan, moet het adres worden gedecodeerd. Deze taak wordt verricht door de Decoder. Daarnaast krijgt de Decoder een Kristal Oscillator van 1MHz (voor de phi2 (Φ2, "p2") van de Sid's) en een Lcd-Teller, die de bewerkingstijd (van 40 usec) van het Lcd-Display telt (een soort van Timer).

Een ander "probleem" is de verkrijgbaarheid van de benodigde IC-s en daardoor de ruimte op de print (zie Lcd-Timer).

Het schema zelf is in deze 3 delen verdeeld.

Het Decoderen.

Het decoderen van het adres is recht-toe recht-aan en gebeurt met 4 losse decoder-IC's (74hct138). Bij 2 decoders worden maar 1 uitgang gebruikt, wat eventueel met losse poorten gedaan zou kunnen worden. Echter decoders nemen minder ruimte op de print in, dus zijn het decoders geworden.

Om een adres te decoderen, moet er eerst bekend worden welke losse adressen de diverse componenten krijgen. Allereerst is het maximum Sids op 8 gesteld, dit aantal zorgt dat er maar 1 decoder nodig is om alle 8 Sids te kunnen adresseren (IC1). Er is bekend dat een Sid 32 adressen nodig heeft ($00..$1F) - Deze decodering gebeurt in de Sids zelf. Bij elkaar zijn dit (8 * 32 =) 256 adres-posities.

Van de Latches is bekend dat er 6 registers zijn, dit geeft een bereik van 8 adressen weer (8 is 2^3). Dit kan met 1 decoder (IC3). Hiervan zijn er 5 write-registers en 1 read-register. Dit read-register geeft een extra verdeling en dus extra poorten, of een extra decoder. Hier is gekozen voor de extra decoder (IC4). Om dit aantal mooi te laten passen met het bereik van de Sids, zijn ook voor deze registers totaal 256 adres-posities verdeeld. Dit resulteert wel dat de registers een aantal keer worden gespiegeld (256 DIV 8 geeft 32 spiegelingen => 5 adres-lijnen), ik heb gekozen om de spiegeling te beperken tot 4 keer (en is er dus nog een extra decoder nodig (IC2)).

Bij elkaar geeft dit de volgende twee tabellen.

Sids

A7654 3210Sid-NrAdres
%000x xxxx0 $00..$1F
%001x xxxx1 $20..$3F
%010x xxxx2 $40..$5F
%011x xxxx3 $60..$7F
%100x xxxx4 $80..$9F
%101x xxxx5 $A0..$BF
%110x xxxx6 $C0..$DF
%111x xxxx7 $E0..$FF

Latches

R/~wA7654 3210Register Adres R/~wA7654 3210Register Adres
w 0 %000x x0000 Leds Cols $00 R 1 %000x x000- $00
w 0 %000x x0011 Leds ColNr$01 R 1 %000x x001- $01
w 0 %000x x0102 Lcd Data $02 R 1 %000x x010- $02
w 0 %000x x0113 Lcd Ctrl $03 R 1 %000x x011- $03
w 0 %000x x100- $04 R 1 %000x x1004 Schaks In $04
w 0 %000x x1015 Schaks Out$05 R 1 %000x x101- $05
w 0 %000x x110- $06 R 1 %000x x110- $06
w 0 %000x x111- $07 R 1 %000x x111- $07
- x %xx1x xxxx- > $20
- x %x1xx xxxx- > $40
- x %1xxx xxxx- > $80

Dit geheel resulteert dus in twee gebieden van elk 256 adres-posities. De verdeling tussen deze twee gebieden wordt door de eerst volgende adres-lijn gemaakt (Adres-lijn A8). Hogere Adres-lijnen worden er niet gebruikt in de ArSid, maar zouden altijd nog geïmplementeerd kunnen worden (Adres A9 t/m A14). Een extra detail is een lijn "Adres-Enable". Hiermee moeten alle I/O worden uitgeschakeld, bijvoorbeeld tijdens het voorbereiden van een nieuw adres om van te lezen of naar te schrijven. Nogmaals deze Adres/Data-bus structuur is afgeleid van de 6502 processor (c.q. 6510), maar mij is niet bekend hoe men het daar opgelost heeft wanneer de processor ergens (intern) mee bezig was, zonder dat er geheugen benaderd moest worden.

EnA8 7654 3210Latches/SidsAdres
%0%0 xxxx xxxxLatches $0000 .. $00FF
%0%1 xxxx xxxxSids $0100 .. $01FF
%1%x xxxx xxxx- -

De Oscillator.

De Sids hebben een tijdbasis nodig met een frequentie van 1 MegaHertz (1.000MHz). In een 65xx structuur wordt deze gehaald uit het klok-signaal van de processor, phi2 genaamd (Φ2, "p2"). Hier moet het apart worden opgewekt. Het kan dat er een klok-signaal op de Arduino Mega print aanwezig is, echter de Arduino werkt op 8MHz (en wellicht nog hoger).

De oscillator is opgebouwd middels een beproefd recept. Een kristal en een IC 74LS04 vormen de basis - dit moet een LS-type zijn. Een HCT-type regaeert veel te snel om te oscilleren op de frequentie van het kristal. De poorten IC5-a en IC5-b vormen de feitelijke oscillator, poort IC5-c is een buffertje.

De Lcd-Timer.

Bij het schrijven naar het Lcd-Display heeft het display ongeveer 40 micro seconden (40us) nodig om de bewerking af te ronden. Deze bewerkingstijd is er ook bij het lezen van het Display, maar in de ArSid wordt alleen geschreven naar het Display. Hier moet rekening mee worden gehouden en dit kan op 3 manieren.

  1. Softwarematig - Na elke schrijf-bewerking komt er een delay(40us); Nadeel is dat de Arduino tijdens deze wachttijd gewoon niets anders kan doen.
  2. Interupt-Timer - Na elke schrijf-bewerking moet een interne Timer in de Arduino op gang worden gebracht, waarna deze een interupt opwekt. Na elke schrijf-bewerking zijn er extra instructies nodig om deze Timer te resetten.
  3. Hardwarematig & Interupt - Ook hier wordt na elke schrijf-bewerking een timer gereset (hier verder een "Teller" genoemd). Dit betreft een hardware-matige aktie en er zijn dus geen extra programma instructies nodig.

Er is gekozen voor de laatste optie, de hardware-matige oplossing met een 8-bits teller. Het idee is dat een teller-IC, aangesloten op de Φ2 (1MHz = 1us) en bij 40us stopt met tellen. Een schrijf-pulse naar het Lcd-Display reset deze teller, zodat deze weer begint met tellen. 40us is geen mooie macht van 2, dus wordt er een hardware-vergelijker (IC7, een 74hct85) gebruikt om bij de benodigde stand de teller te laten stoppen. Met Dip-Switches (S1) wordt deze eindstand opgegeven. Misschien is 40us te weinig, daarom is de stand hier bepaald op 44us. Het kan ook dat de 40us te veel is ... ook dit kan dan nog eenvoudig worden aangepast.

Een mooi IC hiervoor was gevonden in de 74hct590, dat alle benodigde teller-functies in zich heeft (8-bits, tellen, teller-stop, reset). Dit type is echter alleen in SMD (Surface Mounted Device) beschikbaar - en dus niet geschikt voor mijn vaardigheden.

In DIP (Dual In Pin, de standaard IC's met twee rijen pinnetjes) kom ik dan op het type 74hct393 (IC6). Hier zitten twee losse tellers in met elk de volgende eigenschappen: 4-bits, tellen, reset. Een teller-stop moet zelf worden gerealiseert en gebeurt hier met een extra IC met Nand-poorten (IC8-c en IC8-d, een 74hct00). De extra ruimte die de 74hct00 gaat innemen zorgt dat er geen ruimte meer op de print is voor de Dip-Switches. Een blik op de print geeft twee opties voor de Dip-Switches: (Optie 2) een los printje, gemonteerd met een extra schroefje die met draadjes wordt aangesloten op de vergelijker (74hct85), of (Optie 1) met behulp van print-pennen "boven" op de vergelijker monteren. De foto's geven aan dat ik hier voor optie 1 heb gekozen.

De print.

De print zelf is zo smal mogelijk gemaakt, om de meest (nog) mogelijke ruimte te creëren voor de Sids - iets waar nu al echt rekening mee moet worden gehouden. Nu blijkt ook dat de centimeter die naast de voedingsprint is gehouden, wellicht te breed is geweest, waardoor ik nu de overgebleven ruimte zo vol mogelijk moet zien te maken voor het volledige ontwerp.

Zelfs de DipSwitches (S1) monteren op de print zelf, maakte de print al te breed (ook al ging het maar om 7.5mm = 3 gaatjes). De Dipswitches was dan namelijk gepland halverwege naast IC6 en IC7.

De print is volgens een geijkt concept opgebouwd. Montage gaatjes boren, koper-sporen onderbreken, IC-voeten, andere componenten, konnectoren, draadjes en dan op naar de volgende stap.

Het testen.

Eerst is de oscillator getest (IC5). Een oscilloscoop geeft een keurig signaal van 1.000 MHz (±10.1 kHz, toch nog 1 procent afwijking - geen idee hoe hoorbaar deze afwijking is). Misschien dat hier nog een ander ontwerp voor de oscillator moet komen.

Daarna is de teller-IC (IC6) (en toebehoren (IC8)) in de print geprikt en getest. Het oscilloscoop-beeld geeft hier wel een niet-verwacht beeld van onregelmatige pulsen op het B-kanaal (= uitgang Q3 van de teller IC6). Verwacht was een keurige verdeling van 8 pulsen boven geeft 1 puls beneden.

De vergelijker kon op dit moment nog niet worden getest, omdat dit onderdeel nog niet binnen was. Wel is de Dip-Switch (S1) alvast op zijn plek geprikt.

Als laatste zijn de vier ecoder-IC's (IC1 .. IC4) op hun plaats geprikt. De LedRij is als indicatie-Led's op de uitgangen naar resp. de Latches (IC3 en IC4) en de Sids (IC1) aangesloten. Ook zijn de aansluit-connectoren gemaakt tussen de Arduino-Mega, de Latches en de Decoder.

Op de foto's is ook al de (kale) print voor de Sids te zien (rechts onder) en een extra stukje Flat-kabel (voor de Data-bus) is al (opgerold) neergelegd richting de Sids-print.

Tenslotte is er een programmaatje gemaakt die een teller-variabele stuurt naar de toekomstige Adres-bus. Niet alle test-resultaten zijn op de foto gezet, slechts een groene brandende Led van de LedRij.

Wat nu volgt is een uitgebreide test van de samenwerking van de Arduino, Decoder en Latches.

Testen met de Led Rij.

De test-procedure en programma-opbouw is dezelfde als bij de Latches. Maar bij het testen van de LedRij dienen enkele funkties worden aangepast aan de Decoder, namelijk allen die de adres-bus en data-bus aanroepen.

De Adres-bus funkties moeten worden aangepast van een 6-lijns enable naar een 9 bits adres-bus (gecombineerd met een enable). Bij de declaratie van de variabele aa moet het type byte worden veranderd in word. De lage 8-bits van het adres moeten naar PortC en de hoogste bit(s) moet(en) naar PortL.

De Data-bus funkties moeten worden aangepast met een "Enable/Disable" systeem en een juiste R/~W aansturing.

Er is een extra vertraging nodig tussen het klaar zetten van de Data op de Data-bus en het geven van de Enable-puls. Zonder deze vertraging laat de led Rij een onregelmatig ge"knipper" zien van Leds die niet aangezet worden. Dit verklaart waarom sommige regels twee keer worden uitgevoerd.

Theorie over de Sids (en met name de 8580-Sids) doet mij vermoeden dat er nog meer vertraging in deze funktie moet komen, of dat er nog gekeken moet worden naar het Φ2 (p2) signaal ... maar dat wordt een zorg voor later.

Getest is ook dat het niet aktiveren van de Write (op de R/~W-lijn) ook daadwerkelijk geen enkel register aktiveerd (en dus geen enkele Led laat branden). Op zich is dit wel een belangrijke funktie. Het continue aktiveren van de Write aktiveert namelijk WEL de registers en zal zorgen voor onbedoelde akties.

Voor de rest zijn in de Write_Data() funktie ook alle (losse) Adres-regels gedaan. Dit weer om minder tijd-vertragingen te geven bij funktie-oproepen (en zo).

Alles is hier gericht op zo snel mogelijke afhandelingen, met alleen een vertraging waar het echt nodig is.

Testen met de Lcd.

Hier is de test-procedure en programma opbouw ook dezelfde als bij de Latches. En ook hier hoeven alleen de procedures voor de Adres-bus en Data-bus worden aangepast. Daarna werkte dit programma meteen zonder verdere debugging, zoals de foto's laat zien (die met de tekst "Arsid Decoder Check"). De ledRij is hier (net als bij de Latches) keurig met de potmeters te beïnvloeden.

De funktie Read_Data() is bij deze test weggelaten en wordt straks bij de schakelaars (opnieuw) geschreven.

Testen met de schakelaars.

En ook hier is de test-procedure en programma opbouw dezelfde als bij de Latches. En ook hier hoeven alleen de procedures voor de Adres-bus en Data-bus worden aangepast. Daarna werkte dit programma meteen zonder verdere debugging, zoals de foto's laat zien (die met de tekst "Arsid Decoder Check").

En net als bij de Latches zijn de posities van alle potmeters en van alle schakelaars op het Display te zien en is de ledRij is hier (net als bij de Latches) keurig met de potmeters te beïnvloeden.

De Lcd-Timer

Uiteraard moet de Lcd-Timer op zich nog getest worden. Eerst moeten enkele tijden worden vastgesteld van de diverse funkties. Een methode is om de interne tijdbasis van de Arduino Mega te nemen, zoals die gegevens wordt via de funktie tijd = Micros();. In het kort wordt de tijd uit deze funktie genomen aan het begin EN aan het eind van de te testen funkties en dan het verschil hiervan te tonen. Echter voor het zover is, moet eerst het aantal funkties voor de lcd worden uitgebreid met het volgende:

  1. Lcd_gotoxy(X,Y): Plaatst de cursor van het Lcd Display op de gegeven positie.
  2. Lcd_print(string): Plaats de inhoud van de string op het lcd Display.
  3. Lcd_number(nummer, aantal): Plaats de inhoud van het nummer op het lcd Display in aantal posities (met voorloopnullen).

Voor het doel hier, zijn deze funkties hier niet opgenomen, maar worden uitgebreid besproken wanneer deze funkties in een eigen Library opgenomen zijn. De bij-dit-deel behorende listing is daarom ook erg kort.

Wat hier WEL belangrijk is, is de delay(42); in de funktie Lcd-Out(). Deze ingebouwde vertraging staat hier nog vast en deze vertraging moet door de Lcd_Timer worden vervangen. Maar voordat het zover is ...

Aan het eind van de listing staan enkele tijden van geteste funkties. Wat opvalt is dat de timer-funktie Micros() zelf een resolutie heeft van 4 micro secondes. Wat ook opvalt is het tijdsverloop tussen 0uS en 4uS. Er zijn zelf nog geen enkele interupt-routines geaktiveerd, welicht komt dit verloop door interupt-routines die intern al lopen. Tevens is dit verloop bij alle geteste funkties waargenomen en variëerd tussen 4uS en 12uS.

De funktie Lcd-out() heeft 54±2uS nodig. Hierbij wordt er maar 1 teken naar het Lcd Display gestuurd MET de geprogrammeerde Delay(42) erin. De funktie Lcd_print() heeft 4uS meer nodig (namelijk 58±4uS), veroorzaakt door de daarin gebouwde while() constructie die nodig is om een gehele string af te lopen. Hoe meer tekens Lcd_print() moet afdrukken, hoe langer het duurt, tot 4108±4uS voor een heel scherm met tekens ... 4.1 millisecondes voor een heel scherm.

De funktie Lcd_number() heeft voor 1 cijfer 152±2uS nodig. Voor 5 cijfers worden dit 664±4uS.

Het verlagen van de delay(42); tot delay(32); verlaagt de vertraging tot 44±4uS (bij de funktie Lcd_out()). Dit is een versnelling met 10uS.

Omdat ik de Vergelijker-IC (74hct85) nog niet heb, heb ik besloten om (tijdelijk) één van de uitgangen van de teller (74hct393) eens door te koppelen aan de uitgangspin (pin 6, 74hct85). Ik heb extra pinnen gesoldeerd op de print-connectoren voor de oscilloscoop ... en wel op de aansluiting van de Lcd, afkomstig van de latches (probe A) en de Lcd, gaande naar de Arduino probe B) - of te wel, de reset van de Tellers en de uitgang van de Vergelijker. De twee (grijze) probes van de scoop zijn duidelijk te zien op de foto.

Het beeld van de scoop gaf eerst aan dat er iets niet helemaal goed zat. De brede Arduino Mega connector zit onlogischer in elkaar dan verwacht, want ik had er twee aansluitingen verwisseld (de Φ2 en de Lcd). Het goed-om solderen geeft een goed beeld en het programma gaat zoals gepland.

Nu is het een questie geweest om de juiste teller-uitgang (74hct393) te pakken. Pulseert een uitgang te snel, dan geeft het Lcd Display de teksten op willekeurige posities ... een teken dat het schrijven naar het display te snel gaat. Het verbinden van teller-uitgang Q1 (van teller 2, pin 10, 74hct393) (= pin 15 op de Vergelijker, 74hct85) blijkt een goede te zijn. Met een vertraging van 40±0uS (!) toont het display een stabiel beeld. Wat opvalt is dat deze 40uS op zich ook stabiel is. Bovendien geeft de scoop deze 40uS keurig weer in zijn vakjes. Een bewijs dat het Timer-idee op zich goed is ... maar, zonder Vergelijker, is het nog niet kompleet.

Theoretische bepaling van de waarde voor de Dip-Switches.

Er is een theoretische waarde waarop de Dip-Switches ingesteld zouden moeten worden voor een juist gedrag van het Lcd-Display. De Datasheet van het display zegt dat het minimaal 40usec nodig heeft voor een juiste werking, tijd die gebruikt wordt om display-insructies te interpreteren en de tekens naar de juiste positie te sturen. Deze 40usec is bus leidend.

Wetend dat de vertraginsteller op 1MHz loopt en om het display zeker genoeg tijd te geven, moet er minimaal tot de waarde 40 worden geteld. Op 1MHz komt dit overeen met 40usec. Ietsje erbij, geeft 44usec. 44 decimaal komt overeen met %0010 1100. Dit is de waarde die in het schema staat boven de (8-bits) teller-IC en de vergelijker-IC. Dit geeft de volgende tabel (inclusief gemeten waardes en display conclusies).

Instellen Tellerwaarde TheoretischArduino usecScoop usec GekozenOpmerking
%1111%0011 111062 68 .. 72 69 .. 70
%1110%0011 101058 64 .. 68 65 .. 65
%1101%0011 011054 60 .. 64 61 .. 61
%1100%0011 001050 56 .. 60 57 .. 58
%1011%0010 111046 52 .. 56 53 .. 54 Theoretische waarde
%1010%0010 101042 48 .. 52 49 .. 50
%1001%0010 011038 44 .. 48 45 .. 46
%1000%0010 001034 40 .. 44 41 .. 42<== Net goed (genoeg)
%0111%0001 111030 36 .. 40 37 .. 38te snel Puinhoop op Display
%0110%0001 101026 32 .. 36 33 .. 34veel te snel Puinhoop
%0111%0001 011022 28 .. 32 29 .. 30veel te snel Puinhoop
%0110%0001 001018 24 .. 28 25 .. 26veel te snel Puinhoop
%0011%0000 111014 20 .. 24 21 .. 22veel te snel Puinhoop
%0010%0000 101010 16 .. 20 17 .. 18veel te snel Puinhoop
%0001%0000 0110 6 12 .. 16 13 .. 14veel te snel Puinhoop
%0000%0000 0010 2 ? 7 .. 8veel te snel Puinhoop

De Vergelijker-IC en de Dip-Switches.

Nadat de Vergelijker-IC (74hct85) (eindelijk) is binnengekomen, is ook dit gedeelte getest. Er kwam nog een vergeten draadbrugje op de opsteekprint met de Dip-Switchen aan het licht. De oscilloscoop is weer aangesloten op de punten Lcd-Timer (linksboven in het schema, het derde aansluitpunt) en Lcd-Enable (rechtsmidden in het schema, het onderste aansluitpunt) en de Dip-Switches zijn één voor één omgezet (op dit punt werd de vergeten draadbrug ontdekt).

Na de eerder bepaalde waarde van %1011 op de Dip-Switches te hebben ingesteld, ontstond er een gemeten Lcd-tijd van 52usec tot 56usec. De oscilloscoop geeft een Lcd-tijd van 53usec tot 54usec. Langzamer dan de eerder bepaalde 44usec. Uiteraard is deze instel-waarde gevarieerd en dan blijkt er een belangrijk kantelpunt te zitten bij de waardes van %0111 en %1000. De theoretische waarde is duidelijk te hoog bepaald.

Zoals de foto's ook aangeven functioneerd het Lcd-Display niet correct bij de waarde van %0111. Er vallen tekens weg en het titelscherm is door elkaar gehusseld, puinhoop dus. Er is wel een vertragingswaarde zichtbaar van 36usec tot 40usec. Dit is dus duidelijk te snel. Met de Dip-Swichen ingesteld op een waarde hoger (%1000), dan worden de tekens wel correct op het display aangegeven en ontstaat er een vertragingswaarde van 40usec en 44usec (de oscilloscoop geeft een tijd van 41usec tot 42usec).

Is er bij de te-snelle instel-waardes nog wel een meet-getal te lezen op het display, bij een instel-waarde van %0000 (onderste regel in de tabel) valt dit meet-getal niet meer te ontdekken, omdat hij wegvalt in de getallen-puinhoop op het display. De Oscilloscoop geeft wel een waarde, namelijk van 7usec tot 8usec, keurig binnen de verwachtingen van de tabel - elke Dip-Switch stap is 4usec.

Op zich is het kantel-punt van %0111 en %1000 op de Dip-Switches een mooie waarde, omdat deze evenveel naar boven als naar beneden kan worden ingesteld. De gemeten waarde van 41.5usec (gemiddeld) valt ook keurig boven de waarde van 40usec die het display nodig heeft.

Wat op de oscilloscoop ook opvalt is dat de teller-tijd varieert binnen 1usec. In bovenstaand tabel is dit ook aangegeven. En dit is ook te zien doordat de teller in het laatste osciloscoop plaatje schijnbaar telt tot stand 33.5. Deze variatie wordt veroorzaakt door de a-synchrone reset van de teller EN doordat de oscilatoren van zowel de Arduino, als op de decoder-print niet met elkaar gekoppeld zijn en dus niet synchroon met elkaar lopen. De éne keer wordt de reset van de teller ge-de-activeerd als de clock-pulse laag is, een andere keer wanneer deze hoog is.

Wat ook opvalt is dat de oscilloscoop een vertraginstijd geeft van 41usec tot 42usec en dat de Arduino een waarde van 40usec tot 44usec aangeeft. Deze afwijking wordt hoofdzakelijk veroorzaakt door de resolutie van 4usec die de gebruikte meet-funkties hebben.

Al met al geeft het laatste oscilloscoop-beeld een plaatje die aan de verwachtingen voldoet en waarbij alle tijden te verklaren zijn aan de aan de Dip-Switch instellingen en werking van de functies van het draaiende programma.

Einde Test.

Nu in deze fase alles werkt, kunnen de volgende fases worden gestart (zoals de Sids print en versterkers). De meest essentiele I/O-routines werken, de rest hoeft er alleen nog omheen worden geprogrammeerd.

Ook kan nu alvast begonnen worden met andere stukjes programma, zoals noten-tabellen of de opbouw van diverse schermen, of "libraries" bouwen. 


[Tekst] [Afbeeldingen] [Aansluitingen] [Broncodes]

Afbeeldingen

decoder_01-schema.jpg
1/21: decoder_01-schema.jpg.
decoder_02-printontwerp.jpg
2/21: decoder_02-printontwerp.jpg.
decoder_03-printcut.jpg
3/21: decoder_03-printcut.jpg.
decoder_04-oscillator.jpg
4/21: decoder_04-oscillator.jpg.
decoder_05-osc1mhz.jpg
5/21: decoder_05-osc1mhz.jpg.
decoder_06-oscteller.jpg
6/21: decoder_06-oscteller.jpg.
decoder_07-oscteller.jpg
7/21: decoder_07-oscteller.jpg.
decoder_08-oscteller.jpg
8/21: decoder_08-oscteller.jpg.
decoder_09-dipswitch.jpg
9/21: decoder_09-dipswitch.jpg.
decoder_10-decoders.jpg
10/21: decoder_10-decoders.jpg.
decoder_11-spanning.jpg
11/21: decoder_11-spanning.jpg.
decoder_12-led.jpg
12/21: decoder_12-led.jpg.
decoder_13-ledrij.jpg
13/21: decoder_13-ledrij.jpg.
decoder_14-lcdschaks.jpg
14/21: decoder_14-lcdschaks.jpg.
decoder_15-lcdtimer.jpg
15/21: decoder_15-lcdtimer.jpg.
decoder_16-lcdtimer.jpg
16/21: decoder_16-lcdtimer.jpg.
decoder_17-osctimer.jpg
17/21: decoder_17-osctimer.jpg.
decoder_18-print-osc.jpg
18/21: decoder_18-print-osc.jpg.
decoder_19-dip0111.jpg
19/21: decoder_19-dip0111.jpg.
decoder_20-dip1000.jpg
20/21: decoder_20-dip1000.jpg.
decoder_21-osctimer-dip1000.jpg
21/21: decoder_21-osctimer-dip1000.jpg.

[Tekst] [Afbeeldingen] [Aansluitingen] [Broncodes]

De aansluitingen van Decoder

Diverse tests van de Latches-print

Arduino Mega

Pwr USB ?
 
?
aref
gnd Gnd's
? d13 Lr = Backlight Blauw
ioreff d12 Lg = Backlight Groen
Reset reset d11 Lb = Backlight Rood
+3.3v d10
+5V L+ = LCDBacklight +5v d9
Gnd's gnd d8
Gnd's gnd
Vin d7
d6
Potmeter 0 a0 d5
Potmeter 1 a1 d4
Potmeter 2 a2 d3
Potmeter 3 a3 d2
Potmeter 4 a4 d1
Potmeter 5 a5 d0
Potmeter 6 a6
Potmeter 7 a7 d14
d15
Potmeter 8 a8 d16
Potmeter 9 a9 d17
Potmeter A a10 d18 Tx1 = Midi Out
Potmeter B a11 d19 Rx1 = Midi In
Potmeter C a12 d20
Potmeter D a13 d21
Potmeter E a14 /~\
Potmeter F a15 \_/
Onderconnector
D0 = Data 0 d22 | d23 D1 = Data 1
D2 = Data 2 d24 | d25 D3 = Data 3
D4 = Data 4 d26 | d27 D5 = Data 5
D6 = Data 6 d28 | d29 D7 = Data 7
 | 
A7 = Adres 7 d30 | d31 A6 = Adres 6
A5 = Adres 5 d32 | d33 A4 = Adres 4
A3 = Adres 3 d34 | d35 A2 = Adres 2
A1 = Adres 1 d36 | d37 A0 = Adres 0
 | 
(hier niet nodig) Reset d38 | d39 Lcd
R/~W d40 | d41 phi2
 | 
~Enable Adres d42 | d43
d44 | d45
d46 | d47
d48 | d49 A8 = Adres 8
 | 
d50 | d51
d52 | d53



[Tekst] [Afbeeldingen] [Aansluitingen] [Broncodes]
Broncode: [1: Decoder met LedRij] [2: Decoder met Lcd] [3: Decoder met Schakelaars] [4: Decoder met Lcd-Timing]
[5: Decoder met LcdOut-funktie]

1: De broncode van Decoder met LedRij

(Sun 03 July 2016) Het testen van de Decoder met de LedRij. Hierbij is de Decoder en de Aansturing nodig.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/****************************************************************************
    ArSid Decoder Test LedRij

    Decoder Print test Programma.
    Nodig: Latches
           Control-Potmeters
           Aansturing ledRij

*****************************************************************************/


const byte bitje[8] = {1,2,4,8,16,32,64,128};

void setup()
{ Set_Adres_Out();
  Write_Data (0, 0xFF);
  Write_Data (1, 0xFF);

  Write_Lcdback(0x02);   delay(250);
  Write_Lcdback(0x01);   delay(250);
  Write_Lcdback(0x02);

}

void loop()
{ // put your main code here, to run repeatedly:
  for (word qq = 1; qq <= 255; qq = qq + 1)
      { byte ql = qq & 0x0F;
        Write_Lcdback(ql);
        for (word ww = 0; ww <= 255; ww = ww + 1)
            { Write_Led (ww, ql, ql, ql);
              delay(  2);                // wait some time
            }
      }
}


// ===================================================================

void Write_Led(byte nr, byte L1, byte L2, byte L3)
{
  nr = nr & 0x0F;
  L1 = (L1 & 0x0F) ^ 0x0F;
  L2 = (L2 & 0x0F) ^ 0x0F;
  L3 = (L3 & 0x0F) ^ 0x0F;
  Write_Data (0, (L2 << 4) + L1);
  Write_Data (1, (nr << 4) + L3);
}

// ===================================================================
// ===================================================================
// ===================================================================

byte readwrite = 0b00000010;   // R/~W bitje op de Control-bus.

void Write_Lcdback(byte LL)
{ // Write byte naar Lcd Backlight
  LL = LL & 0b00000111;
  LL = LL ^ 0x07;
  DDRB = DDRB | 0b11100000;
  PORTB = (PORTB & 0x1F) | ( LL << 5);
}

void Set_Adres_Out()
{ // Set de Adres op Output
  DDRC = 0xFF;
  DDRL = 0xFF;
  // Zet Adres 0x0000 op de Adres-bus, inclusief Disable.
  PORTG = 0b00000000;
  PORTL = 0b10000000;
  // Set Control-bus p2 en Lcd op Input  en  R/~W op Output
  DDRG = readwrite;
  // Zet de Control-bus op Read
  PORTG = readwrite;
}

void Write_Adres(word aa)
{ // Write byte naar Adresbus
  PORTC = aa & 0xFF;
  PORTL = ((aa >> 8) & 0x01) | 0x80;
}

void Set_Data_Out()
{ // Set de Databus op Output
  DDRA = 0xFF;
}

void Set_Data_In()
{ // Set de Databus op Int
  DDRA = 0x00;
}

void Write_Data(word aa, byte dd)
{ // Write byte naar Databus
  // Write Adres to Adres-bus
  PORTC = aa & 0xFF;
  PORTL = ((aa >> 8) & 0x01 ) | 0x80;
  // Set Databus as Output
  DDRA = 0xFF;
  // Schrijf de Data
  PORTA = dd;
//  PORTA = dd;             // Twee keer voor een korte vertraging
  // Zet Write op Control-bus
  PORTG = 0b00000000;
  // Enable Adres
  PORTL = PORTL & 0x7F;
  PORTL = PORTL & 0x7F;   // Twee keer voor een korte vertraging
  // Disable Adres
  PORTL = PORTL | 0x80;
  PORTG = readwrite;
}


Broncode: [1: Decoder met LedRij] [2: Decoder met Lcd] [3: Decoder met Schakelaars] [4: Decoder met Lcd-Timing]
[5: Decoder met LcdOut-funktie]

2: De broncode van Decoder met Lcd

(Sun 03 July 2016) Het testen van de Decoder met de Lcd. Hierbij is de Decoder en de LedRij (met Aansturing) nodig.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/****************************************************************************
    ArSid Decoder Test Lcd

    Decoder Print test Programma.
    Nodig: Latches
           Control-Potmeters
           Aansturing ledRij

*****************************************************************************/


const byte bitje[8] = {1,2,4,8,16,32,64,128};

word P0 = 0;
word P1 = 0;
word P2 = 0;
word P3 = 0;
word P4 = 0;
word P5 = 0;
word P6 = 0;
word P7 = 0;
word P8 = 0;
word P9 = 0;
word PA = 0;
word PB = 0;
word PC = 0;
word PD = 0;
word PE = 0;
word PF = 0;

void setup()
{ Set_Adres_Out();
  Write_Data (0, 0xFE); // Init LedRij Col
  Write_Data (1, 0x0F); // Init LedRij ColNr

  Write_Lcdback(0x02);

  Lcd_Init();
}

void loop()
{ // put your main code here, to run repeatedly:
  P0 = analogRead( 0) / 64;
  P1 = analogRead( 1) / 64;
  P2 = analogRead( 2) / 64;
  P3 = analogRead( 3) / 64;
  P4 = analogRead( 4) / 64;
  P5 = analogRead( 5) / 64;
  P6 = analogRead( 6) / 64;
  P7 = analogRead( 7) / 64;
  P8 = analogRead( 8) / 64;
  P9 = analogRead( 9) / 64;
  PA = analogRead(10) / 64;
  PB = analogRead(11) / 64;
  PC = analogRead(12) / 64;
  PD = analogRead(13) / 64;
  PE = analogRead(14) / 64;
  PF = analogRead(15) / 64;

  Write_Led(P8,P0,P1,P2);
  Write_Lcdback(P9);

  Pots_On_Lcd();
}

void Pots_On_Lcd()
{ // Write Alle Potmeter Waardes
  Lcd_Out(0,0b11000000);    // GotoXY(0,1)
  Lcd_Out(1,Byte2Hexchar(P0));
  Lcd_Out(1,Byte2Hexchar(P1));
  Lcd_Out(1,Byte2Hexchar(P2));
  Lcd_Out(1,Byte2Hexchar(P3));
  Lcd_Out(1,' ');
  Lcd_Out(1,Byte2Hexchar(P4));
  Lcd_Out(1,Byte2Hexchar(P5));
  Lcd_Out(1,Byte2Hexchar(P6));
  Lcd_Out(1,Byte2Hexchar(P7));
  Lcd_Out(1,' ');
  Lcd_Out(1,Byte2Hexchar(P8));
  Lcd_Out(1,Byte2Hexchar(P9));
  Lcd_Out(1,Byte2Hexchar(PA));
  Lcd_Out(1,Byte2Hexchar(PB));
  Lcd_Out(1,' ');
  Lcd_Out(1,Byte2Hexchar(PC));
  Lcd_Out(1,Byte2Hexchar(PD));
  Lcd_Out(1,Byte2Hexchar(PE));
  Lcd_Out(1,Byte2Hexchar(PF));
  delay(100);
}

byte Byte2Hexchar(byte bb)
{ if (bb < 0x0A)
     { return bb+'0';
     }
  else
     { return bb+('A'-0x0A);
     }
}

// ===================================================================

void Write_Led(byte nr, byte L1, byte L2, byte L3)
{
  nr = nr & 0x0F;
  L1 = (L1 & 0x0F) ^ 0x0F;
  L2 = (L2 & 0x0F) ^ 0x0F;
  L3 = (L3 & 0x0F) ^ 0x0F;
  Write_Data (0, (L2 << 4) + L1);
  Write_Data (1, (nr << 4) + L3);
}

void Lcd_Init()
{ delay(20);                          // Wait while the LCD-unit itself is initialized
  // Sent Lcd Initialisation, 3 times (as described in the datasheet).
  Lcd_Out(0,0b00111000); delay(5);   // 1st LCD write (set 8bits interface)
  Lcd_Out(0,0b00111000); delay(1);   // 2nd LCD write (set 8bits interface)
  Lcd_Out(0,0b00111000); delay(1);   // 3rd LCD write (set 8bits interface)
  // Sent Lcd Instructions
  Lcd_Out(0,0b00111000);    // Function-Set 8-bits, 2-lines, 5x8-font, <none>, <none>
  Lcd_Out(0,0b00001000);    // Set Display On/Off Control: Cursor, Blinking
  Lcd_Out(0,0b00001100);    // Set Display On/Off Control: Cursor, Blinking
  Lcd_Out(0,0b00010100);    // Set Cursor/ Display Shift: Shift/Cursor, Right/Left, <none>, <none>
  Lcd_Out(0,0b00000110);    // Entry Mode Set: Inc/Dec, DisplShift
  Lcd_Out(0,0b00000001);    // Clear Display
  delay(2);
  Lcd_Out(0,0b10000000);    // GotoXY(0,0)
  Write_Lcd_LatchTest_Text();
}

void Write_Lcd_LatchTest_Text()
{ // Sent Characters
  Lcd_Out(1,'A');
  Lcd_Out(1,'r');
  Lcd_Out(1,'S');
  Lcd_Out(1,'i');
  Lcd_Out(1,'d');
  Lcd_Out(1,' ');
  Lcd_Out(1,'D');
  Lcd_Out(1,'e');
  Lcd_Out(1,'c');
  Lcd_Out(1,'o');
  Lcd_Out(1,'d');
  Lcd_Out(1,'e');
  Lcd_Out(1,'r');
  Lcd_Out(1,' ');
  Lcd_Out(1,'C');
  Lcd_Out(1,'h');
  Lcd_Out(1,'e');
  Lcd_Out(1,'c');
  Lcd_Out(1,'k');
}

void Lcd_Out(byte rr, byte bb)
{ // Rs  0  %00000000 = Instruction Register
  // Rs  1  %00000001 = Data Register
  // En  0  %00000000 = Enable     (Falling Edge)
  // En  1  %00001000 = Not Enable (Raising Edge)

  rr=rr & 0b00000001;

  Write_Data(3,0b00001000 | rr);
  Write_Data(2,bb);
  delayMicroseconds(42);
  Write_Data(3,0b00000000 | rr);
}

// ===================================================================
// ===================================================================
// ===================================================================

byte readwrite = 0b00000010;   // R/~W bitje op de Control-bus.

void Write_Lcdback(byte LL)
{ // Write byte naar Lcd Backlight
  LL = LL & 0b00000111;
  LL = LL ^ 0x07;
  DDRB = DDRB | 0b11100000;
  PORTB = (PORTB & 0x1F) | ( LL << 5);
}

void Set_Adres_Out()
{ // Set de Adres op Output
  DDRC = 0xFF;
  DDRL = 0xFF;
  // Zet Adres 0x0000 op de Adres-bus, inclusief Disable.
  PORTG = 0b00000000;
  PORTL = 0b10000000;
  // Set Control-bus p2 en Lcd op Input  en  R/~W op Output
  DDRG = readwrite;
  // Zet de Control-bus op Read
  PORTG = readwrite;
}

void Write_Adres(word aa)
{ // Write byte naar Adresbus
  PORTC = aa & 0xFF;
  PORTL = ((aa >> 8) & 0x01) | 0x80;
}

void Set_Data_Out()
{ // Set de Databus op Output
  DDRA = 0xFF;
}

void Set_Data_In()
{ // Set de Databus op Int
  DDRA = 0x00;
}

void Write_Data(word aa, byte dd)
{ // Write byte naar Databus
  // Write Adres to Adres-bus
  PORTC = aa & 0xFF;
  PORTL = ((aa >> 8) & 0x01 ) | 0x80;
  // Set Databus as Output
  DDRA = 0xFF;
  // Schrijf de Data
  PORTA = dd;
//  PORTA = dd;             // Twee keer voor een korte vertraging
  // Zet Write op Control-bus
  PORTG = 0b00000000;
  // Enable Adres
  PORTL = PORTL & 0x7F;
  PORTL = PORTL & 0x7F;   // Twee keer voor een korte vertraging
  // Disable Adres
  PORTL = PORTL | 0x80;
  PORTG = readwrite;
}


Broncode: [1: Decoder met LedRij] [2: Decoder met Lcd] [3: Decoder met Schakelaars] [4: Decoder met Lcd-Timing]
[5: Decoder met LcdOut-funktie]

3: De broncode van Decoder met Schakelaars

(Sun 03 July 2016) Het testen van de Decoder met de Schakelaars. Hierbij is de Decoder, de Lcd en de LedRij (met Aansturing) nodig.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/****************************************************************************
    ArSid Decoder Test Schakelaars

    Latches Print test Programma.
    Nodig: Schakelaars
           Lcd (Rgb Backlight)
           Control-Potmeters
           Aansturing ledRij

*****************************************************************************/


const byte bitje[8] = {1,2,4,8,16,32,64,128};

word P0 = 0;
word P1 = 0;
word P2 = 0;
word P3 = 0;
word P4 = 0;
word P5 = 0;
word P6 = 0;
word P7 = 0;
word P8 = 0;
word P9 = 0;
word PA = 0;
word PB = 0;
word PC = 0;
word PD = 0;
word PE = 0;
word PF = 0;
byte Schak = 0;

void setup()
{ Set_Adres_Out();
  Write_Data (0, 0xFE); // Init LedRij Col
  Write_Data (1, 0x0F); // Init LedRij ColNr

  Write_Lcdback(0x02);

  Lcd_Init();
}

void loop()
{ // Lees Potmeters
  P0 = analogRead( 0) / 64;
  P1 = analogRead( 1) / 64;
  P2 = analogRead( 2) / 64;
  P3 = analogRead( 3) / 64;
  P4 = analogRead( 4) / 64;
  P5 = analogRead( 5) / 64;
  P6 = analogRead( 6) / 64;
  P7 = analogRead( 7) / 64;
  P8 = analogRead( 8) / 64;
  P9 = analogRead( 9) / 64;
  PA = analogRead(10) / 64;
  PB = analogRead(11) / 64;
  PC = analogRead(12) / 64;
  PD = analogRead(13) / 64;
  PE = analogRead(14) / 64;
  PF = analogRead(15) / 64;

  // Doe Potmeters naar LedRij Kleur en Nr
  Write_Led(P8,P0,P1,P2);

  // Doe Potmeters naar Lcd BackLight Kleur
  Write_Lcdback(P9);

  // Lees en Schrijf Schakelaars
  Schaks_On_Lcd(0xFF,00);
  Schak=Read_Schak(0x00);    Schaks_On_Lcd(0x00,Schak);
  Schak=Read_Schak(0x01);    Schaks_On_Lcd(0x01,Schak);
  Schak=Read_Schak(0x02);    Schaks_On_Lcd(0x02,Schak);
  Schak=Read_Schak(0x03);    Schaks_On_Lcd(0x03,Schak);

  Schak=Read_Schak(0x04);    Schaks_On_Lcd(0x04,Schak);
  Schak=Read_Schak(0x05);    Schaks_On_Lcd(0x05,Schak);
  Schak=Read_Schak(0x06);    Schaks_On_Lcd(0x06,Schak);
  Schak=Read_Schak(0x07);    Schaks_On_Lcd(0x07,Schak);

  Schak=Read_Schak(0x08);    Schaks_On_Lcd(0x08,Schak);
  Schak=Read_Schak(0x09);    Schaks_On_Lcd(0x09,Schak);
  Schak=Read_Schak(0x0A);    Schaks_On_Lcd(0x0A,Schak);
  Schak=Read_Schak(0x0B);    Schaks_On_Lcd(0x0B,Schak);

  Schak=Read_Schak(0x0C);    Schaks_On_Lcd(0x0C,Schak);
  Schak=Read_Schak(0x0D);    Schaks_On_Lcd(0x0D,Schak);
  Schak=Read_Schak(0x0E);    Schaks_On_Lcd(0x0E,Schak);
  Schak=Read_Schak(0x0F);    Schaks_On_Lcd(0x0F,Schak);
  Pots_On_Lcd();
}

void Schaks_On_Lcd(byte SchakNr, byte Schak)
{ // Write Schakelaar Waardes
  if (SchakNr >= 0x10)
     { // Schrijf "e" (Eerste Schakelaar Bits) en "o" ( hOogste Schakelaar Bits)
       Lcd_Out(0,0b10000000 | 20 | 0b00000000);    // GotoXY(0,2)
       Lcd_Out(1,'e');
       Lcd_Out(0,0b10000000 | 20 | 0b01000000);    // GotoXY(0,3)
       Lcd_Out(1,'o');
     }
  else
     { // Schrijf Schakelaar Stand
       if (SchakNr >= 0x0C) { SchakNr = SchakNr + 1; }
       if (SchakNr >= 0x08) { SchakNr = SchakNr + 1; }
       if (SchakNr >= 0x04) { SchakNr = SchakNr + 1; }
       Lcd_Out(0,0b10000000 | 21+SchakNr | 0b00000000);    // GotoXY(0,2)
       Lcd_Out(1,Byte2Hexchar(Schak & 0x0F));
       Lcd_Out(0,0b10000000 | 21+SchakNr | 0b01000000);    // GotoXY(0,3)
       Lcd_Out(1,Byte2Hexchar(Schak >> 4));
     }
}

void Pots_On_Lcd()
{ // Schrijf "p" (Potmeters)
  Lcd_Out(0,0b11000000);    // GotoXY(0,1)
  Lcd_Out(1,'p');
  // Schrijf Alle Potmeter Waardes
  Lcd_Out(1,Byte2Hexchar(P0));
  Lcd_Out(1,Byte2Hexchar(P1));
  Lcd_Out(1,Byte2Hexchar(P2));
  Lcd_Out(1,Byte2Hexchar(P3));
  Lcd_Out(1,' ');
  Lcd_Out(1,Byte2Hexchar(P4));
  Lcd_Out(1,Byte2Hexchar(P5));
  Lcd_Out(1,Byte2Hexchar(P6));
  Lcd_Out(1,Byte2Hexchar(P7));
  Lcd_Out(1,' ');
  Lcd_Out(1,Byte2Hexchar(P8));
  Lcd_Out(1,Byte2Hexchar(P9));
  Lcd_Out(1,Byte2Hexchar(PA));
  Lcd_Out(1,Byte2Hexchar(PB));
  Lcd_Out(1,' ');
  Lcd_Out(1,Byte2Hexchar(PC));
  Lcd_Out(1,Byte2Hexchar(PD));
  Lcd_Out(1,Byte2Hexchar(PE));
  Lcd_Out(1,Byte2Hexchar(PF));
  delay(100);
}

byte Byte2Hexchar(byte bb)
{ if (bb < 0x0A)
     { return bb+'0';
     }
  else
     { return bb+('A'-0x0A);
     }
}

// ===================================================================

void Write_Led(byte nr, byte L1, byte L2, byte L3)
{
  nr = nr & 0x0F;
  L1 = (L1 & 0x0F) ^ 0x0F;
  L2 = (L2 & 0x0F) ^ 0x0F;
  L3 = (L3 & 0x0F) ^ 0x0F;
  Write_Data (0, (L2 << 4) + L1);
  Write_Data (1, (nr << 4) + L3);
}

void Lcd_Init()
{ delay(20);                          // Wait while the LCD-unit itself is initialized
  // Sent Lcd Initialisation, 3 times (as described in the datasheet).
  Lcd_Out(0,0b00111000); delay(5);   // 1st LCD write (set 8bits interface)
  Lcd_Out(0,0b00111000); delay(1);   // 2nd LCD write (set 8bits interface)
  Lcd_Out(0,0b00111000); delay(1);   // 3rd LCD write (set 8bits interface)
  // Sent Lcd Instructions
  Lcd_Out(0,0b00111000);    // Function-Set 8-bits, 2-lines, 5x8-font, <none>, <none>
  Lcd_Out(0,0b00001000);    // Set Display On/Off Control: Cursor, Blinking
  Lcd_Out(0,0b00001100);    // Set Display On/Off Control: Cursor, Blinking
  Lcd_Out(0,0b00010100);    // Set Cursor/ Display Shift: Shift/Cursor, Right/Left, <none>, <none>
  Lcd_Out(0,0b00000110);    // Entry Mode Set: Inc/Dec, DisplShift
  Lcd_Out(0,0b00000001);    // Clear Display
  delay(2);
  Lcd_Out(0,0b10000010);    // GotoXY(1,0)
  Write_Lcd_LatchTest_Text();
}

void Write_Lcd_LatchTest_Text()
{ // Sent Characters
  Lcd_Out(1,'A');
  Lcd_Out(1,'r');
  Lcd_Out(1,'S');
  Lcd_Out(1,'i');
  Lcd_Out(1,'d');
  Lcd_Out(1,' ');
  Lcd_Out(1,'L');
  Lcd_Out(1,'a');
  Lcd_Out(1,'t');
  Lcd_Out(1,'c');
  Lcd_Out(1,'h');
  Lcd_Out(1,' ');
  Lcd_Out(1,'C');
  Lcd_Out(1,'h');
  Lcd_Out(1,'e');
  Lcd_Out(1,'c');
  Lcd_Out(1,'k');
}

void Lcd_Out(byte rr, byte bb)
{ // Rs  0  %00000000 = Instruction Register
  // Rs  1  %00000001 = Data Register
  // En  0  %00000000 = Enable     (Falling Edge)
  // En  1  %00001000 = Not Enable (Raising Edge)

  rr=rr & 0b00000001;

  Write_Data(3,0b00001000 | rr);
  Write_Data(2,bb);
  delayMicroseconds(42);
  Write_Data(3,0b00000000 | rr);
}

byte Read_Schak(byte SchakNr)
{ byte ss = 0;
  SchakNr = SchakNr & 0x0F;
  Write_Data(5,SchakNr);     // Write Schakelaars Out
  ss = ~ Read_Data(4);       // Read  Schakelaars In
  return ss;
}

// ===================================================================
// ===================================================================
// ===================================================================

byte readwrite = 0b00000010;   // R/~W bitje op de Control-bus.

void Write_Lcdback(byte LL)
{ // Write byte naar Lcd Backlight
  LL = LL & 0b00000111;
  LL = LL ^ 0x07;
  DDRB = DDRB | 0b11100000;
  PORTB = (PORTB & 0x1F) | ( LL << 5);
}

void Set_Adres_Out()
{ // Set de Adres op Output
  DDRC = 0xFF;
  DDRL = 0xFF;
  // Zet Adres 0x0000 op de Adres-bus, inclusief Disable.
  PORTG = 0b00000000;
  PORTL = 0b10000000;
  // Set Control-bus p2 en Lcd op Input  en  R/~W op Output
  DDRG = readwrite;
  // Zet de Control-bus op Read
  PORTG = readwrite;
}

void Write_Adres(word aa)
{ // Write byte naar Adresbus
  PORTC = aa & 0xFF;
  PORTL = ((aa >> 8) & 0x01) | 0x80;
}

void Set_Data_Out()
{ // Set de Databus op Output
  DDRA = 0xFF;
}

void Set_Data_In()
{ // Set de Databus op Int
  DDRA = 0x00;
}

void Write_Data(word aa, byte dd)
{ // Write byte naar Databus
  // Write Adres to Adres-bus
  PORTC = aa & 0xFF;
  PORTL = ((aa >> 8) & 0x01 ) | 0x80;
  // Set Databus as Output
  DDRA = 0xFF;
  // Schrijf de Data
  PORTA = dd;
//  PORTA = dd;             // Twee keer voor een korte vertraging
  // Zet Write op Control-bus
  PORTG = 0b00000000;
  // Enable Adres
  PORTL = PORTL & 0x7F;
  PORTL = PORTL & 0x7F;   // Twee keer voor een korte vertraging
  // Disable Adres
  PORTL = PORTL | 0x80;
  PORTG = readwrite;
}

byte Read_Data(word aa)
{ // Write byte naar Databus
  byte dd = 0;
  // Write Adres to Adres-bus
  PORTC = aa & 0xFF;
  PORTL = ((aa >> 8) & 0x01 ) | 0x80;
  // Set Databus as Output
  DDRA = 0x00;
//  PORTA = dd;             // Twee keer voor een korte vertraging
  // Zet Write op Control-bus
  PORTG = readwrite;
  // Enable Adres
  PORTL = PORTL & 0x7F;
  PORTL = PORTL & 0x7F;   // Twee keer voor een korte vertraging
  // Lees de Data
  dd = PINA;
  // Disable Adres
  PORTL = PORTL | 0x80;
  PORTG = readwrite;
  // Return de data
  return dd;
}


Broncode: [1: Decoder met LedRij] [2: Decoder met Lcd] [3: Decoder met Schakelaars] [4: Decoder met Lcd-Timing]
[5: Decoder met LcdOut-funktie]

4: De broncode van Decoder met Lcd-Timing

(Sun 17 July 2016) Het testen van de Decoder met de Lcd-Timer. Hierbij is de Decoder, de Lcd en de LedRij (met Aansturing) nodig.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/****************************************************************************
    ArSid Decoder Test Lcd-Timer

    Latches Print test Programma.
    Nodig: Schakelaars
           Lcd (Rgb Backlight)
           Control-Potmeters
           Aansturing ledRij

*****************************************************************************/



void init()
{ //
  // Inhoud funktie niet specifiek gegeven hier.
  //
}

//==========================================================================

byte telled = 0;
unsigned long tijd0 = 0;
unsigned long tijd1 = 0;
unsigned long tijd2 = 0;
unsigned long time_out = 0;

void loop()
{ // Doe TelLed naar LedRij Kleur en Nr
  if (telled < 8)      { Write_Led(telled,3,0,0)}
  else                 { Write_Led(telled,0,3,0)}

  Lcd_gotoxy(19,1);
  Lcd_out(1,'*');
  tijd0 = micros();
//------------------------------------begin tijd experiment----
// * Te Testen Funkties
//------------------------------------einde tijd experiment----
  tijd1 = micros();

  Lcd_gotoxy(19,1);
  lcd_out(1,' ');
  tijd2 = tijd1 - tijd0;

  Lcd_gotoxy(0,1);
  Lcd_print("Start:");
  Lcd_number(tijd0,10);
  Lcd_print("uS");

  Lcd_gotoxy(0,2);
  Lcd_print("Eind :");
  Lcd_number(tijd1,10);
  Lcd_print("uS");

  Lcd_gotoxy(0,3);
  Lcd_print("Duur :");
  Lcd_number(tijd2,10);
  Lcd_print("uS");

  if (telled < 8)      { Write_Led(telled,1,0,0)}
  else                 { Write_Led(telled,0,1,0)}
  telled = (telled + 1 ) &0x0F;
  delay(250);
}

//==========================================================================

//
// Overige funkties niet gegeven hier.
//
// Maar de naamgeving in de Loop-funktie moet voldoende zijn om aan
// te geven wat betreffende funkties gaan doen.
//

//==========================================================================

Tijd (usec)       Te testen funktie
----------------------------------------------------------------------------
   0 ..    4      // *niets*
  52 ..   56      Lcd_out   (1,'*');         // Met delay(42);
  56 ..   60      Lcd_print ("*");
 104 ..  116      Lcd_print ("**");          //  2 tekens
 156 ..  164      Lcd_print ("***");         //  3 tekens
 208 ..  216      Lcd_print ("****");        //  4 tekens
 260 ..  268      Lcd_print ("****");        //  5 tekens
 512 ..  524      Lcd_print ("*****#####");  // 10 tekens
4104 .. 4112      Lcd_print ( *80-tekens* ); // = 4 regels, geheel scherm
 152 ..  156      Lcd_number(0,1);
 280 ..  288      Lcd_number(0,2);
 404 ..  416      Lcd_number(0,3);
 532 ..  540      Lcd_number(0,4);
 660 ..  668      Lcd_number(0,5);
1176 .. 1184      Lcd_print ("AbcdeFghij"); Lcd_number(0,5);
2348 .. 2356      Lcd_print ("AbcdeFghij"); Lcd_number(0,5); // Twee Maal
----------------------------------------------------------------------------
  40 ..   48      Lcd_out(1,'*');            // Met delay(32);
----------------------------------------------------------------------------
  40 ..   40      Lcd_out(1,'*');            // Met scannen op Lcd-Timer
----------------------------------------------------------------------------


Broncode: [1: Decoder met LedRij] [2: Decoder met Lcd] [3: Decoder met Schakelaars] [4: Decoder met Lcd-Timing]
[5: Decoder met LcdOut-funktie]

5: De broncode van Decoder met LcdOut-funktie

(Sun 17 July 2016) De nieuwe funktie LcdOut(), die werkt met de Lcd-Timer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/****************************************************************************
    ArSid Decoder Test Lcd-Timer

    Latches Print test Programma.
    Nodig: Schakelaars
           Lcd (Rgb Backlight)
           Control-Potmeters
           Aansturing ledRij

*****************************************************************************/



void init()
{ //
  // Inhoud funktie niet specifiek gegeven hier.
  //
}

void loop()
{ //
  // Inhoud funktie niet specifiek gegeven hier.
  //
}

//==========================================================================

const byte Lcd_timer    = 0b00000100;   // Lcd bitje op de Control-bus.
const byte Lcd_register = 0b00000001;   // Lcd register Select
const byte Lcd_enable   = 0b00001000;   // Lcd Enable

void Lcd_out(byte rs, byte bb)
{ // Rs  0  %00000000 = Instruction Register
  // Rs  1  %00000001 = Data Register
  // En  0  %00000000 = Enable     (Falling Edge)
  // En  1  %00001000 = Not Enable (Raising Edge) = Lcd_enable

  rs=rs & Lcd_Register;
   // Wait until the Lcd-Timer has ended
   while (PING & Lcd_timer) == 0)
    { // Do Nothing
    }

  Write_Data(3,Lcd_enable | rs); // Make Enable High
  Write_Data(2,bb);
  delayMicroseconds(1);
  Write_Data(3,0b00000000 | rs); // Make Enable Low
  delayMicroseconds(1);
}

//==========================================================================

//
// Overige funkties niet gegeven hier.
//
// Maar de naamgeving in de Loop-funktie moet voldoende zijn om aan
// te geven wat betreffende funkties gaan doen.
//



Broncode: [1: Decoder met LedRij] [2: Decoder met Lcd] [3: Decoder met Schakelaars] [4: Decoder met Lcd-Timing]
[5: Decoder met LcdOut-funktie]
[Tekst] [Afbeeldingen] [Aansluitingen] [Broncodes]