Advertisement
ayush3504

test interface board - arduino sketch

Sep 9th, 2013
388
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.51 KB | None | 0 0
  1. // coreboot test interface board
  2. // by Ayush Sagar (ayush@ieee.org) for coreboot GSoC 2013
  3. // Last revised on 8 Sep 2013
  4.  
  5. //     Pin assignments
  6.  
  7. #define pinICP 4
  8. #define pinPowerSwitch 5
  9. #define pinResetSwitch 6
  10. #define pinPowerLED 7
  11. #define pinVCCP A0
  12. #define pinVCCF A1
  13. #define pinVCCM A2
  14.  
  15. // Note: HSync and VSync pins are assigned to pins 2 and 3 using attachInterrupt() in beginFreqCounter()
  16.  
  17.  
  18. //     ADC related
  19.  
  20.   /* INTERNAL ADC VOLTAGE REFERENCE (important)
  21.   Set 1.1V for Atmega168/328 and 2.56 for Atmega32U4
  22.   e.g. for Uno, Duemilanove use 1.1V and for Leonardo use 2.56V. See the chip name on your board and refer to its datasheet*/
  23. #define internalAnalogReference 2.56
  24.  
  25. // sets voltage divider resistances in ohms. Use tight tolerance resistors to ensure accuracy of ADC readings.
  26. #define upperResistance 9940 // connected across measured voltage and ADC input.
  27. #define lowerResistance 457  // connected across ADC input and ground.
  28.  
  29.  
  30. //     Sync frequency counter
  31.  
  32.   // stores count of HS/VS pulses in given time window
  33. volatile unsigned short HSPulseCount = 0;
  34. volatile unsigned short VSPulseCount = 0;
  35.  
  36.   // stores HSync and VSync frequency in Hz
  37. unsigned short HSync = 0;
  38. unsigned short VSync = 0;
  39.  
  40.   // sets timer limit in msec for HSync and VSync frequency counter
  41. #define fcTimerLimit 500
  42.  
  43.   // timer for freq. calculations
  44. unsigned long fcTimer;
  45.  
  46.   // flag to convey state of counter
  47. boolean flagCounterActive = false;
  48.  
  49.   // flag that conveys whether to print sync frequency or sync presence
  50. boolean flagPrintFreq;
  51.  
  52.   // Valid sync limits
  53. #define VSyncLB  30
  54. #define VSyncUB  125
  55. #define HSyncLB  25000
  56. #define HSyncUB  60000
  57.  
  58.  
  59. //    Other declarations
  60.  
  61.   // init ICP mode flag (in circuit programming)
  62. boolean flagICP = false;
  63.  
  64.   // sets the unit switch press time in milliseconds
  65. #define switchPressUnit 500;
  66.  
  67.   // init power and reset switch flags
  68. boolean flagPWR_SW;
  69. boolean flagRST_SW;
  70.  
  71.   // time holder for switch release/deactivation
  72. unsigned long powerSwitchReleaseTime;
  73. unsigned long resetSwitchReleaseTime;
  74.  
  75.  
  76. void setup()
  77. {
  78.   // start serial at 9600 bps, 8 bits, no parity, 1 stop bit
  79.   Serial.begin(9600);
  80.  
  81.   // set pin modes for ICP and power LED pins.
  82.   pinMode(pinICP, OUTPUT);
  83.   pinMode(pinPowerLED, INPUT_PULLUP);  //internal pull-up is required to translate open-drain output of PWR_LED signal source.
  84.  
  85.   // set ADC reference to internal
  86.   analogReference(INTERNAL);  //set ADC reference to internal
  87.  
  88.   // set ICP mode depending on flag initialization
  89.   if (flagICP) digitalWrite(pinICP, HIGH);
  90.   else digitalWrite(pinICP, LOW);
  91.  
  92.   // init power and reset button flags and outputs
  93.   flagPWR_SW = false;
  94.   openDrainOutput(pinPowerSwitch, false);
  95.   flagRST_SW = false;
  96.   openDrainOutput(pinResetSwitch, false);
  97.  
  98. }
  99.  
  100.  
  101. void loop()
  102. {
  103.   // check if data bytes are available on serial port. If true, pop a byte from
  104.   // serial FIFO buffer and send it to command interpreter.
  105.   if (Serial.available() > 0) commandInterpreter(Serial.read());
  106.    
  107.   // check if sync frequency counter is active and timer has finished. If true, end counter.
  108.   if ( flagCounterActive and (millis() - fcTimer >= fcTimerLimit) ) endFreqCounter();
  109.  
  110.   // check if power switch is activated and whether activation time has passed. If true, deactivate it.
  111.   if (flagPWR_SW and (millis() > powerSwitchReleaseTime))
  112.   {
  113.     flagPWR_SW = false;
  114.     openDrainOutput(pinPowerSwitch, false);
  115.   }  
  116.  
  117.   // check if reset switch is activated and whether activation time has passed. If true, deactivate it.
  118.   if (flagRST_SW and (millis() > resetSwitchReleaseTime))
  119.   {
  120.     flagRST_SW = false;
  121.     openDrainOutput(pinResetSwitch, false);
  122.   }  
  123. }
  124.  
  125.  
  126. // command interpreter that checks for vaild command byte and executes the given command
  127. void commandInterpreter(char command)
  128. {
  129.   switch(command)
  130.   {
  131.     case 'P':
  132.       //print VCCP voltage, rounded to 1 decimal digit
  133.       printFloat(getVoltage(pinVCCP), 1);
  134.       break;
  135.    
  136.     case 'F':
  137.       //print VCCF voltage, rounded to 1 decimal digit
  138.       printFloat(getVoltage(pinVCCF), 1);
  139.       break;
  140.    
  141.     case 'M':
  142.       //print VCCM voltage, rounded to 1 decimal digit
  143.       printFloat(getVoltage(pinVCCM), 1);
  144.       break;
  145.    
  146.     case '3':
  147.       //print A3 voltage, rounded to 1 decimal digit
  148.       printFloat(getVoltage(A3), 1);
  149.       break;
  150.    
  151.     case '4':
  152.       //print A4 voltage, rounded to 1 decimal digit
  153.       printFloat(getVoltage(A4), 1);
  154.       break;
  155.    
  156.     case '5':
  157.       //print A5 voltage, rounded to 1 decimal digit
  158.       printFloat(getVoltage(A5), 1);
  159.       break;
  160.    
  161.     case 'f':  //print HSync,VSync freq in Hz
  162.       flagPrintFreq = true;
  163.       beginFreqCounter();
  164.       break;
  165.              
  166.     case 'v': //print whether VGA is present
  167.       flagPrintFreq = false;
  168.       beginFreqCounter();
  169.       break;
  170.  
  171.     case 'i':  //get ICP mode
  172.       Serial.println(flagICP ? '1':'0');
  173.       break;
  174.      
  175.     case 'I':  //toggle ICP mode
  176.       if (flagICP)
  177.       {
  178.         digitalWrite(pinICP, LOW);
  179.         flagICP = false;
  180.       }
  181.       else
  182.       {
  183.         digitalWrite(pinICP, HIGH);
  184.         flagICP = true;
  185.       }
  186.       break;
  187.      
  188.     case 'p':  //activate soft power switch for 500ms
  189.       if (flagPWR_SW)
  190.       {
  191.         powerSwitchReleaseTime += switchPressUnit;
  192.       }
  193.       else
  194.       {
  195.         powerSwitchReleaseTime = millis() + switchPressUnit;
  196.         openDrainOutput(pinPowerSwitch, true);
  197.         flagPWR_SW = true;
  198.       }
  199.       break;
  200.  
  201.     case 'r':  //activate reset switch for 500ms
  202.       if (flagRST_SW)
  203.       {
  204.         resetSwitchReleaseTime += switchPressUnit;
  205.       }
  206.       else
  207.       {
  208.         resetSwitchReleaseTime = millis() + switchPressUnit;
  209.         openDrainOutput(pinResetSwitch, true);
  210.         flagRST_SW = true;
  211.       }
  212.       break;
  213.  
  214.     case 'l': //get power LED state
  215.       if (digitalRead(pinPowerLED) == HIGH)
  216.       {
  217.         Serial.println('0');
  218.       }
  219.       else
  220.       {
  221.         Serial.println('1');
  222.       }
  223.      
  224.       break;
  225.   }
  226. }
  227.  
  228.  
  229. // HSync pulse counting interrupt service routine
  230. void incrementHSPulseCount()
  231. {
  232.   HSPulseCount++;
  233. }
  234.  
  235.  
  236. // VSync pulse counting interrupt service routine
  237. void incrementVSPulseCount()
  238. {
  239.   VSPulseCount++;
  240. }
  241.  
  242.  
  243. // starts sync frequency counter.
  244. void beginFreqCounter()
  245. {
  246.   // reset timer and counters
  247.   fcTimer = millis();
  248.   HSPulseCount = 0;
  249.   VSPulseCount = 0;
  250.  
  251.   // enable frequency counter interrupts
  252.   attachInterrupt(0, incrementHSPulseCount, FALLING); // falling edge on pin 2 calls increment function for HSync counter
  253.   attachInterrupt(1, incrementVSPulseCount, FALLING); // falling edge on pin 3 calls increment function for VSync counter
  254.  
  255.   // convey to loop() that counter is active
  256.   flagCounterActive = true;
  257. }
  258.  
  259.  
  260. // ends sync frequency counter and prints out the result
  261. void endFreqCounter()
  262. {
  263.   // Count pulses and calculate frequency
  264.   HSync = HSPulseCount * (1000 / float(fcTimerLimit));
  265.   VSync = VSPulseCount * (1000 / float(fcTimerLimit));
  266.  
  267.   //remove interrupts
  268.   detachInterrupt(0);
  269.   detachInterrupt(1);
  270.  
  271.   // check for result type
  272.   if (flagPrintFreq)
  273.   {
  274.     //print frequencies
  275.     Serial.print('(');
  276.     Serial.print(HSync);
  277.     Serial.print(',');
  278.     Serial.print(VSync);
  279.     Serial.println(')');
  280.   }
  281.   else
  282.   {
  283.     // determine if sync frequencies are in correct range and print VGA presence
  284.     if ( VSyncLB < VSync and VSync < VSyncUB and HSyncLB < HSync and HSync < HSyncUB) Serial.println('1');
  285.     else Serial.println('0');
  286.    
  287.   }  
  288.   // set counter state to inactive
  289.   flagCounterActive = false;
  290. }
  291.  
  292.  
  293. // sorts given array. This is used in mode filtering
  294. void isort(short *a, short n){
  295. // *a is an array pointer function
  296.   for (short i = 1; i < n; ++i)
  297.   {
  298.     short j = a[i];
  299.     short k;
  300.     for (k = i - 1; (k >= 0) and (j < a[k]); k--)
  301.     {
  302.       a[k + 1] = a[k];
  303.     }
  304.     a[k + 1] = j;
  305.   }
  306. }
  307.  
  308.  
  309. // returns the mode of given array or return median if there's no mode.
  310. // (thanks to Arduino Playground)
  311. short mode(short *x,short n){
  312.   short i = 0;
  313.   short count = 0;
  314.   short maxCount = 0;
  315.   short mode = 0;
  316.   short bimodal;
  317.   short prevCount = 0;
  318.   while(i<(n-1))
  319.   {
  320.     prevCount=count;
  321.     count=0;
  322.     while(x[i]==x[i+1])
  323.     {
  324.       count++;
  325.       i++;
  326.     }
  327.     if(count>prevCount&count>maxCount)
  328.     {
  329.       mode=x[i];
  330.       maxCount=count;
  331.       bimodal=0;
  332.     }
  333.     if(count==0){
  334.       i++;
  335.     }
  336.     if(count==maxCount)  // If the sample array has 2 or more modes.
  337.     {
  338.       bimodal=1;
  339.     }
  340.     if(mode==0||bimodal==1)  // Return the median if there is no unique mode.
  341.     {
  342.       mode=x[(n/2)];
  343.     }
  344.     return mode;
  345.   }
  346. }
  347.  
  348.  
  349. // takes samples from ADC on the given pin and applies
  350. // mode function to get a concordant value
  351. short filteredAnalogRead(short pin)
  352. {
  353.   #define sampleArraySize 6  // set sample count for mode filtering
  354.  
  355.   short sampleArray[sampleArraySize];
  356.   for(short i=0; i < sampleArraySize; i++)
  357.   {
  358.     sampleArray[i] = analogRead(pin);
  359.     delay(1);
  360.   }
  361.   // sort array
  362.   isort(sampleArray, sampleArraySize);
  363.   // return mode
  364.   return mode(sampleArray, sampleArraySize);
  365. }
  366.  
  367.  
  368. // calculates voltage on given analog pin
  369. float getVoltage(short pin)
  370. {
  371.   return float(filteredAnalogRead(pin))/1023 * (upperResistance + lowerResistance) / lowerResistance * internalAnalogReference;
  372. }
  373.  
  374.  
  375. // emulates open drain output on power and reset switch outputs
  376. void openDrainOutput(int pin, boolean activate)
  377. {
  378.   if (activate) //if activate is true, set pin to Lo-Z
  379.   {
  380.     digitalWrite(pin, LOW);
  381.     pinMode(pin, OUTPUT);
  382.   }
  383.   else  //else set pin to Hi-Z
  384.   {
  385.     digitalWrite(pin, LOW);
  386.     pinMode(pin, INPUT);
  387.   }
  388. }
  389.  
  390.  
  391. // prints out the float 'value' rounded to 'places' places after
  392. // the decimal point. (Thanks to Arduino Playground)
  393. void printFloat(float value, int places) {
  394.   // this is used to cast digits
  395.   int digit;
  396.   float tens = 0.1;
  397.   int tenscount = 0;
  398.   int i;
  399.   float tempfloat = value;
  400.  
  401.   // calculate rounding term d:   0.5/pow(10,places)  
  402.   float d = 0.5;
  403.   if (value < 0)
  404.     d *= -1.0;
  405.  
  406.   // divide by ten for each decimal place
  407.   for (i = 0; i < places; i++)
  408.     d/= 10.0;    
  409.  
  410.   // this small addition, combined with truncation will round our values properly
  411.   tempfloat +=  d;
  412.  
  413.   // first get value tens to be the large power of ten less than value
  414.   // tenscount isn't necessary but it would be useful if you wanted to know after this how many chars the number will take
  415.  
  416.   if (value < 0)
  417.     tempfloat *= -1.0;
  418.   while ((tens * 10.0) <= tempfloat) {
  419.     tens *= 10.0;
  420.     tenscount += 1;
  421.   }
  422.  
  423.   // write out the negative if needed
  424.   if (value < 0)
  425.     Serial.print('-');
  426.  
  427.   if (tenscount == 0)
  428.     Serial.print(0, DEC);
  429.  
  430.   for (i=0; i< tenscount; i++) {
  431.     digit = (int) (tempfloat/tens);
  432.     Serial.print(digit, DEC);
  433.     tempfloat = tempfloat - ((float)digit * tens);
  434.     tens /= 10.0;
  435.   }
  436.  
  437.   // if no places after decimal, stop now and return
  438.   if (places <= 0)
  439.     return;
  440.  
  441.   // otherwise, write the point and continue on
  442.   Serial.print('.');  
  443.  
  444.   // now write out each decimal place by shifting digits one by one into the ones place and writing the truncated value
  445.   for (i = 0; i < places; i++) {
  446.     tempfloat *= 10.0;
  447.     digit = (int) tempfloat;
  448.     Serial.print(digit,DEC);  
  449.     // once written, subtract off that digit
  450.     tempfloat = tempfloat - (float) digit;
  451.   }
  452.   Serial.print("\r\n"); //print carriage return and line feed as println() does
  453. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement