/*
* Author: Michael Albert * 11.03.2008 * * Configure your ttyS0 to 2400 8N1 * Wakes an ATX PC in xx Seconds transmitted by uart * * Unterstands 3 commands: * ATC resets/deletes an active wakeup * ATS1234 starts PC in 1234 seconds * ATP prints out the Timer state * * Editor/avr-gcc WinAVR 20071221 * License: GNU General Public License * * LICENSE: * Copyright (C) 2008 Michael Albert * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Feel free to modify! * * Changes: * 11.04.2008 Michael Albert V1.1 Option to start the box delayed after power is connected. */ /* TODO INTERRUPT */ #include <avr/io.h> #include <avr/interrupt.h> #include <string.h> #include <stdlib.h> #include <util/delay.h> // Peter fleury's uart library #include "uart.h" // For bool variables #define TRUE 1 #define FALSE 0 // 9600 does not work for my atmega8 ???? #define BAUD_RATE 2400 // Should we echo each received byte back to uart? #define UART_ECHO 1 // Define my Port BIT Names // Timer running PortC 2, atmega8 Pin 25 #define COUNTER_ACTIVE_LED PC2 // Board running PortC 1, atmega8 Pin 24 #define ACTIVE_LED PC1 // PIN for POWER button, atmega8 Pin 23 #define POWER_PIN PC0 // Input PIN for 5V VDC, atmega8 Pin 28 #define PIN_5VDC PINC5 // Input PIN for Press Powerbutton after xx Seconds wenn Powersupply is connected to electricity network. // atmega8 Pin 26, is Low Active, means Powerbutton would only pressed wenn PIN26 is conntect to GND #define IN_AUTO_PRESS_POWERBUTTON_STARTUP PINC3 // When AUTO_PRESS_POWERBUTTON_STARTUP how much seconds should we wait #define AUTO_PRESS_POWERBUTTON_STARTUP_WAIT_TIME 15 // Macros // Toogles a LED/Bit at Port and pin #define TOGGLE_LED(_port,_pin){((_port) & (1<<(_pin)))?((_port)&=~(1<<(_pin))):((_port)|=(1<<(_pin)));} // Clear LED at Port and pin = VOltage to High 5V #define CLEAR_LED(_port,_pin){((_port)|=(1<<(_pin)));} // Set LED on at Port and pin = VOltage to Low 0V #define SET_LED(_port,_pin){((_port)&=~((1<<(_pin))));} // Press powerbutton for 200ms 0V, wait 200ms, 5V // #define PRESS_POWERBUTTON(_port,_pin){((_port)&=~(1<<(_pin)));(_delay_ms(200));((_port)|=(1<<(_pin)));} #define PRESS_POWERBUTTON {((PORTC)&=~(1<<(POWER_PIN)));(_delay_ms(200));((PORTC)|=(1<<(POWER_PIN)));} // Is powersupply still on #define IS_POWER_ON ((PINC) & (1<<PIN_5VDC)) // Prefix of the commands, 2 chars char sATCommandPrefix[3]="AT"; // Complete String which is received from uart char sReceived[30]=""; // Position of Pointer when we parse the string char* sStrPos; // Position of Errorpointer when we convert string to long char* pStrErrPos; // Receives 2Bytes from uart, lower byte data, higher byte stat unsigned int iReceive; // Is a complete string received ? uint8_t bSringComplete; // Seconds to start my PC // As long -1=Timer inactive long iSecondsToPowerOn=-1; // Should we start the box? uint8_t bStartBox; // Auto Press Counter long iPressCounterForAutoStart=0; // Function prototypes static int is_at_command(char *sCom,char *sATPrefix); static void init_ioports(void); static void init_counter(void); static void fPrintCounterState(void); int main(void){ // IO port init init_ioports(); // counter init with external 32,768khz xtal init_counter(); // UART Init uart_init(UART_BAUD_SELECT(BAUD_RATE,F_CPU)); //Interrupts On sei(); // We say hello ;-) uart_puts("\rS100 Wakeup V1.1 \r\n"); // init bSringComplete=FALSE; bStartBox=FALSE; for(;;){ /*************************** begin read string from uart ***********************/ // Get data from uart iReceive=uart_getc(); // Errors if ( iReceive & (UART_FRAME_ERROR | UART_OVERRUN_ERROR | UART_BUFFER_OVERFLOW) ){ } // No data else if(iReceive & UART_NO_DATA){ // Do nothing } // Data available else{ // echo char if (UART_ECHO){uart_putc((char)iReceive);} // ...until Return Character is 0x0d = 13 is received if ((char)iReceive=='\r'){ bSringComplete=TRUE; if (UART_ECHO){uart_putc('\n');} } else { // Only if enough space in sReceived free if(sizeof(sReceived)>strlen(sReceived)){ // Concatinate all characters to a string....., we need only the lower byte. // Valid character or return?? if ((((uint8_t)iReceive >= 32)&&((uint8_t)iReceive <= 126)) || ((uint8_t)iReceive==13)){ strcat(sReceived,(char*)&iReceive); } } } } /*************************** end read string from uart ***********************/ // When string is now completed if (bSringComplete){ // Is an AT Command if (is_at_command(sReceived,sATCommandPrefix)){ sStrPos=sReceived; // String pointer to 3rd Character sStrPos+=2; // Which AT command, allowed are S,P and C switch (*sStrPos) { case 'S': // String pointer to 4th Character sStrPos++; iSecondsToPowerOn=0; // Try to convert string to long iSecondsToPowerOn=strtol(sStrPos,&pStrErrPos,10); if (*pStrErrPos=='\0'){ fPrintCounterState(); } else{ iSecondsToPowerOn=0; uart_puts("Convert error at char: "); uart_puts(pStrErrPos); uart_puts("\r\n"); } break; case 'C': //Clear Counter iSecondsToPowerOn=-1; break; case 'P': // We print the Timer state if (iSecondsToPowerOn>=0){ // Timer is active fPrintCounterState(); } else{ // Timer is inactive uart_puts("Timer inactive\n\r"); } break; } } // No AT command else{ } // String reset strcpy(sReceived,""); // bSringComplete=FALSE; } // End string is complete received // Any actions? // Must we press the power button? // Either on Active Counter or at box startup if (bStartBox) { if (! IS_POWER_ON){ uart_puts("Pressing powerbutton.\r\n"); PRESS_POWERBUTTON; } else{ uart_puts("Pressing powerbutton canceled. Power is active.\r\n"); } // Waiting for next bStartBox=FALSE; CLEAR_LED(PORTC,COUNTER_ACTIVE_LED); } } // end loop return(0); } // END MAIN // Check if first 2 Characters are right prefix static int is_at_command(char *sCom,char *sATPrefix){ if (strncmp(sCom,sATPrefix,2)){ return(0); } else{ return(1); } } // Init the oi ports static void init_ioports(void){ DDRB = 0xff; /* Ports definition PORTC output: PC0=Power button PC1=Timer active, blinking 1Hz PC2=Counter active, blinking 1Hz PORTC input: PC4=Debug Mode, if this connect to GND. PC5=Input +5 VDC PC, to see if the box is already running */ // PORT // All Output Ports=off=5V, on input pins pullups on PORTC = (0xff); DDRC = 0x0f; } // init counter static void init_counter(void){ // Timer2 clocked by external 32.768kHz ASSR |= (1<<AS2); // Clock/128 for 0,5Hz blinking and timer overflow every 1 second TCCR2 |= (1<<CS22) | (1<<CS20); // Clock/64=2Hz for 1Hz blinking with toogle_bit TCNT2 = 0; // Timer2(8Bit) Overflow Interrupt enabled (256) TIMSK |= (1<<TOIE2); } // timer overflow, every 1 second SIGNAL(SIG_OVERFLOW2){ // toogle led to show the board is alive TOGGLE_LED(PORTC,ACTIVE_LED); // Counter active when >= 0, decrement counter if (iSecondsToPowerOn>=0){ // dec one second iSecondsToPowerOn--; TOGGLE_LED(PORTC,COUNTER_ACTIVE_LED); // Counter = 0, it's time we must start the box if (iSecondsToPowerOn==0){ // We press the power button in mainloop, not in interrupt bStartBox=TRUE; } } // Timer is inactive, we do nothing /* else{ CLEAR_LED(PORTC,COUNTER_ACTIVE_LED); }*/ // AutoStartCounter // IN_AUTO_PRESS_POWERBUTTON_STARTUP = Low(0V) and Counter < Wait Time if ((~PINC & (1<<IN_AUTO_PRESS_POWERBUTTON_STARTUP)) && (iPressCounterForAutoStart<=AUTO_PRESS_POWERBUTTON_STARTUP_WAIT_TIME)){ if (iPressCounterForAutoStart==AUTO_PRESS_POWERBUTTON_STARTUP_WAIT_TIME){ bStartBox=TRUE; } TOGGLE_LED(PORTC,COUNTER_ACTIVE_LED); iPressCounterForAutoStart++; } } // Print Counter to uart static void fPrintCounterState(void){ char sCounterState[35]=""; char sCounter[10]=""; strcpy(sCounterState,"Timer active: "); // Long 2 ASCII ltoa(iSecondsToPowerOn,sCounter,10); strcat(sCounterState,sCounter); strcat(sCounterState,"s\n\r"); // Print the string out uart_puts(sCounterState); } |
#!/usr/bin/perl ############################################################################### # Gets the /proc/acpi/alarm or clear string from vdr and send it to the S100 atmega8 wakeup board # Commandline arguments: # 1. Wakeuptime as ACPI Time String (2006-02-09 23:05:00) or UNIX Systemdate (1141941900) # or via STDIN # # 25.03.2008 # changes # # Michael Albert # Comments to michael@albert-hetzles.de # 1. FCN forever http://www.fcn.de ############################################################################### use Time::Local; use File::Basename; use Sys::Syslog; # S100 Serial port $sSerialPort="/dev/ttyS0"; #$sSerialPort="/tmp/ATx.txt"; # Script messages to syslog $bUseSysLog=1; # Set system time $bSetSystemTime=0; # Time Servers @aTimeServer=("ptbtime1.ptb.de","ptbtime2.ptb.de"); # ntpbin $sNTPDate="sudo /usr/sbin/ntpdate -u "; # Setup /InitSerialPort $bSetupSerial=1; # stty exe string, BAUD 2400, Bits 8, Parity None, 1 Stopbit, noflowcontrol, no hardware handshake $ssttyBin="stty -F $sSerialPort 2400 cs8 -cstopb -crtscts -ixon -ixoff"; # $sArg=Variable to store first command line parameter # $iACPIStartTime=Variable to store in systemtime (1141941900) my ($sArg,$iACPIStartTime,$sMessage); $sMessage=" Starting VDR wakeup..."; print $sMessage."\n"; ($bUseSysLog) && &fWriteSyslog($sMessage); # Set time if ($bSetSystemTime){ foreach (@aTimeServer){ $sMessage="Set systemtime from ntpserver $_\n"; print $sMessage."\n"; ($bUseSysLog) && &fWriteSyslog($sMessage); $iResult=system($sNTPDate.$_); if ($iResult){ $sMessage="Error while setting systemtime $iResult\n"; print $sMessage."\n"; ($bUseSysLog) && &fWriteSyslog($sMessage); } } } # Getting parameter if (@ARGV[0]) { # Get command line parameter $sArg=@ARGV[0]; } else{ # Or from stdin $sArg=<STDIN>; } # cut \n chomp($sArg); # Check if format is already UNIX systemtime if ($sArg=~/^[0-9]+$/){ # Yes, cool $sMessage=" Get UNIX system time \($sArg\) via command line."; print $sMessage."\n"; ($bUseSysLog) && &fWriteSyslog($sMessage); $iACPIStartTime=$sArg; } else{ # No, we must convert it. $sMessage=" Get /proc/acpi/alarm formated string \($sArg\) via command line."; print $sMessage."\n"; ($bUseSysLog) && &fWriteSyslog($sMessage); # Convert it to system time format. 2006-02-09 23:05:00 -> 1141941900 $iACPIStartTime=&fGetSystemTimeFromACPIStartTime($sArg); } if ($iACPIStartTime){ ($bSetupSerial) && system($ssttyBin); my ($iTimeNow,$iTimeDiff); # print "ACPI Time: $iACPIStartTime\n"; # Calculating difference between Starttime and now in seconds $iTimeDiff=$iACPIStartTime-time; if ($iTimeDiff>0){ $sMessage=" Starting VDR in $iTimeDiff seconds."; print $sMessage."\n"; ($bUseSysLog) && &fWriteSyslog($sMessage); # send command string to Board via serial port #open(hSTTY,">$sSerialPort")||die "Can't open $sSerialPort\n"; print 'echo -e "\\rATS'.$iTimeDiff.'\\r" > '.$sSerialPort; system('echo -e "\\rATS'.$iTimeDiff.'\\r" > '.$sSerialPort); #close(hSTTY); } else{ # Think positive :-) $iTimeDiff*=-1; $sMessage=" VDR starting time is $iTimeDiff seconds in the past\! Resetting timer."; warn $sMessage."\n"; ($bUseSysLog) && &fWriteSyslog($sMessage); system('echo -e "\\rATC\\r" > '.$sSerialPort); } } else{ warn " Unknown command or time format\n"; } ############################################################################### # 1. Parameter ACPI Time (Format: 2006-02-09 23:05:00) # Return systemtime sub fGetSystemTimeFromACPIStartTime(){ my ($sACPIStartTime,$sDate,$sTime,$sSec,$sMin,$sHour,$sDay,$sMon,$sYear); $sACPIStartTime=shift; ($sDate,$sTime)=split(/ /,$sACPIStartTime); ($sHour,$sMin,$sSec)=split(/\:/,$sTime); ($sYear,$sMon,$sDay)=split(/\-/,$sDate); # print"$sSec,$sMin,$sHour,$sDay,$sMon,$sYear\n"; # timelocal wants Month from 0..11 $sMon-=1; # We try to convert it eval{ $iACPISysTime = timelocal($sSec,$sMin,$sHour,$sDay,$sMon,$sYear); }; # successfully? if ($@){ # No my $sErrorMessage; $sErrorMessage=$@; chomp($sErrorMessage); warn " ERROR $sErrorMessage.\n Cannot convert \"$sACPIStartTime\". Wrong format or incorrect date.\n"; ($bUseSysLog) && &fWriteSyslog(" ERROR $sErrorMessage.\n Cannot convert \"$sACPIStartTime\". Wrong format or incorrect date.\n"); return(0); } else{ # Yes return($iACPISysTime); } } # 1. Parameter Text write to syslog sub fWriteSyslog(){ my $sText; $sText = @_[0]; openlog($program . basename($0), 'pid', 'user'); syslog('info', $sText); #syslog('mail|warning', 'this is a better test: %d', time); closelog(); } |