Advertisement
Iv4n

LCD Buses + Weather Report

Jan 13th, 2014
636
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 19.92 KB | None | 0 0
  1. #define ARDUINO_H
  2. #include <stdint.h>
  3. #include <stddef.h>
  4. #include <stdlib.h>
  5. #include "application.h"
  6. #include <time.h>
  7. #ifndef LiquidCrystal_I2C_h
  8. #define LiquidCrystal_I2C_h
  9.  
  10. #define LCD_CLEARDISPLAY 0x01
  11. #define LCD_RETURNHOME 0x02
  12. #define LCD_ENTRYMODESET 0x04
  13. #define LCD_DISPLAYCONTROL 0x08
  14. #define LCD_CURSORSHIFT 0x10
  15. #define LCD_FUNCTIONSET 0x20
  16. #define LCD_SETCGRAMADDR 0x40
  17. #define LCD_SETDDRAMADDR 0x80
  18.  
  19. #define LCD_ENTRYRIGHT 0x00
  20. #define LCD_ENTRYLEFT 0x02
  21. #define LCD_ENTRYSHIFTINCREMENT 0x01
  22. #define LCD_ENTRYSHIFTDECREMENT 0x00
  23.  
  24. // flags for display on/off control
  25. #define LCD_DISPLAYON 0x04
  26. #define LCD_DISPLAYOFF 0x00
  27. #define LCD_CURSORON 0x02
  28. #define LCD_CURSOROFF 0x00
  29. #define LCD_BLINKON 0x01
  30. #define LCD_BLINKOFF 0x00
  31.  
  32. // flags for display/cursor shift
  33. #define LCD_DISPLAYMOVE 0x08
  34. #define LCD_CURSORMOVE 0x00
  35. #define LCD_MOVERIGHT 0x04
  36. #define LCD_MOVELEFT 0x00
  37.  
  38. // flags for function set
  39. #define LCD_8BITMODE 0x10
  40. #define LCD_4BITMODE 0x00
  41. #define LCD_2LINE 0x08
  42. #define LCD_1LINE 0x00
  43. #define LCD_5x10DOTS 0x04
  44. #define LCD_5x8DOTS 0x00
  45.  
  46. // flags for backlight control
  47. #define LCD_BACKLIGHT 0x08
  48. #define LCD_NOBACKLIGHT 0x00
  49.  
  50. //#define En B00000100  // Enable bit
  51. //#define Rw B00000010  // Read/Write bit
  52. //#define Rs B00000001  // Register select bit
  53.  
  54. class LiquidCrystal_I2C : public Print {
  55. public:
  56.   LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows);
  57.   void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS );
  58.   void clear();
  59.   void home();
  60.   void noDisplay();
  61.   void display();
  62.   void noBlink();
  63.   void blink();
  64.   void noCursor();
  65.   void cursor();
  66.   void scrollDisplayLeft();
  67.   void scrollDisplayRight();
  68.   void printLeft();
  69.   void printRight();
  70.   void leftToRight();
  71.   void rightToLeft();
  72.   void shiftIncrement();
  73.   void shiftDecrement();
  74.   void noBacklight();
  75.   void backlight();
  76.   void autoscroll();
  77.   void noAutoscroll();
  78.   void createChar(uint8_t, uint8_t[]);
  79.   void setCursor(uint8_t, uint8_t);
  80.   virtual size_t write(uint8_t); //changed to size_t
  81.   void command(uint8_t);
  82.   void init();
  83.  
  84. ////compatibility API function aliases
  85. void blink_on();            // alias for blink()
  86. void blink_off();                 // alias for noBlink()
  87. void cursor_on();                 // alias for cursor()
  88. void cursor_off();                // alias for noCursor()
  89. void setBacklight(uint8_t new_val);       // alias for backlight() and nobacklight()
  90. void load_custom_character(uint8_t char_num, uint8_t *rows);  // alias for createChar()
  91. void printstr(const char[]);
  92.  
  93. ////Unsupported API functions (not implemented in this library)
  94. uint8_t status();
  95. void setContrast(uint8_t new_val);
  96. uint8_t keypad();
  97. void setDelay(int,int);
  98. void on();
  99. void off();
  100. uint8_t init_bargraph(uint8_t graphtype);
  101. void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len,  uint8_t pixel_col_end);
  102. void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len,  uint8_t pixel_col_end);
  103.    
  104.  
  105. private:
  106.   void init_priv();
  107.   void send(uint8_t, uint8_t);
  108.   void write4bits(uint8_t);
  109.   void expanderWrite(uint8_t);
  110.   void pulseEnable(uint8_t);
  111.   uint8_t _Addr;
  112.   uint8_t _displayfunction;
  113.   uint8_t _displaycontrol;
  114.   uint8_t _displaymode;
  115.   uint8_t _numlines;
  116.   uint8_t _cols;
  117.   uint8_t _rows;
  118.   uint8_t _backlightval;
  119. };
  120.  
  121. #endif
  122. // LiquidCrystal_I2C V2.0
  123.  
  124. // When the display powers up, it is configured as follows:
  125. //
  126. // 1. Display clear
  127. // 2. Function set:
  128. //    DL = 1; 8-bit interface data
  129. //    N = 0; 1-line display
  130. //    F = 0; 5x8 dot character font
  131. // 3. Display on/off control:
  132. //    D = 0; Display off
  133. //    C = 0; Cursor off
  134. //    B = 0; Blinking off
  135. // 4. Entry mode set:
  136. //    I/D = 1; Increment by 1
  137. //    S = 0; No shift
  138. //
  139. // Note, however, that resetting the Arduino doesn't reset the LCD, so we
  140. // can't assume that its in that state when a sketch starts (and the
  141. // LiquidCrystal constructor is called).
  142.  
  143. LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows)
  144. {
  145.   _Addr = lcd_Addr;
  146.   _cols = lcd_cols;
  147.   _rows = lcd_rows;
  148.   _backlightval = LCD_NOBACKLIGHT;
  149. }
  150.  
  151. void LiquidCrystal_I2C::init(){
  152.     init_priv();
  153. }
  154.  
  155. void LiquidCrystal_I2C::init_priv()
  156. {
  157.     Wire.begin();
  158.     _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
  159.     begin(_cols, _rows);  
  160. }
  161.  
  162. void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
  163.     if (lines > 1) {
  164.         _displayfunction |= LCD_2LINE;
  165.     }
  166.     _numlines = lines;
  167.  
  168.     // for some 1 line displays you can select a 10 pixel high font
  169.     if ((dotsize != 0) && (lines == 1)) {
  170.         _displayfunction |= LCD_5x10DOTS;
  171.     }
  172.  
  173.     // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
  174.     // according to datasheet, we need at least 40ms after power rises above 2.7V
  175.     // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
  176.     delay(50);
  177.  
  178.     // Now we pull both RS and R/W low to begin commands
  179.     expanderWrite(_backlightval);   // reset expanderand turn backlight off (Bit 8 =1)
  180.     delay(1000);
  181.  
  182.     //put the LCD into 4 bit mode
  183.     // this is according to the hitachi HD44780 datasheet
  184.     // figure 24, pg 46
  185.    
  186.       // we start in 8bit mode, try to set 4 bit mode
  187.    write4bits(0x03 << 4);
  188.    delayMicroseconds(4500); // wait min 4.1ms
  189.    
  190.    // second try
  191.    write4bits(0x03 << 4);
  192.    delayMicroseconds(4500); // wait min 4.1ms
  193.    
  194.    // third go!
  195.    write4bits(0x03 << 4);
  196.    delayMicroseconds(150);
  197.    
  198.    // finally, set to 4-bit interface
  199.    write4bits(0x02 << 4);
  200.  
  201.  
  202.  
  203.     // set # lines, font size, etc.
  204.     command(LCD_FUNCTIONSET | _displayfunction);  
  205.    
  206.     // turn the display on with no cursor or blinking default
  207.     _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
  208.     display();
  209.    
  210.     // clear it off
  211.     clear();
  212.    
  213.     // Initialize to default text direction (for roman languages)
  214.     _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
  215.    
  216.     // set the entry mode
  217.     command(LCD_ENTRYMODESET | _displaymode);
  218.    
  219.     home();
  220.  
  221. }
  222.  
  223.  
  224.  
  225. /********** high level commands, for the user! */
  226. void LiquidCrystal_I2C::clear(){
  227.     command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero
  228.     delayMicroseconds(2000);  // this command takes a long time!
  229. }
  230.  
  231. void LiquidCrystal_I2C::home(){
  232.     command(LCD_RETURNHOME);  // set cursor position to zero
  233.     delayMicroseconds(2000);  // this command takes a long time!
  234. }
  235.  
  236. void LiquidCrystal_I2C::setCursor(uint8_t col, uint8_t row){
  237.     int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
  238.     if ( row > _numlines ) {
  239.         row = _numlines-1;    // we count rows starting w/0
  240.     }
  241.     command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
  242. }
  243.  
  244. // Turn the display on/off (quickly)
  245. void LiquidCrystal_I2C::noDisplay() {
  246.     _displaycontrol &= ~LCD_DISPLAYON;
  247.     command(LCD_DISPLAYCONTROL | _displaycontrol);
  248. }
  249. void LiquidCrystal_I2C::display() {
  250.     _displaycontrol |= LCD_DISPLAYON;
  251.     command(LCD_DISPLAYCONTROL | _displaycontrol);
  252. }
  253.  
  254. // Turns the underline cursor on/off
  255. void LiquidCrystal_I2C::noCursor() {
  256.     _displaycontrol &= ~LCD_CURSORON;
  257.     command(LCD_DISPLAYCONTROL | _displaycontrol);
  258. }
  259. void LiquidCrystal_I2C::cursor() {
  260.     _displaycontrol |= LCD_CURSORON;
  261.     command(LCD_DISPLAYCONTROL | _displaycontrol);
  262. }
  263.  
  264. // Turn on and off the blinking cursor
  265. void LiquidCrystal_I2C::noBlink() {
  266.     _displaycontrol &= ~LCD_BLINKON;
  267.     command(LCD_DISPLAYCONTROL | _displaycontrol);
  268. }
  269. void LiquidCrystal_I2C::blink() {
  270.     _displaycontrol |= LCD_BLINKON;
  271.     command(LCD_DISPLAYCONTROL | _displaycontrol);
  272. }
  273.  
  274. // These commands scroll the display without changing the RAM
  275. void LiquidCrystal_I2C::scrollDisplayLeft(void) {
  276.     command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
  277. }
  278. void LiquidCrystal_I2C::scrollDisplayRight(void) {
  279.     command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
  280. }
  281.  
  282. // This is for text that flows Left to Right
  283. void LiquidCrystal_I2C::leftToRight(void) {
  284.     _displaymode |= LCD_ENTRYLEFT;
  285.     command(LCD_ENTRYMODESET | _displaymode);
  286. }
  287.  
  288. // This is for text that flows Right to Left
  289. void LiquidCrystal_I2C::rightToLeft(void) {
  290.     _displaymode &= ~LCD_ENTRYLEFT;
  291.     command(LCD_ENTRYMODESET | _displaymode);
  292. }
  293.  
  294. // This will 'right justify' text from the cursor
  295. void LiquidCrystal_I2C::autoscroll(void) {
  296.     _displaymode |= LCD_ENTRYSHIFTINCREMENT;
  297.     command(LCD_ENTRYMODESET | _displaymode);
  298. }
  299.  
  300. // This will 'left justify' text from the cursor
  301. void LiquidCrystal_I2C::noAutoscroll(void) {
  302.     _displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
  303.     command(LCD_ENTRYMODESET | _displaymode);
  304. }
  305.  
  306. // Allows us to fill the first 8 CGRAM locations
  307. // with custom characters
  308. void LiquidCrystal_I2C::createChar(uint8_t location, uint8_t charmap[]) {
  309.     location &= 0x7; // we only have 8 locations 0-7
  310.     command(LCD_SETCGRAMADDR | (location << 3));
  311.     for (int i=0; i<8; i++) {
  312.         write(charmap[i]);
  313.     }
  314. }
  315.  
  316. // Turn the (optional) backlight off/on
  317. void LiquidCrystal_I2C::noBacklight(void) {
  318.     _backlightval=LCD_NOBACKLIGHT;
  319.     expanderWrite(0);
  320. }
  321.  
  322. void LiquidCrystal_I2C::backlight(void) {
  323.     _backlightval=LCD_BACKLIGHT;
  324.     expanderWrite(0);
  325. }
  326.  
  327.  
  328.  
  329. /*********** mid level commands, for sending data/cmds */
  330.  
  331. inline void LiquidCrystal_I2C::command(uint8_t value) {
  332.     send(value, 0);
  333. }
  334.  
  335. inline size_t LiquidCrystal_I2C::write(uint8_t value) {
  336.     send(value, 1);
  337.     return 0;
  338. }
  339.  
  340.  
  341.  
  342.  
  343.  
  344. /************ low level data pushing commands **********/
  345.  
  346. // write either command or data
  347. void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) {
  348.     uint8_t highnib=value&0xf0;
  349.     uint8_t lownib=(value<<4)&0xf0;
  350.        write4bits((highnib)|mode);
  351.     write4bits((lownib)|mode);
  352. }
  353.  
  354. void LiquidCrystal_I2C::write4bits(uint8_t value) {
  355.     expanderWrite(value);
  356.     pulseEnable(value);
  357. }
  358.  
  359. void LiquidCrystal_I2C::expanderWrite(uint8_t _data){                                        
  360.     Wire.beginTransmission(_Addr);
  361.     Wire.write((int)(_data) | _backlightval);
  362.     Wire.endTransmission();  
  363.     }
  364.  
  365. void LiquidCrystal_I2C::pulseEnable(uint8_t _data){
  366.     expanderWrite(_data | (1<<2));  // En high
  367.     delayMicroseconds(1);       // enable pulse must be >450ns
  368.    
  369.     expanderWrite(_data & ~(1<<2)); // En low
  370.     delayMicroseconds(50);      // commands need > 37us to settle
  371. }
  372.  
  373.  
  374. // Alias functions
  375.  
  376. void LiquidCrystal_I2C::cursor_on(){
  377.     cursor();
  378. }
  379.  
  380. void LiquidCrystal_I2C::cursor_off(){
  381.     noCursor();
  382. }
  383.  
  384. void LiquidCrystal_I2C::blink_on(){
  385.     blink();
  386. }
  387.  
  388. void LiquidCrystal_I2C::blink_off(){
  389.     noBlink();
  390. }
  391.  
  392. void LiquidCrystal_I2C::load_custom_character(uint8_t char_num, uint8_t *rows){
  393.         createChar(char_num, rows);
  394. }
  395.  
  396. void LiquidCrystal_I2C::setBacklight(uint8_t new_val){
  397.     if(new_val){
  398.         backlight();        // turn backlight on
  399.     }else{
  400.         noBacklight();      // turn backlight off
  401.     }
  402. }
  403.  
  404. void LiquidCrystal_I2C::printstr(const char c[]){
  405.     //This function is not identical to the function used for "real" I2C displays
  406.     //it's here so the user sketch doesn't have to be changed
  407.     print(c);
  408. }
  409.  
  410.  
  411. // unsupported API functions
  412. void LiquidCrystal_I2C::off(){}
  413. void LiquidCrystal_I2C::on(){}
  414. void LiquidCrystal_I2C::setDelay (int cmdDelay,int charDelay) {}
  415. uint8_t LiquidCrystal_I2C::status(){return 0;}
  416. uint8_t LiquidCrystal_I2C::keypad (){return 0;}
  417. uint8_t LiquidCrystal_I2C::init_bargraph(uint8_t graphtype){return 0;}
  418. void LiquidCrystal_I2C::draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len,  uint8_t pixel_col_end){}
  419. void LiquidCrystal_I2C::draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len,  uint8_t pixel_row_end){}
  420. void LiquidCrystal_I2C::setContrast(uint8_t new_val){}
  421.  
  422.  
  423. LiquidCrystal_I2C   *lcd;
  424. String              line[4];
  425. unsigned int        LineScroll[4] = {0, 0, 0, 0};
  426. unsigned long       LastTime = 0;
  427. unsigned long       refreshTime = 0;
  428. unsigned long       LastScroll = 0;
  429. unsigned long       TimeDiff = 0;
  430. bool                busMultineLine = false;
  431. long timestamp = 0;
  432.  
  433. String http_get(const char* hostname, String path);
  434. long currentTimeMilis();
  435.  
  436. // ------------- HTTP functions --------------
  437.  
  438. /**
  439.  * make http request and return body
  440.  */
  441. TCPClient client;
  442. char buffer[1024];
  443. String http_get(char const* hostname, String path) {
  444.  
  445.         if (client.connect(hostname, 80)) {
  446.                 client.print("GET ");
  447.                 client.print(path);
  448.                 client.print(" HTTP/1.0\n");
  449.                 client.print("HOST: ");
  450.                 client.println(hostname);
  451.                 client.print("\n");
  452.                 //        client.print("Connection: close\n\n");
  453.                 client.flush();
  454.         } else {
  455.                 Serial.println("connection failed");
  456.                 client.stop();
  457.                 return NULL;
  458.         }
  459.  
  460.         // Block until first byte is read.
  461.         client.read();
  462.         for (unsigned int i = 0; i < sizeof(buffer) && client.available(); i++) {
  463.                 char c = client.read();
  464.                 if (c == -1) {
  465.                         break;
  466.                 }
  467.                 buffer[i] = c;
  468.         }
  469.         client.stop();
  470.  
  471.         String response(buffer);
  472.         int bodyPos = response.indexOf("\r\n\r\n");
  473.         if (bodyPos == -1) {
  474.                 Serial.println("can not find http reponse body");
  475.                                 return NULL;
  476.         }
  477.         return response.substring(bodyPos+4);
  478. }
  479.  
  480.  
  481.  
  482. // ------------- DATE / TIME functions --------------
  483. /**
  484.  * parse a string of the form "2014-01-11T17:17:59+0200"
  485.  */
  486. long parseDate(String str) {
  487.         // make sure it works with UTC
  488.         //tzset();  // recognize TZ
  489.         // sy/11.Jan.2014: Not sure if setenv works at all...
  490.  
  491.         // parse date
  492.         struct tm time;
  493.         strptime(str.c_str(), "%Y-%m-%dT%H:%M:%S", &time);
  494.         return (long) mktime(&time); //timegm should be used, but is not available
  495. }
  496.  
  497. /**
  498.  * can parse the timezone offset in the string "2014-01-11T17:17:59+0100"
  499.  */
  500. long parseTzOffset(String str) {
  501.         // strptime currently does not parse the timezone with %z, so we do it ourself:
  502.         // parse 3 digits the "+0100" which result in 1 hour.
  503.         int offsetHours;
  504.         sscanf(str.c_str(), "%*19s%3d", &offsetHours);
  505.         return offsetHours * 3600;
  506. }
  507.  
  508. /**
  509.  * returns current time in milisceconds, from a http server.
  510.  */
  511. long currentTimeMilis() {
  512.         Serial.println("getting current time");
  513.  
  514.         String response = http_get("www.timeapi.org", "/utc/now");
  515.         if (response != NULL) {
  516.                 Serial.print("time=");
  517.                 Serial.println(response);
  518.                 return parseDate(response);
  519.         } else {
  520.                 return 0;
  521.         }
  522. }
  523. void setup()
  524. {
  525.     lcd = new LiquidCrystal_I2C(0x4E, 20, 4);  // set the LCD address to 0x20 for a 16x2 //SparkCore bug, address is actually 27 but shifted (0x27*2)
  526.     Spark.function("lcd1", line_one);
  527.     Spark.function("lcd2", line_two);
  528.     Spark.function("lcd3", line_three);
  529.     Spark.function("lcd4", line_four);
  530.     RGB.control(true);
  531.     RGB.color(20, 0, 0);
  532.     lcd->init();                      // initialize the lcd
  533.     lcd->backlight();
  534.     line[0] = "";
  535.     line[1] = "";
  536.     line[2] = "";
  537.     line[3] = "....";
  538.     lcd->print(".");
  539.     LastTime = millis();
  540.     LastScroll = millis();
  541.     for (unsigned int linePos=0;linePos<4;linePos++) {
  542.         lcd->setCursor(0,linePos);
  543.         for (unsigned int charPos=0;charPos<20;charPos++) {
  544.             if (line[linePos].length() > charPos) lcd->print(line[linePos][charPos]);
  545.             else lcd->print(" ");
  546.         }
  547.     }
  548. }
  549.  
  550. int line_one(String command)
  551. {
  552.     //this line has the ability to wrap to the second one, so they remain static, with this, the time will be gone
  553.     bool eraseLine2 = false;
  554.     int line_index = 0;
  555.     LineScroll[line_index] = 0;
  556.     command.replace("%20", " ");
  557.     if (busMultineLine) {
  558.         if (command.length() > 19) {
  559.             int splitAt;
  560.             line[line_index] = "";
  561.             for (splitAt=0; splitAt < 20; splitAt++) {
  562.                 if (splitAt > 13 && command[splitAt] == ' ') {
  563.                     break;
  564.                 }
  565.                 line[line_index] += command[splitAt];
  566.             }
  567.             line[line_index + 1] = "";
  568.             for (unsigned int x=0; x < 20 && command.length() > (splitAt + x); x++) {
  569.                 if (!(x < 2 && (command[splitAt + x] == ' ' || command[splitAt + x] == ','))) {
  570.                     line[line_index + 1] += command[splitAt + x];
  571.                 }
  572.             }
  573.         } else {
  574.             line[line_index] = command;
  575.             line[line_index + 1] = "";
  576.             eraseLine2 = true;
  577.         }
  578.     } else {
  579.         line[line_index] = command;
  580.         line[line_index + 1] = "";
  581.         eraseLine2 = true;
  582.     }
  583.     lcd->setCursor(0, line_index);
  584.     for (unsigned int x=0; x < 20; x++) {
  585.         if (line[line_index].length() > x) lcd->print(line[line_index][x]);
  586.         else lcd->print(" ");
  587.     }
  588.     if (eraseLine2) {
  589.         lcd->setCursor(0, line_index + 1);
  590.         for (unsigned int x=0; x < 20; x++) {
  591.             if (line[line_index+1].length() > x) lcd->print(line[line_index+1][x]);
  592.             else lcd->print(" ");
  593.         }
  594.     }
  595.     return 1;
  596. }
  597.  
  598. int line_two(String command)
  599. {
  600.     int line_index = 1;
  601.     LineScroll[line_index] = 0;
  602.     command.replace("%20", " ");
  603.     line[line_index] = command;
  604.     lcd->setCursor(0, line_index);
  605.     for (unsigned int x=0; x < 20; x++) {
  606.         if (line[line_index].length() > x) {
  607.             if (line[line_index][x] == '*') lcd->print((char)223);
  608.             else lcd->print(line[line_index][x]);
  609.         }
  610.         else lcd->print(" ");
  611.     }
  612.     return 1;
  613. }
  614.  
  615. int line_three(String command)
  616. {
  617.     int line_index = 2;
  618.     LineScroll[line_index] = 0;
  619.     command.replace("%20", " ");
  620.     line[line_index] = command;
  621.     lcd->setCursor(0, line_index);
  622.     for (unsigned int x=0; x < 20; x++) {
  623.         if (line[line_index].length() > x) {
  624.             if (line[line_index][x] == '*') lcd->print((char)223);
  625.             else lcd->print(line[line_index][x]);
  626.         }
  627.         else lcd->print(" ");
  628.     }
  629.     return 1;
  630. }
  631.  
  632. int line_four(String command)
  633. {
  634.     int line_index = 3;
  635.     LineScroll[line_index] = 0;
  636.     command.replace("%20", " ");
  637.     line[line_index] = command;
  638.     lcd->setCursor(0, line_index);
  639.     for (unsigned int x=0; x < 20; x++) {
  640.         if (line[line_index].length() > x) lcd->print(line[line_index][x]);
  641.         else lcd->print(" ");
  642.     }
  643.     return 1;
  644. }
  645.  
  646. void loop()
  647. {
  648.     if (millis() > LastScroll + 450UL) {
  649.         for (unsigned int linePos=0;linePos<4;linePos++) {
  650.             if (line[linePos].length() <= 20) continue;
  651.             lcd->setCursor(0,linePos);
  652.             for (unsigned int charPos=0;charPos<20;charPos++) {
  653.                 if (charPos + LineScroll[linePos] > line[linePos].length() + 5) lcd->print(line[linePos][charPos - (line[linePos].length() - LineScroll[linePos] + 6)]); //use 4 if want to show begining of line for 450ms longer
  654.                 else if (charPos + LineScroll[linePos] > line[linePos].length() - 1) lcd->print(" ");
  655.                 else lcd->print(line[linePos][charPos + LineScroll[linePos]]);
  656.             }
  657.             if (line[linePos].length() > 20) LineScroll[linePos]++;
  658.             if (LineScroll[linePos] >= line[linePos].length() + 6) LineScroll[linePos] = 0;
  659.         }
  660.         LastScroll = millis();
  661.     }
  662.     if (millis() > LastTime) {
  663.         timestamp = currentTimeMilis();
  664.         TimeDiff = millis();
  665.         timestamp -= 18000;
  666.         struct tm * timeinfo;
  667.         timeinfo = localtime (&timestamp);
  668.         char buffer[80];
  669.         strftime (buffer, 20, "Time: %I:%M %p", timeinfo);
  670.         lcd->setCursor(0, 0);
  671.         lcd->print(buffer);
  672.         LastTime = millis() + (1000 * 60 * 60);
  673.     }
  674.     if (millis() > refreshTime + 60000UL) {
  675.         long tmpTime = timestamp;
  676.         tmpTime += ((millis() - TimeDiff)/1000);
  677.         struct tm * timeinfo;
  678.         timeinfo = localtime (&tmpTime);
  679.         char buffer[80];
  680.         strftime (buffer, 20, "Time: %I:%M %p", timeinfo);
  681.         lcd->setCursor(0, 0);
  682.         lcd->print(buffer);
  683.         refreshTime = millis();
  684.     }
  685.     //
  686. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement