Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // coreboot test interface board
- // by Ayush Sagar (ayush@ieee.org) for coreboot GSoC 2013
- // Last revised on 8 Sep 2013
- // Pin assignments
- #define pinICP 4
- #define pinPowerSwitch 5
- #define pinResetSwitch 6
- #define pinPowerLED 7
- #define pinVCCP A0
- #define pinVCCF A1
- #define pinVCCM A2
- // Note: HSync and VSync pins are assigned to pins 2 and 3 using attachInterrupt() in beginFreqCounter()
- // ADC related
- /* INTERNAL ADC VOLTAGE REFERENCE (important)
- Set 1.1V for Atmega168/328 and 2.56 for Atmega32U4
- 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*/
- #define internalAnalogReference 2.56
- // sets voltage divider resistances in ohms. Use tight tolerance resistors to ensure accuracy of ADC readings.
- #define upperResistance 9940 // connected across measured voltage and ADC input.
- #define lowerResistance 457 // connected across ADC input and ground.
- // Sync frequency counter
- // stores count of HS/VS pulses in given time window
- volatile unsigned short HSPulseCount = 0;
- volatile unsigned short VSPulseCount = 0;
- // stores HSync and VSync frequency in Hz
- unsigned short HSync = 0;
- unsigned short VSync = 0;
- // sets timer limit in msec for HSync and VSync frequency counter
- #define fcTimerLimit 500
- // timer for freq. calculations
- unsigned long fcTimer;
- // flag to convey state of counter
- boolean flagCounterActive = false;
- // flag that conveys whether to print sync frequency or sync presence
- boolean flagPrintFreq;
- // Valid sync limits
- #define VSyncLB 30
- #define VSyncUB 125
- #define HSyncLB 25000
- #define HSyncUB 60000
- // Other declarations
- // init ICP mode flag (in circuit programming)
- boolean flagICP = false;
- // sets the unit switch press time in milliseconds
- #define switchPressUnit 500;
- // init power and reset switch flags
- boolean flagPWR_SW;
- boolean flagRST_SW;
- // time holder for switch release/deactivation
- unsigned long powerSwitchReleaseTime;
- unsigned long resetSwitchReleaseTime;
- void setup()
- {
- // start serial at 9600 bps, 8 bits, no parity, 1 stop bit
- Serial.begin(9600);
- // set pin modes for ICP and power LED pins.
- pinMode(pinICP, OUTPUT);
- pinMode(pinPowerLED, INPUT_PULLUP); //internal pull-up is required to translate open-drain output of PWR_LED signal source.
- // set ADC reference to internal
- analogReference(INTERNAL); //set ADC reference to internal
- // set ICP mode depending on flag initialization
- if (flagICP) digitalWrite(pinICP, HIGH);
- else digitalWrite(pinICP, LOW);
- // init power and reset button flags and outputs
- flagPWR_SW = false;
- openDrainOutput(pinPowerSwitch, false);
- flagRST_SW = false;
- openDrainOutput(pinResetSwitch, false);
- }
- void loop()
- {
- // check if data bytes are available on serial port. If true, pop a byte from
- // serial FIFO buffer and send it to command interpreter.
- if (Serial.available() > 0) commandInterpreter(Serial.read());
- // check if sync frequency counter is active and timer has finished. If true, end counter.
- if ( flagCounterActive and (millis() - fcTimer >= fcTimerLimit) ) endFreqCounter();
- // check if power switch is activated and whether activation time has passed. If true, deactivate it.
- if (flagPWR_SW and (millis() > powerSwitchReleaseTime))
- {
- flagPWR_SW = false;
- openDrainOutput(pinPowerSwitch, false);
- }
- // check if reset switch is activated and whether activation time has passed. If true, deactivate it.
- if (flagRST_SW and (millis() > resetSwitchReleaseTime))
- {
- flagRST_SW = false;
- openDrainOutput(pinResetSwitch, false);
- }
- }
- // command interpreter that checks for vaild command byte and executes the given command
- void commandInterpreter(char command)
- {
- switch(command)
- {
- case 'P':
- //print VCCP voltage, rounded to 1 decimal digit
- printFloat(getVoltage(pinVCCP), 1);
- break;
- case 'F':
- //print VCCF voltage, rounded to 1 decimal digit
- printFloat(getVoltage(pinVCCF), 1);
- break;
- case 'M':
- //print VCCM voltage, rounded to 1 decimal digit
- printFloat(getVoltage(pinVCCM), 1);
- break;
- case '3':
- //print A3 voltage, rounded to 1 decimal digit
- printFloat(getVoltage(A3), 1);
- break;
- case '4':
- //print A4 voltage, rounded to 1 decimal digit
- printFloat(getVoltage(A4), 1);
- break;
- case '5':
- //print A5 voltage, rounded to 1 decimal digit
- printFloat(getVoltage(A5), 1);
- break;
- case 'f': //print HSync,VSync freq in Hz
- flagPrintFreq = true;
- beginFreqCounter();
- break;
- case 'v': //print whether VGA is present
- flagPrintFreq = false;
- beginFreqCounter();
- break;
- case 'i': //get ICP mode
- Serial.println(flagICP ? '1':'0');
- break;
- case 'I': //toggle ICP mode
- if (flagICP)
- {
- digitalWrite(pinICP, LOW);
- flagICP = false;
- }
- else
- {
- digitalWrite(pinICP, HIGH);
- flagICP = true;
- }
- break;
- case 'p': //activate soft power switch for 500ms
- if (flagPWR_SW)
- {
- powerSwitchReleaseTime += switchPressUnit;
- }
- else
- {
- powerSwitchReleaseTime = millis() + switchPressUnit;
- openDrainOutput(pinPowerSwitch, true);
- flagPWR_SW = true;
- }
- break;
- case 'r': //activate reset switch for 500ms
- if (flagRST_SW)
- {
- resetSwitchReleaseTime += switchPressUnit;
- }
- else
- {
- resetSwitchReleaseTime = millis() + switchPressUnit;
- openDrainOutput(pinResetSwitch, true);
- flagRST_SW = true;
- }
- break;
- case 'l': //get power LED state
- if (digitalRead(pinPowerLED) == HIGH)
- {
- Serial.println('0');
- }
- else
- {
- Serial.println('1');
- }
- break;
- }
- }
- // HSync pulse counting interrupt service routine
- void incrementHSPulseCount()
- {
- HSPulseCount++;
- }
- // VSync pulse counting interrupt service routine
- void incrementVSPulseCount()
- {
- VSPulseCount++;
- }
- // starts sync frequency counter.
- void beginFreqCounter()
- {
- // reset timer and counters
- fcTimer = millis();
- HSPulseCount = 0;
- VSPulseCount = 0;
- // enable frequency counter interrupts
- attachInterrupt(0, incrementHSPulseCount, FALLING); // falling edge on pin 2 calls increment function for HSync counter
- attachInterrupt(1, incrementVSPulseCount, FALLING); // falling edge on pin 3 calls increment function for VSync counter
- // convey to loop() that counter is active
- flagCounterActive = true;
- }
- // ends sync frequency counter and prints out the result
- void endFreqCounter()
- {
- // Count pulses and calculate frequency
- HSync = HSPulseCount * (1000 / float(fcTimerLimit));
- VSync = VSPulseCount * (1000 / float(fcTimerLimit));
- //remove interrupts
- detachInterrupt(0);
- detachInterrupt(1);
- // check for result type
- if (flagPrintFreq)
- {
- //print frequencies
- Serial.print('(');
- Serial.print(HSync);
- Serial.print(',');
- Serial.print(VSync);
- Serial.println(')');
- }
- else
- {
- // determine if sync frequencies are in correct range and print VGA presence
- if ( VSyncLB < VSync and VSync < VSyncUB and HSyncLB < HSync and HSync < HSyncUB) Serial.println('1');
- else Serial.println('0');
- }
- // set counter state to inactive
- flagCounterActive = false;
- }
- // sorts given array. This is used in mode filtering
- void isort(short *a, short n){
- // *a is an array pointer function
- for (short i = 1; i < n; ++i)
- {
- short j = a[i];
- short k;
- for (k = i - 1; (k >= 0) and (j < a[k]); k--)
- {
- a[k + 1] = a[k];
- }
- a[k + 1] = j;
- }
- }
- // returns the mode of given array or return median if there's no mode.
- // (thanks to Arduino Playground)
- short mode(short *x,short n){
- short i = 0;
- short count = 0;
- short maxCount = 0;
- short mode = 0;
- short bimodal;
- short prevCount = 0;
- while(i<(n-1))
- {
- prevCount=count;
- count=0;
- while(x[i]==x[i+1])
- {
- count++;
- i++;
- }
- if(count>prevCount&count>maxCount)
- {
- mode=x[i];
- maxCount=count;
- bimodal=0;
- }
- if(count==0){
- i++;
- }
- if(count==maxCount) // If the sample array has 2 or more modes.
- {
- bimodal=1;
- }
- if(mode==0||bimodal==1) // Return the median if there is no unique mode.
- {
- mode=x[(n/2)];
- }
- return mode;
- }
- }
- // takes samples from ADC on the given pin and applies
- // mode function to get a concordant value
- short filteredAnalogRead(short pin)
- {
- #define sampleArraySize 6 // set sample count for mode filtering
- short sampleArray[sampleArraySize];
- for(short i=0; i < sampleArraySize; i++)
- {
- sampleArray[i] = analogRead(pin);
- delay(1);
- }
- // sort array
- isort(sampleArray, sampleArraySize);
- // return mode
- return mode(sampleArray, sampleArraySize);
- }
- // calculates voltage on given analog pin
- float getVoltage(short pin)
- {
- return float(filteredAnalogRead(pin))/1023 * (upperResistance + lowerResistance) / lowerResistance * internalAnalogReference;
- }
- // emulates open drain output on power and reset switch outputs
- void openDrainOutput(int pin, boolean activate)
- {
- if (activate) //if activate is true, set pin to Lo-Z
- {
- digitalWrite(pin, LOW);
- pinMode(pin, OUTPUT);
- }
- else //else set pin to Hi-Z
- {
- digitalWrite(pin, LOW);
- pinMode(pin, INPUT);
- }
- }
- // prints out the float 'value' rounded to 'places' places after
- // the decimal point. (Thanks to Arduino Playground)
- void printFloat(float value, int places) {
- // this is used to cast digits
- int digit;
- float tens = 0.1;
- int tenscount = 0;
- int i;
- float tempfloat = value;
- // calculate rounding term d: 0.5/pow(10,places)
- float d = 0.5;
- if (value < 0)
- d *= -1.0;
- // divide by ten for each decimal place
- for (i = 0; i < places; i++)
- d/= 10.0;
- // this small addition, combined with truncation will round our values properly
- tempfloat += d;
- // first get value tens to be the large power of ten less than value
- // tenscount isn't necessary but it would be useful if you wanted to know after this how many chars the number will take
- if (value < 0)
- tempfloat *= -1.0;
- while ((tens * 10.0) <= tempfloat) {
- tens *= 10.0;
- tenscount += 1;
- }
- // write out the negative if needed
- if (value < 0)
- Serial.print('-');
- if (tenscount == 0)
- Serial.print(0, DEC);
- for (i=0; i< tenscount; i++) {
- digit = (int) (tempfloat/tens);
- Serial.print(digit, DEC);
- tempfloat = tempfloat - ((float)digit * tens);
- tens /= 10.0;
- }
- // if no places after decimal, stop now and return
- if (places <= 0)
- return;
- // otherwise, write the point and continue on
- Serial.print('.');
- // now write out each decimal place by shifting digits one by one into the ones place and writing the truncated value
- for (i = 0; i < places; i++) {
- tempfloat *= 10.0;
- digit = (int) tempfloat;
- Serial.print(digit,DEC);
- // once written, subtract off that digit
- tempfloat = tempfloat - (float) digit;
- }
- Serial.print("\r\n"); //print carriage return and line feed as println() does
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement