//***************************************************************************** // File Name : phoneon.c // // Title : Keeps cellphone switched on. Attempts to power it on when off. // Revision : 1.0 // Notes : // Target MCU : Atmel AVR series, namely ATtiny2313 (should've been ATtiny15 but was out of stock) // Editor Tabs : 4 // // Revision History: // When Who Description of change // ----------- ----------- ----------------------- // 26-Apr-2007 Shaddack Created the program //***************************************************************************** /* Comments: Pinout: Pin 2: Rx for UART, unused; receiving a byte causes lock-up which triggers watchdog and chip reset Pin 3: Tx for UART, used to send chip status; sends "PhoneGuard" string at power-on, then these status chars: '+': normal state, phone is on 'W': phone is off, initial waiting 'S': phone is off, attempting to switch it on (PWR button "pressed") 'w': phone is off, waiting for retry 's': phone is starting to be switched on, initial delay for the button press Pin 8: PORTD:4, Invert, force state inversion when grounded (keep OFF instead of ON), input w/ pullup Pin 9: PORTD:5, LED_COMPAR, indication of comparator state (1=input low, phone off) Pin 10: GND, system power ground Pin 11: PORTD:6, OUTPUT, connected via 1k resistor to the base of a NPN transistor (BC337) that grounds the power button lead Pin 12: AIN0, fixed analog comparator input; connected to a 100k pot serving as adjusting of decision level; the fixed ends of the pot are connected to Vcc and GND Pin 13: AIN1, variable analog comparator input; connected to the battery temperature sense lead. Voltages are: 0V: the phone is off 0.4V: the phone is on Caveat: When the phone is being switched on, a short pulse at OUTPUT causes a pulse at AIN1, so it is required to prolong the duration of the OUTPUT pulse Pin 20: Vcc, system power U1 .--------. -| 1 20|---------------*--------------------o Vcc 3.6V Rx -| 2 19|- | _ Tx -| 3 18|- \ /| Invert o----. -| 4 17|- // | -| 5 16|- /\ R2 LED1 | -| 6 15|- / / 100k,pot | -| 7 14|- | | \\ `------| 8 13|------------------------------------o SENSE 0..0.4V .--|<|----------| 9 12|-----------' | | .------|10 11|---. | \ | `--------' | | .------------o Phone-Power / R2 | ATtiny2313 | | / \ 1k | | R1 | |/ Q1 / | *--/\/\/\-------| BC337 | | | 1k | |\ | | | | _\| | | | | | `--------*-------------------------------*-------*----*-------o GND | | `---/\/\/\------|>|------' R3,1k LED2 \\ LED1/R2 and LED2/R3 are optional. TODO: Add a function for external control of phone power. Suggestion: External input that decides if the phone should be kept ON or OFF, XORed with the result of the comparator .--------. /RST PC6 -| 1 28|- PC5 ADC5 SCL Rx PD0 -| 2 27|- PC4 ADC4 SDA (Shad's RS232 adapter: Rx=edge, Tx=center) Tx PD1 -| 3 26|- PC3 ADC3 INT0 PD2 -| 4 25|- PC2 ADC2 INT1 PD3 -| 5 24|- PC1 ADC1 XCK/T0 PD4 -| 6 23|- PC0 ADC0 Vcc -| 7 22|- GND GND -| 8 21|- ARef Xtal1 PB6 -| 9 20|- AVcc Xtal2 PB7 -|10 19|- PB5 SCK T1 PD5 -|11 18|- PB4 MISO AIN0 PD6 -|12 17|- PB3 MOSI OC2 AIN1 PD7 -|13 16|- PB2 /SS OC1B ICP1 PB0 -|14 15|- PB1 OC1A `--------' Fuse Low Byte = 0xef 1110-1111 (4 MHz xtal) Fuse Low Byte = 0xe1 1110-0001 (1 MHz internal) Fuse Low Byte = 0xe3 1110-0011 (4 MHz internal) Fuse High Byte = 0xd9 1100-1100 Fuse Extended Byte = 0xff Fuse Low: 7: BODLEVEL: brown out detector voltage level 6: BODEN: 1: brown out detector disabled 5,4: SUT1,SUT0, startup time, 1,0: maximum startup delay 3..0: Clock Source; 0000: external clock 0001: internal 1 MHz RC clock 0010: internal 2 MHz RC clock 0011: internal 4 MHz RC clock 0100: internal 8 MHz RC clock 1001: external xtal 32 kHz 1100: external xtal 0.9-3 MHz 1110: external xtal 3-8 MHz 1111: external xtal 3-8 MHz Fuse High: 7: Reset Disable, 1: C6=RESET 6: Watchdog, 1:always-on, 0:controlled by WDTCR 5: SPIEN, 0:enable serial programming 4: CKOPT, oscillator options, 1=full output swing, 0=reduced swing (lower freq, lower noise immunity) 3: EESAVE, 0: keep EEPROM values during chip erase 2,1: BOOTSIZE 0: RESET vector, 1: .--------. Reset, Prog /RST PC6 -| 1 28|- PC5 ADC5 SCL Tx Rx PD0 -| 2 27|- PC4 ADC4 SDA Rx Tx PD1 -| 3 26|- PC3 ADC3 INT0 PD2 -| 4 25|- PC2 ADC2 INT1 PD3 -| 5 24|- PC1 ADC1 XCK/T0 PD4 -| 6 23|- PC0 ADC0 Vcc Vcc -| 7 22|- GND GND GND GND -| 8 21|- ARef Xtal1 PB6 -| 9 20|- AVcc Xtal2 PB7 -|10 19|- PB5 SCK Prog COMPARATOR_LED T1 PD5 -|11 18|- PB4 MISO Prog PHONE_RESET AIN0 PD6 -|12 17|- PB3 MOSI OC2 Prog AIN1 PD7 -|13 16|- PB2 /SS OC1B INPUT2 INPUT0 ICP1 PB0 -|14 15|- PB1 OC1A INPUT1 `--------' MCU:m8 Atmel AVR ATmega8 is found. Fuse Low Byte = 0xe3 Fuse High Byte = 0xd9 Fuse Extended Byte = 0xff Calibration Byte = 0xc4 -- Read Only Lock Bits = 0xff BLB12 -> 1 BLB11 -> 1 BLB02 -> 1 BLB01 -> 1 LB2 -> 1 LB1 -> 1 */ #define PREFIXID "PhG0" //----- Include Files --------------------------------------------------------- #include // include I/O definitions (port names, pin names, etc) //#include // include "signal" names (interrupt names) #include // include "signal" names (interrupt names) #include #include #include #include // include A/D converter function library #include "global.h" // include our global settings #include "uartshad.h" // include Shaddack-modified uart function library //----- Begin Code ------------------------------------------------------------ u16 t; volatile u16 tmr0; volatile u16 tmr1; volatile u16 tmr2; //u08 inline void uartout(u08 c) { while( !( UCSRA & (1<>=4; t&=0x0F; if(t<=9)o(t+'0'); else o(t+'A'-10); } void ohex(u08 t) { ohigh(t);olow(t);} void ohex16(u16 t) { olow(t>>12); olow(t>>8); olow(t>>4); olow(t); } void ohex32(u32 t) { ohex16(t>>16); ohex16(t); } void ohex24(u32 t) { ohex(t>>16); ohex16(t); } void ohex12(u16 t) { olow(t>>8); olow(t>>4); olow(t); } #define VAL_VCC 10 #define VAL_SENS 5 void printmV(u16 t,u08 factor) { // Assuming 2.560V internal reference // Use factor = 10 for 1:1 voltage divider // Use factor = 5 for direct connection to ADC // ohex12(t); //debug // o('|'); //debug t*=factor; // beware of type overflow - does not apply for 12-bit value but beware of code reuse t/=2; // total multiplier *5 or *2.5 t+=5; // rounding o('0'+((t/1000)%10)); o('.'); o('0'+((t/100)%10)); o('0'+((t/10)%10)); // o('0'+(t%10)); } void printtime(u32 tm) { u16 t; tm*=206; tm/=100;//*2.06[041], in seconds t=tm/86400; // days o('0'+((t/100)%10)); o('0'+((t/10)%10)); o('0'+((t)%10)); o(':'); t=(tm/3600)%24; // hours o('0'+((t/10)%10)); o('0'+((t)%10)); o(':'); t=(tm/60)%60; // minutes o('0'+((t/10)%10)); o('0'+((t)%10)); o(':'); t=tm%60; // seconds o('0'+((t/10)%10)); o('0'+((t)%10)); } u08 phonestate; u16 adc1; u16 adc2; u08 state_prev=0; u08 state_now=0; u16 adc1thr=0x80; u16 rst_pulse_length=0x20; u16 rst_pulse_delay=0x90; u16 rst_pulseon_delay=0x10; u16 add_rst_pulse=0; u16 add_rst_delay=0; u16 add_rst_step=0; u16 add_pulseon_delay=0; #define ADD_RST_PULSE_STEP 0x04 #define ADD_RST_DELAY_STEP 0x20 #define ADD_RST_MAXSTEP 0x07 #define ADD_PULSEON_DELAY_STEP 0x04 #define TIMER_SUCCESSFUL_POWERON 0x1000 u32 adc2avg=0; u16 adc2cnt=0; u16 adc2lo=0xFFF; u16 adc2hi=0; u08 adc2done; u32 adc1avg=0; u16 adc1lo=0xFFF; u16 adc1hi=0; u08 outstat; u32 uptime=0; u32 uptimeph=0; u16 resetcnt=0; u08 volatile rxlastchar='?'; int main(void) { wdt_enable(WDTO_2S); wdt_reset(); // initialize the UART (serial port) uartInit(); // set the baud rate of the UART for our debug/reporting output uartSetBaudRate(9600); /* for ATtiny2323 */ /* DDRA = 0x00; PORTA = 0x00; outb(DDRB,0x00); // all pins input outb(PORTB,0x00); // no pullups // outb(DDRD,0xff); // all pins output outb(DDRD,0xff-0x10); // all pins output except D4 outb(PORTD,0x00+0x10); // all pins set to 0, pullup at D4 // init the comparator ACSR=0x00; DIDR=0x00; // init the timer0 outb(TCCR0A,0x00); // no PWM, no comparator outb(TCCR0B,TIMER_CLK_DIV256); // prescaler outb(TCNT0, 0); // reset TCNT0 sbi(TIMSK, TOIE0); // enable TCNT0 overflow interrupt */ /* for ATmega8 */ outb(UBRRL, BAUDDIV); outb(UBRRH, BAUDDIV>>8); UCSRB=BV(RXEN)|BV(TXEN); UCSRC=(BV(URSEL))|(3<rst_pulseon_delay+add_pulseon_delay){LED_RESET_OFF;} if(tmr2>TIMER_SUCCESSFUL_POWERON) {tmr2=0;add_rst_pulse=0;add_rst_delay=0;add_rst_step=0;add_pulseon_delay=0;opstrlf("PhoneAssumedConnected");} } else if(state_prev==1) {tmr2=0; if(tmr1==0) {tmr1=1;tmr2=1;outstat=1; opstrlf("PhoneIsDown");} else if(tmr1adc2)adc2lo=adc2; if(adc2hiadc1)adc1lo=adc1; if(adc1hi=RXBUFSIZE)rxbufptr=0; rxnextlinelen++; */ }