Arduino Projekten

Wed 20-Mar-19
19:13:07




LCD Library - Eerste versie

Datum: Fri 31 July 2015
Samenvatting: Mijn Eerste bibliotheek met afzonderlijke funkties.


Het is altijd prettig om een eigen "include-file" (zoals dat heette in Turbo-Parcal, c.q. Borland pascal) te kunnen maken en die te vullen met eigen routines. Meestal korte routines die best wel handige funkties regelen, zoals een instelbaar minimum/ maximum van een variabele te bepalen en eventueel deze waarde af te kappen tot deze minimum/ maximum waarde. In Pascal was het 1 bestand die in een programma kon worden ge-include-d. In C heet zo'n include-file een bibliotheek (library) en moet deze bestaan uit 2 aparte files.

Met de Led-Panelen had ik al een poging gedaan om zo'n library te maken, maar dat strandde in de vele uitleg die ik op internet vond. Veel uitleg die meteen uitging dat men een methode, record, structuur variabele wilde bouwen. Variabelen met procedures en functies er aan vast. En hoewel ik deze structuren/ methodes wel eens geprogrammeerd en gebruikt heb in Pascal, ben ik in C nog niet zover. Maar die ingewikkelde uitleg zorgde toen wel dat een eenvoudige library toen niet lukte. Zelfs de library-uitleg voor Morse-Piepjes op de site voor Arduino Reference kon ik niet omzetten naar een eenvoudiger model.

De tweede poging is nu geweest ... En deze is gelukt. De aanstuur-functies voor het Lcd heb ik in een eigen library kunnen stoppen en het werkt. Ik laat de funktie-namen zelf nog wel met "lcd_" beginnen, maar er is een basis. En deze basis is verder uit te breiden.

Bitmap-funkties in het hoofdprogramma.

Het hoofdprogramma zelf heb ik uitgebreid met meer eigen character-bitmaps voor de volgende 3 instellingen:

  1. Oscilator-nummer "O:" Voorlopig komen er 2 Sid's in mijn Arsid en elke Sid heeft 3 Voices (stemmen/ oscilatoren). Met schakelaars wil ik kunnen kiezen voor welke voice de instelling gemaakt wordt, zoals golfvorm en ADSR.

  2. Filtertype "F:" De Sids heeft filtering in zich, Lowpass (Laagdoorlaat) Bandpass (Bandfilter) Highpass (Hoogdoorlaat). Deze filter-types zijn te combineren. Zo geeft de Lowpass met de Highpass een soort van Notch filter (Bandsper). Het symbooltje moet aangeven welke van de 7 mogelijkheden is ingeschakeld.

  3. Golfvorm "W:" De Sid heeft niet alleen de Zaagtand, Driehoek, Blokgolf, maar zij zijn ook te combineren door er meer tegelijk aan te zetten. Dit geeft interessante golfvormen en ook al deze 15 soorten moeten getoond kunnen worden.

  4. ADSR heeft (nog) geen eigen characters, maar misschien gaat dit nog komen wanneer er meer informatie op het display moet verschijnen.

Deze bitmaps zijn eenvoudig te vinden in het programma en zitten in hun eigen funktie opgesloten. Deze bitmap-funkties moeten in een eigen Library terecht gaan komen. De foto's tonen het resultaat.

Overige instelling-nummers.

De overige instelling-nummers, zoals frequenties, ADSR, deze staan nu nog in 1 funktie die de potentiometers uitleest en meteen verwerkt tot een nummertje. Uiteindelijk moeten deze ook in eigen funkties komen.

Een C-Library

Het doel waar het in dit experiment om draait, is de eigen library met de Lcd-routines. Zoals in de inleiding is beschreven, heeft C 2 aparte bestanden nodig. Een "Header"-file en een "CPP"-file.

De Header-file is een soort van interface-file. Het vertelt het "hoofd"programma wat er allemaal beschikbaar is. De Header-file bevat ook de headers (de koppen/ de definities) van alle funkties die een "hoofd"-programma mag aanroepen.

In het kort: De volledige funktie-definitie, inclusief parameters. Hoe ik variabele namen moet doorgeven, is nu nog niet duidelijk. In Pascal kon dit relatief eenvoudig. Maar als dit in C alleen kan via funkties, vind ik dat ook prima.

