This entry's latest version is outdated and must be revised. Please see the documentation for the latest API.

Midas I2C LCD Driver by Jason

Aug. 21, 2014   |   Snippet   |   Licensed as Apache 2.0   |   3480 views

Fewer wires, very fast, bus architecture. I2C seems to way to go. This code take a low cost Midas I2C and drives it via I2C. Initialise the LCD and ten clear it, home it, scroll it and print strings or characters to it. You can even set the location. All it uses is an I2C socket; I used socket 4 on my Spider. I hope to add further functions including custom characters in due course.

Comments or questions?   Discuss on the forum.



Author Version Date
Jason 2 08/21 '14 at 11:58am
Jason 1 08/21 '14 at 07:19am
1 — Source
  1. //////////////////////////////////////////////////////////////////////////////////////////////
  2. // This codes uses a Midas 2x16 I2C LCD connected, via an extended in //
  3. // socket 4 on my GHI Spider. //
  4. // The part is a Fanell 2063208 //
  5. // http://uk.farnell.com/midas/mccog21605b6w-sptlyi/lcd-cog-2x16-stn-grn-b-l-i2c/dp/2063208 //
  6. //////////////////////////////////////////////////////////////////////////////////////////////
  7. using System;
  8. using System.Collections;
  9. using System.Threading;
  10. using Microsoft.SPOT;
  11. using Microsoft.SPOT.Presentation;
  12. using Microsoft.SPOT.Presentation.Controls;
  13. using Microsoft.SPOT.Presentation.Media;
  14. using Microsoft.SPOT.Presentation.Shapes;
  15. using Microsoft.SPOT.Touch;
  16.  
  17. using Gadgeteer.Networking;
  18. using GT = Gadgeteer;
  19. using GTM = Gadgeteer.Modules;
  20. using Gadgeteer.Modules.GHIElectronics;
  21. using Microsoft.SPOT.Hardware;
  22. using System.Text;
  23. using Gadgeteer.Interfaces;
  24.  
  25. namespace I2CLCD
  26. {
  27. public partial class Program
  28. {
  29. // Midas I2C Commands
  30. private static byte MIDAS_ADDR = 0x3E;
  31. private static byte DISP_CMD = 0x00;
  32. private static byte FUNC_SET_TBL0 = 0x38; // Function 0
  33. private static byte FUNC_SET_TBL1 = 0x39; // Function 1
  34. private static byte SET_OSC = 0x14; // Set Bias 1/5
  35. private static byte SET_CONTRAST = 0x74; // Set contrast
  36. private static byte SET_ICON = 0x54; // Icon display
  37. private static byte SET_FOLLOWER = 0x6F; // FOllower circuit
  38. private static byte SET_DDRAM_CMD = 0x80;
  39. private static byte DISPLAY_ON = 0x0C;
  40. private static byte DISPLAY_OFF = 0x08;
  41. private static byte DISPLAY_HOME = 0x02;
  42. private static byte DISPLAY_CLEAR = 0x01;
  43. private static byte SHIFT_LEFT = 0x18;
  44. private static byte SHIFT_RIGHT = 0x1C;
  45. private static byte CURSOR_LEFT = 0x10;
  46. private static byte CURSOR_RIGHT = 0x14;
  47. private static byte CGRAM_BASE = 0x40;
  48. private static byte DATA_SEND = 0x40;
  49.  
  50. // I2C Configuration and Device variables
  51. private static I2CDevice I2C;
  52. private static I2CDevice.Configuration I2CConfig;
  53.  
  54. DigitalOutput backLight;
  55.  
  56. // This method is run when the mainboard is powered up or reset.
  57. void ProgramStarted()
  58. {
  59. Debug.Print("Program Started");
  60. InitialiseI2CLCD();
  61. Home();
  62.  
  63. LoadCustomCharacters();
  64.  
  65. //TextScrolling();
  66.  
  67. // Grow a shrink the first column bar
  68. SpecialCharacterDisplay();
  69. }
  70.  
  71. /// <summary>
  72. /// Initialise the Midas I2C 2x16 LCD
  73. /// </summary>
  74. private void InitialiseI2CLCD()
  75. {
  76. // Setup a digital pin to control the back light
  77. backLight = extender.SetupDigitalOutput(GT.Socket.Pin.Three, true);
  78.  
  79. try
  80. {
  81. // Setup the I2C bus
  82. I2CConfig = new I2CDevice.Configuration(MIDAS_ADDR, 380);
  83. I2C = new I2CDevice(I2CConfig);
  84. // Send the initialisation string
  85. //WriteI2C(new byte[] {FUNC_SET_TBL0, FUNC_SET_TBL1, SET_OSC, SET_CONTRAST, SET_ICON, SET_FOLLOWER, DISPLAY_ON, DISPLAY_CLEAR, FUNC_SET_TBL0 });
  86. WriteI2C(new byte[] { FUNC_SET_TBL1, SET_OSC, SET_CONTRAST, SET_ICON, SET_FOLLOWER, DISPLAY_ON, DISPLAY_CLEAR });
  87. Thread.Sleep(100);
  88. WriteI2C(FUNC_SET_TBL0);
  89. Thread.Sleep(100);
  90. }
  91. catch (Exception ex)
  92. {
  93. Debug.Print(ex.Message);
  94. }
  95. }
  96.  
  97.  
  98. #region Custom Characters
  99.  
  100. private void LoadCustomCharacters()
  101. {
  102. CreateSpecialChar(0x00, new byte[] { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff });
  103. CreateSpecialChar(0x08, new byte[] { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff });
  104. CreateSpecialChar(0x10, new byte[] { 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff });
  105. CreateSpecialChar(0x18, new byte[] { 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff });
  106. CreateSpecialChar(0x20, new byte[] { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff });
  107. CreateSpecialChar(0x28, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff });
  108. CreateSpecialChar(0x30, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff });
  109. CreateSpecialChar(0x38, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff });
  110. }
  111.  
  112. private void SpecialCharacterDisplay()
  113. {
  114. Thread myThreadHandler;
  115. myThreadHandler = new Thread(SpecialCharacterThread);
  116. myThreadHandler.Start();
  117. }
  118.  
  119. private void SpecialCharacterThread()
  120. {
  121. // Continuously scroll through each custom character at column zero to elumate a move bar.
  122. while (true)
  123. {
  124. byte row = 0;
  125.  
  126. SetCursor(row, 0);
  127. Print(0x20);
  128. SetCursor(0, 0);
  129. Print(0x20);
  130. Thread.Sleep(100);
  131. row = 1;
  132.  
  133. for(int x = 0; x <2; x++)
  134. {
  135. SetCursor(row, 0);
  136. Print(0x07);
  137. Thread.Sleep(100);
  138. SetCursor(row, 0);
  139. Print(0x06);
  140. Thread.Sleep(100);
  141. SetCursor(row, 0);
  142. Print(0x05);
  143. Thread.Sleep(100);
  144. SetCursor(row, 0);
  145. Print(0x04);
  146. Thread.Sleep(100);
  147. SetCursor(row, 0);
  148. Print(0x03);
  149. Thread.Sleep(100);
  150. SetCursor(row, 0);
  151. Print(0x02);
  152. Thread.Sleep(100);
  153. SetCursor(row, 0);
  154. Print(0x01);
  155. Thread.Sleep(100);
  156. SetCursor(row, 0);
  157. Print(0x00);
  158. Thread.Sleep(100);
  159.  
  160. row = 0;
  161. }
  162.  
  163. for (int x = 0; x < 2; x++)
  164. {
  165. SetCursor(row, 0);
  166. Print(0x01);
  167. Thread.Sleep(100);
  168. SetCursor(row, 0);
  169. Print(0x02);
  170. Thread.Sleep(100);
  171. SetCursor(row, 0);
  172. Print(0x03);
  173. Thread.Sleep(100);
  174. SetCursor(row, 0);
  175. Print(0x04);
  176. Thread.Sleep(100);
  177. SetCursor(row, 0);
  178. Print(0x05);
  179. Thread.Sleep(100);
  180. SetCursor(row, 0);
  181. Print(0x06);
  182. Thread.Sleep(100);
  183. SetCursor(row, 0);
  184. Print(0x07);
  185. Thread.Sleep(100);
  186. SetCursor(row, 0);
  187. Print(0x20);
  188. Thread.Sleep(100);
  189.  
  190. row = 1;
  191. }
  192.  
  193.  
  194. }
  195.  
  196. }
  197.  
  198.  
  199. #endregion
  200.  
  201.  
  202. #region Text Scrolling Thread
  203.  
  204. private void TextScrolling()
  205. {
  206. Thread myThreadHandler;
  207. myThreadHandler = new Thread(ScrollThread);
  208. myThreadHandler.Start();
  209. }
  210.  
  211. public void ScrollThread()
  212. {
  213. SetCursor(0, 3);
  214. Print('I');
  215. Thread.Sleep(100);
  216. Print('2');
  217. Thread.Sleep(100);
  218. Print('C');
  219. Thread.Sleep(100);
  220. Print(' ');
  221. Thread.Sleep(100);
  222. Print('R');
  223. Thread.Sleep(100);
  224. Print('o');
  225. Thread.Sleep(100);
  226. Print('c');
  227. Thread.Sleep(100);
  228. Print('k');
  229. Thread.Sleep(100);
  230. Print('s');
  231. Thread.Sleep(100);
  232. Print('!');
  233. Thread.Sleep(100);
  234. Print('!');
  235. Thread.Sleep(100);
  236.  
  237. for (int n = 0; n < 13; n++)
  238. {
  239. Thread.Sleep(250);
  240. ShiftRight();
  241. }
  242.  
  243.  
  244. for (int n = 0; n < 13;n++ )
  245. {
  246. Thread.Sleep(250);
  247. ShiftLeft();
  248. }
  249.  
  250. Thread.Sleep(350);
  251. DisplayOff();
  252. Thread.Sleep(350);
  253. DisplayOn();
  254. Thread.Sleep(350);
  255. DisplayOff();
  256. Thread.Sleep(350);
  257. DisplayOn();
  258. Thread.Sleep(350);
  259. DisplayOff();
  260. Thread.Sleep(350);
  261. DisplayOn();
  262. Thread.Sleep(350);
  263.  
  264. Home();
  265. Print("ABCDEFGHIJKLMNOP");
  266. SetCursor(1, 0);
  267. Print("QRSTUVWXYZ012345");
  268. Thread.Sleep(1000);
  269.  
  270. Clear();
  271. Print("Waiting");
  272. for(int n =0; n<5; n++)
  273. {
  274. SetCursor(0, 7);
  275. Print(".");
  276. Thread.Sleep(200);
  277. SetCursor(0, 8);
  278. Print(".");
  279. Thread.Sleep(200);
  280. SetCursor(0, 9);
  281. Print(".");
  282. Thread.Sleep(200);
  283. SetCursor(0, 9);
  284. Print(" ");
  285. Thread.Sleep(200);
  286. SetCursor(0, 8);
  287. Print(" ");
  288. Thread.Sleep(200);
  289. SetCursor(0, 7);
  290. Print(" ");
  291. Thread.Sleep(200);
  292. }
  293.  
  294. Clear();
  295. Home();
  296. SetCursor(0,5);
  297. Print("NETMF");
  298. SetCursor(1, 3);
  299. Print("Gadgeteer.");
  300. }
  301.  
  302. #endregion
  303.  
  304. /// <summary>
  305. /// Create a custom character in a CGRAM address (Valid Addresses are 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30 and 0x38 only)
  306. /// </summary>
  307. /// <param name="addr">Address</param>
  308. /// <param name="bitPattern">Byte array containing bit pattern</param>
  309. public void CreateSpecialChar(byte addr, byte[] bitPattern)
  310. {
  311. var xActions = new I2CDevice.I2CTransaction[1];
  312. xActions[0] = I2CDevice.CreateWriteTransaction(new byte[] { FUNC_SET_TBL0, (byte)(CGRAM_BASE + addr) });
  313. I2C.Execute(xActions, 100);
  314. Thread.Sleep(10);
  315.  
  316. xActions[0] = I2CDevice.CreateWriteTransaction(new byte[] { DATA_SEND, bitPattern[0], bitPattern[1], bitPattern[2], bitPattern[3], bitPattern[4], bitPattern[5], bitPattern[6], bitPattern[7] });
  317. I2C.Execute(xActions, 100);
  318. Thread.Sleep(100);
  319.  
  320. xActions[0] = I2CDevice.CreateWriteTransaction(new byte[] { FUNC_SET_TBL1, DISPLAY_CLEAR });
  321. I2C.Execute(xActions, 100);
  322. Thread.Sleep(100);
  323. }
  324.  
  325.  
  326. /// <summary>
  327. /// Send an array of bytes over I2C
  328. /// </summary>
  329. /// <param name="command">The byte array to send</param>
  330. private void WriteI2C(byte[] command)
  331. {
  332. var xActions = new I2CDevice.I2CTransaction[1];
  333. byte[] buffer = new byte[command.Length + 1];
  334. buffer[0] = DISP_CMD;
  335. for (int thisByte = 0; thisByte < command.Length; thisByte++)
  336. {
  337. buffer[thisByte + 1] = command[thisByte];
  338. }
  339. xActions[0] = I2CDevice.CreateWriteTransaction(buffer);
  340. I2C.Execute(xActions, 1000);
  341. }
  342.  
  343. /// <summary>
  344. /// Send a single byte command over I2C
  345. /// </summary>
  346. /// <param name="command">The byte command to send</param>
  347. private void WriteI2C(byte command)
  348. {
  349. WriteI2C(new byte[] { command });
  350. }
  351.  
  352. /// <summary>
  353. /// Print a string at the current cursor position. Note, the function will move the cursor position
  354. /// </summary>
  355. /// <param name="text">The text to print</param>
  356. public void Print(string text)
  357. {
  358. // Encode the string
  359. byte[] buf = Encoding.UTF8.GetBytes(text);
  360. // Create a new array to include the header
  361. byte[] header = new byte[buf.Length + 1];
  362. header[0] = DATA_SEND;
  363. Array.Copy(buf, 0, header, 1, buf.Length);
  364.  
  365. var xActions = new I2CDevice.I2CTransaction[1];
  366. xActions[0] = I2CDevice.CreateWriteTransaction(header);
  367. I2C.Execute(xActions, 100);
  368. }
  369.  
  370. /// <summary>
  371. /// Print a string at the current cursor position. Note, the function will move the cursor position
  372. /// </summary>
  373. /// <param name="characters">The byte array to display</param>
  374. public void Print(byte[] characters)
  375. {
  376. // Create a new array to include the header
  377. byte[] header = new byte[characters.Length + 1];
  378. header[0] = DATA_SEND;
  379. Array.Copy(characters, 0, header, 1, characters.Length);
  380.  
  381. var xActions = new I2CDevice.I2CTransaction[1];
  382. xActions[0] = I2CDevice.CreateWriteTransaction(header);
  383. I2C.Execute(xActions, 100);
  384. }
  385.  
  386. /// <summary>
  387. /// Print a string at the current cursor position. Note, the function will move the cursor position
  388. /// </summary>
  389. /// <param name="byte">The byte to display</param>
  390. public void Print(byte character)
  391. {
  392. // Create a new array to include the header
  393. byte[] header = new byte[] { DATA_SEND, character };
  394.  
  395. var xActions = new I2CDevice.I2CTransaction[1];
  396. xActions[0] = I2CDevice.CreateWriteTransaction(header);
  397. I2C.Execute(xActions, 100);
  398. }
  399.  
  400.  
  401. /// <summary>
  402. /// Print a character at the current cursor position. Note, the function will move the cursor position
  403. /// </summary>
  404. /// <param name="character"></param>
  405. public void Print(char character)
  406. {
  407. Print(character.ToString());
  408. }
  409.  
  410. /// <summary>
  411. /// Set the cursor position with the top left being (0,0)
  412. /// </summary>
  413. /// <param name="row">The required row, starting at 0</param>
  414. /// <param name="column">The required column, starting at 0</param>
  415. public void SetCursor(byte row, byte column)
  416. {
  417. byte position = SET_DDRAM_CMD;
  418. byte rowValue = 0;
  419. if (row == 1)
  420. rowValue = 0x40;
  421. position = (byte)(position + rowValue + column);
  422. WriteI2C(position);
  423. }
  424.  
  425. /// <summary>
  426. /// Shift the display one position to the left;
  427. /// </summary>
  428. private void ShiftLeft()
  429. {
  430. WriteI2C(SHIFT_LEFT);
  431. }
  432.  
  433. /// <summary>
  434. /// Shift the display one position to the left;
  435. /// </summary>
  436. private void ShiftRight()
  437. {
  438. WriteI2C(SHIFT_RIGHT);
  439. }
  440.  
  441. /// <summary>
  442. /// Shift the cursor one position to the left;
  443. /// </summary>
  444. private void CursorLeft()
  445. {
  446. WriteI2C(CURSOR_LEFT);
  447. }
  448.  
  449. /// <summary>
  450. /// Shift the cursor one position to the left;
  451. /// </summary>
  452. private void CursorRight()
  453. {
  454. WriteI2C(CURSOR_RIGHT);
  455. }
  456.  
  457. /// <summary>
  458. /// Send the cursors to the home (0,0) position
  459. /// </summary>
  460. public void Home()
  461. {
  462. WriteI2C(DISPLAY_HOME);
  463. }
  464.  
  465. /// <summary>
  466. /// Clear the display
  467. /// </summary>
  468. public void Clear()
  469. {
  470. WriteI2C(DISPLAY_CLEAR);
  471. }
  472.  
  473. /// <summary>
  474. /// Turn the display on
  475. /// </summary>
  476. public void DisplayOn()
  477. {
  478. WriteI2C(DISPLAY_ON);
  479. }
  480.  
  481. // Turn the display off
  482. public void DisplayOff()
  483. {
  484. WriteI2C(DISPLAY_OFF);
  485. }
  486.  
  487. public void CursorOn()
  488. {
  489. // To be implemented
  490. }
  491.  
  492. public void CursorOff()
  493. {
  494. // To be implemented
  495. }
  496.  
  497. public void BlinkOn()
  498. {
  499. // To be implemented
  500. }
  501.  
  502. public void BlinkOff()
  503. {
  504. // To be implemented
  505. }
  506.  
  507. public void BacklightOn()
  508. {
  509. backLight.Write(true);
  510. }
  511.  
  512. public void BacklightOff()
  513. {
  514. backLight.Write(false);
  515. }
  516. }
  517. }