PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

319 lines
7.0KB

  1. /*
  2. * This is free software: you can redistribute it and/or modify
  3. * it under the terms of the GNU Lesser General Public License as published by
  4. * the Free Software Foundation, either version 3 of the License, or
  5. * (at your option) any later version.
  6. *
  7. * DogLcd is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU Lesser General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU Lesser General Public License
  13. * along with DogLcd. If not, see <http://www.gnu.org/licenses/>.
  14. *
  15. * Copyright 2010 Eberhard Fahle <e.fahle@wayoda.org>
  16. */
  17. #include "DogLcd.h"
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <inttypes.h>
  21. #if (ARDUINO >= 100)
  22. #include <Arduino.h>
  23. #else
  24. #include <WProgram.h>
  25. #endif
  26. DogLcd::DogLcd(int lcdSI, int lcdCLK, int lcdRS, int lcdCSB, int lcdRESET, int backLight) {
  27. this->lcdSI=lcdSI;
  28. this->lcdCLK=lcdCLK;
  29. this->lcdRS=lcdRS;
  30. this->lcdCSB=lcdCSB;
  31. this->lcdRESET=lcdRESET;
  32. this->backLight=backLight;
  33. }
  34. int DogLcd::begin(int model, int contrast, int vcc) {
  35. //init all pins to go HIGH, we dont want to send any commands by accident
  36. pinMode(this->lcdCSB,OUTPUT);
  37. digitalWrite(this->lcdCSB,HIGH);
  38. pinMode(this->lcdSI,OUTPUT);
  39. digitalWrite(this->lcdSI,HIGH);
  40. pinMode(this->lcdCLK,OUTPUT);
  41. digitalWrite(this->lcdCLK,HIGH);
  42. pinMode(this->lcdRS,OUTPUT);
  43. digitalWrite(this->lcdRS,HIGH);
  44. if(this->lcdRESET!=-1) {
  45. pinMode(this->lcdRESET,OUTPUT);
  46. digitalWrite(this->lcdRESET,HIGH);
  47. }
  48. if(this->backLight!=-1) {
  49. pinMode(this->backLight,OUTPUT);
  50. digitalWrite(this->backLight,LOW);
  51. }
  52. if(model==DOG_LCD_M081) {
  53. this->model=model;
  54. rows=1;
  55. cols=8;
  56. memSize=80;
  57. startAddress[0]=0;
  58. startAddress[1]=-1;
  59. startAddress[2]=-1;
  60. }
  61. else if(model==DOG_LCD_M162) {
  62. this->model=model;
  63. rows=2;
  64. cols=16;
  65. memSize=40;
  66. startAddress[0]=0;
  67. startAddress[1]=0x40;
  68. startAddress[2]=-1;
  69. }
  70. else if(model==DOG_LCD_M163) {
  71. this->model=model;
  72. rows=3;
  73. cols=16;
  74. memSize=16;
  75. startAddress[0]=0;
  76. startAddress[1]=0x10;
  77. startAddress[2]=0x20;
  78. }
  79. else {
  80. //unknown or unsupported model
  81. return -1;
  82. }
  83. if(contrast < 0 || contrast> 0x3F) {
  84. //contrast is outside the valid range
  85. return -1;
  86. }
  87. this->contrast=contrast;
  88. if(vcc==DOG_LCD_VCC_5V || vcc==DOG_LCD_VCC_3V3) {
  89. this->vcc=vcc;
  90. }
  91. else {
  92. //unknown or unsupported supply voltage
  93. return -1;
  94. }
  95. reset();
  96. return 0;
  97. }
  98. void DogLcd::reset() {
  99. if(lcdRESET!=-1) {
  100. //If user wired the reset line, pull it low and wait for 40 millis
  101. digitalWrite(lcdRESET,LOW);
  102. delay(40);
  103. digitalWrite(lcdRESET,HIGH);
  104. delay(40);
  105. }
  106. else {
  107. //User wants software reset, we simply wait a bit for stable power
  108. delay(50);
  109. }
  110. if(model==DOG_LCD_M081) {
  111. //8-bit,1-line
  112. instructionSetTemplate=(uint8_t)0x30;
  113. }
  114. else if(model==DOG_LCD_M162) {
  115. //8-bit,2-line
  116. instructionSetTemplate=(uint8_t)0x38;
  117. }
  118. else if(model==DOG_LCD_M163) {
  119. //8-bit,2-line
  120. instructionSetTemplate=(uint8_t)0x38;
  121. }
  122. //init data-size and lines, then change to instructionset 1
  123. setInstructionSet(1);
  124. //bias 1/4
  125. writeCommand(0x1D,30);
  126. setContrast(this->contrast);
  127. //Standard setting is : display on, cursor on, no blink
  128. displayMode=0x04;
  129. cursorMode=0x02;
  130. blinkMode=0x00;
  131. writeDisplayMode();
  132. entryMode=0x04;
  133. clear();
  134. leftToRight();
  135. }
  136. void DogLcd::setContrast(int contrast) {
  137. if(contrast<0 || contrast>0x3F)
  138. return;
  139. if(this->vcc==DOG_LCD_VCC_5V) {
  140. /*
  141. For 5v operation the booster must be off, which is on the
  142. same command as the (2-bit) high-nibble of contrast
  143. */
  144. writeCommand((0x50 | ((contrast>>4)&0x03)),30);
  145. /* Set amplification ratio for the follower control */
  146. writeCommand(0x69,30);
  147. }
  148. else {
  149. /*
  150. For 3.3v operation the booster must be on, which is on the
  151. same command as the (2-bit) high-nibble of contrast
  152. */
  153. writeCommand((0x54 | ((contrast>>4)&0x03)),30);
  154. /*
  155. Set amplification ratio for the follower control
  156. this has to be higher it seems at 3.3V operation
  157. */
  158. writeCommand(0x6B,30);
  159. }
  160. //set low-nibble of the contrast
  161. writeCommand((0x70 | (contrast & 0x0F)),30);
  162. }
  163. void DogLcd::clear() {
  164. writeCommand(0x01,1080);
  165. }
  166. void DogLcd::home() {
  167. writeCommand(0x02,1080);
  168. }
  169. void DogLcd::setCursor(int col, int row) {
  170. if(col>=memSize || row>=rows) {
  171. //not a valid cursor position
  172. return;
  173. }
  174. int address=(startAddress[row]+col) & 0x7F;
  175. writeCommand(0x80|address,30);
  176. }
  177. void DogLcd::noDisplay() {
  178. displayMode=0x00;
  179. writeDisplayMode();
  180. }
  181. void DogLcd::display() {
  182. displayMode=0x04;
  183. writeDisplayMode();
  184. }
  185. void DogLcd::noCursor() {
  186. cursorMode=0x00;
  187. writeDisplayMode();
  188. }
  189. void DogLcd::cursor() {
  190. cursorMode=0x02;
  191. writeDisplayMode();
  192. }
  193. void DogLcd::noBlink() {
  194. blinkMode=0x00;
  195. writeDisplayMode();
  196. }
  197. void DogLcd::blink() {
  198. blinkMode=0x01;
  199. writeDisplayMode();
  200. }
  201. void DogLcd::scrollDisplayLeft(void) {
  202. setInstructionSet(0);
  203. writeCommand(0x18,30);
  204. }
  205. void DogLcd::scrollDisplayRight(void) {
  206. setInstructionSet(0);
  207. writeCommand(0x1C,30);
  208. }
  209. void DogLcd::leftToRight(void) {
  210. entryMode|=0x02;
  211. writeCommand(entryMode,30);
  212. }
  213. void DogLcd::rightToLeft(void) {
  214. entryMode&=~0x02;
  215. writeCommand(entryMode,30);
  216. }
  217. void DogLcd::autoscroll(void) {
  218. entryMode|=0x01;
  219. writeCommand(entryMode,30);
  220. }
  221. void DogLcd::noAutoscroll(void) {
  222. entryMode&=~0x01;
  223. writeCommand(entryMode,30);
  224. }
  225. void DogLcd::createChar(int charPos, uint8_t charMap[]) {
  226. int baseAddress;
  227. if(charPos<0 || charPos>7)
  228. return;
  229. baseAddress=charPos*8;
  230. //changing CGRAM address belongs to different instruction set
  231. setInstructionSet(0);
  232. for (int i=0; i<8; i++) {
  233. writeCommand((0x40|(baseAddress+i)),30);
  234. writeChar(charMap[i]);
  235. }
  236. setInstructionSet(0);
  237. writeDisplayMode();
  238. }
  239. void DogLcd::writeDisplayMode() {
  240. writeCommand((0x08 | displayMode | cursorMode | blinkMode),30);
  241. }
  242. void DogLcd::setBacklight(int value, bool usePWM) {
  243. if(backLight!=-1 && value>=0) {
  244. if(!usePWM) {
  245. if(value==LOW) {
  246. digitalWrite(backLight,LOW);
  247. }
  248. else {
  249. digitalWrite(backLight,HIGH);
  250. }
  251. }
  252. else {
  253. if(value>255)
  254. value=255;
  255. analogWrite(backLight,value);
  256. }
  257. }
  258. }
  259. void DogLcd::setInstructionSet(int is) {
  260. if(is<0 || is>3)
  261. return;
  262. int cmd=instructionSetTemplate | is;
  263. writeCommand(cmd,30);
  264. }
  265. void DogLcd::writeChar(int value) {
  266. digitalWrite(lcdRS,HIGH);
  267. spiTransfer(value,30);
  268. }
  269. void DogLcd::writeCommand(int value,int executionTime) {
  270. digitalWrite(lcdRS,LOW);
  271. spiTransfer(value,executionTime);
  272. }
  273. void DogLcd::spiTransfer(int value, int executionTime) {
  274. digitalWrite(lcdCLK,HIGH);
  275. digitalWrite(lcdCSB,LOW);
  276. for(int i=7;i>=0;i--) {
  277. if(bitRead(value,i)) {
  278. digitalWrite(lcdSI,HIGH);
  279. }
  280. else {
  281. digitalWrite(lcdSI,LOW);
  282. }
  283. digitalWrite(lcdCLK,LOW);
  284. digitalWrite(lcdCLK,HIGH);
  285. }
  286. digitalWrite(lcdCSB,HIGH);
  287. delayMicroseconds(executionTime);
  288. }