De CPP-file is de uiteindelijke implementatie van de funkties. Of te wel, hierin staan alle funktie-bewerkingen beschreven, of te wel: hoe voert de funktie uit wat het moet doen. Eventueel met andere (ondersteunings)funkties erin die ook benodigd zijn.

Wat wel opvalt en wat ik ook al nodig had bij de Font-definities van de RGB-LedMatrix, is het gebruik van "IFNDEF <label>" met "DEFINE <label>" en "ENDIF". In het kort komt het hierbij neer dat de gebruikte code in de library maar 1 keer gecompileerd hoeft te worden, ook al worden libraries meer keer gebruikt in diverse "hoofd-programma"-codes en "library"-codes. Een stukje C-discipline die problemen gaat voorkomen (volgens diverse uitleg op internet).

Op internet bestaan ook diverse uitleggen over libraries die elkaar nodig hebben, library A heeft iets uit library B nodig. En library B heeft iets uit Library A nodig. Hoe zij dit oplossen, begrijp ik nog steeds niet. Dit wegens nog te weinig C-ervaring. Maar zoals ik nu nog vooruit kan zien, zal ik dit probleem voorlopig niet tegenkomen. In Pascal kwam ik het ook niet tegen en anders is de geprogrammeerde oplossing te ingewikkeld (immers "Alles moet bekend zijn" gaat dan niet op).

Pascal-Vergelijking: In Pascal heeft een include-file ook een eigen header-stukje met procedure- en funktie-headers erin (ook inclusief parameters), maar die staat bovenaan in het bestand, boven de uiteindelijke implementatie van de procedure- en funktie-code. Precies zoals bij de stelling van Pascal hoort: "Alles moet bekend zijn". Immers, in Pascal gebeurde alles via een 1-pass compilatie. Een verschil in denken dus.

Mijn eigen Lcd-Library.

In mijn eerste Lcd Library heb ik 6 funkties zitten die het "hoofd"-programma kan aanroepen om de Lcd op hardware-niveau aan te sturen. En ook hier wordt de Lcd in 8-bits aangestuurd en zijn de pinnen semi-hard gedefinieerd in de library zelf. De library zelf bevat ook 2 ondersteuningsfunkties.

  1. {Ondersteuningsfunktie}: byte minmax (byte vv, byte minimum, byte maximum); Zoals hierboven al in het kort is aangegeven, bepaalt deze funktie of de waarde van een variabele buiten de grensen MINIMUM en MAXIMUM valt. Zo ja, dan zal de variabele de grenswaarde worden. Het nut van deze funktie is om een waarde altijd geldig te laten zijn in het bereik van een variabele.

    Veel leerboeken over programmeren leren je dat er een foutmelding op moet treden wanneer een waarde te groot of te klein is voor een variabele ("Out Of Range-Error" of zo). En dat je dan deze melding moet weg-enteren of wegklikken om vervolgens weer een nieuwe waarde in te voeren. Mijn eigen ervaring is dat zo'n foutmelding met weg-enteren en opnieuw-invoeren, helemaal niet gebruikers vriendelijk is. PLUS zo'n melding leidt enorm af in de invoer-routine. Vriendelijker vind ik: "Getal te groot? Waarde wordt maximaal!" En ja, ik heb invoer-procedures gemaakt, waarbij te grote waardes op de grens wortd ingesteld, waarna de gebruiker deze (nieuwe) waarde alleen nog hoeft te bevestigen, in plaats van helemaal opnieuw in te voeren.

  2. {Ondersteuningsfunktie}: void digi_out (byte pin); Deze maakt een aansluitpin OUTPUT en zet hem meteen LOW. Eenvoudig, doeltreffend en leesbaarheid verhogend.

  3. {Header-funktie}: void lcd_init (); De initialisatie van het display, op 8-bits, 2 regels en 5x8 font, PLUS andere Lcd-instellingen. Het wist alle eigen characters en zet uiteindelijk de RGB-Backlight aan op halve helderheid.

  4. {Header-funktie}: void lcd_backlight (byte rr, byte gg, byte bb); Deze zet de RGB-Backlight aan op de ingegeven R, G en B waarde, met de standaard AnalogWrite. Hierbij wordt er gecorrigeerd op de Common-Anode van de Backlight RGB-Led ("255 - <nummer>").

  5. {Header-funktie}: void lcd_write (byte rr, byte dd); Deze schrijft de waarde DD (van Data) naar de Lcd, rekening houdend met de warde RR (van Register) voor Register-waarde of Data-waarde. Dit is nog steeds de oorspronkelijke funktie van het vorige experiment, inclusief losse IF/THEN-statements om de losse uitgangen op LOW of HIGH te zetten.

  6. {Header-funktie}: void lcd_print (char* ss); Deze schrijft een rijtje tekens (characters) in de string SS naar het display. Dit gaat door tot het einde-string teken "\0" (ASCII-waarde asc(0)) is gevonden.

  7. {Header-funktie}: void lcd_gotoxy(byte x, byte y); Deze plaatst de cursor op de positie (X;Y), rekening houdend met de afwijkende regel-nummering van het display (het CASE-statement met de keuzes 0 2 1 3).

  8. {Header-funktie}: void lcd_number (long vv, byte num); Deze plaatst een getal VV (van Value) op het display in NUM cijfers (1 t/m 6 cijfers). De berekening is recht-toe recht-aan. Deel het getal door een macht van 10 (1, 10, 100, 1000, enz) in een integer deling. En bepaal dan de restwaarde SS van deze uitkomst in een deling met 10. Daar blijft een getal van 0..9 van over.

    Deze restwaarde SS wordt gebruikt om betreffende cijfer als ASCII-teken naar de LCD te schrijven (met "SS+48"). Deze laatste truuk is al heel oud en werd al op de CBM64 (en zelfs nog eerder) veelvuldig gebruikt (al of niet in assembly, c.q. machine-taal).

