TiniestGoat

PoE Arduino Socketing Simulator

Nov 23rd, 2019
6,107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.83 KB | None | 0 0
  1. // NEOPIXEL BEST PRACTICES for most reliable operation:
  2. // - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
  3. // - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
  4. // - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
  5. // - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
  6. //   connect GROUND (-) first, then +, then data.
  7. // - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
  8. //   a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
  9. // (Skipping these may work OK on your workbench but can fail in the field)
  10.  
  11. #include <Adafruit_NeoPixel.h>
  12. #ifdef __AVR__
  13.  #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
  14. #endif
  15.  
  16. // Digital IO pin connected to the button. This will be driven with a
  17. // pull-up resistor so the switch pulls the pin to ground momentarily.
  18. // On a high -> low transition the button press logic will execute.
  19. #define SOCKET_PIXELS   6
  20. #define LINK_PIXELS   2
  21. #define PIXELS_PIN    1
  22. #define JEWELLER_BUTTON_PIN   0
  23. #define CHROME_BUTTON_PIN   2
  24. #define FUSE_BUTTON_PIN   3
  25.  
  26. Adafruit_NeoPixel strip(SOCKET_PIXELS + LINK_PIXELS * (SOCKET_PIXELS - 1), PIXELS_PIN, NEO_GRB + NEO_KHZ800);
  27.  
  28. const int maxLinks = SOCKET_PIXELS - 1;
  29. int     buttonPins[] = {JEWELLER_BUTTON_PIN, CHROME_BUTTON_PIN, FUSE_BUTTON_PIN};
  30. int     numSockets = 1;
  31. bool    buttonPinsOldState[] = {HIGH, HIGH, HIGH};
  32. bool    buttonPinsNewState[] = {HIGH, HIGH, HIGH};
  33. int     activeLinks[SOCKET_PIXELS - 1];
  34. int     oldActiveLinks[SOCKET_PIXELS - 1];
  35. int     linkPixelMap[LINK_PIXELS * (SOCKET_PIXELS - 1)] = {};
  36. int     socketPixelMap[SOCKET_PIXELS] = {};
  37. char    pixelMap[SOCKET_PIXELS + LINK_PIXELS * (SOCKET_PIXELS - 1)] = {};
  38. int     pixelCount = strip.numPixels();
  39. bool    fullyLinked = LOW;
  40. int     socketColors[SOCKET_PIXELS];
  41. int     oldSocketColors[SOCKET_PIXELS];
  42. long    fusingTable[6][5] = {
  43.  {100000, 100000, 100000, 100000, 100000},
  44.  {33670, 100000, 100000, 100000, 100000},
  45.  {22377, 66461, 100000, 100000, 100000},
  46.  {17991, 53435, 80401, 100000, 100000},
  47.  {17844, 52997, 79741, 99178, 100000},
  48.  {17826, 52944, 79661, 99079, 99900}
  49. };
  50.  
  51.  
  52. void setup() {
  53.   // These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
  54.   // Any other board, you can remove this part (but no harm leaving it):
  55. #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  56.   clock_prescale_set(clock_div_1);
  57. #endif
  58.   // END of Trinket-specific code.
  59.  
  60.   strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  61.   strip.show();            // Turn OFF all pixels ASAP
  62.   strip.setBrightness(100); // Set BRIGHTNESS to about 1/5 (max = 255)
  63.   randomSeed(analogRead(4)); // nothing connected to 5 so read sees noise
  64.  
  65.   pinMode(JEWELLER_BUTTON_PIN, INPUT_PULLUP);
  66.   pinMode(CHROME_BUTTON_PIN, INPUT_PULLUP);
  67.   pinMode(FUSE_BUTTON_PIN, INPUT_PULLUP);
  68.  
  69.   //set up mapping to pixels
  70.   int socketPixelMapIndex = 0;
  71.   int linkPixelMapIndex = 0;
  72.   for(int pixelIndex = 0; pixelIndex < pixelCount; pixelIndex++) {
  73.     if((pixelIndex % (LINK_PIXELS + 1)) == 0) {
  74.       socketPixelMap[socketPixelMapIndex] = pixelIndex;
  75.       pixelMap[pixelIndex] = 'S';
  76.       socketPixelMapIndex++;
  77.     } else {
  78.       linkPixelMap[linkPixelMapIndex] = pixelIndex;
  79.       pixelMap[pixelIndex] = 'L';
  80.       linkPixelMapIndex++;
  81.     }
  82.   }
  83.  
  84.   // Initialization before button presses
  85.   int initSockets = jeweller(0);
  86.   numSockets = min(initSockets, SOCKET_PIXELS);  // Jeweller's Orb
  87.   chromatic(numSockets);    // Chromatic Orb
  88.   fullyLinked = fusing(numSockets);     // Fusing Orb
  89. }
  90.  
  91.  
  92. void loop() {
  93. /*numSockets = 6;
  94.   testFusings();
  95. }/*
  96.   testJewellers();
  97. }*/
  98.   int buttonActive = checkButtons();   // Get current button state.
  99.   switch(buttonActive) {                // Determine function based on button press
  100.     case JEWELLER_BUTTON_PIN:
  101.       if((numSockets != SOCKET_PIXELS) && (fullyLinked == LOW)) {
  102.         numSockets = jeweller(numSockets);          // Jeweller's Orb
  103.         chromatic(numSockets);            // Chromatic Orb
  104.         fullyLinked = fusing(numSockets); // Fusing Orb
  105.       }
  106.       break;
  107.     case CHROME_BUTTON_PIN:
  108.       chromatic(numSockets);            // Chromatic Orb
  109.       break;
  110.     case FUSE_BUTTON_PIN:
  111.       if(fullyLinked == LOW) {
  112.           fullyLinked = fusing(numSockets); // Fusing Orb
  113.       }
  114.       break;
  115.   }
  116.   strip.show(); // Update strip with new contents
  117.   delay(50);  // Pause for a moment
  118. }
  119.  
  120.  
  121. // Get current button state.
  122. int checkButtons() {
  123.   for(int buttonIndex = 0; buttonIndex < 3; buttonIndex++) { //  'buttonPins' counts from 0 to 2...
  124.     buttonPinsOldState[buttonIndex] = buttonPinsNewState[buttonIndex];
  125.     buttonPinsNewState[buttonIndex] = debounceButton(buttonPins[buttonIndex]);
  126.     // Check if state changed from high to low (button press).
  127.     if((buttonPinsNewState[buttonIndex] == LOW) && (buttonPinsOldState[buttonIndex] == HIGH)) {
  128.       buttonPinsOldState[buttonIndex] = buttonPinsNewState[buttonIndex];
  129.       return buttonPins[buttonIndex];
  130.     }
  131.   }
  132.   return -99;
  133. }
  134.  
  135.  
  136. // Debounce button press
  137. bool debounceButton(int buttonPin) {
  138.     bool newState = digitalRead(buttonPin);
  139.     delay(20);
  140.     // Check if button is still low after debounce.
  141.     newState = digitalRead(buttonPin);
  142.     if(newState == LOW) {      // Yes, still low
  143.       return LOW;
  144.     } else {
  145.       return HIGH;
  146.     }
  147. }
  148.  
  149.  
  150. // Randomly set number of sockets based on Chris Wilson's percentages + x/6 chance of rolling x sockets for 20% quality
  151. int jeweller(int incSockets) {
  152.   long randNumber = random(0,100001);
  153.   if(incSockets == 6) {
  154.     return 6;
  155.   } else if((incSockets != 1) && (((numSockets == 2) && (randNumber < 36900)) || ((numSockets == 3) && (randNumber < 37453)) || ((numSockets == 4) && (randNumber < 30211)) || ((numSockets == 5) && (randNumber < 27027)))) {
  156.     return 1;
  157.   } else if((incSockets != 2) && (((numSockets == 1) && (randNumber < 38710)) || ((numSockets == 3) && (randNumber < 77903)) || ((numSockets == 4) && (randNumber < 62840)) || ((numSockets == 5) && (randNumber < 56216)))) {
  158.     return 2;
  159.   } else if((incSockets != 3) && (((numSockets == 1) && (randNumber < 78853)) || ((numSockets == 2) && (randNumber < 78229)) || ((numSockets == 4) && (randNumber < 96676)) || ((numSockets == 5) && (randNumber < 86486)))) {
  160.     return 3;
  161.   } else if((incSockets != 4) && (((numSockets == 1) && (randNumber < 96057)) || ((numSockets == 2) && (randNumber < 95941)) || ((numSockets == 3) && (randNumber < 95880)) || ((numSockets == 5) && (randNumber < 99459)))) {
  162.     return 4;
  163.   } else if((incSockets != 5) && (((numSockets == 1) && (randNumber < 99283)) || ((numSockets == 2) && (randNumber < 99262)) || ((numSockets == 3) && (randNumber < 99251)) || ((numSockets == 4) && (randNumber < 99396)))) {
  164.     return 5;
  165.   } else {
  166.     return 6;
  167.   }
  168. }
  169.  
  170.  
  171. // Randomly set colors of sockets
  172. // Note: Chromatic orbs cannot reroll the same color permutation twice, so the chromatic success chance is always higher than the drop rate.
  173. // For mono-requirement items, on-color: 0.9 * (R + 10) / (R + 20)
  174. // For mono-requirement items, off-color: 0.05 + 4.5 / (R + 20)
  175. // For dual-requirement items, on-color: 0.9 * R1 / (R1 + R2)
  176. // For dual-requirement items, off-color: 10% flat chance, regardless of requirements
  177. // Requirements: 170 dex
  178. void chromatic(int numSockets) {
  179.   copy(socketColors, oldSocketColors, SOCKET_PIXELS);
  180.   for(int socketIndex = 0; socketIndex < numSockets; socketIndex++) {
  181.     long randNumber = random(0,100001);
  182.     if(randNumber < 85263) {
  183.       strip.setPixelColor(socketPixelMap[socketIndex], 0, 255, 0);
  184.       socketColors[socketIndex] = 2;
  185.     } else if(randNumber < 92631) {
  186.       strip.setPixelColor(socketPixelMap[socketIndex], 0, 0, 255);
  187.       socketColors[socketIndex] = 3;
  188.     } else {
  189.       strip.setPixelColor(socketPixelMap[socketIndex], 255, 0, 0);
  190.       socketColors[socketIndex] = 1;
  191.     }
  192.   }
  193.   if(numSockets < SOCKET_PIXELS) {
  194.     for(int socketIndex = numSockets; socketIndex < SOCKET_PIXELS; socketIndex++) {
  195.       strip.setPixelColor(socketPixelMap[socketIndex], 0, 0, 0);
  196.       socketColors[socketIndex] = 0;
  197.     }
  198.   }
  199.   bool compareColors = memcmp(socketColors, oldSocketColors, sizeof(socketColors));
  200.   if(!(compareColors)) {
  201.     chromatic(numSockets);
  202.   }
  203. }
  204.  
  205.  
  206. // Randomly set links of sockets
  207. bool fusing(int remainingSockets) {
  208.   copy(activeLinks, oldActiveLinks, SOCKET_PIXELS - 1);
  209.   int socketIndex = 0;
  210.   while((remainingSockets > 0) && (socketIndex < numSockets)) {
  211.     int linksNum = 0;
  212.     long randNumber = random(0,100001);
  213.     for(int probIndex = remainingSockets - 1; probIndex > 0; probIndex--) {
  214.       long probCheck = fusingTable[remainingSockets - 1][probIndex - 1];
  215.       if(randNumber > probCheck) {
  216.         linksNum = probIndex;
  217.         break;
  218.       }
  219.     }
  220.     switch(linksNum) {
  221.       case 0:     // No links
  222.         setLinks(socketIndex, 0);
  223.         socketIndex++;
  224.         remainingSockets--;
  225.         break;
  226.       case 1:     // 1 link
  227.         setLinks(socketIndex, 1);
  228.         socketIndex += 2;
  229.         remainingSockets -= 2;
  230.         break;
  231.       case 2:
  232.         setLinks(socketIndex, 2);     // 2 links
  233.         socketIndex += 3;
  234.         remainingSockets -= 3;
  235.         break;
  236.       case 3:
  237.         setLinks(socketIndex, 3);     // 3 links
  238.         socketIndex += 4;
  239.         remainingSockets -= 4;
  240.         break;
  241.       case 4:
  242.         setLinks(socketIndex, 4);   // 4 links
  243.         socketIndex += 5;
  244.         remainingSockets -= 5;
  245.         break;
  246.       case 5:                        // fully linked!
  247.         setLinks(socketIndex, 5);
  248.         socketIndex += 6;
  249.         remainingSockets -= 6;
  250.         return HIGH;
  251.         break;
  252.     }
  253.   }
  254.   bool compareLinks = memcmp(activeLinks, oldActiveLinks, sizeof(activeLinks));
  255.   if(!(compareLinks) && (numSockets != 1)) {
  256.     fullyLinked = fusing(numSockets);
  257.   } else {
  258.     return LOW;
  259.   }
  260. }
  261.  
  262.  
  263. // Set pixels on for active links, and off for the inactive link afterward (if not fully linked)
  264. void setLinks(int startingSocket, int linksNum) {
  265.   int linkIndex;
  266.   for(int pixelIndex = socketPixelMap[startingSocket]; pixelIndex < pixelCount; pixelIndex++) {
  267.     if(pixelMap[pixelIndex] == 'S') {
  268.       linkIndex = pixelIndex / (LINK_PIXELS + 1);
  269.     } else if(pixelMap[pixelIndex] == 'L') {
  270.       if((linksNum > 0) && (linkIndex < (startingSocket + linksNum))) {
  271.         activeLinks[linkIndex] = 1;
  272.         //strip.setPixelColor(pixelIndex, 255, 0, 255);  //  Set pixel's color (in RAM)
  273.         strip.setPixelColor(pixelIndex, 90, 100, 15);  //  Set pixel's color (in RAM)
  274.       } else {
  275.         activeLinks[linkIndex] = 0;
  276.         strip.setPixelColor(pixelIndex, 0, 0, 0);  //  Set pixel's color off (in RAM)
  277.       }
  278.     }
  279.   }
  280. }
  281.  
  282.  
  283. // Function to copy 'len' elements from 'src' to 'dst'
  284. void copy(int* src, int* dst, int len) {
  285.     memcpy(dst, src, sizeof(src[0])*len);
  286. }
Advertisement
Add Comment
Please, Sign In to add comment