PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

323 lines
8.6KB

  1. /*
  2. LedDisplay -- controller library for Avago HCMS-297x displays -- version 0.2
  3. Copyright (c) 2009 Tom Igoe. Some right reserved.
  4. Revisions on version 0.2 and 0.3 by Mark Liebman, 27 Jan 2010
  5. * extended a bit to support up to four (4) 8 character displays.
  6. vim: set ts=4:
  7. Controls an Avago HCMS29xx display. This display has 8 characters, each 5x7 LEDs
  8. This library is free software; you can redistribute it and/or
  9. modify it under the terms of the GNU Lesser General Public
  10. License as published by the Free Software Foundation; either
  11. version 2.1 of the License, or (at your option) any later version.
  12. This library is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. Lesser General Public License for more details.
  16. You should have received a copy of the GNU Lesser General Public
  17. License along with this library; if not, write to the Free Software
  18. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include "LedDisplay.h"
  21. // Pascal Stang's 5x7 font library:
  22. #include "font5x7.h"
  23. // The font library is stored in program memory:
  24. #include <avr/pgmspace.h>
  25. #include <string.h>
  26. /*
  27. * Constructor. Initializes the pins and the instance variables.
  28. */
  29. LedDisplay::LedDisplay(uint8_t _dataPin,
  30. uint8_t _registerSelect,
  31. uint8_t _clockPin,
  32. uint8_t _chipEnable,
  33. uint8_t _resetPin,
  34. uint8_t _displayLength)
  35. {
  36. // Define pins for the LED display:
  37. this->dataPin = _dataPin; // connects to the display's data in
  38. this->registerSelect = _registerSelect; // the display's register select pin
  39. this->clockPin = _clockPin; // the display's clock pin
  40. this->chipEnable = _chipEnable; // the display's chip enable pin
  41. this->resetPin = _resetPin; // the display's reset pin
  42. this->displayLength = _displayLength; // number of bytes needed to pad the string
  43. this->cursorPos = 0; // position of the cursor in the display
  44. // do not allow a long multiple display to use more than LEDDISPLAY_MAXCHARS
  45. if (_displayLength > LEDDISPLAY_MAXCHARS) {
  46. _displayLength = LEDDISPLAY_MAXCHARS;
  47. }
  48. // fill stringBuffer with spaces, and a trailing 0:
  49. for (unsigned int i = 0; i < sizeof(stringBuffer); i++) {
  50. stringBuffer[i] = ' ';
  51. }
  52. this->setString(stringBuffer); // give displayString a default buffer
  53. }
  54. /*
  55. * Initialize the display.
  56. */
  57. void LedDisplay::begin() {
  58. // set pin modes for connections:
  59. pinMode(dataPin, OUTPUT);
  60. pinMode(registerSelect, OUTPUT);
  61. pinMode(clockPin, OUTPUT);
  62. pinMode(chipEnable, OUTPUT);
  63. pinMode(resetPin, OUTPUT);
  64. // reset the display:
  65. digitalWrite(resetPin, LOW);
  66. delay(10);
  67. digitalWrite(resetPin, HIGH);
  68. // load dot register with lows
  69. loadDotRegister();
  70. // set control register 0 for max brightness, and no sleep:
  71. loadAllControlRegisters(B01111111);
  72. }
  73. /*
  74. * Clear the display
  75. */
  76. void LedDisplay::clear() {
  77. this->setString(stringBuffer);
  78. for (int displayPos = 0; displayPos < displayLength; displayPos++) {
  79. // put the character in the dot register:
  80. writeCharacter(' ', displayPos);
  81. }
  82. // send the dot register array out to the display:
  83. loadDotRegister();
  84. }
  85. /*
  86. * set the cursor to the home position (0)
  87. */
  88. void LedDisplay::home() {
  89. // set the cursor to the upper left corner:
  90. this->cursorPos = 0;
  91. }
  92. /*
  93. * set the cursor anywhere
  94. */
  95. void LedDisplay::setCursor(int whichPosition){
  96. this->cursorPos = whichPosition;
  97. }
  98. /*
  99. * return the cursor position
  100. */
  101. int LedDisplay::getCursor() {
  102. return this->cursorPos;
  103. }
  104. /*
  105. * write a byte out to the display at the cursor position,
  106. * and advance the cursor position.
  107. */
  108. #if ARDUINO >= 100
  109. size_t LedDisplay::write(uint8_t b) {
  110. #else
  111. void LedDisplay::write(uint8_t b) {
  112. #endif
  113. // make sure cursorPos is on the display:
  114. if (cursorPos >= 0 && cursorPos < displayLength) {
  115. // put the character into the dot register:
  116. writeCharacter(b, cursorPos);
  117. // put the character into the displayBuffer
  118. // but do not write the string constants pass
  119. // to us from the user by setString()
  120. if (this->displayString == stringBuffer && cursorPos < LEDDISPLAY_MAXCHARS) {
  121. stringBuffer[cursorPos] = b;
  122. }
  123. cursorPos++;
  124. // send the dot register array out to the display:
  125. loadDotRegister();
  126. }
  127. #if ARDUINO >= 100
  128. return 1;
  129. #endif
  130. }
  131. /*
  132. * Scroll the displayString across the display. left = -1, right = +1
  133. */
  134. void LedDisplay::scroll(int direction) {
  135. cursorPos += direction;
  136. // length of the string to display:
  137. int stringEnd = strlen(displayString);
  138. // Loop over the string and take displayLength characters to write to the display:
  139. for (int displayPos = 0; displayPos < displayLength; displayPos++) {
  140. // which character in the strings you want:
  141. int whichCharacter = displayPos - cursorPos;
  142. // which character you want to show from the string:
  143. char charToShow;
  144. // display the characters until you have no more:
  145. if ((whichCharacter >= 0) && (whichCharacter < stringEnd)) {
  146. charToShow = displayString[whichCharacter];
  147. } else {
  148. // if none of the above, show a space:
  149. charToShow = ' ';
  150. }
  151. // put the character in the dot register:
  152. writeCharacter(charToShow, displayPos);
  153. }
  154. // send the dot register array out to the display:
  155. loadDotRegister();
  156. }
  157. /*
  158. * set displayString
  159. */
  160. void LedDisplay::setString(const char * _displayString) {
  161. this->displayString = _displayString;
  162. }
  163. /*
  164. * return displayString
  165. */
  166. const char * LedDisplay::getString() {
  167. return displayString;
  168. }
  169. /*
  170. * return displayString length
  171. */
  172. int LedDisplay::stringLength() {
  173. return strlen(displayString);
  174. }
  175. /*
  176. * set brightness (0 - 15)
  177. */
  178. void LedDisplay::setBrightness(uint8_t bright)
  179. {
  180. // Limit the brightness
  181. if (bright > 15) {
  182. bright = 15;
  183. }
  184. // set the brightness:
  185. loadAllControlRegisters(B01110000 + bright);
  186. }
  187. /* this method loads bits into the dot register array. It doesn't
  188. * actually communicate with the display at all,
  189. * it just prepares the data:
  190. */
  191. void LedDisplay::writeCharacter(char whatCharacter, byte whatPosition) {
  192. // calculate the starting position in the array.
  193. // every character has 5 columns made of 8 bits:
  194. byte thisPosition = whatPosition * 5;
  195. // copy the appropriate bits into the dot register array:
  196. for (int i = 0; i < 5; i++) {
  197. dotRegister[thisPosition+i] = (pgm_read_byte(&Font5x7[((whatCharacter - 0x20) * 5) + i]));
  198. }
  199. }
  200. // This method sends 8 bits to one of the control registers:
  201. void LedDisplay::loadControlRegister(uint8_t dataByte) {
  202. // select the control registers:
  203. digitalWrite(registerSelect, HIGH);
  204. // enable writing to the display:
  205. digitalWrite(chipEnable, LOW);
  206. // shift the data out:
  207. shiftOut(dataPin, clockPin, MSBFIRST, dataByte);
  208. // disable writing:
  209. digitalWrite(chipEnable, HIGH);
  210. }
  211. // This method sends 8 bits to the control registers in all chips:
  212. void LedDisplay::loadAllControlRegisters(uint8_t dataByte) {
  213. // Each display can have more than one control chip, and displays
  214. // can be daisy-chained into long strings. For some operations, such
  215. // as setting the brightness, we need to ensure that a single
  216. // control word reaches all displays simultaneously. We do this by
  217. // putting each chip into simultaneous mode - effectively coupling
  218. // all their data-in pins together. (See section "Serial/Simultaneous
  219. // Data Output D0" in datasheet.)
  220. // One chip drives four characters, so we compute the number of
  221. // chips by diving by four:
  222. int chip_count = displayLength / 4;
  223. // For each chip in the chain, write the control word that will put
  224. // it into simultaneous mode (seriel mode is the power-up default).
  225. for (int i = 0; i < chip_count; i++) {
  226. loadControlRegister(B10000001);
  227. }
  228. // Load the specified value into the control register.
  229. loadControlRegister(dataByte);
  230. // Put all the chips back into serial mode. Because they're still
  231. // all in simultaneous mode, we only have to write this word once.
  232. loadControlRegister(B10000000);
  233. }
  234. // this method originally sent 320 bits to the dot register: 12_30_09 ML
  235. void LedDisplay::loadDotRegister() {
  236. // define max data to send, patch for 4 length displays by KaR]V[aN
  237. int maxData = displayLength * 5;
  238. // select the dot register:
  239. digitalWrite(registerSelect, LOW);
  240. // enable writing to the display:
  241. digitalWrite(chipEnable, LOW);
  242. // shift the data out:
  243. for (int i = 0; i < maxData; i++) {
  244. shiftOut(dataPin, clockPin, MSBFIRST, dotRegister[i]);
  245. }
  246. // disable writing:
  247. digitalWrite(chipEnable, HIGH);
  248. }
  249. /*
  250. version() returns the version of the library:
  251. */
  252. int LedDisplay::version(void)
  253. {
  254. return 4;
  255. }