Uiteindelijk is het idee om in deze library een interupt gestuurde routine te programmeren met een data-buffer voor de display-tekens, zodat de ArSid niet gehinderd gaat worden door de verplichte vertragingen (van minimaal 40 micro-seconde), die het Lcd-Display nodig heeft om zijn data te accepteren.


Broncode: [1: LCD Library - Eerste versie] [2: LCD Library - De CPP-file] [3: LCD Library - De Header-file]

1: De broncode van LCD Library - Eerste versie

(Fri 31 July 2015) Mijn Eerste bibliotheek met afzonderlijke funkties.

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
//
// Exploring Program for a LCD 20x4 (8-Bit Interface)
//
// First building with Display Master-Layout and Library
//

// Include the Lcd Library Inits
#include "lcdlib_init.h"
// Next line is needed for PROGMEM and pgm_read_byte_near-function
#include <avr/pgmspace.h>

byte qqstart=0;
byte qq=32;

word oscfreq  = 0;
word filtfreq = 0;
word waveduty = 0;
byte adsr_a   = 0;
byte adsr_d   = 0;
byte adsr_s   = 0;
byte adsr_r   = 0;

void setup ()
{
lcd_init();
display_init();
}

void loop ()
{
do_pots();
}

//=======================================================================================
// Potmeters
//=======================================================================================

void do_pots ()
{
  oscfreq  =analogRead(A5)   ;
  waveduty =analogRead(A4)   ;
  adsr_a   =analogRead(A3)/64;
  adsr_d   =analogRead(A2)/64;
  adsr_s   =analogRead(A1)/64;
  adsr_r   =analogRead(A0)/64;

  filtfreq = (adsr_a ^ adsr_d ^ adsr_s ^ adsr_r) * 4096 ) ^
             (adsr_a ^ adsr_d ^ adsr_s ^ adsr_r) *  256 ) ^
             oscfreq ^
             waveduty ;

  lcd_gotoxy( 7,0);
  lcd_number(oscfreq ,5);
  lcd_gotoxy( 7,1);
  lcd_number(filtfreq,5);
  lcd_gotoxy( 7,2);
  lcd_number(waveduty,5);

  lcd_gotoxy( 2,3);
  lcd_number(adsr_a  ,2);
  lcd_gotoxy( 7,3);
  lcd_number(adsr_d  ,2);
  lcd_gotoxy(12,3);
  lcd_number(adsr_s  ,2);
  lcd_gotoxy(17,3);
  lcd_number(adsr_r  ,2);

  display_oscnums   ((adsr_a & 0x04)<<1) + ((adsr_d & 0x04)   ) + ((adsr_s & 0x04)>>1) + ((adsr_r & 0x04)>>2) );
  display_filtertype(waveduty/128);
  display_waveform  (oscfreq /64);

  lcd_backlight ( adsr_a ^ adsr_d ) * 16 | 0x0F , ( adsr_a ^ adsr_s ) * 16 | 0x0F , ( adsr_a ^ adsr_r ) * 16 | 0x0F );
}

