Advertisement
mat8854

CPP light

Mar 4th, 2020
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.46 KB | None | 0 0
  1. #include <Adafruit_MCP23017.h>
  2. Adafruit_MCP23017 mcp_1;
  3. Adafruit_MCP23017 mcp_2;
  4.  
  5. // modes
  6. enum MODE {OFF, TURN_LEFT, TURN_RIGHT, HAZARD_LIGHTS};
  7. MODE mode = OFF;
  8.  
  9. const int LED_COUNT = 8;
  10. const boolean MCP_MODE_ONE_BYTE_AT_ONCE = false;
  11. int currentCount = 0;
  12. int state = 0;
  13. boolean first_mode_call = true;
  14. long lastMillis = 0;
  15.  
  16. // blink delay
  17. const long blinkMs = 50;
  18.  
  19. // hazard light delay
  20. const long hazardDeltaMs = 250;
  21. const int hazardCountMax = hazardDeltaMs / blinkMs;
  22. int counterHazard = 0;
  23. boolean stateHazardActive = false;
  24.  
  25. #define MCP_LEFT 0
  26. #define MCP_RIGHT 1
  27.  
  28. int inline get_bit_from_int(int val, int pos) {
  29.   int mask = 1 << pos;
  30.   int masked_val = val & mask;
  31.   return masked_val >> pos;
  32. }
  33.  
  34. /*
  35.  * @param   mcp_num   set MCP left or right
  36.  * @param   high_byte flag to write upper 8 bit of 16bit
  37.  * @param   val       byte to be written
  38.  * @param   pos       define a single bit, if NULL full 8 bit will be written
  39.  */
  40. void write_to_MCP(byte mcp_num, boolean high_byte, byte val, byte pos) {
  41.   // select right MCP
  42.   Adafruit_MCP23017* mcp;
  43.   mcp_num == MCP_LEFT ? *mcp = mcp_1 : *mcp = mcp_2;
  44.  
  45.   // set high byte offset
  46.   int bit_offset = 0;
  47.   high_byte ? bit_offset = 8: bit_offset = 0;
  48.  
  49.   if (MCP_MODE_ONE_BYTE_AT_ONCE) {
  50.     // fast version goes here
  51.     // direct I2C access for pos == NULL case, maybe if version below is too slow
  52.   } else {
  53.     // slower version
  54.     if(pos == NULL) {
  55.       // write bit by bit
  56.       for(int i = 0; i < 8; i++) {
  57.         mcp->digitalWrite(i + bit_offset, get_bit_from_int(val, i));
  58.       }
  59.     } else {
  60.       // only write the desired position (one access only)
  61.       mcp->digitalWrite(pos + bit_offset, val);
  62.     }
  63.   }
  64.  
  65.   debug_output(val);
  66. }
  67.  
  68. void debug_output(int val) {
  69.   // debug output
  70.   Serial.print("mode: ");
  71.   Serial.print(mode);
  72.   Serial.print(" val: ");
  73.   Serial.print(val);
  74.   Serial.println();
  75. }
  76.  
  77. void turn_left() {
  78.   turn_generic(MCP_RIGHT, MCP_LEFT);
  79. }
  80.  
  81. void turn_right() {
  82.   turn_generic(MCP_LEFT, MCP_RIGHT);
  83. }
  84.  
  85. void turn_generic(byte mcp_inactive, byte mcp_active) {
  86.  
  87.   if (first_mode_call) {
  88.     // turn unused leds off once
  89.     write_to_MCP(mcp_inactive, false, 0x00, NULL);
  90.     write_to_MCP(mcp_inactive, true, 0x00, NULL);
  91.     // reset count state
  92.     currentCount = 0;
  93.     // clear flag
  94.     first_mode_call = false;
  95.   }
  96.  
  97.   // calc output bit vector and write to MCPs
  98.   int val = pow(2, currentCount) - 1;
  99.   // check for reset
  100.   if(currentCount == 0) {
  101.     // force a complete write
  102.     write_to_MCP(mcp_active, false, (byte)val, NULL);
  103.     write_to_MCP(mcp_active, true, (byte)val, NULL);
  104.   } else {
  105.     // also pass position of bit
  106.     write_to_MCP(mcp_active, false, (byte)val, currentCount);
  107.     write_to_MCP(mcp_active, true, (byte)val, currentCount);
  108.   }
  109.  
  110.   // counter logic
  111.   currentCount++;
  112.   if (currentCount > LED_COUNT) {
  113.     currentCount = 0;
  114.   }
  115. }
  116.  
  117. void hazard_lights() {
  118.   if (first_mode_call) {
  119.     first_mode_call = false;
  120.     counterHazard = 0;
  121.     // turn all leds on once
  122.     set_all_leds(0xFF);
  123.     stateHazardActive = true;
  124.   }
  125.  
  126.   // check for toggle condition
  127.   if (counterHazard > hazardCountMax) {
  128.     if (stateHazardActive) {
  129.       set_all_leds(0x00);
  130.       stateHazardActive = false;
  131.     } else {
  132.       set_all_leds(0xFF);
  133.       stateHazardActive = true;
  134.     }
  135.     // reset counter
  136.     counterHazard = 0;
  137.   }
  138.   counterHazard++;
  139. }
  140.  
  141. void set_all_leds(byte val) {
  142.   write_to_MCP(MCP_LEFT, false, val, NULL);
  143.   write_to_MCP(MCP_LEFT, true, val, NULL);
  144.   write_to_MCP(MCP_RIGHT, false, val, NULL);
  145.   write_to_MCP(MCP_RIGHT, true, val, NULL);
  146. }
  147.  
  148. void setup() {
  149.  
  150.   // setup serial
  151.   Serial.begin(9600);
  152.  
  153.   // setup MCPs
  154.   mcp_1.begin(0);      // Start MCP 1 on Hardware address 0x20
  155.   mcp_2.begin(1);      // Start MCP 2 on Hardware address 0x21
  156.  
  157.   // configure all outputs
  158.   for(int i = 0; i < 16; i++) {
  159.     mcp_1.pinMode(i, OUTPUT);
  160.     mcp_2.pinMode(i, OUTPUT);
  161.     mcp_1.digitalWrite(i, 0);
  162.     mcp_2.digitalWrite(i, 0);
  163.   }
  164.  
  165.   // hard code mode here
  166.   mode = TURN_LEFT;
  167.   //mode = TURN_RIGHT;
  168.   //mode = HAZARD_LIGHTS;
  169. }
  170.  
  171. void loop() {
  172.  
  173.   // main loop
  174.   if (millis() - lastMillis > blinkMs) {
  175.     lastMillis = millis();
  176.  
  177.     // check for mode
  178.     if (mode == TURN_LEFT) {
  179.       turn_left();
  180.     } else if (mode == TURN_RIGHT) {
  181.       turn_right();
  182.     } else if (mode == HAZARD_LIGHTS) {
  183.       hazard_lights();
  184.     } else {
  185.       // mode is off, do nothing
  186.     }
  187.   }
  188.  
  189. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement