极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 15784|回复: 15

开源下的丑丑蓝牙小表

[复制链接]
发表于 2014-7-1 11:03:49 | 显示全部楼层 |阅读模式
    在开源的网站下看到一个蓝牙小表,自己也去捣鼓一下:
放在桌面上的样子(面板是早上早餐卡免费送的,奇丑,勿喷.......)


拉了个橡皮筋绑在手里{:soso_e106:}





绝对不是土豪,专职吊打屌丝一名。
用到东西有:pro mini  ,HC-06蓝牙,DDS1306 OLED显示屏,一堆小线
:连线,热硅胶不可缺少的粘合物,奔着资源短缺就地利用见啥用啥的原则


基本的线接好之后,就这个挫样{:soso_e113:}

先装载APP,说到APP就难搞了,要安卓4.3以上才可以,让我等4.2的用户情何以堪,为了能顺利安装,把烂手机怒刷成4.4,结果APP装上了,手机的基本电话功给丧失了{:soso_e136:}.......


通过蓝牙控制可以操作手表的三种模式,模拟、数字、还有混合的
加个小电池,上电看看效果:


拉起橡皮筋(手表有误差.....别看肉包{:soso_e120:})



在这基础上还可以添加其他的功能,例如温湿度啊,GPS啊等等,有待开发,好了,在这里谢谢原著,感谢开源,自己DIY了一把,玩了一下。贴出我稍微改动的代码:把显示模块改成了SPI模式
  1. /*
  2.     RetroWatch Arduino is a part of open source smart watch project.
  3.     Copyright (C) 2014  Suh Young Bae

  4.     This program is free software: you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation, either version 3 of the License, or
  7.     (at your option) any later version.

  8.     This program is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.     GNU General Public License for more details.

  12.     You should have received a copy of the GNU General Public License
  13.     along with this program.  If not, see [http://www.gnu.org/licenses/].
  14. */
  15. /*
  16. Retro Watch Arduino v1.0

  17.   Get the latest version, android host app at
  18.   ------> https://github.com/godstale/retrowatch
  19.   ------> or http://www.hardcopyworld.com

  20. Written by Suh Young Bae ([email][email protected][/email])
  21. All text above, and the first splash screen(Adafruit) must be included in any redistribution
  22. */

  23. #include <avr/pgmspace.h>
  24. #include <Wire.h>
  25. #include <SoftwareSerial.h>
  26. #include <Adafruit_GFX.h>
  27. #include <Adafruit_SSD1306.h>
  28. #include <math.h>
  29. #include "bitmap.h"
  30. #include <SPI.h>

  31. ///////////////////////////////////////////////////////////////////
  32. //----- OLED instance
  33. #define OLED_MOSI   9
  34. #define OLED_CLK   10
  35. #define OLED_DC    11
  36. #define OLED_CS    12
  37. #define OLED_RESET 13
  38. Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

  39. #if (SSD1306_LCDHEIGHT != 64)
  40. #error("Height incorrect, please fix Adafruit_SSD1306.h!");
  41. #endif
  42. ///////////////////////////////////////////////////////////////////

  43. ///////////////////////////////////////////////////////////////////
  44. //----- BT instance
  45. SoftwareSerial BTSerial(2, 3); //Connect HC-06, RX, TX
  46. ///////////////////////////////////////////////////////////////////

  47. //----- Bluetooth transaction parsing
  48. #define TR_MODE_IDLE 1
  49. #define TR_MODE_WAIT_CMD 11
  50. #define TR_MODE_WAIT_MESSAGE 101
  51. #define TR_MODE_WAIT_TIME 111
  52. #define TR_MODE_WAIT_ID 121
  53. #define TR_MODE_WAIT_COMPLETE 201

  54. #define TRANSACTION_START_BYTE 0xfc
  55. #define TRANSACTION_END_BYTE 0xfd

  56. #define CMD_TYPE_NONE 0x00
  57. #define CMD_TYPE_RESET_EMERGENCY_OBJ 0x05
  58. #define CMD_TYPE_RESET_NORMAL_OBJ 0x02
  59. #define CMD_TYPE_RESET_USER_MESSAGE 0x03

  60. #define CMD_TYPE_ADD_EMERGENCY_OBJ 0x11
  61. #define CMD_TYPE_ADD_NORMAL_OBJ 0x12
  62. #define CMD_TYPE_ADD_USER_MESSAGE 0x13

  63. #define CMD_TYPE_DELETE_EMERGENCY_OBJ 0x21
  64. #define CMD_TYPE_DELETE_NORMAL_OBJ 0x22
  65. #define CMD_TYPE_DELETE_USER_MESSAGE 0x23

  66. #define CMD_TYPE_SET_TIME 0x31
  67. #define CMD_TYPE_REQUEST_MOVEMENT_HISTORY 0x32
  68. #define CMD_TYPE_SET_CLOCK_STYLE 0x33
  69. #define CMD_TYPE_SET_INDICATOR 0x34

  70. #define CMD_TYPE_PING 0x51
  71. #define CMD_TYPE_AWAKE 0x52
  72. #define CMD_TYPE_SLEEP 0x53
  73. #define CMD_TYPE_REBOOT 0x54

  74. byte TRANSACTION_POINTER = TR_MODE_IDLE;
  75. byte TR_COMMAND = CMD_TYPE_NONE;

  76. //----- Message item buffer
  77. #define MSG_COUNT_MAX 7
  78. #define MSG_BUFFER_MAX 19
  79. unsigned char msgBuffer[MSG_COUNT_MAX][MSG_BUFFER_MAX];
  80. char msgParsingLine = 0;
  81. char msgParsingChar = 0;
  82. char msgCurDisp = 0;

  83. //----- Emergency item buffer
  84. #define EMG_COUNT_MAX 3
  85. #define EMG_BUFFER_MAX 19
  86. char emgBuffer[EMG_COUNT_MAX][EMG_BUFFER_MAX];
  87. char emgParsingLine = 0;
  88. char emgParsingChar = 0;
  89. char emgCurDisp = 0;

  90. //----- Time
  91. #define UPDATE_TIME_INTERVAL 60000
  92. byte iMonth = 1;
  93. byte iDay = 1;
  94. byte iWeek = 1;    // 1: SUN, MON, TUE, WED, THU, FRI,SAT
  95. byte iAmPm = 0;    // 0:AM, 1:PM
  96. byte iHour = 0;
  97. byte iMinutes = 0;
  98. byte iSecond = 0;

  99. #define TIME_BUFFER_MAX 6
  100. char timeParsingIndex = 0;
  101. char timeBuffer[6] = {-1, -1, -1, -1, -1, -1};
  102. PROGMEM const char* weekString[] = {"", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  103. PROGMEM const char* ampmString[] = {"AM", "PM"};

  104. //----- Display features
  105. #define DISPLAY_MODE_START_UP 0
  106. #define DISPLAY_MODE_CLOCK 1
  107. #define DISPLAY_MODE_EMERGENCY_MSG 2
  108. #define DISPLAY_MODE_NORMAL_MSG 3
  109. #define DISPLAY_MODE_IDLE 11
  110. byte displayMode = DISPLAY_MODE_START_UP;

  111. #define CLOCK_STYLE_SIMPLE_ANALOG  0x01
  112. #define CLOCK_STYLE_SIMPLE_DIGIT  0x02
  113. #define CLOCK_STYLE_SIMPLE_MIX  0x03
  114. byte clockStyle = CLOCK_STYLE_SIMPLE_MIX;

  115. #define INDICATOR_ENABLE 0x01
  116. boolean updateIndicator = true;

  117. byte centerX = 64;
  118. byte centerY = 32;
  119. byte iRadius = 28;

  120. #define IDLE_DISP_INTERVAL 60000
  121. #define CLOCK_DISP_INTERVAL 60000
  122. #define EMERGENCY_DISP_INTERVAL 5000
  123. #define MESSAGE_DISP_INTERVAL 3000
  124. unsigned long prevClockTime = 0;
  125. unsigned long prevDisplayTime = 0;

  126. unsigned long next_display_interval = 0;
  127. unsigned long mode_change_timer = 0;
  128. #define CLOCK_DISPLAY_TIME 300000
  129. #define EMER_DISPLAY_TIME 10000
  130. #define MSG_DISPLAY_TIME 5000

  131. //----- Button control
  132. int buttonPin = 5;
  133. boolean isClicked = false;



  134. void setup()   {
  135.   //Serial.begin(9600);    // Do not enable serial. This makes serious problem because of shortage of RAM.
  136.   pinMode(buttonPin, INPUT);  // Defines button pin
  137.   
  138.   init_emg_array();
  139.   init_msg_array();
  140.   
  141.   //----- by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  142.   display.begin(SSD1306_SWITCHCAPVCC);  // initialize with the I2C addr 0x3D (for the 128x64)
  143.   display.display();    // show splashscreen
  144.   delay(1000);
  145.   drawStartUp();    // Show RetroWatch Logo
  146.   centerX = display.width() / 2;
  147.   centerY = display.height() / 2;
  148.   iRadius = centerY - 2;

  149.   BTSerial.begin(9600);  // set the data rate for the BT port
  150. }


  151. void loop()
  152. {
  153.   boolean isReceived = false;
  154.   unsigned long current_time = 0;
  155.   
  156.   // Get button input
  157.   if(digitalRead(buttonPin) == LOW) isClicked = LOW;
  158.   
  159.   // Receive data from remote and parse
  160.   isReceived = receiveBluetoothData();
  161.   
  162.   // Update clock time
  163.   current_time = millis();
  164.   updateTime(current_time);
  165.   
  166.   // Display routine
  167.   onDraw(current_time);
  168.   
  169.   // If data doesn't arrive, wait for a while to save battery
  170.   if(!isReceived)
  171.     delay(300);
  172. }




  173. ///////////////////////////////////
  174. //----- Utils
  175. ///////////////////////////////////
  176. void init_msg_array() {
  177.   for(int i=0; i<MSG_COUNT_MAX; i++) {
  178.     for(int j=0; j<MSG_BUFFER_MAX; j++) {
  179.       msgBuffer[i][j] = 0x00;
  180.     }
  181.   }
  182.   msgParsingLine = 0;
  183.   msgParsingChar = 0;    // First 2 byte is management byte
  184.   msgCurDisp = 0;
  185. }

  186. void init_emg_array() {
  187.   for(int i=0; i<EMG_COUNT_MAX; i++) {
  188.     for(int j=0; j<EMG_BUFFER_MAX; j++) {
  189.       emgBuffer[i][j] = 0x00;
  190.     }
  191.   }
  192.   emgParsingLine = 0;
  193.   emgParsingChar = 0;    // First 2 byte is management byte
  194.   emgCurDisp = 0;
  195. }

  196. ///////////////////////////////////
  197. //----- Time functions
  198. ///////////////////////////////////
  199. void setTimeValue() {
  200.   iMonth = timeBuffer[0];
  201.   iDay = timeBuffer[1];
  202.   iWeek = timeBuffer[2];    // 1: SUN, MON, TUE, WED, THU, FRI,SAT
  203.   iAmPm = timeBuffer[3];    // 0:AM, 1:PM
  204.   iHour = timeBuffer[4];
  205.   iMinutes = timeBuffer[5];
  206. }

  207. void updateTime(unsigned long current_time) {
  208.   if(iMinutes >= 0) {
  209.     if(current_time - prevClockTime > UPDATE_TIME_INTERVAL) {
  210.       // Increase time
  211.       iMinutes++;
  212.       if(iMinutes >= 60) {
  213.         iMinutes = 0;
  214.         iHour++;
  215.         if(iHour > 12) {
  216.           iHour = 1;
  217.           (iAmPm == 0) ? iAmPm=1 : iAmPm=0;
  218.           if(iAmPm == 0) {
  219.             iWeek++;
  220.             if(iWeek > 7)
  221.               iWeek = 1;
  222.             iDay++;
  223.             if(iDay > 30)  // Yes. day is not exact.
  224.               iDay = 1;
  225.           }
  226.         }
  227.       }
  228.       prevClockTime = current_time;
  229.     }
  230.   }
  231.   else {
  232.     displayMode = DISPLAY_MODE_START_UP;
  233.   }
  234. }

  235. ///////////////////////////////////
  236. //----- BT, Data parsing functions
  237. ///////////////////////////////////

  238. // Parsing packet according to current mode
  239. boolean receiveBluetoothData() {
  240.   int isTransactionEnded = false;
  241.   while(!isTransactionEnded) {
  242.     if(BTSerial.available()) {
  243.       byte c = BTSerial.read();
  244.       
  245.       if(c == 0xFF && TRANSACTION_POINTER != TR_MODE_WAIT_MESSAGE) return false;
  246.       
  247.       if(TRANSACTION_POINTER == TR_MODE_IDLE) {
  248.         parseStartSignal(c);
  249.       }
  250.       else if(TRANSACTION_POINTER == TR_MODE_WAIT_CMD) {
  251.         parseCommand(c);
  252.       }
  253.       else if(TRANSACTION_POINTER == TR_MODE_WAIT_MESSAGE) {
  254.         parseMessage(c);
  255.       }
  256.       else if(TRANSACTION_POINTER == TR_MODE_WAIT_TIME) {
  257.         parseTime(c);
  258.       }
  259.       else if(TRANSACTION_POINTER == TR_MODE_WAIT_ID) {
  260.         parseId(c);
  261.       }
  262.       else if(TRANSACTION_POINTER == TR_MODE_WAIT_COMPLETE) {
  263.         isTransactionEnded = parseEndSignal(c);
  264.       }
  265.       
  266.     }  // End of if(BTSerial.available())
  267.     else {
  268.       isTransactionEnded = true;
  269.     }
  270.   }  // End of while()
  271.   return true;
  272. }  // End of receiveBluetoothData()

  273. void parseStartSignal(byte c) {
  274.   //drawLogChar(c);
  275.   if(c == TRANSACTION_START_BYTE) {
  276.     TRANSACTION_POINTER = TR_MODE_WAIT_CMD;
  277.     TR_COMMAND = CMD_TYPE_NONE;
  278.   }
  279. }

  280. void parseCommand(byte c) {
  281.   if(c == CMD_TYPE_RESET_EMERGENCY_OBJ || c == CMD_TYPE_RESET_NORMAL_OBJ || c == CMD_TYPE_RESET_USER_MESSAGE) {
  282.     TRANSACTION_POINTER = TR_MODE_WAIT_COMPLETE;
  283.     TR_COMMAND = c;
  284.     processTransaction();
  285.   }
  286.   else if(c == CMD_TYPE_ADD_EMERGENCY_OBJ || c == CMD_TYPE_ADD_NORMAL_OBJ || c == CMD_TYPE_ADD_USER_MESSAGE) {
  287.     TRANSACTION_POINTER = TR_MODE_WAIT_MESSAGE;
  288.     TR_COMMAND = c;
  289.     if(c == CMD_TYPE_ADD_EMERGENCY_OBJ) {
  290.       emgParsingChar = 0;
  291.       if(emgParsingLine >= MSG_COUNT_MAX || emgParsingLine < 0)
  292.         emgParsingLine = 0;
  293.     }
  294.     else if(c == CMD_TYPE_ADD_NORMAL_OBJ) {
  295.       msgParsingChar = 0;
  296.       if(msgParsingLine >= MSG_COUNT_MAX || msgParsingLine < 0)
  297.         msgParsingLine = 0;
  298.     }
  299.   }
  300.   else if(c == CMD_TYPE_DELETE_EMERGENCY_OBJ || c == CMD_TYPE_DELETE_NORMAL_OBJ || c == CMD_TYPE_DELETE_USER_MESSAGE) {
  301.     TRANSACTION_POINTER = TR_MODE_WAIT_COMPLETE;
  302.     TR_COMMAND = c;
  303.   }
  304.   else if(c == CMD_TYPE_SET_TIME) {
  305.     TRANSACTION_POINTER = TR_MODE_WAIT_TIME;
  306.     TR_COMMAND = c;
  307.   }
  308.   else if(c == CMD_TYPE_SET_CLOCK_STYLE || c == CMD_TYPE_SET_INDICATOR) {
  309.     TRANSACTION_POINTER = TR_MODE_WAIT_ID;
  310.     TR_COMMAND = c;
  311.   }
  312.   else {
  313.     TRANSACTION_POINTER = TR_MODE_IDLE;
  314.     TR_COMMAND = CMD_TYPE_NONE;
  315.   }
  316. }

  317. void parseMessage(byte c) {
  318.   if(c == TRANSACTION_END_BYTE) {
  319.     processTransaction();
  320.     TRANSACTION_POINTER = TR_MODE_IDLE;
  321.   }
  322.   
  323.   if(TR_COMMAND == CMD_TYPE_ADD_EMERGENCY_OBJ) {
  324.     if(emgParsingChar < EMG_BUFFER_MAX) {
  325.       if(emgParsingChar > 1) {
  326.         emgBuffer[emgParsingLine][emgParsingChar] = c;
  327.       }
  328.       emgParsingChar++;
  329.     }
  330.     else {
  331.       TRANSACTION_POINTER = TR_MODE_WAIT_COMPLETE;
  332.     }
  333.   }
  334.   else if(TR_COMMAND == CMD_TYPE_ADD_NORMAL_OBJ) {
  335.     if(msgParsingChar < MSG_BUFFER_MAX) {
  336.       if(msgParsingChar > 1) {
  337.         msgBuffer[msgParsingLine][msgParsingChar] = c;
  338.       }
  339.       msgParsingChar++;
  340.     }
  341.     else {
  342.       TRANSACTION_POINTER = TR_MODE_WAIT_COMPLETE;
  343.     }
  344.   }
  345.   else if(TR_COMMAND == CMD_TYPE_ADD_USER_MESSAGE) {
  346.     // Not available yet.
  347.     TRANSACTION_POINTER = TR_MODE_WAIT_COMPLETE;
  348.   }
  349. }

  350. void parseTime(byte c) {
  351.   if(TR_COMMAND == CMD_TYPE_SET_TIME) {
  352.     if(timeParsingIndex >= 0 && timeParsingIndex < TIME_BUFFER_MAX) {
  353.       timeBuffer[timeParsingIndex] = (int)c;
  354.       timeParsingIndex++;
  355.     }
  356.     else {
  357.       processTransaction();
  358.       TRANSACTION_POINTER = TR_MODE_WAIT_COMPLETE;
  359.     }
  360.   }
  361. }

  362. void parseId(byte c) {
  363.   if(TR_COMMAND == CMD_TYPE_SET_CLOCK_STYLE) {
  364.     clockStyle = c;
  365.     processTransaction();
  366.   }
  367.   else if(TR_COMMAND == CMD_TYPE_SET_INDICATOR) {
  368.     if(c == INDICATOR_ENABLE)
  369.       updateIndicator = true;
  370.     else
  371.       updateIndicator = false;
  372.     processTransaction();
  373.   }
  374.   TRANSACTION_POINTER = TR_MODE_WAIT_COMPLETE;
  375. }

  376. boolean parseEndSignal(byte c) {
  377.   if(c == TRANSACTION_END_BYTE) {
  378.     TRANSACTION_POINTER = TR_MODE_IDLE;
  379.     return true;
  380.   }
  381.   return false;
  382. }

  383. void processTransaction() {
  384.   if(TR_COMMAND == CMD_TYPE_RESET_EMERGENCY_OBJ) {
  385.     init_emg_array();//init_msg_array();
  386.   }
  387.   else if(TR_COMMAND == CMD_TYPE_RESET_NORMAL_OBJ) {
  388.     init_msg_array();//init_emg_array();
  389.   }
  390.   else if(TR_COMMAND == CMD_TYPE_RESET_USER_MESSAGE) {
  391.     // Not available yet.
  392.   }
  393.   else if(TR_COMMAND == CMD_TYPE_ADD_NORMAL_OBJ) {
  394.     msgBuffer[msgParsingLine][0] = 0x01;
  395.     msgParsingChar = 0;
  396.     msgParsingLine++;
  397.     if(msgParsingLine >= MSG_COUNT_MAX)
  398.       msgParsingLine = 0;
  399.     setNextDisplayTime(millis(), 0);  // update screen immediately
  400.   }
  401.   else if(TR_COMMAND == CMD_TYPE_ADD_EMERGENCY_OBJ) {
  402.     emgBuffer[emgParsingLine][0] = 0x01;
  403.     emgParsingChar = 0;
  404.     emgParsingLine++;
  405.     if(emgParsingLine >= EMG_COUNT_MAX)
  406.       emgParsingLine = 0;
  407.     startEmergencyMode();
  408.     setNextDisplayTime(millis(), 2000);
  409.   }
  410.   else if(TR_COMMAND == CMD_TYPE_ADD_USER_MESSAGE) {
  411.   }
  412.   else if(TR_COMMAND == CMD_TYPE_DELETE_EMERGENCY_OBJ || TR_COMMAND == CMD_TYPE_DELETE_NORMAL_OBJ || TR_COMMAND == CMD_TYPE_DELETE_USER_MESSAGE) {
  413.     // Not available yet.
  414.   }
  415.   else if(TR_COMMAND == CMD_TYPE_SET_TIME) {
  416.     setTimeValue();
  417.     timeParsingIndex = 0;
  418.     setNextDisplayTime(millis(), 0);  // update screen immediately
  419.   }
  420.   if(TR_COMMAND == CMD_TYPE_SET_CLOCK_STYLE || CMD_TYPE_SET_INDICATOR) {
  421.     setNextDisplayTime(millis(), 0);  // update screen immediately
  422.   }
  423. }

  424. ///////////////////////////////////
  425. //----- Drawing methods
  426. ///////////////////////////////////

  427. // Main drawing routine.
  428. // Every drawing starts here.
  429. void onDraw(unsigned long currentTime) {
  430.   if(!isDisplayTime(currentTime))    // Do not re-draw at every tick
  431.     return;
  432.   
  433.   if(displayMode == DISPLAY_MODE_START_UP) {
  434.     drawStartUp();
  435.   }
  436.   else if(displayMode == DISPLAY_MODE_CLOCK) {
  437.     if(isClicked == LOW) {    // User input received
  438.       startEmergencyMode();
  439.       setPageChangeTime(0);    // Change mode with no page-delay
  440.       setNextDisplayTime(currentTime, 0);    // Do not wait next re-draw time
  441.     }
  442.     else {
  443.       drawClock();
  444.       
  445.       if(isPageChangeTime(currentTime)) {  // It's time to go into idle mode
  446.         startIdleMode();
  447.         setPageChangeTime(currentTime);  // Set a short delay
  448.       }
  449.       setNextDisplayTime(currentTime, CLOCK_DISP_INTERVAL);
  450.     }
  451.   }
  452.   else if(displayMode == DISPLAY_MODE_EMERGENCY_MSG) {
  453.     if(findNextEmerMessage()) {
  454.       drawEmergency();
  455.       emgCurDisp++;
  456.       if(emgCurDisp >= EMG_COUNT_MAX) {
  457.         emgCurDisp = 0;
  458.         startMessageMode();
  459.       }
  460.       setNextDisplayTime(currentTime, EMERGENCY_DISP_INTERVAL);
  461.     }
  462.     // There's no message left to display. Go to normal message mode.
  463.     else {
  464.       startMessageMode();
  465.       //setPageChangeTime(0);
  466.       setNextDisplayTime(currentTime, 0);  // with no re-draw interval
  467.     }
  468.   }
  469.   else if(displayMode == DISPLAY_MODE_NORMAL_MSG) {
  470.     if(findNextNormalMessage()) {
  471.       drawMessage();
  472.       msgCurDisp++;
  473.       if(msgCurDisp >= MSG_COUNT_MAX) {
  474.         msgCurDisp = 0;
  475.         startClockMode();
  476.       }
  477.       setNextDisplayTime(currentTime, MESSAGE_DISP_INTERVAL);
  478.     }
  479.     // There's no message left to display. Go to clock mode.
  480.     else {
  481.       startClockMode();
  482.       setPageChangeTime(currentTime);
  483.       setNextDisplayTime(currentTime, 0);  // with no re-draw interval
  484.     }
  485.   }
  486.   else if(displayMode == DISPLAY_MODE_IDLE) {
  487.     if(isClicked == LOW) {    // Wake up watch if there's an user input
  488.       startClockMode();
  489.       setPageChangeTime(currentTime);
  490.       setNextDisplayTime(currentTime, 0);
  491.     }
  492.     else {
  493.       drawIdleClock();
  494.       setNextDisplayTime(currentTime, IDLE_DISP_INTERVAL);
  495.     }
  496.   }
  497.   else {
  498.     startClockMode();    // This means there's an error
  499.   }
  500.   
  501.   isClicked = HIGH;
  502. }  // End of onDraw()


  503. // To avoid re-draw on every drawing time
  504. // wait for time interval according to current mode
  505. // But user input(button) breaks this sleep
  506. boolean isDisplayTime(unsigned long currentTime) {
  507.   if(currentTime - prevDisplayTime > next_display_interval) {
  508.     return true;
  509.   }
  510.   if(isClicked == LOW) {
  511.     delay(500);
  512.     return true;
  513.   }
  514.   return false;
  515. }

  516. // Set next re-draw time
  517. void setNextDisplayTime(unsigned long currentTime, unsigned long nextUpdateTime) {
  518.   next_display_interval = nextUpdateTime;
  519.   prevDisplayTime = currentTime;
  520. }

  521. // Decide if it's the time to change page(mode)
  522. boolean isPageChangeTime(unsigned long currentTime) {
  523.   if(displayMode == DISPLAY_MODE_CLOCK) {
  524.     if(currentTime - mode_change_timer > CLOCK_DISPLAY_TIME)
  525.       return true;
  526.   }
  527.   return false;
  528. }

  529. // Set time interval to next page(mode)
  530. void setPageChangeTime(unsigned long currentTime) {
  531.   mode_change_timer = currentTime;
  532. }

  533. // Check if available emergency message exists or not
  534. boolean findNextEmerMessage() {
  535.   if(emgCurDisp < 0 || emgCurDisp >= EMG_COUNT_MAX) emgCurDisp = 0;
  536.   while(true) {
  537.     if(emgBuffer[emgCurDisp][0] == 0x00) {  // 0x00 means disabled
  538.       emgCurDisp++;
  539.       if(emgCurDisp >= EMG_COUNT_MAX) {
  540.         emgCurDisp = 0;
  541.         return false;
  542.       }
  543.     }
  544.     else {
  545.       break;
  546.     }
  547.   }  // End of while()
  548.   return true;
  549. }

  550. // Check if available normal message exists or not
  551. boolean findNextNormalMessage() {
  552.   if(msgCurDisp < 0 || msgCurDisp >= MSG_COUNT_MAX) msgCurDisp = 0;
  553.   while(true) {
  554.     if(msgBuffer[msgCurDisp][0] == 0x00) {
  555.       msgCurDisp++;
  556.       if(msgCurDisp >= MSG_COUNT_MAX) {
  557.         msgCurDisp = 0;
  558.         return false;
  559.       }
  560.     }
  561.     else {
  562.       break;
  563.     }
  564.   }  // End of while()
  565.   return true;
  566. }

  567. // Count all available emergency messages
  568. int countEmergency() {
  569.   int count = 0;
  570.   for(int i=0; i<EMG_COUNT_MAX; i++) {
  571.     if(emgBuffer[i][0] != 0x00)
  572.       count++;
  573.   }
  574.   return count;
  575. }

  576. // Count all available normal messages
  577. int countMessage() {
  578.   int count = 0;
  579.   for(int i=0; i<MSG_COUNT_MAX; i++) {
  580.     if(msgBuffer[i][0] != 0x00)
  581.       count++;
  582.   }
  583.   return count;
  584. }

  585. void startClockMode() {
  586.   displayMode = DISPLAY_MODE_CLOCK;
  587. }

  588. void startEmergencyMode() {
  589.   displayMode = DISPLAY_MODE_EMERGENCY_MSG;
  590.   emgCurDisp = 0;
  591. }

  592. void startMessageMode() {
  593.   displayMode = DISPLAY_MODE_NORMAL_MSG;
  594.   msgCurDisp = 0;
  595. }

  596. void startIdleMode() {
  597.   displayMode = DISPLAY_MODE_IDLE;
  598. }

  599. // Draw indicator. Indicator shows count of emergency and normal message
  600. void drawIndicator() {
  601.   if(updateIndicator) {
  602.     int msgCount = countMessage();
  603.     int emgCount = countEmergency();
  604.     int drawCount = 1;
  605.    
  606.     if(msgCount > 0) {
  607.       display.drawBitmap(127 - 8, 1, IMG_indicator_msg, 8, 8, WHITE);
  608.       display.setTextColor(WHITE);
  609.       display.setTextSize(1);
  610.       display.setCursor(127 - 15, 1);
  611.       display.print(msgCount);
  612.       drawCount++;
  613.     }
  614.    
  615.     if(emgCount > 0) {
  616.       display.drawBitmap(127 - 8*drawCount - 7*(drawCount-1), 1, IMG_indicator_emg, 8, 8, WHITE);
  617.       display.setTextColor(WHITE);
  618.       display.setTextSize(1);
  619.       display.setCursor(127 - 8*drawCount - 7*drawCount, 1);
  620.       display.print(emgCount);
  621.     }

  622.   }
  623. }

  624. // RetroWatch splash screen
  625. void drawStartUp() {
  626.   display.clearDisplay();
  627.   
  628.   display.drawBitmap(10, 15, IMG_logo_24x24, 24, 24, WHITE);
  629.   
  630.   display.setTextSize(2);
  631.   display.setTextColor(WHITE);
  632.   display.setCursor(45,12);
  633.   display.println("Retro");
  634.   display.setCursor(45,28);
  635.   display.println("Watch");
  636.   display.setTextSize(1);
  637.   display.setCursor(45,45);
  638.   display.setTextColor(WHITE);
  639.   display.println("Arduino v1.0");
  640.   display.display();
  641.   delay(2000);
  642.   
  643.   startClockMode();
  644. }

  645. // Draw emergency message page
  646. void drawEmergency() {
  647.   int icon_num = 60;
  648.   display.clearDisplay();
  649.   
  650.   if(updateIndicator)
  651.     drawIndicator();
  652.   
  653.   if(emgBuffer[emgCurDisp][2] > -1 && emgBuffer[emgCurDisp][2] < ICON_ARRAY_SIZE)
  654.     icon_num = (int)(emgBuffer[emgCurDisp][2]);
  655.   
  656.   drawIcon(centerX - 8, centerY - 20, icon_num);
  657.   
  658.   display.setTextColor(WHITE);
  659.   display.setTextSize(1);
  660.   display.setCursor(getCenterAlignedXOfEmg(emgCurDisp), centerY + 10);
  661.   for(int i=3; i<EMG_BUFFER_MAX; i++) {
  662.     char curChar = emgBuffer[emgCurDisp][i];
  663.     if(curChar == 0x00) break;
  664.     if(curChar >= 0xf0) continue;
  665.     display.write(curChar);
  666.   }

  667.   display.display();
  668. }

  669. // Draw normal message page
  670. void drawMessage() {
  671.   int icon_num = 0;
  672.   display.clearDisplay();
  673.   
  674.   if(updateIndicator)
  675.     drawIndicator();
  676.   
  677.   if(msgBuffer[msgCurDisp][2] > -1 && msgBuffer[msgCurDisp][2] < ICON_ARRAY_SIZE)
  678.     icon_num = (int)(msgBuffer[msgCurDisp][2]);
  679.   
  680.   drawIcon(centerX - 8, centerY - 20, icon_num);
  681.   
  682.   display.setTextColor(WHITE);
  683.   display.setTextSize(1);
  684.   display.setCursor(getCenterAlignedXOfMsg(msgCurDisp), centerY + 10);
  685. //  display.print(msgCurDisp);  // For debug
  686.   for(int i=3; i<MSG_BUFFER_MAX; i++) {
  687.     char curChar = msgBuffer[msgCurDisp][i];
  688.     if(curChar == 0x00) break;
  689.     if(curChar >= 0xf0) continue;
  690.     display.write(curChar);
  691.   }

  692.   display.display();
  693. }

  694. // Draw main clock screen
  695. // Clock style changes according to user selection
  696. void drawClock() {
  697.   display.clearDisplay();

  698.   if(updateIndicator)
  699.     drawIndicator();
  700.   
  701.   // CLOCK_STYLE_SIMPLE_DIGIT
  702.   if(clockStyle == CLOCK_STYLE_SIMPLE_DIGIT) {
  703.     display.setTextSize(2);
  704.     display.setTextColor(WHITE);
  705.     display.setCursor(centerX - 34, centerY - 17);
  706.     display.println((const char*)pgm_read_word(&(weekString[iWeek])));
  707.     display.setTextSize(2);
  708.     display.setCursor(centerX + 11, centerY - 17);
  709.     display.println((const char*)pgm_read_word(&(ampmString[iAmPm])));

  710.     display.setTextSize(2);
  711.     display.setCursor(centerX - 29, centerY + 6);
  712.     if(iHour < 10)
  713.       display.print("0");
  714.     display.print(iHour);
  715.     display.print(":");
  716.     if(iMinutes < 10)
  717.       display.print("0");
  718.     display.println(iMinutes);
  719.    
  720.     display.display();
  721.   }
  722.   // CLOCK_STYLE_SIMPLE_MIX
  723.   else if(clockStyle == CLOCK_STYLE_SIMPLE_MIX) {
  724.     display.drawCircle(centerY, centerY, iRadius - 6, WHITE);
  725.     showTimePin(centerY, centerY, 0.1, 0.4, iHour*5 + (int)(iMinutes*5/60));
  726.     showTimePin(centerY, centerY, 0.1, 0.70, iMinutes);
  727.    
  728.     display.setTextSize(1);
  729.     display.setTextColor(WHITE);
  730.     display.setCursor(centerY*2 + 3, 23);
  731.     display.println((const char*)pgm_read_word(&(weekString[iWeek])));
  732.     display.setCursor(centerY*2 + 28, 23);
  733.     display.println((const char*)pgm_read_word(&(ampmString[iAmPm])));
  734.    
  735.     display.setTextSize(2);
  736.     display.setCursor(centerY*2, 37);
  737.     if(iHour < 10)
  738.       display.print("0");
  739.     display.print(iHour);
  740.     display.print(":");
  741.     if(iMinutes < 10)
  742.       display.print("0");
  743.     display.println(iMinutes);
  744.     display.display();
  745.   }
  746.   else {
  747.     // CLOCK_STYLE_SIMPLE_ANALOG.
  748.     display.drawCircle(centerX, centerY, iRadius, WHITE);
  749.     showTimePin(centerX, centerY, 0.1, 0.5, iHour*5 + (int)(iMinutes*5/60));
  750.     showTimePin(centerX, centerY, 0.1, 0.78, iMinutes);
  751.     // showTimePin(centerX, centerY, 0.1, 0.9, iSecond);
  752.     display.display();
  753.    
  754.     iSecond++;
  755.     if(iSecond > 60) iSecond = 0;
  756.   }
  757. }

  758. // Draw idle page
  759. void drawIdleClock() {
  760.     display.clearDisplay();

  761.     if(updateIndicator)
  762.       drawIndicator();

  763.     display.setTextSize(2);
  764.     display.setCursor(centerX - 29, centerY - 4);
  765.     if(iHour < 10)
  766.       display.print("0");
  767.     display.print(iHour);
  768.     display.print(":");
  769.     if(iMinutes < 10)
  770.       display.print("0");
  771.     display.println(iMinutes);

  772.     display.display();
  773. }

  774. // Returns starting point of normal string to display
  775. int getCenterAlignedXOfMsg(int msgIndex) {
  776.   int pointX = centerX;
  777.   for(int i=3; i<MSG_BUFFER_MAX; i++) {
  778.     char curChar = msgBuffer[msgIndex][i];
  779.     if(curChar == 0x00) break;
  780.     if(curChar >= 0xf0) continue;
  781.     pointX -= 3;
  782.   }
  783.   if(pointX < 0) pointX = 0;
  784.   return pointX;
  785. }

  786. // Returns starting point of emergency string to display
  787. int getCenterAlignedXOfEmg(int emgIndex) {
  788.   int pointX = centerX;
  789.   for(int i=3; i<EMG_BUFFER_MAX; i++) {
  790.     char curChar = emgBuffer[emgIndex][i];
  791.     if(curChar == 0x00) break;
  792.     if(curChar >= 0xf0) continue;
  793.     pointX -= 3;
  794.   }
  795.   if(pointX < 0) pointX = 0;
  796.   return pointX;
  797. }

  798. // Calculate clock pin position
  799. double RAD=3.141592/180;
  800. double LR = 89.99;
  801. void showTimePin(int center_x, int center_y, double pl1, double pl2, double pl3) {
  802.   double x1, x2, y1, y2;
  803.   x1 = center_x + (iRadius * pl1) * cos((6 * pl3 + LR) * RAD);
  804.   y1 = center_y + (iRadius * pl1) * sin((6 * pl3 + LR) * RAD);
  805.   x2 = center_x + (iRadius * pl2) * cos((6 * pl3 - LR) * RAD);
  806.   y2 = center_y + (iRadius * pl2) * sin((6 * pl3 - LR) * RAD);
  807.   
  808.   display.drawLine((int)x1, (int)y1, (int)x2, (int)y2, WHITE);
  809. }

  810. // Icon drawing tool
  811. void drawIcon(int posx, int posy, int icon_num) {
  812.   if(icon_num < 0 || icon_num >= ICON_ARRAY_SIZE)
  813.     return;
  814.    
  815.   display.drawBitmap(posx, posy, (const unsigned char*)pgm_read_word(&(bitmap_array[icon_num])), 16, 16, WHITE);
  816. }
复制代码

出处的网址http://www.hardcopyworld.com/ngine/aduino/index.php/archives/670






















本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2014-7-1 11:54:10 | 显示全部楼层
穿戴式原型机有意思.
回复 支持 反对

使用道具 举报

发表于 2014-7-1 12:17:37 | 显示全部楼层
很可爱呢
回复 支持 反对

使用道具 举报

发表于 2014-7-1 12:19:01 | 显示全部楼层
太好玩了,可惜啊,这个时间,第一眼看见的是蘑菇肉包,瞬间就饿的不行了。 楼主的杀伤力太大了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-1 13:35:08 | 显示全部楼层
shihaipeng04 发表于 2014-7-1 12:19
太好玩了,可惜啊,这个时间,第一眼看见的是蘑菇肉包,瞬间就饿的不行了。 楼主的杀伤力太大了

没有亚克力,早上真功夫路边发传单卡用来就地用的,勿看包子
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-1 13:36:31 | 显示全部楼层
wing 发表于 2014-7-1 12:17
很可爱呢

哈哈
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-1 13:37:39 | 显示全部楼层
林定祥 发表于 2014-7-1 11:54
穿戴式原型机有意思.

只能找到这个卡片做外客了
回复 支持 反对

使用道具 举报

发表于 2014-7-1 18:47:58 | 显示全部楼层
第一眼看见的还以为是蘑菇云。。。
回复 支持 反对

使用道具 举报

发表于 2014-7-1 18:52:19 | 显示全部楼层
显示屏是什么型号?,那个TI的表是什么表?
回复 支持 反对

使用道具 举报

发表于 2014-7-1 21:20:12 | 显示全部楼层
以前看过这个,但他用的是I2C,中国的OLED屏用Adafruit库只能用SPI,楼主这个屏在哪买的?
回复 支持 反对

使用道具 举报

发表于 2014-7-1 21:21:31 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2014-7-2 11:02:16 | 显示全部楼层
编译出错!!!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-2 18:21:49 | 显示全部楼层
幻生幻灭 发表于 2014-7-1 18:47
第一眼看见的还以为是蘑菇云。。。

包子是亮点
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-2 18:23:06 | 显示全部楼层
pdfan 发表于 2014-7-1 18:52
显示屏是什么型号?,那个TI的表是什么表?

SSD1306  终于有人知道TI的表了,当年参加电赛TI送的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-2 18:24:54 | 显示全部楼层
heiketiguo 发表于 2014-7-1 21:20
以前看过这个,但他用的是I2C,中国的OLED屏用Adafruit库只能用SPI,楼主这个屏在哪买的?

我做了两个,这个是SPI的屏,把代码修改了一下,今天再买了一个I2C的屏,把温湿度也加上去了
感觉挺好玩的

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-25 14:07 , Processed in 0.062064 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表