void display_oscnums (byte oscnums)
{ static const byte oscchar[256] PROGMEM = // Array with Char-patrons of Sids (bits 32) & Voices (bits 10)
                                           // - bit3=Sid2 bit2=Sid1   bit1:Voice All/2 bit0:Voice 3/1
                            { // [0] --.non --.non --.v11
                              B00000, B00000, B00000, B00000, B00000, B00001, B00001, B00000,
                              B00000, B00000, B00000, B00000, B00000, B00001, B00001, B00000,
                              // [1] --.non --.v22 --.non
                              B00000, B00000, B00000, B00000, B00000, B00100, B00100, B00000,
                              B00000, B00000, B00000, B00000, B00000, B00100, B00100, B00000,
                              // [2] --.v33 --.non --.non
                              B00000, B00000, B00000, B00000, B00000, B10000, B10000, B00000,
                              B00000, B00000, B00000, B00000, B00000, B10000, B10000, B00000,
                              // [3] --.v33 --.v22 --.v11
                              B00000, B00000, B00000, B00000, B00000, B10101, B10101, B00000,
                              B00000, B00000, B00000, B00000, B00000, B10101, B10101, B00000,
                              // [4] 11.non 11.non 11.v11
                              B00000, B11111, B10001, B00000, B00000, B00001, B00001, B00000,
                              B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000,
                              // [5] 11.non 11.v22 11.non
                              B00000, B11111, B10001, B00000, B00000, B00100, B00100, B00000,
                              B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000,
                              // [6] 11.v33 11.non 11.non
                              B00000, B11111, B10001, B00000, B00000, B10000, B10000, B00000,
                              B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000,
                              // [7] 11.v33 11.v22 11.v33
                              B00000, B11111, B10001, B00000, B00000, B10101, B10101, B00000,
                              B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000,
                              // [8] 22.non 22.non 22.v11
                              B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000,
                              B00000, B11111, B10001, B00000, B00000, B00001, B00001, B00000,
                              // [9] 22.non 22.v22 22.non
                              B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000,
                              B00000, B11111, B10001, B00000, B00000, B00100, B00100, B00000,
                              // [A] 22.v33 22.non 22.non
                              B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000,
                              B00000, B11111, B10001, B00000, B00000, B10000, B10000, B00000,
                              // [B] 22.v33 22.v22 22.v11
                              B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000,
                              B00000, B11111, B10001, B00000, B00000, B10101, B10101, B00000,
                              // [C] 21.non 21.non 21.non
                              B00000, B11111, B10001, B00000, B00000, B00001, B10101, B00000,
                              B00000, B11111, B10001, B00000, B00000, B00001, B10101, B00000,
                              // [D] 21.non 21.non 21.non
                              B00000, B11111, B10001, B00000, B00000, B00100, B10101, B00000,
                              B00000, B11111, B10001, B00000, B00000, B00100, B10101, B00000,
                              // [E] 21.non 21.non 21.non
                              B00000, B11111, B10001, B00000, B00000, B10000, B10101, B00000,
                              B00000, B11111, B10001, B00000, B00000, B10000, B10101, B00000,
                              // [F] 21.non 21.non 21.non
                              B00000, B11111, B10001, B00000, B00000, B10101, B10101, B00000,
                              B00000, B11111, B10001, B00000, B00000, B10101, B10101, B00000,
                            };
  oscnums=(oscnums & 0x0F) * 16;
  lcd_write(0,64 + 0*8); // Set to Char Ram
  for (byte qq=0; qq<=15; qq=qq+1)
      { lcd_write(1, pgm_read_byte_near( oscchar + oscnums + qq ) );
      }
  lcd_write(0, B10000000); // Set to Display
}

