SujetTP3-2018: lcd_user.c

File lcd_user.c, 6.9 KB (added by franck, 7 years ago)
Line 
1/*******************************************************************************
2 * lcdr_user.c - Controleur pour LCd HD44780 ( 20x4 )
3 ******************************************************************************/
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <unistd.h>
8#include <stdint.h>
9#include <string.h>
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <fcntl.h>
13#include <sys/mman.h>
14
15/*******************************************************************************
16 * GPIO Pins
17 ******************************************************************************/
18#define RS 7
19#define E  27
20#define D4 22
21#define D5 23
22#define D6 24
23#define D7 25
24
25#define GPIO_INPUT  0
26#define GPIO_OUTPUT 1
27
28#define RPI_BLOCK_SIZE  0xB4
29#define RPI_GPIO_BASE   0x20200000
30
31struct gpio_s
32{
33  uint32_t gpfsel[7];
34  uint32_t gpset[3];
35  uint32_t gpclr[3];
36  uint32_t gplev[3];
37  uint32_t gpeds[3];
38  uint32_t gpren[3];
39  uint32_t gpfen[3];
40  uint32_t gphen[3];
41  uint32_t gplen[3];
42  uint32_t gparen[3];
43  uint32_t gpafen[3];
44  uint32_t gppud[1];
45  uint32_t gppudclk[3];
46  uint32_t test[1];
47};
48volatile struct gpio_s* gpio_regs;
49
50/*******************************************************************************
51 * GPIO Operations
52 ******************************************************************************/
53
54int gpio_setup ( void ){
55
56  int mmap_fd = open ("/dev/mem", O_RDWR | O_SYNC );
57  if ( mmap_fd < 0 ) {
58    return -1;
59  }
60
61  gpio_regs = mmap ( NULL, RPI_BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mmap_fd, RPI_GPIO_BASE );
62  if ( gpio_regs == MAP_FAILED ) {
63    close ( mmap_fd );
64    return -1;
65  }
66
67  return 0;
68}
69
70void  gpio_teardown ( void ){
71  munmap((void*)gpio_regs, RPI_BLOCK_SIZE);
72}
73
74
75void gpio_config(int gpio, int value)
76{
77  gpio_regs->gpfsel[gpio/10] = ( gpio_regs->gpfsel[gpio/10] & ~(0x7 << ((gpio % 10) * 3)) )
78                             | (value << ((gpio % 10) * 3));
79}
80
81void gpio_update(int gpio, int value)
82{
83  if( value )
84    gpio_regs->gpset[gpio/32] = (0x1 << (gpio % 32) );
85  else
86    gpio_regs->gpclr[gpio/32] = (0x1 << (gpio % 32) );
87}
88
89/*******************************************************************************
90 * LCD's Instructions ( source = doc )
91 ******************************************************************************/
92
93#define B_0000  0
94#define B_0001  1
95#define B_0010  2
96#define B_0011  3
97#define B_0100  4
98#define B_0101  5
99#define B_0110  6
100#define B_0111  7
101#define B_1000  8
102#define B_1001  9
103#define B_1010  a
104#define B_1011  b
105#define B_1100  c
106#define B_1101  d
107#define B_1110  e
108#define B_1111  f
109
110/* On veut definir une macro HEX()
111 * qui prend en argument deux nombres de 4 bits exprimes en binaire
112 * representant resp. les 4 bits de poids fort et les 4 bits de poids faible d'un entier sur 8bits 
113 * qui rend l'entier.
114 * p. ex: HEX(0000,0010) rend 2
115 * p. ex: HEX(0001,0000) rend 16
116 *
117 * QUESTION: expliquez comment ca marche ....
118 */
119#define __HEX(h,l) 0x##h##l
120#define _HEX(h,l)  __HEX(h,l)
121#define HEX(h,l)   _HEX(B_##h,B_##l)
122
123/* QUESTION: que fait cette macro ?
124 */
125#define BIT(b,n)   (((n)>>(b))&1)
126
127/* commands */
128#define LCD_CLEARDISPLAY        HEX(0000,0001)
129#define LCD_RETURNHOME          HEX(0000,0010)
130#define LCD_ENTRYMODESET        HEX(0000,0100)
131#define LCD_DISPLAYCONTROL      HEX(0000,1000)
132#define LCD_CURSORSHIFT         HEX(0001,0000)
133#define LCD_FUNCTIONSET         HEX(0010,0000)
134#define LCD_SETCGRAMADDR        HEX(0100,0000)
135#define LCD_SETDDRAMADDR        HEX(1000,0000)
136
137/* flags for display entry mode : combine with LCD_ENTRYMODESET */
138#define LCD_EM_RIGHT            HEX(0000,0000)
139#define LCD_EM_LEFT             HEX(0000,0010)
140#define LCD_EM_DISPLAYSHIFT     HEX(0000,0001)
141#define LCD_EM_DISPLAYNOSHIFT   HEX(0000,0000)
142
143/* flags for display on/off control : combine with LCD_DISPLAYCONTROL */
144#define LCD_DC_DISPLAYON        HEX(0000,0100)
145#define LCD_DC_DISPLAYOFF       HEX(0000,0000)
146#define LCD_DC_CURSORON         HEX(0000,0010)
147#define LCD_DC_CURSOROFF        HEX(0000,0000)
148#define LCD_DC_BLINKON          HEX(0000,0001)
149#define LCD_DC_BLINKOFF         HEX(0000,0000)
150
151/* flags for display/cursor shift : combine with LCD_CURSORSHIFT */
152#define LCD_CS_DISPLAYMOVE      HEX(0000,1000)
153#define LCD_CS_CURSORMOVE       HEX(0000,0000)
154#define LCD_CS_MOVERIGHT        HEX(0000,0100)
155#define LCD_CS_MOVELEFT         HEX(0000,0000)
156
157/* flags for function set : combine with LCD_FUNCTIONSET */
158#define LCD_FS_8BITMODE         HEX(0001,0000)
159#define LCD_FS_4BITMODE         HEX(0000,0000)
160#define LCD_FS_2LINE            HEX(0000,1000)
161#define LCD_FS_1LINE            HEX(0000,0000)
162#define LCD_FS_5x10DOTS         HEX(0000,0100)
163#define LCD_FS_5x8DOTS          HEX(0000,0000)
164
165/*******************************************************************************
166 * LCD's Operations
167 ******************************************************************************/
168
169/* generate E signal */
170void lcd_strobe(void)
171{
172  /* A completer */
173}
174
175/* send 4bits to LCD */
176void lcd_write4bits(int data)
177{
178  /* first 4 bits */
179  gpio_update(D7, BIT(7,data));
180  /* a completer */
181  lcd_strobe();
182
183  /* second 4 bits */
184  /* a completer */
185  lcd_strobe();
186  usleep(50); /* le délai minimum est de 37us */
187}
188
189void lcd_command(int cmd)
190{
191  gpio_update(RS, 0);
192  lcd_write4bits(cmd);
193  usleep(2000); /* delai nécessaire pour certaines commandes */
194}
195
196void lcd_data(int character)
197{
198  gpio_update(RS, 1);
199  lcd_write4bits(character);
200}
201
202/* initialization
203 * Question : commenter ces initialisations:
204 *
205 * LCD_FUNCTIONSET    | LCD_FS_4BITMODE | LCD_FS_2LINE | LCD_FS_5x8DOTS
206 * LCD_DISPLAYCONTROL | LCD_DC_DISPLAYON | LCD_DC_CURSOROFF
207 * LCD_ENTRYMODESET   | LCD_EM_RIGHT | LCD_EM_DISPLAYNOSHIFT
208 */
209void lcd_init(void)
210{
211  gpio_update(E, 0);
212  lcd_command(HEX(0011,0011)); /* initialization */
213  lcd_command(HEX(0011,0010)); /* initialization */
214  lcd_command(LCD_FUNCTIONSET    | LCD_FS_/* a completer */ );
215  lcd_command(LCD_DISPLAYCONTROL | LCD_DC_/* a completer */ );
216  lcd_command(LCD_ENTRYMODESET   | LCD_EM_/* a completer */ );
217}
218
219void lcd_clear(void)
220{
221  lcd_command(LCD_CLEARDISPLAY);
222  lcd_command(LCD_RETURNHOME);
223}
224
225void lcd_message(char* txt)
226{
227  int i, j;
228  for(i=0; i<20 && i<strlen(txt); i++){
229    lcd_data(txt[i]);
230  }
231}
232/*******************************************************************************
233 * Finally, the main function
234 ******************************************************************************/
235int main(int argc, char** argv)
236{
237  /* arg */
238  if( argc < 2 ){
239    fprintf(stderr, "ERROR: must take a string as argument\n");
240    exit(1);
241  }
242
243  /* Retreive the mapped GPIO memory */
244  if( gpio_setup() == -1 ){
245    perror("ERROR: gpio_setup\n");
246    exit(1);
247  }
248
249  /* Setting up GPIOs to output */
250  gpio_config(RS, GPIO_OUTPUT);
251  gpio_config(E , GPIO_OUTPUT);
252  gpio_config(D4, GPIO_OUTPUT);
253  gpio_config(D5, GPIO_OUTPUT);
254  gpio_config(D6, GPIO_OUTPUT);
255  gpio_config(D7, GPIO_OUTPUT);
256
257  /* initialization */
258  lcd_init();
259  lcd_clear();
260
261  /* print app argument */
262  lcd_message(argv[1]);
263
264  /* Release the GPIO memory mapping */
265  gpio_teardown();
266
267  return 0;
268}