ButterflyMP3

power.c

Go to the documentation of this file.
00001 
00037 #include <avr/io.h>
00038 #include <avr/pgmspace.h>
00039 #include <avr/interrupt.h>
00040 
00041 #include "power.h"
00042 #include "main.h"
00043 #include "types.h"
00044 #include "uart.h"
00045 #include "vs1001.h"
00046 #include "lcdgraphics.h"
00047 #include "eeprom.h"
00048 #include "ADC.h"
00049 #include "button.h"
00050 
00051 
00058 void Power_save(void)
00059 {
00060 //      PRINT("pDWN");
00061         SMCR = (2<<SM0) | (1<<SE);      // Enable Power-down mode
00062         asm volatile ("sleep"::);
00063         // NOTE: need to hit a button when inserting card to wakeup. !!
00064         // will add RTC later for power down time out etc which should 
00065         // wake up and detect card once a second.
00066         SMCR = 0;                       // Just woke, disable sleep
00067 }
00068 
00069 
00076 void Power_idle(void)
00077 {
00078         //PRINT("pIDLE");
00079         SMCR = (1<<SE);                 // Enable idle mode
00080         asm volatile ("sleep"::);
00081         
00082         SMCR = 0;                       // Just woke, disable sleep
00083 }
00084 
00085 
00091 void Power_off(void)
00092 {
00093         char k;
00094         PRINT("pOFF");EOL();
00095 #ifdef VS1001
00096         uint16  buf[2];
00097 #endif
00098     
00099         //SHUTDOWN LCD
00100         LCD_Sleep();                                    
00101         
00102         //SHUTDOWN UART
00103         UART_Shutdown();
00104         
00105         //SHUTDOWN vs1001k
00106 #ifdef VS1001
00107         vs1001_read(SCI_MODE, 1, buf);
00108         buf[1] |= SM_PDOWN;
00109         vs1001_write(SCI_MODE,1,buf);
00110 #else
00111     //TODO: put routines for vs1011e here!
00112 #endif
00113         CBI(RESET_PORT, RESET_PIN);     // RESET- low
00114         // RESET_PIN is pulled low by external resistor ( R9 rev C) during bootloader mode
00115         // R9 is neccesary to hold reset low while Butterfly is in bootloader mode.
00116         
00117         //MMC should go into shutdown by default as per 
00118         //"SanDisk MultiMediaCard and Reduced-Size MultiMediaCard Product Manual"
00119         //Doc No. 80-36-00320 v1.0 page 1-4 sec 1.10
00120         
00121         while(1){
00122                 // Put into low power mode (no write to eeprom)
00123                 Power_save();
00124                 
00125                 if(!(PINB & (1<<PINB6)))        // mt if(!(PINB & (1<<PORTB6)))
00126                 {   // joystick "up" detected
00127                         
00128                         //wake up UART
00129                         UART_Init();
00130                         
00131                         //wake up VS1001
00132                         SBI(RESET_PORT, RESET_PIN);     // RESET- Hi
00133                         
00134                         //wake up LCD
00135                         LCD_Wake();
00136                         
00137                         // wait for up key to be released to avoid double detect.
00138                         while (!(PINB & (1<<PINB6)));
00139                         
00140                         k = getkey();           //clear the key buffer of any false detections
00141                         gPowerSaveTimer = 0;    // reset the timeout.
00142                         
00143                         return;
00144                 }
00145                 else if(!(PINB & (1<<PINB7)))                
00146                 {       //Joystick "down" detected
00147                         
00148                         //save current settings
00149                         save_player_options();
00150                         
00151                         //TODO: Write MMC Serial Number to EEPROM
00152                         
00153                         //write current song to EEPROM
00154                         save_player_state();
00155                         
00156                         //Jump to Bootloader
00157                         WDTCR = (1<<WDCE) | (1<<WDE);     //Enable Watchdog Timer to give reset
00158                         while(1);   
00159                         // wait for watchdog-reset, since the BOOTRST-fuse is 
00160                         // programmed, the Boot-section will be entered upon reset.
00161                         
00162                         // Press UP to turn on again. (and exit the bootloader)
00163                         
00164                 }
00165         }
00166         
00167         // NOTE: for the standby mode to work as intended, the butterfly must have 
00168         // the original bootloader installed and have the 
00169         // "Boot Reset vector Enabled - BOOTRST" fuse programmed.
00170         
00171 }
00172 
00179 void Power_Init(void)
00180 {
00181         
00182         // clear portf for ADC use 
00183         DDRF = 0x00;
00184         PORTF = 0x00;
00185         
00186         //setup adc internal 1.1 volt reference and voltage sensor
00187         ADMUX = VOLTAGE_SENSOR|(1<<REFS0)|(1<<REFS1);
00188         //Free running mode 
00189         ADCSRB = (0<<ADTS2) |(0<<ADTS1) |(0<<ADTS0);
00190         // set ADC prescaler to , 8MHz / 128 = 62.5kHz  ,  auto trigger
00191         ADCSRA = (1<<ADEN)| (1<<ADSC) | (0<<ADATE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
00192         
00193 }
00194 
00195 
00196 
00197 
00205 uint16  Power_check(void)
00206 {
00207         uint8 i;
00208         uint16  batteryVoltage=0;
00209         uint32 ADC_temp;
00210         
00211         // Check Battery Voltage.
00212         ADCSRA |= (1<<ADEN)|(1<<ADSC);          //Start ADC
00213         while(!(ADCSRA & 0x10));    // wait for conversion done, ADIF flag active
00214         
00215     for(i=0;i<8;i++)            // do the ADC conversion 8 times for better accuracy 
00216     {
00217         ADCSRA |= (1<<ADSC);        // do single conversion
00218         while(!(ADCSRA & 0x10));    // wait for conversion done, ADIF flag active
00219         
00220         ADC_temp = ADCL;            // read out ADCL register
00221         ADC_temp += (ADCH << 8);    // read out ADCH register        
00222                 
00223         batteryVoltage += ADC_temp;      // accumulate result (8 samples) for later averaging
00224     }
00225         
00226     batteryVoltage = batteryVoltage >> 3;     // average the 8 samples
00227         
00228         ADCSRA &= ~((1<<ADEN));
00229         //ADCSRA |= (1<<ADIF); //reset interruppt flag
00230         
00231         PRINT("VOLTAGE ");
00232         UART_Printfu16(batteryVoltage);
00233         EOL();
00234         
00235         return batteryVoltage;
00236 }
00237 
00254 uint16 Power_pcnt(uint16 voltage)
00255 {
00256         uint16 percentage;
00257         
00258         if (voltage > PWR_MAX_V){ // battery is really really good
00259                 percentage = 100;
00260                 
00261         }else if (voltage> PWR_GOOD_V){ // battery is freshly charged
00262                 percentage =  (voltage - PWR_GOOD_V) * (100-66);
00263                 percentage /= (PWR_MAX_V -PWR_GOOD_V);
00264                 percentage += 66;
00265                 
00266         }else if (voltage>PWR_LOW_V){ // normal operation mode
00267                 percentage =  (voltage - PWR_LOW_V) * (66-12); 
00268                 percentage /= (PWR_GOOD_V - PWR_LOW_V);
00269                 percentage += 12;
00270                 
00271         }else{ // only 12% left
00272                 percentage =  (voltage - PWR_ABS_MIN_V) * (12-0);
00273                 percentage /= (PWR_LOW_V - PWR_ABS_MIN_V);
00274                 
00275         }
00276         
00277         // old calculation
00278         //percentage = (voltage-PWR_ABS_MIN_V)*100/(PWR_MAX_V-PWR_ABS_MIN_V);   
00279 
00280         return percentage;
00281 }
00282 
 All Files Functions Variables Typedefs Enumerations Enumerator Defines