void display_filtertype (byte filtertype)
{ static const byte filterchar[128] PROGMEM = // Array with Char-patrons of all posible filters
                                              // Bit2=HighPass  Bit1=BandPass  Bit0=LowPass
                            { // [0] -none- -none- -none-
                              B00000, B11111, B00000, B00000, B00000, B00000, B00000, B00000,
                              B00000, B11111, B00000, B00000, B00000, B00000, B00000, B00000,
                              // [1] -none- -none- -Low-
                              B00000, B11100, B00010, B00010, B00001, B00001, B00001, B00001,
                              B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000,
                              // [2] -none- -Band- -none-
                              B00000, B00001, B00010, B00010, B00100, B00100, B00100, B00100,
                              B00000, B10000, B01000, B01000, B00100, B00100, B00100, B00100,
                              // [3] -none- -Band- -Low-
                              B00000, B11101, B00010, B00010, B00101, B00101, B00101, B00101,
                              B00000, B10000, B01000, B01000, B00100, B00100, B00100, B00100,
                              // [4] -High- -none- -none-
                              B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000,
                              B00000, B00111, B01000, B01000, B10000, B10000, B10000, B10000,
                              // [5] -High- -none- -Low-
                              B00000, B11100, B00010, B00010, B00001, B00001, B00001, B00001,
                              B00000, B00111, B01000, B01000, B10000, B10000, B10000, B10000,
                              // [6] -Hign- -Band- -none-
                              B00000, B00001, B00010, B00010, B00100, B00100, B00100, B00100,
                              B00000, B10111, B01000, B01000, B10100, B10100, B10100, B10100,
                              // [7] -High- -Band- -Low-
                              B00000, B11101, B00010, B00010, B00101, B00101, B00101, B00101,
                              B00000, B10111, B01000, B01000, B10100, B10100, B10100, B10100
                            };
  filtertype=(filtertype & 0x07) * 16;
  lcd_write(0,64 + 2*8); // Set to Char Ram
  for (byte qq=0; qq<=15; qq=qq+1)
      { lcd_write(1, pgm_read_byte_near( filterchar + filtertype + qq ) );
      }
  lcd_write(0, B10000000); // Set to Display
}

void display_waveform (byte wavetype)
{ static const byte wavechar[256] PROGMEM = // Array with Char-patrons of all posible waveforms
                                            // Bit3=Noise  Bit2=Square  Bit1=SawTooth  Bit0=Triangle
                            { // [0] -none-   -none-   -none-   -none-
                              B00000, B00000, B00000, B00000, B00000, B00000, B11111, B00000,
                              B00000, B00000, B00000, B00000, B00000, B00000, B11111, B00000,
                              // [1] -none-   -none-   -none-   Triangle
                              B00000, B00000, B00001, B00010, B00100, B01000, B10000, B00000,
                              B00000, B00000, B10000, B01000, B00100, B00010, B00001, B00000,
                              // [2] -none-   -none-   Sawtooth -none-
                              B00000, B00000, B00000, B00000, B00011, B01100, B10000, B00000,
                              B00000, B00011, B01101, B10001, B00001, B00001, B00001, B00000,
                              // [3] -none-   -none-   Sawtooth Triangle
                              B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000,
                              B00011, B01101, B10001, B00000, B00100, B01010, B10001, B00000,
                              // [4] -none-   Square   -none-   -none-
                              B00000, B00001, B00001, B00001, B00001, B00001, B11111, B00000,
                              B00000, B11111, B00001, B00001, B00001, B00001, B00001, B00000,
                              // [5] -none-   Square   -none-   Triangle
                              B00000, B00000, B00000, B00000, B01111, B01001, B11001, B00000,
                              B00000, B00000, B00000, B00000, B00100, B01010, B10001, B00000,
                              // [6] -none-   Square   Sawtooth -none-
                              B00000, B00000, B00000, B00000, B01111, B01001, B11001, B00000,
                              B00011, B01101, B10001, B00000, B00000, B00000, B00000, B00000,
                              // [7] -none-   Square   Sawtooth Triangle
                              B00000, B00000, B00000, B00000, B01111, B01001, B11001, B00000,
                              B00011, B01101, B10001, B00000, B00100, B01010, B10001, B00000,
                              // [8] Noise    -none-   -none-   -none-
                              B00000, B00001, B00001, B01001, B01001, B01101, B10010, B00000,
                              B00000, B00010, B00011, B10101, B10101, B01101, B01000, B00000,
                              // [9] Noise    -none-   -none-   Triangle
                              B01010, B10111, B10000, B00000, B00000, B00000, B00000, B00000,
                              B00000, B00000, B00000, B00000, B00100, B01010, B10001, B00000,
                              // [A] Noise    -none-   Sawtooth -none-
                              B01010, B10111, B10000, B00000, B00000, B00000, B00000, B00000,
                              B00011, B01101, B10001, B00000, B00000, B00000, B00000, B00000,
                              // [B] Noise    -none-   Sawtooth Triangle
                              B01010, B10111, B10000, B00000, B00000, B00000, B00000, B00000,
                              B00011, B01101, B10001, B00000, B00100, B01010, B10001, B00000,
                              // [C] Noise    Square   -none-   -none-
                              B01010, B10111, B10000, B00000, B01111, B01001, B11001, B00000,
                              B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000,
                              // [D] Noise    Square   -none-   Triangle
                              B01010, B10111, B10000, B00000, B01111, B01001, B11001, B00000,
                              B00000, B00000, B00000, B00000, B00100, B01010, B10001, B00000,
                              // [E] Noise    Square   Sawtooth -none-
                              B01010, B10111, B10000, B00000, B01111, B01001, B11001, B00000,
                              B00011, B01101, B10001, B00000, B00000, B00000, B00000, B00000,
                              // [F] Noise    Square   Sawtooth Triangle
                              B01010, B10111, B10000, B00000, B01111, B01001, B11001, B00000,
                              B00011, B01101, B10001, B00000, B00100, B01010, B10001, B00000
                            };
  wavetype=(wavetype & 0x0F) * 16;
  lcd_write(0,64 + 4*8); // Set to Char Ram
  for (byte qq=0; qq<=15; qq=qq+1)
      { lcd_write(1, pgm_read_byte_near( wavechar + wavetype + qq ) );
      }
  lcd_write(0, B10000000); // Set to Display
}

