PsiSwarm Library  0.8
display.cpp
1 /* University of York Robotics Laboratory PsiSwarm Library: Display Driver Source File
2  *
3  * Copyright 2016 University of York
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
7  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS
8  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9  * See the License for the specific language governing permissions and limitations under the License.
10  *
11  * File: display.cpp
12  *
13  * (C) Dept. Electronics & Computer Science, University of York
14  *
15  * James Hilder, Alan Millard, Alexander Horsfield, Homero Elizondo, Jon Timmis
16  *
17  * PsiSwarm Library Version: 0.8
18  *
19  * October 2016
20  *
21  * Driver for the Midas 16x2 I2C LCD Display (MCCOG21605x6W) LCD
22  * [Farnell part 2218942 or 2063206]
23  *
24  */
25 
26 #include "psiswarm.h"
27 
28 Timeout init_timeout;
29 Timeout backlight_timeout;
30 Timeout debug_timeout;
31 int backlight_on_time;
32 int backlight_off_time;
33 char backlight_step;
34 char multipage[200];
35 char multipage_length = 0;
36 char preserve_line_1 [17];
37 char preserve_line_2 [17];
38 char c_row=0;
39 char c_column=0;
40 char p_row;
41 char p_column;
42 
43 
44 Display::Display(PinName sda, PinName scl, PinName reset, PinName backlight) : Stream("display"), _i2c(sda,scl), _reset(reset), _backlight(backlight) {
45 }
46 
47 Display::Display() : Stream("display"), _i2c(p28,p27), _reset(p29), _backlight(p30) {
48 }
49 
50 int Display::i2c_message(char byte){
51  char bytes [2];
52  bytes[0]=0x80;
53  bytes[1]=byte;
54  int ret=_i2c.write(LCD_ADDRESS,bytes,2);
55  wait(0.01);
56  return ret;
57 }
58 
59 int Display::disp_putc(int c){
60  char message [2];
61  message[0]=0x40;
62  message[1]=c;
63  _i2c.write(LCD_ADDRESS,message,2);
64  wait(0.01);
65  return c;
66 }
67 
68 void Display::init_display(char mode){
69  //Set initial states: display on, cursor off
70  display_on = 1;
72  cursor_on = 0;
73  blink_on = 0;
74 
75  _reset=1;
76  wait(0.02);
77  //Set reset low
78  _reset=0;
79  wait(0.001);
80  _reset=1;
81  wait(0.03);
82  i2c_message(0x38);
83  i2c_message(0x39);
84  i2c_message(0x14);
85  i2c_message(0x74);
86  i2c_message(0x54);
87  i2c_message(0x6F);
88  _set_display();
89  clear_display();
90  char psis[17];
91  for(int i=0;i<16;i++){
92  psis[i]=0x1D;
93  }
94  set_position(0,0);
95  write_string(psis,16);
96  set_position(1,0);
97  write_string(psis,16);
98  wait(0.25);
99  clear_display();
100  if(mode == 0) {
101  set_position(0,0);
102  write_string(" YORK ROBOTICS");
103  set_position(1,0);
104  write_string(" LABORATORY");
105  init_timeout.attach(this,&Display::post_init,0.3);}
106  else {
107  set_position(0,0);
108  write_string("Hold button to");
109  set_position(1,0);
110  write_string("launch demo code");
111  }
112 }
113 
114 void Display::post_init(){
115  clear_display();
116  home();
117  write_string("PSI SWARM ROBOT");
118  set_position(1,0);
119  char line [17];
120  sprintf(line,"VERSION %1.2f", SOFTWARE_VERSION_CODE );
121  set_position(1,0);
122  write_string(line);
123  init_timeout.attach(this,&Display::post_post_init,0.3);
124 }
125 
126 void Display::post_post_init(){
127  clear_display();
128  home();
129 }
130 
131 void Display::write_string(char * message){
132  size_t length = strlen(message);
133  if (length > 16) length = 16;
134  char to_send [length+1];
135  to_send[0]=0x40;
136  for(int i=0;i<length;i++){
137  to_send[i+1] = message[i];
138  }
139  _i2c.write(LCD_ADDRESS,to_send,length+1);
140  // Add to saved buffer
141  int count = 0;
142  for(int i=c_column;i<16;i++){
143  if(count < length){
144  if(c_row == 0) preserve_line_1[i] = message[count];
145  else preserve_line_2[i] = message[count];
146  }
147  count++;
148  }
149  c_column+=length;
150  if(c_column>15) c_column=15;
151 }
152 
153 
154 void Display::write_string(char * message, char length){
155  char to_send [length+1];
156  to_send[0]=0x40;
157  for(int i=0;i<length;i++){
158  to_send[i+1] = message[i];
159  }
160  _i2c.write(LCD_ADDRESS,to_send,length+1);
161  // Add to saved buffer
162  int count = 0;
163  for(int i=c_column;i<16;i++){
164  if(count < length){
165  if(c_row == 0) preserve_line_1[i] = message[count];
166  else preserve_line_2[i] = message[count];
167  }
168  count++;
169  }
170  c_column+=length;
171  if(c_column>15) c_column=15;
172 }
173 
174 void Display::set_position(char row, char column){
175  if(row < 2 && column < 16){
176  char pos = 128 +((row * 64)+column);
177  i2c_message(pos);
178  c_row= row;
179  c_column = column;
180  }
181 }
182 
183 void Display::set_cursor(char enable){
184  cursor_on=enable;
185  _set_display();
186 }
187 
188 void Display::set_blink(char enable){
189  blink_on=enable;
190  _set_display();
191 }
192 
193 void Display::set_display(char enable){
194  display_on=enable;
195  _set_display();
196 }
197 
198 void Display::set_backlight_brightness(float brightness){
199  if(brightness > 1) brightness = 0;
200  if(brightness < 0) brightness = 0;
201  backlight_brightness = brightness;
202  if(backlight_brightness == 1) {
203  backlight_timeout.detach();
204  _backlight = 1;
205  }else{
206  if(backlight_brightness == 0){
207  backlight_timeout.detach();
208  _backlight = 0;
209  } else {
210  backlight_on_time = (int) (10000.0f * backlight_brightness);
211  backlight_off_time = 10000 - backlight_on_time;
212  backlight_step = 0;
213  _backlight = 0;
214  backlight_timeout.attach_us(this,&Display::IF_backlight_toggle,backlight_off_time);
215  }
216  }
217 }
218 
219 void Display::IF_backlight_toggle(){
220  if(backlight_step == 0){
221  _backlight = 1;
222  backlight_step = 1;
223  backlight_timeout.attach_us(this,&Display::IF_backlight_toggle,backlight_on_time);
224  } else {
225  _backlight = 0;
226  backlight_step = 0;
227  backlight_timeout.attach_us(this,&Display::IF_backlight_toggle,backlight_off_time);
228  }
229 }
231  for(int i=0;i<16;i++){
232  preserve_line_1[i] = 0x20;
233  preserve_line_2[i] = 0x20;
234  }
235  i2c_message(0x01);
236 }
237 
239  c_row = 0;
240  c_column = 0;
241  i2c_message(0x02);
242 }
243 
244 void Display::debug_page(char * message, char length){
245  p_row=c_row;
246  p_column=c_column;
247  i2c_message(0x01);
248  home();
249  char multipage_mode = 0;
250  char line_1[18];
251  char line_2[18];
252  line_1[0]=0x40;
253  line_2[0]=0x40;
254  if(length > 16){
255  strncpy(line_1+1, message, 16);
256  char f_length = length - 16;
257  if(f_length > 16) {
258  f_length = 16;
259  multipage_mode = 1;
260  }
261  strncpy(line_2+1, message+16, f_length);
262  line_1[17]=0;
263  line_2[f_length+1]=0;
264  _i2c.write(LCD_ADDRESS,line_1,17);
265  set_position(1,0);
266  _i2c.write(LCD_ADDRESS,line_2,f_length+1);
267  } else {
268  strncpy(line_1+1, message, length);
269  _i2c.write(LCD_ADDRESS,line_1,length+1);
270  }
271  if(multipage_mode == 1){
272  strncpy(multipage, message + 32, length - 32);
273  multipage_length = length - 32;
274  debug_timeout.attach(this,&Display::IF_debug_multipage,PAGE_TIME);
275  } else debug_timeout.attach(this,&Display::IF_restore_page,CLEAR_TIME);
276 }
277 
278 void Display::IF_restore_page(){
279  i2c_message(0x01);
280  home();
281  char line_1[17];
282  char line_2[17];
283  line_1[0]=0x40;
284  line_2[0]=0x40;
285  strncpy(line_1+1, preserve_line_1, 16);
286  strncpy(line_2+1, preserve_line_2, 16);
287  _i2c.write(LCD_ADDRESS,line_1,17);
288  set_position(1,0);
289  _i2c.write(LCD_ADDRESS,line_2,17);
290  set_position(p_row,p_column);
291 }
292 
293 void Display::IF_debug_multipage(){
294  i2c_message(0x01);
295  home();
296  char multipage_mode = 0;
297  char line_1[18];
298  char line_2[18];
299  line_1[0]=0x40;
300  line_2[0]=0x40;
301  if(multipage_length > 16){
302  strncpy(line_1+1, multipage, 16);
303  char f_length = multipage_length - 16;
304  if(f_length > 16) {
305  f_length = 16;
306  multipage_mode = 1;
307  }
308  strncpy(line_2+1, multipage+16, f_length);
309  line_1[17]=0;
310  line_2[f_length+1]=0;
311  _i2c.write(LCD_ADDRESS,line_1,17);
312  set_position(1,0);
313  _i2c.write(LCD_ADDRESS,line_2,f_length+1);
314  } else {
315  strncpy(line_1+1, multipage, multipage_length);
316  _i2c.write(LCD_ADDRESS,line_1,multipage_length+1);
317  }
318  if(multipage_mode == 1){
319  char temp[200];
320  strncpy(temp, multipage + 32, multipage_length - 32);
321  multipage_length -= 32;
322  strncpy(multipage, temp, multipage_length);
323  debug_timeout.attach(this,&Display::IF_debug_multipage,PAGE_TIME);
324  }else debug_timeout.attach(this,&Display::IF_restore_page,CLEAR_TIME);
325 }
326 
327 void Display::_set_display(){
328  char mode = 8;
329  if(display_on>0) mode += 4;
330  if(cursor_on>0) mode += 2;
331  if(blink_on>0) mode ++;
332  i2c_message(mode);
333 }
334 
335 
336 int Display::_putc (int c) {
337  putc(c);
338  return(c);
339 }
340 
341 int Display::_getc (void) {
342  char r = 0;
343  return(r);
344 }
void write_string(char *message)
Definition: display.cpp:131
void set_position(char row, char column)
Definition: display.cpp:174
void set_display(char enable)
Definition: display.cpp:193
void home(void)
Definition: display.cpp:238
void clear_display(void)
Definition: display.cpp:230
void set_cursor(char enable)
Definition: display.cpp:183
void set_backlight_brightness(float brightness)
Definition: display.cpp:198
Display()
Definition: display.cpp:47
void set_blink(char enable)
Definition: display.cpp:188