AskSin++
Lcd4seg.h
1 //- -----------------------------------------------------------------------------------------------------------------------
2 // AskSin++
3 // 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
4 // LCD4SEG class
5 // 2019-10-20 jp112sdl Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
6 //- -----------------------------------------------------------------------------------------------------------------------
7 
8 //designed for 4 digit lcd from
9 //https://de.aliexpress.com/item/1000002117470.html
10 
11 #include <AlarmClock.h>
12 #ifndef __LCD4SEGHT1621_H__
13 #define __LCD4SEGHT1621_H__
14 
15 #define LCD4SEG_BUFSIZE 4
16 
17 //============DEFINE CONTROL CODES=============
18 #define BIAS 0x52 //0b1000 0101 0010
19 #define SYSDIS 0X00 //0b1000 0000 0000
20 #define SYSEN 0X02 //0b1000 0000 0010
21 #define LCDOFF 0X04 //0b1000 0000 0100
22 #define LCDON 0X06 //0b1000 0000 0110
23 #define XTAL 0x28 //0b1000 0010 1000
24 #define RC256 0X30 //0b1000 0011 0000
25 #define TONEON 0X12 //0b1000 0001 0010
26 #define TONEOFF 0X10 //0b1000 0001 0000
27 #define WDTDIS1 0X0A //0b1000 0000 1010
28 
29 namespace as {
30 
31 template<uint8_t CS, uint8_t WR, uint8_t DT>
32 class LCD4SEG {
33 private:
34  uint8_t _cs, _wr, _data, _bufferMem;
35  char _localBuffer[LCD4SEG_BUFSIZE]; //store the mapping segment number
36  uint8_t _lcdbuffer[LCD4SEG_BUFSIZE]; //store the data that will use to send to LCD RAM
37 
38  void sendCmd(byte command) {
39  digitalWrite(_cs, LOW);
40  uint16_t cmd = 0x800;
41  cmd = cmd | command;
42 
43  for (uint8_t i = 0; i <12; i ++){
44  digitalWrite(_wr, LOW);
45  digitalWrite(_data, (cmd & 0x800) ? HIGH : LOW);
46  cmd <<=1;
47  digitalWrite(_wr, HIGH);
48  }
49  digitalWrite(_cs, HIGH);
50  }
51 
52  void update(uint8_t type) {
53  memset(_lcdbuffer, 0, LCD4SEG_BUFSIZE);
54 
55  //maping number to lcd segment.
56  for (int i = 0 ; i < LCD4SEG_BUFSIZE; i ++){
57  switch(_localBuffer[i]){
58  /* segments bitorder
59  * a
60  * -
61  * f | | b
62  * - <-g
63  * e | | c
64  * - . <-h
65  * d
66  *
67  * a b c d e f g h
68  */
69 
70  case '0':
71  _lcdbuffer[i] = 0b11111100;
72  break;
73  case '1':
74  _lcdbuffer[i] = 0b01100000;
75  break;
76  case '2':
77  _lcdbuffer[i] = 0b11011010;
78  break;
79  case '3':
80  _lcdbuffer[i] = 0b11110010;
81  break;
82  case '4':
83  _lcdbuffer[i] = 0b01100110;
84  break;
85  case '5':
86  _lcdbuffer[i] = 0b10110110;
87  break;
88  case '6':
89  _lcdbuffer[i] = 0b10111110;
90  break;
91  case '7':
92  _lcdbuffer[i] = 0b11100000;
93  break;
94  case '8':
95  _lcdbuffer[i] = 0b11111110;
96  break;
97  case '9':
98  _lcdbuffer[i] = 0b11110110;
99  break;
100  case '-':
101  _lcdbuffer[i] = 0b00000010;
102  break;
103  case ' ':
104  _lcdbuffer[i] = 0b00000000;
105  break;
106  }
107  }
108 
109  switch (type){
110  case 1: //for _h
111  _lcdbuffer[2] = 0b00001010; // r
112  _lcdbuffer[3] = 0b01101110; // H
113  break;
114 
115  case 2: //for temp C format
116  _lcdbuffer[1]|= 0b00000001; //dot
117  _lcdbuffer[3] = 0b10011101; //print *C
118  break;
119 
120  case 3: //print b.Lo
121  _lcdbuffer[0] = 0b00111111; // b.
122  _lcdbuffer[1] = 0b00011100; // L
123  _lcdbuffer[2] = 0b00111010; // o
124  _lcdbuffer[3] = 0b00000000; //
125  break;
126  }
127 
128  //sending 101 to inform HT1621 that MCU send data then follow by address 000000.
129  uint16_t cmd =0x140;
130  digitalWrite(_cs, LOW);
131  for(int i = 0 ;i < 9;i ++){
132  digitalWrite(_wr, LOW);
133  digitalWrite(_data, (cmd & 0x100) ? HIGH : LOW);
134  cmd <<=1;
135  digitalWrite(_wr, HIGH);
136  }
137 
138  //sending 32 bit of segment to LCD RAM.
139  for (int i =0; i < 8; i++){
140  for (int j =0; j<4;j++){
141  digitalWrite(_wr,LOW);
142  _bufferMem =_lcdbuffer[j]<<i;
143  digitalWrite(_data, (_bufferMem & 0x80) ? HIGH : LOW);
144  digitalWrite(_wr, HIGH);
145  }
146  }
147  digitalWrite(_cs, HIGH);
148  }
149 
150 public:
151  LCD4SEG () : _cs(0), _wr(0), _data(0),_bufferMem(0) {}
152  virtual ~LCD4SEG() {}
153 
154  void init(){
155  _cs = CS;
156  _wr = WR;
157  _data = DT;
158  pinMode(_cs, OUTPUT);
159  pinMode(_wr, OUTPUT);
160  pinMode(_data, OUTPUT);
161 
162  sendCmd(BIAS);
163  sendCmd(SYSDIS);
164  sendCmd(SYSEN);
165  sendCmd(RC256);
166  sendCmd(WDTDIS1);
167  sendCmd(LCDON);
168  }
169 
170  void clear(){
171  uint16_t cmd = 0x140;
172 
173  digitalWrite(_cs, LOW);
174  for (uint8_t i =0; i<9; i++){
175  digitalWrite(_wr, LOW);
176  digitalWrite(_data, (cmd & 0x100) ? HIGH : LOW);
177  cmd <<=1;
178  digitalWrite(_wr, HIGH);
179  }
180 
181  for (uint8_t i =0 ; i<32; i++){
182  digitalWrite(_wr, LOW);
183  digitalWrite(_data, LOW);
184  digitalWrite(_wr, HIGH);
185  }
186  digitalWrite(_cs, HIGH);
187  }
188 
189  void printH(uint8_t number){
190  if (number > 99){ number = 99; }
191  snprintf(_localBuffer, 3, "%2i", number);
192  update(1);
193  }
194 
195  void printC(int16_t number){
196  snprintf(_localBuffer, 4, "%3i", number);
197  if (number > -10) {
198  if (number < 0) _localBuffer[0] = '-';
199  if (number < 10) _localBuffer[1] = '0';
200  }
201  update(2);
202  }
203 
204  void printLowBat() {
205  update(3);
206  }
207 };
208 
209 template<class LCDTYPE>
210 class LCDToggleTH : public Alarm {
211 public:
212  typedef LCDTYPE LcdType;
213  LcdType lcd;
214 private:
215  uint8_t _screenNum;
216  int16_t _t;
217  uint8_t _h;
218  uint8_t _toggleTimeSecs;
219  bool _lowBat;
220 public:
221  LCDToggleTH () : Alarm(0), _screenNum(0), _t(0), _h(0), _toggleTimeSecs(10), _lowBat(false) { async(true); }
222  virtual ~LCDToggleTH () {}
223 
224  void init() {
225  lcd.init();
226  lcd.clear();
227  sysclock.init();
228  sysclock.add(*this);
229  }
230 
231  void setValues(int16_t t, uint8_t h, bool b) {
232  _t = t;
233  _h = h;
234  _lowBat = b;
235  displayValues();
236  }
237 
238  void setToggleTime(uint8_t time) {
239  _toggleTimeSecs = time;
240  sysclock.cancel(*this);
241  set(seconds2ticks(_toggleTimeSecs));
242  sysclock.add(*this);
243  }
244 
245  void displayValues() {
246  switch (_screenNum) {
247  case 0:
248  lcd.printH(_h);
249  break;
250  case 1:
251  lcd.printC(_t);
252  break;
253  case 2:
254  lcd.printLowBat();
255  break;
256  }
257  _screenNum++;
258  if (_screenNum > (_lowBat ? 2 : 1)) _screenNum = 0;
259  }
260 
261  virtual void trigger (__attribute__((unused)) AlarmClock& clock) {
262  set(seconds2ticks(_toggleTimeSecs));
263  displayValues();
264  sysclock.add(*this);
265  }
266 };
267 
268 }
269 
270 /* example:
271 #include <displays/Lcd4seg.h>
272 
273 using namespace as;
274 
275 LCDToggleTH<LCD4SEG<6, 3, 7>> lcd;
276 
277 void setup(){
278  lcd.init();
279  lcd.setToggleTime(3); //toggle display every 3 seconds
280  lcd.setValues(256, 38, false); //25.6°C, 38rH, no LowBat
281 }
282 
283 void loop(){}
284 
285  */
286 #endif
287 
as::Alarm
Definition: Alarm.h:15
as::AlarmClock
Definition: AlarmClock.h:32
as::LCD4SEG
Definition: Lcd4seg.h:32
as::LCDToggleTH
Definition: Lcd4seg.h:210