//=======================================================================================
// LCD-Screen
//=======================================================================================

void display_init ()
{
// Intro Title Screen
// Line 2
lcd_gotoxy(6,1);
lcd_print("  Lcd");
// Line 3
lcd_gotoxy(6,2);
lcd_print("Library");
delay(2000);

// Init Operating Screen
// Line 1
lcd_gotoxy(0,0);
lcd_print("O:   f:00000   Ch:00");
// Line 3
lcd_print("W:   d:00000        ");
// Line 2
lcd_print("F:   f:00000    r:00");
// Line 4
lcd_print("A:00 D:00 S:00 R:00 ");

lcd_gotoxy(2,0);
lcd_write(1,0);
lcd_write(1,1);
lcd_gotoxy(2,1);
lcd_write(1,2);
lcd_write(1,3);
lcd_gotoxy(2,2);
lcd_write(1,4);
lcd_write(1,5);
}

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



Broncode: [1: LCD Library - Eerste versie] [2: LCD Library - De CPP-file] [3: LCD Library - De Header-file]

2: De broncode van LCD Library - De CPP-file

(Fri 31 July 2015) Mijn Eerste bibliotheek met afzonderlijke funkties.

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
//=======================================================================================
//
// LCD-Screen - My own LCD-Display functions
//
// It's always great to built my own functions for controling hardware
// at pin-level.
//
// Here is used an LCD-display with RGB-backlight in 8-bit mode.
//
//=======================================================================================

#ifndef LCDLIB_INIT_CPP
#define LCDLIB_INIT_CPP

#include "Arduino.h"
#include "lcdlib_init.h"
//=====================================================================================

byte lcd_d0 =  0; // Data 0
byte lcd_d1 =  1; // Data 1
byte lcd_d2 =  2; // Data 2
byte lcd_d3 =  3; // Data 3
byte lcd_d4 =  4; // Data 4
byte lcd_d5 =  5; // Data 5
byte lcd_d6 =  6; // Data 6
byte lcd_d7 =  7; // Data 7
byte lcd_rs = 12; // Register Select
byte lcd_en = 13; // Enable
byte lcd_br =  9; // PowerBacklight Red
byte lcd_bg = 10; // PowerBacklight Red
byte lcd_bb = 11; // PowerBacklight Red

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

byte minmax (byte vv, byte minimum, byte maximum)
{ // Check if VV is in the boudaries of MINIMUM and MAXIMUM.
  // If not, then make VV either MINIMUM or MAXIMUM.
  if ( vv < minimum )     { return minimum; }
  if ( vv > maximum )     { return maximum; }
  return vv;
}

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

