You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

796 lines
21 KiB

3 years ago
  1. /*
  2. * ZMHW Project: Map
  3. *
  4. * A device to give you a visual representation of what Monitors
  5. * are active in your camera network.
  6. *
  7. * SteakElectronics, December 2018
  8. * Rare steak, well done electronics.
  9. *
  10. * Based on: telnet client
  11. *
  12. * Requires: UIPEthernet library
  13. *
  14. * Nice to haves in future:
  15. * PWM dimming, after alarms are off, so you know what was recently on.
  16. * Blinking on active alarms, instead of solid light, maybe.
  17. * Faster direct port access than digitalwrite. There are some libraries
  18. * but I don't know if they support the Mega. Instead, I'm going to rebuild the board
  19. * with a led matrix, and then use pwm pins, and I will deal with it then.
  20. * EDIT: instead maybre I'll use two 0402 resistors, and make a voltage divider, to allow for
  21. * dimmer led, with hardware instead of software.
  22. *
  23. * Troubleshooting Programming: When connecting, it can take 30-60 seconds
  24. * to speed this up, run the test suite telnet connect and it should connect
  25. * immediately after. The idea is that, it seems to connect as soon as a packet is
  26. * sent from zmtrigger. So send a test telnet packet, then it will connect after.
  27. */
  28. /*
  29. Telnet client
  30. This sketch connects to a a telnet server (http://www.google.com)
  31. using an Arduino Wiznet Ethernet shield. You'll need a telnet server
  32. to test this with.
  33. Processing's ChatServer example (part of the network library) works well,
  34. running on port 10002. It can be found as part of the examples
  35. in the Processing application, available at
  36. http://processing.org/
  37. Circuit:
  38. * Ethernet shield attached to pins 10, 11, 12, 13
  39. created 14 Sep 2010
  40. modified 9 Apr 2012
  41. by Tom Igoe
  42. */
  43. #include <SPI.h>
  44. #include <UIPEthernet.h>
  45. #define DEBUGMODE 0 // 1:on 0:off
  46. #define DEBUGMODE2 0
  47. // Enter a MAC address and IP address for your controller below.
  48. // The IP address will be dependent on your local network:
  49. byte mac[] = {
  50. 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x41
  51. };
  52. IPAddress ip(192, 168, 78, 60);
  53. // Enter the IP address of the server you're connecting to:
  54. IPAddress server(192, 168, 78, 123);
  55. // Port of ZMTrigger
  56. #define ZMTRIGGERPORT 6802
  57. // Initialize the Ethernet client library
  58. // with the IP address and port of the server
  59. // that you want to connect to (port 23 is default for telnet;
  60. // if you're using Processing's ChatServer, use port 10002):
  61. EthernetClient client;
  62. //Make a server
  63. //Not currently working.
  64. #define LISTENPORT 80 // (port 80 is default for HTTP)
  65. EthernetServer server2 = EthernetServer(LISTENPORT);
  66. //Globals
  67. char* zmtrigarray[50] = {0};
  68. uint8_t x = 0;
  69. uint8_t y = 0;
  70. uint8_t Mon1 = 0;
  71. uint8_t Mon2 = 0;
  72. uint8_t MonFIN = 0;
  73. char mask = 0x0F; //get last nibble
  74. uint8_t Mon1Nib = Mon1 & mask;
  75. uint8_t Mon2Nib = Mon2 & mask;
  76. char on = 0b01101110; //n (ascii)
  77. char off = 0b01100110; //f (ascii)
  78. int value = 0;
  79. int ADD = 3; //We start at digital pin 4. so add 3 to everything.
  80. //e.g. Monitor 3 is digital pin 6.
  81. uint8_t NEEDCOLOUR = 0;
  82. // Simple PWM
  83. //if this is 1, bypass interrupt / softpwm, else do softpwm
  84. uint8_t BypassSoftPWM[50] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  85. int ledState[50] = {0}; // ledState used to set the LED
  86. #define LEDTIME 10000 // 2000 comes out to about 8 seconds
  87. uint16_t onInterval[50] = {LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME,LEDTIME}; // How long to display dimmed led
  88. uint8_t FLIP[50] = {0};
  89. uint8_t PWMCounter = 0;
  90. uint8_t OffOverride[50] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  91. uint8_t OffCtr[50] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  92. //during interrupt, we SoftPWM any LEDs that are ready to be done so
  93. ISR(TIMER3_COMPA_vect) {
  94. for(x=1;x<51;x++){
  95. if(BypassSoftPWM[x] == 1){
  96. //Serial.print("Bypass activated for monitor: ");
  97. //Serial.println(x);
  98. ///FLIP[x] = 0;
  99. if(onInterval[x] == LEDTIME){
  100. //note: These serial prints, cause delays that mess up softpwm
  101. if(DEBUGMODE){
  102. Serial.print(F("Turning on SoftPWM for Monitor: "));
  103. Serial.println(x);
  104. }
  105. }
  106. //turn off
  107. //might be better to do equals for all cases
  108. if(PWMCounter < 7){
  109. digitalWrite(x + ADD, 0);
  110. }
  111. //turn on
  112. //must be after turn off, otherwise, if before, it will
  113. //immediately be turned off
  114. if(PWMCounter > 7){
  115. digitalWrite(x + ADD, 1);
  116. PWMCounter = 0;
  117. //Serial.print(F("Dim Led #: "));
  118. //Serial.println(x);
  119. }
  120. PWMCounter = PWMCounter + 1;
  121. //Serial.print("PWM Count is: ");
  122. //Serial.println(PWMCounter);
  123. //This is only for debug. Slows delay down.
  124. //Serial.print("oninterval is:");
  125. //Serial.println(onInterval[x]);
  126. onInterval[x] = onInterval[x] - 1;
  127. if (onInterval[x] == 0){
  128. BypassSoftPWM[x] = 0;
  129. //note: These serial prints, cause delays that mess up softpwm
  130. if(DEBUGMODE){
  131. Serial.print("Turning off softPWM on Monitor: ");
  132. Serial.println(x);
  133. }
  134. digitalWrite(x + ADD, 0);
  135. onInterval[x] = LEDTIME;
  136. //no need for softpwm override
  137. OffOverride[x] = 0;
  138. OffCtr[x] = 0;
  139. }
  140. }
  141. }
  142. }
  143. //Check if any monitors that didn't get the shutdown message
  144. ISR(TIMER4_COMPA_vect) {
  145. for(x=1;x<51;x++){
  146. if (OffOverride[x] == 1){
  147. OffCtr[x]++;
  148. if (OffCtr[x] == 50){
  149. OffOverride[x] = 0;
  150. OffCtr[x] = 0;
  151. digitalWrite(x + ADD, 0);
  152. Serial.print(F("Turning off due to override. Monitor #: "));
  153. Serial.println(x);
  154. sendPixel(0,10,10);
  155. }
  156. }
  157. }
  158. }
  159. void setup() {
  160. // in case we are restarting the setup loop because we didn't connect,
  161. // we don't want timer to interfere
  162. TCCR3A = 0;
  163. TCCR3B = 0;
  164. TCNT3 = 0;
  165. //RGB LED
  166. /*define Pin 2/PE4 as output*/
  167. /*Libraries included w/arduino IDE*/
  168. DDRE = 0b00010000;
  169. // Open serial communications and wait for port to open:
  170. Serial.begin(9600);
  171. while (!Serial) {
  172. ; // wait for serial port to connect. Needed for native USB port only
  173. }
  174. sendPixel(10,0,0);
  175. delay(500);
  176. sendPixel(0,10,0);
  177. delay(500);
  178. sendPixel(0,0,10);
  179. Serial.println("ZMHW Project: Map");
  180. //Using pins 4 to 49
  181. for (x=4;x<49;x++){
  182. pinMode(x, OUTPUT);
  183. digitalWrite(x, LOW);
  184. }
  185. // start the Ethernet connection:
  186. Ethernet.begin(mac, ip);
  187. // give the Ethernet shield a second to initialize:
  188. delay(1000);
  189. Serial.println("connecting...");
  190. // if you get a connection, report back via serial:
  191. if (client.connect(server, ZMTRIGGERPORT)) {
  192. Serial.println("connected");
  193. //Test all LEDs
  194. for (x=4;x<49;x++){
  195. digitalWrite(x, HIGH);
  196. delay(50);
  197. digitalWrite(x, LOW);
  198. }
  199. } else {
  200. // if you didn't get a connection to the server:
  201. Serial.println("connection failed");
  202. for(int err = 0; err<3;err++){
  203. sendPixel(0,10,0);
  204. delay(100);
  205. sendPixel(0,0,0);
  206. delay(100);
  207. }
  208. }
  209. // AVR Timer CTC Interrupts Calculator
  210. // v. 8
  211. // http://www.arduinoslovakia.eu/application/timer-calculator
  212. // Microcontroller: ATmega2560
  213. // Created: 2019-02-02T06:08:33.492Z
  214. //dimming is buggy. doesn't quite work.
  215. //problem is viewed with a scope, the timers seem to fault
  216. //only pwming on one led occasionally
  217. //setupTimer3();
  218. sendPixel(0,10,10);
  219. setupTimer4();
  220. }
  221. void loop() {
  222. // if there are incoming bytes available
  223. // from the server, read them and print them:
  224. //original
  225. /*if (client.available()) {
  226. char c = client.read();
  227. Serial.print(c);
  228. }*/
  229. //if (client.available()) {
  230. // char* zmtrigarray = client.read();
  231. // Serial.print(zmtrigarray);
  232. //}
  233. if (client.available()){
  234. for(int x=0;x<40;x++){
  235. //there are two UIPClient.ccp client.read functions. this is the 2nd
  236. zmtrigarray[x] = client.read();
  237. if(zmtrigarray[x] == 0b00001010){ //if line break is found in telnet
  238. y = x;
  239. goto PRINT;
  240. }
  241. }
  242. PRINT:
  243. uint8_t WhereInTheWorldIsThe1stLine = 0;
  244. uint8_t WhereInTheWorldIsThe2ndLine = 0;
  245. //Serial.println("Finished reading client");
  246. if(DEBUGMODE){
  247. for(int x=0;x<y;x++){
  248. Serial.print((char)zmtrigarray[x]);
  249. }
  250. Serial.println(F(""));
  251. //debugging
  252. for(int x=0;x<y;x++){
  253. Serial.print(F("x is: "));
  254. Serial.print(x);
  255. Serial.print(F(" val is: "));
  256. Serial.print((char)zmtrigarray[x]);
  257. Serial.print(F(" bytecode is: "));
  258. Serial.print((char)zmtrigarray[x], DEC); //print int rep of byte
  259. Serial.print(F(" binary is: "));
  260. Serial.print((char)zmtrigarray[x], BIN); //print int rep of byte
  261. //line break is 10 in telnet
  262. Serial.println(F(""));
  263. }
  264. Serial.println(F(""));
  265. }//end DEBUG
  266. //Find out monitor we have
  267. //
  268. if(zmtrigarray[1] == 0b01111100) { //looking for vertical dash, in spot 2 (1 of array)
  269. Mon1 = zmtrigarray[0];
  270. Mon1Nib = Mon1 & mask;
  271. MonFIN = Mon1Nib;
  272. WhereInTheWorldIsThe1stLine = 1;
  273. if(DEBUGMODE){
  274. Serial.print(F("Mon1 is: "));
  275. Serial.println(Mon1Nib, BIN);
  276. Serial.print(F("Monitor number is: "));
  277. Serial.println(MonFIN, DEC);
  278. Serial.println(MonFIN, BIN);
  279. }
  280. }
  281. if(zmtrigarray[1] != 0b01111100){ //looking for vertical dash, for two digit number
  282. Mon1 = zmtrigarray[0];
  283. Mon1Nib = Mon1 & mask; //convert from ascii to decimal
  284. WhereInTheWorldIsThe1stLine = 2;
  285. if(DEBUGMODE){
  286. Serial.print(F("Mon1 is: "));
  287. Serial.println(Mon1Nib, BIN);
  288. }
  289. Mon2 = zmtrigarray[1];
  290. Mon2Nib = Mon2 & mask; //convert from ascii to decimal
  291. if(DEBUGMODE){
  292. Serial.print(F("Mon2 is: "));
  293. Serial.println(Mon2Nib, BIN);
  294. }
  295. MonFIN = Mon1Nib & Mon2Nib;
  296. char MonBUF[2];
  297. sprintf(MonBUF,"%d%d", Mon1Nib,Mon2Nib);
  298. MonFIN = atoi(MonBUF); //To convert from Ascii to dec, we take the lower 4 bits,
  299. //convert to a string, then convert to int.
  300. if(DEBUGMODE){
  301. Serial.print(F("Monitor number is: "));
  302. Serial.println(MonFIN, DEC);
  303. Serial.println(MonFIN, BIN);
  304. }
  305. }//end vertical dash search (when in spot 3)
  306. //Looking for an N or an F (for ON or OFF)
  307. //possible values: On, Off
  308. char OnOffSwitch = 0;
  309. OnOffSwitch = zmtrigarray[WhereInTheWorldIsThe1stLine+2];
  310. if(DEBUGMODE){
  311. Serial.print(F("On/Off Switch is: "));
  312. Serial.println(OnOffSwitch);
  313. }
  314. if(OnOffSwitch == on){
  315. //Now, we block SoftPWM, in case LED was dimmed
  316. BypassSoftPWM[MonFIN] = 0;
  317. //Reset this, in case LED was dimmed
  318. onInterval[MonFIN] = LEDTIME;
  319. OffOverride[MonFIN] = 0;
  320. OffCtr[MonFIN] = 0;
  321. if (DEBUGMODE){
  322. Serial.print("Bypass soft pwm value is:");
  323. Serial.println(BypassSoftPWM[MonFIN], DEC);
  324. Serial.print(F("On Detected for Monitor: "));
  325. Serial.println(MonFIN, DEC);
  326. }
  327. value = (MonFIN + ADD);
  328. //minus 1 as array starts at 0
  329. //BypassSoftPWM[MonFIN - 1] = 1;
  330. //Serial.print("Bypass soft pwm value is:");
  331. //Serial.println(BypassSoftPWM[MonFIN - 1], DEC);
  332. LEDAlight(value, 0xFF);
  333. //Visual notification alarm has been off lately
  334. sendPixel(20,20,20);
  335. }
  336. else if(OnOffSwitch == off){
  337. if (DEBUGMODE){
  338. Serial.print(F("Off Detected for Monitor: "));
  339. Serial.println(MonFIN, DEC);
  340. }
  341. value = (MonFIN + ADD);
  342. //Start watchdog timer to shutdown leds that dont stop
  343. OffOverride[MonFIN] = 1;
  344. //Now, we allow SoftPWM, as LED was just turned off.
  345. //minus 1 as array starts at 0
  346. BypassSoftPWM[MonFIN] = 1;
  347. if (DEBUGMODE){
  348. Serial.print(F("Bypass soft pwm value is:"));
  349. Serial.println(BypassSoftPWM[MonFIN], DEC);
  350. }
  351. LEDAlight(value, 0x00); //turn led off
  352. //SoftPWM_LED_dim(value, Interval, MonFIN);
  353. }
  354. else if (OnOffSwitch != on && OnOffSwitch != off){
  355. Serial.println(F("Incorrect On/Off Value"));
  356. }
  357. }
  358. //WebServer(); //todo
  359. // as long as there are bytes in the serial queue,
  360. // read them and send them out the socket if it's open:
  361. while (Serial.available() > 0) {
  362. char inChar = Serial.read();
  363. if (client.connected()) {
  364. client.print(inChar);
  365. }
  366. }
  367. // if the server's disconnected, stop the client:
  368. if (!client.connected()) {
  369. Serial.println();
  370. Serial.println("disconnecting.");
  371. client.stop();
  372. // do nothing:
  373. //while (true);
  374. //GREEN to RED Error
  375. for(int err = 0; err<9;err++){
  376. sendPixel(10,0,0);
  377. delay(100);
  378. sendPixel(0,10,0);
  379. delay(100);
  380. }
  381. //start over
  382. setup();
  383. }
  384. }
  385. uint8_t LEDAlight (int Monitor, int Switch){
  386. //Enable or Disable GPIO based on Monitor
  387. //and Switch value
  388. digitalWrite(Monitor, Switch);
  389. if (DEBUGMODE){
  390. Serial.print(F("LED # has been switched: "));
  391. Serial.print(Monitor);
  392. Serial.print(F(" "));
  393. }
  394. if(Switch == 0xFF){
  395. if (DEBUGMODE){
  396. Serial.println(F(" On"));
  397. }
  398. }
  399. else{
  400. if (DEBUGMODE){
  401. Serial.println(F(" Off"));
  402. }
  403. }
  404. }
  405. //This will fade out the LED
  406. uint8_t SoftPWM_LED_dim (uint8_t Monbitbangpwm, uint16_t *ptr, uint8_t ptrarraynum){
  407. //arrays start at 0
  408. ptrarraynum = ptrarraynum - 1;
  409. if(DEBUGMODE){
  410. //check I did my pointers right...
  411. Serial.println(F("SoftPWM: ...."));
  412. Serial.print(F("Mega Pin is:"));
  413. Serial.println(Monbitbangpwm);
  414. int TempMon = Monbitbangpwm - ADD;
  415. Serial.print(F("Monitor is:"));
  416. Serial.println(TempMon);
  417. Serial.print(F("Interval from within softPWM is:"));
  418. //It's easier to understand, if you call it pass reference to pointer, not pass by reference to pointer.
  419. //aka pointer can pass value (the value of the data, but not the original data), or pass reference (a reference to the original data)
  420. //that little "by" word, makes things much more incomprehensible.
  421. for( int x = 0 ; x <= 50 ; x++ ){
  422. Serial.println( ptr[x], HEX );
  423. //ptr[x] = ptr[x] + 1; //looks like by default arrays pass a reference to array
  424. //no need for ptr magic
  425. // https://forum.arduino.cc/index.php?topic=42546.0
  426. }
  427. }
  428. if(DEBUGMODE)
  429. {
  430. Serial.println( ptr[ptrarraynum], DEC );
  431. //Now start LED dimming timer
  432. //ptr[ptrarraynum] = 200;
  433. //Serial.println( "now 200: ");
  434. //Serial.println( ptr[ptrarraynum], DEC );
  435. }
  436. //start LED dimming timer
  437. ptr[ptrarraynum] = 2000;
  438. Serial.println( ptr[ptrarraynum], DEC );
  439. Serial.println( ptrarraynum, DEC );
  440. Serial.println( "Is now at what was above the num.");
  441. }
  442. //interrupt 15hz
  443. //from https://www.arduinoslovakia.eu/application/timer-calculator
  444. //would be nice if it was downloadable...
  445. void setupTimer3() {
  446. noInterrupts();
  447. // Clear registers
  448. TCCR3A = 0;
  449. TCCR3B = 0;
  450. TCNT3 = 0;
  451. /*
  452. // 15.00060002400096 Hz (16000000/((16665+1)*64))
  453. OCR3A = 16665;
  454. // CTC
  455. TCCR3B |= (1 << WGM32);
  456. // Prescaler 64
  457. TCCR3B |= (1 << CS31) | (1 << CS30);
  458. // Output Compare Match A Interrupt Enable
  459. TIMSK3 |= (1 << OCIE3A);
  460. */
  461. /*
  462. // 60.00060000600006 Hz (16000000/((33332+1)*8))
  463. OCR3A = 33332;
  464. // CTC
  465. TCCR3B |= (1 << WGM32);
  466. // Prescaler 8
  467. TCCR3B |= (1 << CS31);
  468. // Output Compare Match A Interrupt Enable
  469. TIMSK3 |= (1 << OCIE3A);
  470. */
  471. // 240.00960038401536 Hz (16000000/((8332+1)*8))
  472. OCR3A = 8332;
  473. // CTC
  474. TCCR3B |= (1 << WGM32);
  475. // Prescaler 8
  476. TCCR3B |= (1 << CS31);
  477. // Output Compare Match A Interrupt Enable
  478. TIMSK3 |= (1 << OCIE3A);
  479. interrupts();
  480. }
  481. //using this to count 1hz, in case any buggy reports from telnet
  482. //sometimes i see a lot of monitors light up, then immediately turn off
  483. //on telnet, so accounting for that.
  484. void setupTimer4() {
  485. noInterrupts();
  486. // Clear registers
  487. TCCR4A = 0;
  488. TCCR4B = 0;
  489. TCNT4 = 0;
  490. // 1 Hz (16000000/((15624+1)*1024))
  491. OCR4A = 15624;
  492. // CTC
  493. TCCR4B |= (1 << WGM42);
  494. // Prescaler 1024
  495. TCCR4B |= (1 << CS42) | (1 << CS40);
  496. // Output Compare Match A Interrupt Enable
  497. TIMSK4 |= (1 << OCIE4A);
  498. interrupts();
  499. }
  500. void WebServer (void){
  501. /********************SERVER STATUS PAGE*********************/
  502. /*
  503. * With this, you can logon to the Sensor from your LAN to find
  504. * out just what device this IP address is, in case you happen to
  505. * forget.
  506. */
  507. //Serial.println("In server");
  508. //Server Status Page
  509. // listen for incoming clients
  510. EthernetClient client3 = server2.available();
  511. if (client3) {
  512. Serial.println(F("web visitor"));
  513. // an http request ends with a blank line
  514. boolean currentLineIsBlank = true;
  515. while (client3.connected()) {
  516. if (client3.available()) {
  517. char c = client3.read();
  518. Serial.write(c);
  519. // if you've gotten to the end of the line (received a newline
  520. // character) and the line is blank, the http request has ended,
  521. // so you can send a reply
  522. if (c == '\n' && currentLineIsBlank) {
  523. // send a standard http response header
  524. client3.println("HTTP/1.1 200 OK");
  525. client3.println("Content-Type: text/html");
  526. client3.println();
  527. client3.println("<!DOCTYPE HTML>");
  528. client3.println("<html><pre>");
  529. client3.println("<b>Steak Electronics</b>");
  530. client3.println("\"Steak it One Steak at a time.\"");
  531. client3.println("");
  532. //client.println("<b>IP Address:</b>");
  533. //client.println(Ethernet.localIP());
  534. //client.print("Sensor Location:");
  535. //client.println(LOCATIONOFSENSOR);
  536. client3.print("Type:");
  537. client3.println("ZMHW Map");
  538. client3.print("Last Activity was Monitor: ");
  539. client3.println(MonFIN);
  540. client3.println("</pre></html>");
  541. break;
  542. }
  543. if (c == '\n') {
  544. // you're starting a new line
  545. currentLineIsBlank = true;
  546. } else if (c != '\r') {
  547. // you've gotten a character on the current line
  548. currentLineIsBlank = false;
  549. }
  550. }
  551. }
  552. // give the web browser time to receive the data
  553. delay(1);
  554. // close the connection:
  555. client.stop();
  556. Serial.println(F("web visitor disconnected"));
  557. }
  558. }
  559. void PixZero (void){
  560. PORTE = 0b00010000;
  561. //_delay_us(0.25);
  562. PORTE = 0x00;
  563. //_delay_us(0.25);
  564. }
  565. void PixOne (void){
  566. PORTE = 0b00010000;
  567. //_delay_us(0.55);
  568. _delay_us(0.55);
  569. PORTE = 0x00;
  570. }
  571. void PixBit (bool res){
  572. if (res == false){
  573. PixZero();
  574. }
  575. if (res == true){
  576. PixOne();
  577. }
  578. }
  579. void PixByte (char input){
  580. uint8_t changer = 0;
  581. //WS2812 reads bits as left is lowest (high in first), so go backwards
  582. for(changer=8;changer>0;changer--){
  583. PixBit(bitRead(input, changer));
  584. //input <<= 1; //Atmega didn't like this, so instead, using changer
  585. //instead of shifting input
  586. }
  587. }
  588. void sendPixel(uint8_t g, uint8_t r, uint8_t b){
  589. /*ws2812, reads bits left side as lowest*/
  590. /*PixByte(0b10100000); //This is dim green
  591. PixByte(0b00000000);
  592. PixByte(0b00000000);
  593. PixByte(0b00000000); //no white on my LED*/
  594. PixByte(g);
  595. PixByte(r);
  596. PixByte(b);
  597. //PixByte(w);
  598. PORTE = 0x00;
  599. }
  600. void PulseRGB_g (uint8_t max, uint8_t r, uint8_t b){
  601. int rgbfunc = 0;
  602. for (rgbfunc = 0; rgbfunc < max; rgbfunc++){
  603. sendPixel(rgbfunc,r,b);
  604. delay(22);
  605. }
  606. for (rgbfunc = max; rgbfunc > 0; rgbfunc--){
  607. sendPixel(rgbfunc,r,b);
  608. delay(22);
  609. }
  610. }
  611. void PulseRGB_r (uint8_t max, uint8_t g, uint8_t b){
  612. int rgbfunc = 0;
  613. for (rgbfunc = 0; rgbfunc < max; rgbfunc++){
  614. sendPixel(g,rgbfunc, b);
  615. delay(22);
  616. }
  617. for (rgbfunc = max; rgbfunc > 0; rgbfunc--){
  618. sendPixel(g,rgbfunc, b);
  619. delay(22);
  620. }
  621. }
  622. void PulseRGB_b (uint8_t max, uint8_t g, uint8_t r){
  623. int rgbfunc = 0;
  624. for (rgbfunc = 0; rgbfunc < max; rgbfunc++){
  625. sendPixel(g,r,rgbfunc);
  626. delay(22);
  627. }
  628. for (rgbfunc = max; rgbfunc > 0; rgbfunc--){
  629. sendPixel(g,r,rgbfunc);
  630. delay(22);
  631. }
  632. }