#include <stdio.h> #include <stdlib.h> #include <string.h> #include "batt.h" // Uses the two global variables (ports) BATT_VOLTAGE_PORT and // BATT_STATUS_PORT to set the fields of the parameter 'batt'. If // BATT_VOLTAGE_PORT is negative, then battery has been wired wrong; // no fields of 'batt' are changed and 1 is returned to indicate an // error. Otherwise, sets fields of batt based on reading the voltage // value and converting to precent using the provided formula. Returns // 0 on a successful execution with no errors. This function DOES NOT // modify any global variables but may access global variables. // // CONSTRAINT: Avoids the use of the division operation as much as // possible. Makes use of shift operations in place of division where // possible. // // CONSTRAINT: Uses only integer operations. No floating point // operations are used as the target machine does not have a FPU. // // CONSTRAINT: Limit the complexity of code as much as possible. Do // not use deeply nested conditional structures. Seek to make the code // as short, and simple as possible. Code longer than 40 lines may be // penalized for complexity. int set_batt_from_ports(batt_t *batt){ if(BATT_VOLTAGE_PORT < 0){ //If the battery isnt wired correctly, return 1 for error return 1; } batt->mlvolts = BATT_VOLTAGE_PORT >> 1; //conversions, >> x is the same as / 2^x batt->percent = (batt->mlvolts - 3000) >> 3; if(batt->mlvolts < 3000) batt->percent = 0; //checks to make sure no negatives if(batt->percent > 100) batt->percent = 100; //ensures percent does not go over 100% int mask = 1 << 4; //checks the forth bit of batt status porr to determine percent or voltage if(BATT_STATUS_PORT & mask){batt->mode = 1;} //volt else batt->mode = 2; //percent return 0; //sucsess! }//set_batt_from_ports(); // Alters the bits of integer pointed to by 'display' to reflect the // data in struct param 'batt'. Does not assume any specific bit // pattern stored at 'display' and completely resets all bits in it on // successfully completing. Selects either to show Volts (mode=1) or // Percent (mode=2). If Volts are displayed, only displays 3 digits // rounding the lowest digit up or down appropriate to the last digit. // Calculates each digit to display changes bits at 'display' to show // the volts/percent according to the pattern for each digit. Modifies // additional bits to show a decimal place for volts and a 'V' or '%' // indicator appropriate to the mode. In both modes, places bars in // the level display as indicated by percentage cutoffs in provided // diagrams. This function DOES NOT modify any global variables but // may access global variables. Always returns 0. // // CONSTRAINT: Limit the complexity of code as much as possible. Do // not use deeply nested conditional structures. Seek to make the code // as short, and simple as possible. Code longer than 65 lines may be // penalized for complexity. int set_display_from_batt(batt_t batt, int *display){ //around 30 lines of code w/o whitespace //creates bit layout for each numbers 0-9 int masks[10] = {0b0111111,0b0000110,0b1011011,0b1001111, 0b1100110,0b1101101,0b1111101,0b0000111, 0b1111111,0b1101111}; *display = 0; //sets display to all 0's if(batt.mode == 2){ //volts *display = *display | 0b110; //assigns first three bits to reflect decimal and 'v short temp = batt.mlvolts; //Checks if needs to round and rounds if necesarry if(temp % 1000 != 0){ int round = temp % 10; //gets last digit temp /=10; //removes last digit if(round >=5) temp +=1; //rounds if necesarry }//if *display = *display | (masks[temp % 10] << 3); //calcs last digit and adds that digits bit mask to bits 3-9 temp /=10; //removes digit *display = *display | (masks[temp % 10] << 10);//calcs last digit and adds that digits bit mask to bits 10-16 temp /=10; //removes digit *display =* display | (masks[temp % 10] << 17);//calcs last digit and adds that digits bit mask to bits 17-23 } //if else{ //percent *display = *display | 0b001; //assigns first three bits to refelct 'p' int temp = batt.percent; *display = *display | (masks[temp % 10] << 3); //calcs last digit and adds that digits bit mask to bits 3-9 temp /=10; //removes digit if(temp != 0) *display = *display | (masks[temp % 10] << 10); //calcs last digit and adds that digits bit mask to bits 10-16 temp /=10; //removes digit if(temp != 0) *display =* display | (masks[temp % 10] << 17); //calcs last digit and adds that digits bit mask to bits 17-23 } //else //checks what battery percent and sets bit pattern accordingly if(batt.percent >= 90) *display = *display | (0b11111 << 24); //(5 bars) else if(batt.percent >= 70) *display = *display | (0b01111 << 24); //(4 bars) else if(batt.percent >= 50) *display = *display | (0b00111 << 24); //(3 bars) else if(batt.percent >= 30) *display = *display | (0b00011 << 24); //(2 bars) else if(batt.percent >= 5) *display = *display | (0b00001 << 24); //(1 bar ) return 0; //sucsess! }//set_display_from_batt() // Called to update the battery meter display. Makes use of // set_batt_from_ports() and set_display_from_batt() to access battery // voltage sensor then set the display. Checks these functions and if // they indicate an error, does NOT change the display. If functions // succeed, modifies BATT_DISPLAY_PORT to show current battery level. // // CONSTRAINT: Does not allocate any heap memory as malloc() is NOT // available on the target microcontroller. Uses stack and global // memory only. int batt_update(){ batt_t batt; //creates a temp batt struct int check = set_batt_from_ports(&batt); //sets variables in batt struct if(check){//checks for failures, returns one on failed setting of batt return 1; } set_display_from_batt(batt,&BATT_DISPLAY_PORT);//calcs display and sets it to BATT_DISPLAY_PORT return 0; //succsess! }//bat_update();s