void digi_out (byte pin)
{ // A plain function to OUTPUT a pin and make it LOW
  pinMode(pin, OUTPUT);  digitalWrite(pin,  LOW );
}

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

void lcd_init ()
{ // Put all pins as OUTPUT and make them LOW
  digi_out(lcd_d0);
  digi_out(lcd_d1);
  digi_out(lcd_d2);
  digi_out(lcd_d3);
  digi_out(lcd_d4);
  digi_out(lcd_d5);
  digi_out(lcd_d6);
  digi_out(lcd_d7);

  digi_out(lcd_rs);
  digi_out(lcd_en);

  digi_out(lcd_br);
  digi_out(lcd_bg);
  digi_out(lcd_bb);
  lcd_backlight(0,0,0);
  //-----------------------------------------------------------------------------------
  // "Reset" the display
  delay(20);                  // Wait while the LCD-unit itself is initialized
  lcd_write(0, B00110000);    // 1st LCD write (set 8bits interface)
  delay(6);                   // Wait some
  lcd_write(0, B00110000);    // 2nd LCD write (set 8bits interface)
  delay(1);                   //  Wait some more
  lcd_write(0, B00110000);    // 3rd LCD write (set 8bits interface)
  //--------------------------------------------------------------------------------------------------------
  // Init the display
  lcd_write(0, B00111000);    // Function-Set 8-bits, 2-lines, 5x8-font, <none>, <none>
  lcd_write(0, B00001000);    // Set Display On/Off Control: Cursor, Blinking
  lcd_write(0, B00000001);    // Clear Display
  lcd_write(0, B00001100);    // Set Display On/Off Control: Cursor, Blinking
  lcd_write(0, B00010100);    // Set Cursor/ Display Shift: Shift/Cursor, Right/Left, <none>, <none>
  lcd_write(0, B00000110);    // Entry Mode Set: Inc/Dec, DisplShift
  //--------------------------------------------------------------------------------------------------------
  // Clear the Character Ram
  lcd_write(0,64); // Set to Char Ram
  for (byte qq=0; qq<=63; qq=qq+1)
      { lcd_write(1, B00000000);
      }
  lcd_write(0, B00000010);    // Set to Display
  lcd_write(0, 128 +   0);    // Home the Crsr
  lcd_backlight(127, 127, 127);
}

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

void lcd_backlight (byte rr, byte gg, byte bb)
{ // Switch the RGB-backlight
  analogWrite( lcd_br, 255 - rr );
  analogWrite( lcd_bg, 255 - gg );
  analogWrite( lcd_bb, 255 - bb );
}

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

void lcd_write (byte rr, byte dd)
{ // Just write one byte to the display: RR==> Command  RR==> Data
  digitalWrite(lcd_en,  LOW);
  delayMicroseconds(1);
  // Look at bit0 to write a Command (0) or Data (1)?
  if ((rr & 0x01) == 0) { digitalWrite(lcd_rs, LOW)} else {digitalWrite(lcd_rs, HIGH)};

  // Sent bit 7..0
  if ((dd & 0x01) == 0) { digitalWrite(lcd_d0, LOW)} else { digitalWrite(lcd_d0, HIGH)}
  if ((dd & 0x02) == 0) { digitalWrite(lcd_d1, LOW)} else { digitalWrite(lcd_d1, HIGH)}
  if ((dd & 0x04) == 0) { digitalWrite(lcd_d2, LOW)} else { digitalWrite(lcd_d2, HIGH)}
  if ((dd & 0x08) == 0) { digitalWrite(lcd_d3, LOW)} else { digitalWrite(lcd_d3, HIGH)}
  if ((dd & 0x10) == 0) { digitalWrite(lcd_d4, LOW)} else { digitalWrite(lcd_d4, HIGH)}
  if ((dd & 0x20) == 0) { digitalWrite(lcd_d5, LOW)} else { digitalWrite(lcd_d5, HIGH)}
  if ((dd & 0x40) == 0) { digitalWrite(lcd_d6, LOW)} else { digitalWrite(lcd_d6, HIGH)}
  if ((dd & 0x80) == 0) { digitalWrite(lcd_d7, LOW)} else { digitalWrite(lcd_d7, HIGH)}
  // Set Enable and Reset it again.
  digitalWrite(lcd_en,  HIGH);
  delayMicroseconds(1);
  digitalWrite(lcd_en,  LOW);
  delayMicroseconds(40);
  // Give a longer delay at ClearScreen and HomeScreen
  if ((rr & 0x01) == 0) && ( dd == 0x01 ) )
     { // If Clear Display => Wait some longer.
       delay(2);
     }
  if ((rr & 0x01) == 0) && (dd & 0xF7) == 0x02 ) )
     { // If Home Display => Wait some longer.
       delay(2);
     }
}

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

void lcd_print (char* ss)
{ // Print a string with characters
  byte qq = 0;
  while ( ss[qq] != '\0' )
    { // check every char if it is in the table.
      char cc=ss[qq];
      lcd_write(1,cc);
      qq=qq+1;
    }
}

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

void lcd_gotoxy(byte x, byte y)
{ // Place cursor at position (x,y) (left-up is (0,0))
  byte bb=0;
  x = minmax (x, 0, 19);
  y = minmax (y, 0,  3);
  switch (y)
    { case 0: { bb = 0x80 +  0 + x;
                break;
              }
      case 2: { bb = 0x80 + 20 + x;
                break;
              }
      case 1: { bb = 0x80 + 64 + x;
                break;
              }
      case 3: { bb = 0x80 + 84 + x;
                break;
              }
    }
  lcd_write(0,bb);
}

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

void lcd_number (long vv, byte num)
{ // print a number VV on the display in NUM numbers (1..6)
  const long power10 [6] = {1, 1, 10, 100, 1000, 10000};
  num = minmax (num, 1, 6);
  byte ss=0;
  for (byte qq = num; qq > 0; qq = qq - 1)
    { ss = ( vv / power10 [qq] ) % 10;
      lcd_write (1,ss + 48);
    }
}

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

#endif // LCDLIB_INIT_CPP



Broncode: [1: LCD Library - Eerste versie] [2: LCD Library - De CPP-file] [3: LCD Library - De Header-file]

3: De broncode van LCD Library - De Header-file

(Fri 31 July 2015) Mijn Eerste bibliotheek met afzonderlijke funkties.

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
//=======================================================================================
//
// LCD-Screen - My own LCD-Display functions
//
// It's always great to built my own functions for controling hardware
// at pin-level.
//
// Here is used an LCD-display with RGB-backlight in 8-bit mode.
//
//=======================================================================================

#ifndef LCDLIB_INIT_H
#define LCDLIB_INIT_H

#include "Arduino.h"

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

void lcd_init ();
     // Init the Lcd-Display

void lcd_backlight (byte rr, byte gg, byte bb);
     // Switch the RGB-backlight

void lcd_write (byte rr, byte dd);
     // Just write one byte to the display: RR==> Command  RR==> Data

void lcd_print (char* ss);
     // Print a string with characters

void lcd_gotoxy(byte x, byte y);
     // Place cursor at position (x,y) (left-up is (0,0))

void lcd_number (long vv, byte num);
     // Print a number VV on the display in NUM numbers (1..6)

//=====================================================================================
#endif // LCDLIB_INIT_H



Broncode: [1: LCD Library - Eerste versie] [2: LCD Library - De CPP-file] [3: LCD Library - De Header-file]

Afbeeldingen

lcdlib_init_1.jpg
1/2: lcdlib_init_1.jpg.
lcdlib_init_2.jpg
2/2: lcdlib_init_2.jpg.

De aansluitingen van LCD Library - Eerste versie

Mijn Eerste bibliotheek met afzonderlijke funkties.

Arduino Uno

Pwr USB ?
 
?
aref
gnd Lcd Read/Write
? d13 Lcd Enable
ioreff d12 Lcd Register Select
reset d11 Lcd Backlight Blauw
+3.3v d10 Lcd Backlight Groen
+5v d9 Lcd Backlight Rood
Lcd Read/Write gnd d8
Lcd Read/Write gnd
Vin d7 Lcd D7
d6 Lcd D6
Release BG_Rood  Potm 1 a0 d5 Lcd D5
Sustain BG_Groen Potm 2 a1 d4 Lcd D4
Decay   BG_Blauw Potm 3 a2 d3 Lcd D3
Attack  BG_Xor   Potm 4 a3 d2 Lcd D2
Wave Duty cycle  Potm 5 a4 d1 Lcd D1
Osc. Frequentie  Potm 6 a5 d0 Lcd D0