[Tinyos-contrib-commits] CVS: tinyos-1.x/contrib/diku/evb13192/tos/sensorboards/lpreceiver TPMM.nc, NONE, 1.1 DCF77M.nc, NONE, 1.1 AMTransceiver.nc, NONE, 1.1 AMTransmitterC.nc, NONE, 1.1 AMTransceiverM.nc, NONE, 1.1 PinControlM.nc, NONE, 1.1 TPMTimer16.nc, NONE, 1.1 DCF77.nc, NONE, 1.1 AMTransmitter.nc, NONE, 1.1 AMTransmitterM.nc, NONE, 1.1 README, NONE, 1.1 LocalCounter.nc, NONE, 1.1 AMReceiver.nc, NONE, 1.1 AMTransceiverC.nc, NONE, 1.1 TPMTimer32.nc, NONE, 1.1 TPM.nc, NONE, 1.1 AMReceiverM.nc, NONE, 1.1 DCF77Hibernation.nc, NONE, 1.1 DCF77HibernationC.nc, NONE, 1.1 DCF77HibernationM.nc, NONE, 1.1 DCF77C.nc, NONE, 1.1 AMReceiverC.nc, NONE, 1.1

Marcus Chang marcus_chang at users.sourceforge.net
Sat Jun 3 12:45:41 PDT 2006


Update of /cvsroot/tinyos/tinyos-1.x/contrib/diku/evb13192/tos/sensorboards/lpreceiver
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv996/evb13192/tos/sensorboards/lpreceiver

Added Files:
	TPMM.nc DCF77M.nc AMTransceiver.nc AMTransmitterC.nc 
	AMTransceiverM.nc PinControlM.nc TPMTimer16.nc DCF77.nc 
	AMTransmitter.nc AMTransmitterM.nc README LocalCounter.nc 
	AMReceiver.nc AMTransceiverC.nc TPMTimer32.nc TPM.nc 
	AMReceiverM.nc DCF77Hibernation.nc DCF77HibernationC.nc 
	DCF77HibernationM.nc DCF77C.nc AMReceiverC.nc 
Log Message:
Components to support the low-power receiver board series:

 * DIKU Receiver Board
 * DIKU Transmitter Board
 * DIKU Transceiver Board

Features:

 * Secondary radio
 * DCF77 global time synchronization
 * DCF77 enabled long-term hibernation
 * 16/32-bit async timers


--- NEW FILE: TPMM.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/


module TPMM {
	provides {
		interface StdControl;
		interface TPM;
		interface TPMTimer16;
		interface TPMTimer32;
		interface LocalCounter;
	}
}

implementation {

	void bigTimerFired();
	
	default async event result_t TPM.signalReceived(uint8_t edge, uint32_t counter) { return FAIL; }
	default async event result_t TPMTimer16.fired() {return FAIL;}
	default async event result_t TPMTimer32.fired() {return FAIL;}

	enum
	{	
		SCM = 0x00,
		FEI = 0x01,
		FBE = 0x02,
		FEE = 0x03
	};

	uint8_t init = 1, bigAlarmEnable = 0;
	uint16_t carryCounter = 0;
	uint32_t highCounter = 0, lowCounter = 0, interuptCounter = 0;
	uint32_t bigAlarmInterval, bigAlarm, smallAlarmInterval;

	command result_t StdControl.init() 
	{

		/////////////////////////////////////////////////
		// allow only ONE call to init()
		/////////////////////////////////////////////////
		if (init == 1) {
			init = 0;
		} else {
			return FAIL;
		}

		///////////////////////////
		// Set timers correctly
		///////////////////////////
		
		// enable software pull-up
		PTDDD_PTDDD2 = 0;
		PTDPE_PTDPE2 = 1;
		

		// When CPWMS = 0:
		// MS2B:MS2A = 00 : Input Capture
		// MS2B:MS2A = 01 : Output Compare
		// MS2B:MS2A = 1x : Edge aligned PWM
		// ELS2B:ELS2A = 01: Rising Edge 
		// ELS2B:ELS2A = 10: Falling Edge 
		// ELS2B:ELS2A = 11: Both Rising and Falling Edges

		// set timer 1 channel 0 to output compare
		atomic {
			TPM1C0SC_CH0IE = 0;
			TPM1C0SC_MS0B = 0;
			TPM1C0SC_MS0A = 1;
			TPM1C0SC_ELS0B = 0;
			TPM1C0SC_ELS0A = 0;
		}

		// set timer 1 channel 1 to output compare
		atomic {
			TPM1C1SC_CH1IE = 0;
			TPM1C1SC_MS1B = 0;
			TPM1C1SC_MS1A = 1;
			TPM1C1SC_ELS1B = 0;
			TPM1C1SC_ELS1A = 0;
		}

		// set timer 1 channel 2 to input capture on both edges
		atomic {
			TPM1C2SC_CH2IE = 0;
			TPM1C2SC_MS2B = 0;
			TPM1C2SC_MS2A = 0;
			TPM1C2SC_ELS2B = 1;
			TPM1C2SC_ELS2A = 1;
		}
		
		return SUCCESS;
	}

	command result_t StdControl.start() {
		
		// enable interupt on input pin
		atomic {
			TPM1C2SC_CH2F = 0;
			TPM1C2SC_CH2IE = 1;
		}

		return SUCCESS;
	}
	
	command result_t StdControl.stop() {

		// disable interupt on input pin
		atomic {
			TPM1C2SC_CH2IE = 0;
		}
		
		return SUCCESS;
	}

	/////////////////////////////////////////////////////////////////////////////
	// 
	/////////////////////////////////////////////////////////////////////////////
	command uint8_t TPM.returnClockSource() {

		if (TPM1SC_CLKSB == 1 || TPM1SC_CLKSA == 0) {
			return 1;
		} else if (TPM1SC_CLKSB == 0 || TPM1SC_CLKSA == 1) {
			return 0;
		} else {
			return 2;
		}
	}

	command uint8_t TPM.setClockSource(uint8_t source) {

		// Timer x Status and Control Register (TPMxSC)
		// Bit 7 6 5 4 3 2 1 0
		// TOF TOIE CPWMS CLKSB CLKSA PS2 PS1 PS0

		// external source available - use fixed system clock
		if ( (ICGS1_CLKST == FBE || ICGS1_CLKST == FEE) && source == 1) {

			// set divider to assure at least 1ms resolution		
			if ( (extClock / 2) > 128000) {

				atomic {
					TPM1SC_TOIE = 1;
					TPM1SC_CPWMS = 0;
					TPM1SC_CLKSB = 1;
					TPM1SC_CLKSA = 0;
					TPM1SC_PS2 = 1;
					TPM1SC_PS1 = 1;
					TPM1SC_PS0 = 1;
				}

				return 128;

			} else {

				atomic {
					TPM1SC_TOIE = 1;
					TPM1SC_CPWMS = 0;
					TPM1SC_CLKSB = 1;
					TPM1SC_CLKSA = 0;
					TPM1SC_PS2 = 0;
					TPM1SC_PS1 = 0;
					TPM1SC_PS0 = 0;
				}

				return 1;
			}


		// use internal clock (busclock) as source
		} else {

			// set divider to assure at least 1ms resolution		
			if (busClock > 128000) {
		
				atomic {
					TPM1SC_TOIE = 1;
					TPM1SC_CPWMS = 0;
					TPM1SC_CLKSB = 0;
					TPM1SC_CLKSA = 1;
					TPM1SC_PS2 = 1;
					TPM1SC_PS1 = 1;
					TPM1SC_PS0 = 1;
				}

				return 128;

			} else {
				atomic {
					TPM1SC_TOIE = 1;
					TPM1SC_CPWMS = 0;
					TPM1SC_CLKSB = 0;
					TPM1SC_CLKSA = 1;
					TPM1SC_PS2 = 0;
					TPM1SC_PS1 = 0;
					TPM1SC_PS0 = 0;
				}
			
				return 1;
			}

		}
		
	}


	/////////////////////////////////////////////////////////////////////////////
	// Timer 16 bit
	/////////////////////////////////////////////////////////////////////////////
	command result_t TPMTimer16.start(uint16_t interval) {
		uint16_t smallCounter;
		
		smallAlarmInterval = interval;
		
		atomic {
			smallCounter = TPM1CNTH;
			smallCounter = (smallCounter << 8) + TPM1CNTL;
			
			smallCounter += interval;
		
			// set timer
			TPM1C1VH = smallCounter >> 8;
			TPM1C1VL = smallCounter;

			// enable interupt
			TPM1C1SC_CH1F = 0;
			TPM1C1SC_CH1IE = 1;
		}

		return SUCCESS;
	}

	command result_t TPMTimer16.stop() {

		atomic {
			smallAlarmInterval = 0;

			// disable interupt
			TPM1C1SC_CH1IE = 0;
			TPM1C1SC_CH1F = 0;
		}

		return SUCCESS;
	}

	/////////////////////////////////////////////////////////////////////////////
	// Timer 32 bit
	/////////////////////////////////////////////////////////////////////////////
	command result_t TPMTimer32.start(uint32_t interval) {
		uint32_t sum;
		uint16_t smallCounter;

		bigAlarmInterval = interval;
		
		atomic {
			smallCounter = TPM1CNTH;
			smallCounter = (smallCounter << 8) + TPM1CNTL;
		
			sum = bigAlarmInterval + smallCounter;

			// check for overflow
			if (sum < bigAlarmInterval) {
			
				return FAIL;
			
			} else if (sum < 0x00010000) {

				// set timer
				TPM1C0VH = sum >> 8;
				TPM1C0VL = sum;

				// enable interupt
				TPM1C0SC_CH0F = 0;
				TPM1C0SC_CH0IE = 1;
			} else {

				bigAlarm = sum;
			}

			bigAlarmEnable = 1;
		}

		return SUCCESS;
	}


	command result_t TPMTimer32.stop() {
	
		// disable big timer interupt
		atomic {
			TPM1C0SC_CH0IE = 0;
			TPM1C0SC_CH0F = 0;
			bigAlarmEnable = 0;
		}

		return SUCCESS;
	}


	/////////////////////////////////////////////////////////////////////////////
	// Get low-32bit, high-32bit and interupt-counters
	/////////////////////////////////////////////////////////////////////////////
	command uint32_t LocalCounter.getHighCounter() {

		return highCounter;
	}

	command uint32_t LocalCounter.getLowCounter() {
		uint32_t smallCounter;

		atomic {
			smallCounter = TPM1CNTH;
			smallCounter = (smallCounter << 8) + TPM1CNTL;
			smallCounter += lowCounter;
			
			// check if timer overflew during command call
			smallCounter += (TPM1SC_TOF * 0x00010000);
		}

		return smallCounter;
	}

	command uint32_t LocalCounter.getInteruptCounter() {
		uint32_t smallCounter;

		atomic {		
			smallCounter = TPM1CNTH;
			smallCounter = (smallCounter << 8) + TPM1CNTL;
			smallCounter += interuptCounter - carryCounter;
		}

		return smallCounter;
	}

	/////////////////////////////////////////////////////////////////////////////
	// Interupt handlers
	/////////////////////////////////////////////////////////////////////////////

	// Main Timer 1 overflow
	TOSH_SIGNAL(TPM1OVF) {
		uint16_t TOF;
		
		// update big alarm
		if (bigAlarmEnable == 1) {
			// count down
			bigAlarm -= 0x00010000;

			// is remaining time less than 16bit
			if (bigAlarm < 0x00010000) {
				atomic {
					// set timer
					TPM1C0VH = bigAlarm >> 8;
					TPM1C0VL = bigAlarm;

					// enable interupt
					TPM1C0SC_CH0F = 0;
					TPM1C0SC_CH0IE = 1;
				}
			}
		}


		// update counters
		if (lowCounter == 0xffff0000) {
			highCounter++; 
		}

		lowCounter += 0x00010000;

		if (interuptCounter < 0xffff0000) {
			interuptCounter += 0x00010000;
		}

		// clear interupt
		TOF = TPM1SC_TOF;
		TPM1SC_TOF = 0;
	}


	// big alarm fired
	TOSH_SIGNAL(TPM1CH0) {

		bigTimerFired();
		
	}

	// small alarm fired
	TOSH_SIGNAL(TPM1CH1) {
		uint16_t smallCounter;

		atomic {
			if (smallAlarmInterval > 0 ) {
				smallCounter = TPM1C1VH;
				smallCounter = (smallCounter << 8) + TPM1C1VL;
	
				smallCounter += smallAlarmInterval;
			
				// set timer
				TPM1C1VH = smallCounter >> 8;
				TPM1C1VL = smallCounter;

				// clear and enable interupt
				TPM1C1SC_CH1F = 0;
				TPM1C1SC_CH1IE = 1;
			}
		}

		signal TPMTimer16.fired();
	}

	// interupt from timer input pin
	TOSH_SIGNAL(TPM1CH2) {
		uint8_t edge;
		uint16_t smallCounter;
		uint32_t totalCounts;
		
		smallCounter = TPM1C2VH;
		smallCounter = (smallCounter << 8) + TPM1C2VL;

		totalCounts = interuptCounter + smallCounter - carryCounter;


		// clear counters
		interuptCounter = 0;
		carryCounter = smallCounter;

		// clear interupt
		TPM1C2SC_CH2F = 0;
		TPM1C2SC_CH2IE = 1;

		edge = PTDD_PTDD2;	
		signal TPM.signalReceived(edge, totalCounts);
	}
	
	
	void bigTimerFired() {
		uint32_t sum;
		uint16_t smallCounter;

		atomic {
			smallCounter = TPM1C0VH;
			smallCounter = (smallCounter << 8) + TPM1C0VL;
		}


		atomic {		
			sum = bigAlarmInterval + smallCounter;
			
			if (sum < 0x00010000) {

				// set timer
				TPM1C0VH = sum >> 8;
				TPM1C0VL = sum;

				// clear and enable interupt
				TPM1C0SC_CH0F = 0;
				TPM1C0SC_CH0IE = 1;

			} else {
				bigAlarm = sum;

				// clear and disable interupt
				TPM1C0SC_CH0F = 0;
				TPM1C0SC_CH0IE = 0;
			}
		}

		signal TPMTimer32.fired();
	}

}

--- NEW FILE: DCF77M.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
[...1087 lines suppressed...]

		// extra seconds caused by leap day
		if (month > 2) {
			if (year % 4 == 0) {
				result += 24*60*60;
			}
		}

		// seconds since base offset (01/01/2000 00:00)
		result += year*365*24*60*60;

		// extra seconds caused by leap year
		result += (year / 4 + 1) * 24*60*60;


		return result + baseOffset;
	}
}



--- NEW FILE: AMTransceiver.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/

interface AMTransceiver {
	
	
	command result_t setBaudrate(uint16_t rate);
	command result_t put(uint32_t data);
	async event result_t putDone();
	
	async event result_t get(uint32_t data, uint32_t timestamp);

}

--- NEW FILE: AMTransmitterC.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/


configuration AMTransmitterC {
	provides {
		interface AMTransmitter;
	}
}

implementation {
	components TPMM, AMTransmitterM, PinControlM;

	AMTransmitter = AMTransmitterM;

	AMTransmitterM.AMRadioControl	-> PinControlM.StdControl[6];

	AMTransmitterM.TPMTimer		-> TPMM;
	AMTransmitterM.TPM		-> TPMM;
	AMTransmitterM.TPMControl	-> TPMM;
	
}

--- NEW FILE: AMTransceiverM.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/


module AMTransceiverM {
	provides {
		interface StdControl as AMTransmitterControl;
		interface StdControl as AMReceiverControl;
		interface AMTransceiver;
	}

	uses { 
		interface AMTransmitter;
		interface AMReceiver;
	}
}

implementation {

	uint32_t rx_timestamp;

	///////////////////////////////////////////////////////////////////////
	// Transmitter StdControl
	///////////////////////////////////////////////////////////////////////
	command result_t AMTransmitterControl.init() {

		return call AMTransmitter.init();
	}

	command result_t AMTransmitterControl.start() {

		return call AMTransmitter.start();
	}

	command result_t AMTransmitterControl.stop() {

		return call AMTransmitter.stop();
	}

	///////////////////////////////////////////////////////////////////////
	// Receiver StdControl
	///////////////////////////////////////////////////////////////////////
	command result_t AMReceiverControl.init() {

		return call AMReceiver.init();
	}

	command result_t AMReceiverControl.start() {

		return call AMReceiver.start();
	}

	command result_t AMReceiverControl.stop() {

		return call AMReceiver.stop();
	}

	///////////////////////////////////////////////////////////////////////
	// Transceiver commands
	///////////////////////////////////////////////////////////////////////
	command result_t AMTransceiver.setBaudrate(uint16_t rate) {
	
		call AMTransmitter.setBaudrate(rate);
		
		return SUCCESS;
	}

	command result_t AMTransceiver.put(uint32_t data) {
	
		call AMTransmitter.put(data);
		
		return SUCCESS;
	}

	///////////////////////////////////////////////////////////////////////
	// Transceiver async events
	///////////////////////////////////////////////////////////////////////
	async event result_t AMTransmitter.putDone() {

		signal AMTransceiver.putDone();

		return SUCCESS;
	}
	
	async event result_t AMReceiver.get(uint32_t data, uint32_t timestamp) {
	
		signal AMTransceiver.get(data,timestamp);	
		
		return SUCCESS;
	}
}

--- NEW FILE: PinControlM.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/


module PinControlM {
	provides {
		interface StdControl[uint8_t id];
	}

}

implementation {

	
	command result_t StdControl.init[uint8_t id]() {
	
		switch(id) {
			case 5:
				// Set power port C pin 5 as output pin
				PTCD_PTCD5 = 0;
				PTCDD_PTCDD5 = 1;
				break;
			case 6:
				// Set power port C pin 6 as output pin
				PTCD_PTCD6 = 0;
				PTCDD_PTCDD6 = 1;
				break;
			case 7:
				// Set power port C pin 7 as output pin
				PTCD_PTCD7 = 0;
				PTCDD_PTCDD7 = 1;
				break;
			default:
				return FAIL;
				break;
		}


		return SUCCESS;
	}

	command result_t StdControl.start[uint8_t id]() {

		switch(id) {
			case 5:
				// Turn on port C pin 5
				PTCD_PTCD5 = 1;
				PTCDD_PTCDD5 = 1;
				break;
			case 6:
				// Turn on port C pin 6
				PTCD_PTCD6 = 1;
				PTCDD_PTCDD6 = 1;
				break;
			case 7:
				// Turn on port C pin 7
				PTCD_PTCD7 = 1;
				PTCDD_PTCDD7 = 1;
				break;
			default:
				return FAIL;
				break;
		}

		return SUCCESS;
	}

	command result_t StdControl.stop[uint8_t id]() {

		switch(id) {
			case 5:
				// Turn off port C pin 5
				PTCD_PTCD5 = 0;
				break;
			case 6:
				// Turn off port C pin 6
				PTCD_PTCD6 = 0;
				break;
			case 7:
				// Turn off port C pin 7
				PTCD_PTCD7 = 0;
				break;
			default:
				return FAIL;
				break;
		}
	
		return SUCCESS;
	}
  
}

--- NEW FILE: TPMTimer16.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/

interface TPMTimer16 {

	command result_t start(uint16_t interval);
	command result_t stop();

	async event result_t fired();
}

--- NEW FILE: DCF77.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/

interface DCF77 {
	
	// modified StdControl
	command result_t init();
	command result_t start(uint8_t clockSource);
	command result_t stop();
	command uint32_t getEstimatedBusClock();

	command uint16_t getMilliseconds();
	command uint8_t getSeconds();
	command uint8_t getMinutes();
	command uint8_t getHours();
	command uint8_t getDayOfMonth();
	command uint8_t getDayOfWeek();
	command uint8_t getMonth();
	command uint8_t getYear();

	command uint32_t getUnixTimestamp();
	command uint32_t getTimestamp();
	command uint32_t getTimestampInMilliseconds();
	command uint32_t getDatestamp();

	event result_t inSync(uint32_t calculatedBusClock);
	event result_t outSync();
	

}

--- NEW FILE: AMTransmitter.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/

interface AMTransmitter {
	
	command result_t init();
	command result_t start();
	command result_t stop();

	command result_t setBaudrate(uint16_t baudrate);	
	command result_t put(uint32_t data);
	async event result_t putDone();
}

--- NEW FILE: AMTransmitterM.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/


module AMTransmitterM {
	provides {
		interface AMTransmitter;
	}

	uses { 
		interface StdControl as AMRadioControl;
		interface StdControl as TPMControl;
		interface TPM;
		interface TPMTimer16 as TPMTimer;
	}
}

implementation {

	uint8_t bitCounter, center, divider;
	uint16_t baudrate = 100;
	uint32_t initBusClock = 1;

	enum
	{	
		IDLE = 0,
		HEADER = 1,
		DATA = 2,
		FOOTER = 3,
		END  = 4,
	};

	uint8_t currentState = IDLE, header = 0;
	uint32_t transmitBuffer;

	
	///////////////////////////////////////////////////////////////////////
	// StdControl
	//
	///////////////////////////////////////////////////////////////////////
	command result_t AMTransmitter.init() {
		result_t result;

		// Initialize radio power pin
		result = call AMRadioControl.init();

		// Initialize timer port
		result *= call TPMControl.init();
		
		PTBD_PTBD2 = 0;
		PTBDD_PTBDD2 = 1;

		return result;
	}

	command result_t AMTransmitter.start() {
		result_t result;
		uint8_t divider, highPrecisionClock;

		// Turn on radio
		result = call AMRadioControl.start();

		// set internal counters
		divider = call TPM.setClockSource(0);
		highPrecisionClock = call TPM.returnClockSource();
		
		if (highPrecisionClock == 1) {
			initBusClock = extClock / (2 * divider);
		} else {
			initBusClock = busClock / divider;
		}

		return result;
	}

	command result_t AMTransmitter.stop() {
		result_t result;

		// Turn off radio
		result = call AMRadioControl.stop();

		return result;
	}

	///////////////////////////////////////////////////////////////////////
	// Set baudrate
	///////////////////////////////////////////////////////////////////////
	command result_t AMTransmitter.setBaudrate(uint16_t rate) {

		baudrate = rate;
		
		return SUCCESS;
	}

	///////////////////////////////////////////////////////////////////////
	// Transmit 32-bit data
	///////////////////////////////////////////////////////////////////////
	command result_t AMTransmitter.put(uint32_t data) {
		uint8_t result, i, tmp, par = 0;
		
		if (currentState == IDLE) {
			transmitBuffer = 0xFFFFFFFF - data;

			for (i = 0; i < 32; i++) {
				par ^= (data >> i) & 0x01;
			}

			header = 0xFF - (par << 7) - (0x01 << 6);
			currentState = HEADER;
			bitCounter = 8;
			center = 0;

			result = call TPMTimer.start(initBusClock / (2 * baudrate));

			return SUCCESS;
		} else {
		
			return FAIL;
		}
	}

	///////////////////////////////////////////////////////////////////////
	// Timer fired - transmit next bit
	///////////////////////////////////////////////////////////////////////
	async event result_t TPMTimer.fired() {
		uint16_t tmp;

		if (currentState == HEADER) {

			// Manchester encoding of a single byte
			if (center == 0) {

				PTBD_PTBD2 = (header & 0x01);
				header = header >> 1;

				bitCounter--;
				center = 1;
			} else {
				// flip signal
				PTBD_PTBD2 ^= 0x01;

				// reset center flag
				center = 0;

				if (bitCounter == 0) {

					currentState = DATA;
					bitCounter = 32;
				}
			}
		
		} else if (currentState == DATA) {

			// Manchester encoding of a single byte
			if (center == 0) {

				PTBD_PTBD2 = (transmitBuffer & 0x01);
				transmitBuffer = transmitBuffer >> 1;

				bitCounter--;
				center = 1;
			} else {

				PTBD_PTBD2 ^= 0x01;
				center = 0;

				if (bitCounter == 0) {

					currentState = FOOTER;
					bitCounter = 8;	
				} 
			}
		
		} else if (currentState == FOOTER) {

			// Manchester encoding of a single byte
			if (center == 0) {

				PTBD_PTBD2 = 0;

				bitCounter--;
				center = 1;
			} else {
				PTBD_PTBD2 ^= 0x01;
				center = 0;

				if (bitCounter == 0) {

					currentState = END;
				}
			}

		} else if (currentState == END) {

			PTBD_PTBD2 = 0;
			call TPMTimer.stop();

			currentState = IDLE;

			signal AMTransmitter.putDone();

		}

		
		return SUCCESS;	
	}

	async event result_t TPM.signalReceived(uint8_t edge, uint32_t counter) { 
		return SUCCESS; 
	}  
}

--- NEW FILE: README ---
These are the files to support the:

 * DIKU Receiver Board
 * DIKU Transmitter Board
 * DIKU Transceiver Board

June, 2006. Marcus Chang <marcus at diku.dk>
--- NEW FILE: LocalCounter.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/

interface LocalCounter {

	command uint32_t getHighCounter();
	command uint32_t getLowCounter();
	command uint32_t getInteruptCounter();
}

--- NEW FILE: AMReceiver.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/

interface AMReceiver {
	
	command result_t init();
	command result_t start();
	command result_t stop();
	
	async event result_t get(uint32_t data, uint32_t timestamp);

}

--- NEW FILE: AMTransceiverC.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/


configuration AMTransceiverC {
	provides {
		interface StdControl as AMTransmitterControl;
		interface StdControl as AMReceiverControl;
		interface AMTransceiver;
	}
	
}

implementation {
	components TPMM, AMReceiverM, AMTransmitterM, PinControlM, AMTransceiverM;

	AMTransceiver = AMTransceiverM;
	AMTransmitterControl = AMTransceiverM.AMTransmitterControl;
	AMReceiverControl = AMTransceiverM.AMReceiverControl;

	AMTransceiverM.AMReceiver 	-> AMReceiverM;
	AMTransceiverM.AMTransmitter 	-> AMTransmitterM;

	AMReceiverM.AMRadioControl	-> PinControlM.StdControl[7];
	AMReceiverM.TPMControl		-> TPMM;
	AMReceiverM.TPM			-> TPMM;
	AMReceiverM.LocalCounter	-> TPMM;

	AMTransmitterM.AMRadioControl	-> PinControlM.StdControl[6];
	AMTransmitterM.TPMTimer		-> TPMM;
	AMTransmitterM.TPM		-> TPMM;
	AMTransmitterM.TPMControl	-> TPMM;
}

--- NEW FILE: TPMTimer32.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/

interface TPMTimer32 {

	command result_t start(uint32_t interval);
	command result_t stop();

	async event result_t fired();
}

--- NEW FILE: TPM.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/

interface TPM {

	command uint8_t returnClockSource();
	command uint8_t setClockSource(uint8_t source);
	async event result_t signalReceived(uint8_t type, uint32_t timer);
}

--- NEW FILE: AMReceiverM.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/


module AMReceiverM {
	provides {
		interface AMReceiver;
	}

	uses { 
		interface StdControl as AMRadioControl;
		interface StdControl as TPMControl;
		interface TPM;
		interface LocalCounter;
	}
}

implementation {

#define HEADERMASK 0xAAA4
#define FOOTERMASK 0x5555


	enum
	{	
		IDLE = 0,
		INIT = 1,
		HEADER = 2,
		DATA = 3,
	};

	uint8_t turnedOn = 0, currentState = IDLE;

	uint32_t expectedPulseWidth, deviation, timestamp, initBusClock, margin;

	uint16_t footerBuffer = 0, headerBuffer = 0;
	uint32_t firstReceiveBuffer = 0, secondReceiveBuffer = 0;

	
	///////////////////////////////////////////////////////////////////////
	// StdControl
	///////////////////////////////////////////////////////////////////////
	command result_t AMReceiver.init() {
		result_t result;

		// Initialize radio power pin
		result = call AMRadioControl.init();

		// Initialize timer port
		result *= call TPMControl.init();
	
		return result;
	}

	command result_t AMReceiver.start() {
		uint8_t divider, highPrecisionClock;
		result_t result;

		// Turn on radio
		result = call AMRadioControl.start();

		// set internal counters
		divider = call TPM.setClockSource(0);
		highPrecisionClock = call TPM.returnClockSource();
		
		if (highPrecisionClock == 1) {
			initBusClock = extClock / (2 * divider);
		} else {
			initBusClock = busClock / divider;
		}

		// new signal margin
		margin = initBusClock / 50;

		// Turn on timer port
		result *= call TPMControl.start();
		
		atomic turnedOn = 1;

		return result;
	}

	command result_t AMReceiver.stop() {
		result_t result;

		// Turn off radio
		result = call AMRadioControl.stop();

		// Turn off timer port
		result *= call TPMControl.stop();
	
		atomic turnedOn = 0;

		return result;
	}

	///////////////////////////////////////////////////////////////////////
	// Signal edge detected
	//
	// Manchester decode signal
	///////////////////////////////////////////////////////////////////////
	async event result_t TPM.signalReceived(uint8_t edge, uint32_t counter) {
		uint8_t i, par = 0;
		uint32_t result;

		if (turnedOn == 0) {
			return FAIL;
		}


		// new signal received
		if (currentState == IDLE || counter > margin) {

			timestamp = call LocalCounter.getLowCounter();

			headerBuffer = 0;
			firstReceiveBuffer = 0;
			secondReceiveBuffer = 0;

			footerBuffer = (edge ^ 0x01);

			currentState = INIT;
		
		} else if (currentState == INIT) {

			expectedPulseWidth = counter;
			deviation = (counter * 3) / 2;
			
			footerBuffer = (footerBuffer << 1) | (edge ^ 0x01);

			currentState = HEADER;

		} else if (currentState == HEADER) {

			if (counter < deviation) {
			
				expectedPulseWidth += counter;
				expectedPulseWidth /= 2;
				deviation = (expectedPulseWidth * 3) / 2;

				footerBuffer = (footerBuffer << 1) | (edge ^ 0x01);

				if ( (footerBuffer & 0xFFFC) == HEADERMASK) {
					currentState = DATA;
				} 

			} else {
			
				expectedPulseWidth += counter;
				expectedPulseWidth /= 3;
				deviation = (expectedPulseWidth * 3) / 2;

				footerBuffer = (footerBuffer << 1) | (edge ^ 0x01);

				if ( (footerBuffer & 0xFFFC) == HEADERMASK) {

					secondReceiveBuffer = footerBuffer >> 15;
					footerBuffer = (footerBuffer << 1) | (edge ^ 0x01);

					currentState = DATA;
				} else {

					footerBuffer = (footerBuffer << 1) | (edge ^ 0x01);

					if ( (footerBuffer & 0xFFFC) == HEADERMASK) {
						currentState = DATA;
					} 
				}
			} 

		} else if (currentState == DATA) {

			if (counter < deviation) {

				headerBuffer = (headerBuffer << 1) 
					     | (firstReceiveBuffer >> 31);

				firstReceiveBuffer = (firstReceiveBuffer << 1) 
						   | (secondReceiveBuffer >> 31);

				secondReceiveBuffer = (secondReceiveBuffer << 1)
						    | (footerBuffer >> 15);

				footerBuffer = (footerBuffer << 1) | (edge ^ 0x01);

			} else {

				headerBuffer = (headerBuffer << 2) 
					     | (firstReceiveBuffer >> 30);

				firstReceiveBuffer = (firstReceiveBuffer << 2) 
						   | (secondReceiveBuffer >> 30);

				secondReceiveBuffer = (secondReceiveBuffer << 2)
						    | (footerBuffer >> 14);

				footerBuffer = (footerBuffer << 1) | (edge ^ 0x01);
				footerBuffer = (footerBuffer << 1) | (edge ^ 0x01);

			} 

			if ( (headerBuffer & 0xFFFC) == HEADERMASK && footerBuffer == FOOTERMASK) {

				for (i = 0; i < 16; i++) {
					result = (result << 1) 
					| ((secondReceiveBuffer >> (i * 2)) & 0x01);
				}

				for (i = 0; i < 16; i++) {
					result = (result << 1) 
					| ((firstReceiveBuffer >> (i * 2)) & 0x01);
				}

				for (i = 0; i < 32; i++) {
					par ^= (result >> i) & 0x01;
				}

				if (par == (headerBuffer & 0x01) ) {
					signal AMReceiver.get(result, timestamp);
				} else {
					signal AMReceiver.get(0, 0);
				}

				currentState = IDLE;
				
				return SUCCESS;

			}


		} else {
		
			currentState = IDLE;
		
		}


		return SUCCESS;
	}
  
}

--- NEW FILE: DCF77Hibernation.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/

interface DCF77Hibernation {

	command result_t start();
	
	command result_t hibernateUntil(uint32_t time);
	async event result_t wakeUp(int32_t error);
	
	command uint32_t getWakeUpTime();
	command uint16_t getOffset();
	command result_t setOffset(uint16_t offset);

}

--- NEW FILE: DCF77HibernationC.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/


configuration DCF77HibernationC {
	provides {
		interface DCF77;
		interface DCF77Hibernation;
	}
}

implementation {
	components TPMM, 
		   DCF77M, 
		   DCF77HibernationM,
		   PinControlM;

	DCF77 = DCF77M;
	DCF77Hibernation = DCF77HibernationM;
	
	DCF77M.TPMControl	-> TPMM;
	DCF77M.TPM		-> TPMM;
	DCF77M.LocalCounter	-> TPMM;
	DCF77M.TPMTimer16	-> TPMM.TPMTimer16;
	DCF77M.TPMTimer32	-> TPMM.TPMTimer32;
	DCF77M.ConradControl	-> PinControlM.StdControl[5];
	
	DCF77HibernationM.DCF77 	-> DCF77M;
	DCF77HibernationM.TPMTimer32	-> TPMM.TPMTimer32;
}

--- NEW FILE: DCF77HibernationM.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/



module DCF77HibernationM {
	provides {
		interface DCF77Hibernation;
	}

	uses { 
		interface DCF77;
		interface TPMTimer32;
	}
}

implementation {

	uint32_t compensateDrift(uint32_t sleep);

	/////////////////////////////////////////////////////////////////////////////////
	// Mode of operation
	/////////////////////////////////////////////////////////////////////////////////
	enum
	{	
		OFF = 0x00,
		TIMER = 0x01,
		DCF = 0x02,
	};
	
	uint8_t currentMode = 0;

	// control
	uint8_t inSync = 0, hibernating = 0;
	uint32_t estimatedBusClock = 1, maxSleepSeconds, estimatedSyncTime = 180;

	// wake-up
	uint16_t msecOffset = 0;
	uint32_t wakeUpTime = 0, secondsLeft = 0;


	/////////////////////////////////////////////////////////////////////////////////
	// Mutators
	/////////////////////////////////////////////////////////////////////////////////
	command result_t DCF77Hibernation.start() {
	
		estimatedBusClock = call DCF77.getEstimatedBusClock();
		
		return SUCCESS;
	}

	command uint32_t DCF77Hibernation.getWakeUpTime() {
	
		return wakeUpTime;
	}
	
	command result_t DCF77Hibernation.setOffset(uint16_t offset) {

		// msecOffset = (offset < 1000) ? offset : 999;
		msecOffset = offset;
		
		return SUCCESS;
	}
	
	command uint16_t DCF77Hibernation.getOffset() {
	
		return msecOffset;
	}
	
	/////////////////////////////////////////////////////////////////////////////////
	// Hibernation entry point
	//
	// Wake-up at the specified time - formatted as a UNIX timestamp 
	/////////////////////////////////////////////////////////////////////////////////
	command result_t DCF77Hibernation.hibernateUntil(uint32_t time) {
		uint32_t now, sleep, msec;

		// stop timer 
		call TPMTimer32.stop();

		// calculate sleep time
		now = call DCF77.getUnixTimestamp();
		wakeUpTime = time;
		secondsLeft = wakeUpTime - now; 

		maxSleepSeconds = 0xFFFF0000 / estimatedBusClock;

		//////////////////////////////////////////////////////////////////////////
		// CASE 1 
		// wakeUpTime is not in the future - no need to hibernate
		//////////////////////////////////////////////////////////////////////////
		if (wakeUpTime <= now) {

			return FAIL;

		//////////////////////////////////////////////////////////////////////////
		// CASE 2 
		// Sleeptime two seconds or less 
		// - set timer with msec accuracy 
		// - sleep with DCF77 turned on
		//////////////////////////////////////////////////////////////////////////
		} else if (secondsLeft <= 2) {
		
			msec = (secondsLeft * 1000) - call DCF77.getMilliseconds() + msecOffset;
			
			call TPMTimer32.start( (msec * estimatedBusClock) / 1000);
			secondsLeft = 0;

		//////////////////////////////////////////////////////////////////////////
		// CASE 3 
		// Sleeptime less than the synchronization time 
		// - set timer to 2 seconds before wakeUpTime 
		// - sleep with DCF77 turned on
		//////////////////////////////////////////////////////////////////////////
		} else if (secondsLeft <= estimatedSyncTime) {
		
			msec = (call DCF77.getMilliseconds() * estimatedBusClock) / 2000;

			call TPMTimer32.start( (secondsLeft - 2) * estimatedBusClock - msec);
			secondsLeft = 2;
			
		//////////////////////////////////////////////////////////////////////////
		// CASE 4 
		// Sleeptime less than the maximal sleep interval 
		// - set timer to wakeUpTime minus time needed for synchronization
		// - sleep with DCF77 turned off
		//////////////////////////////////////////////////////////////////////////
		} else if (secondsLeft <= maxSleepSeconds) {
		
			sleep = secondsLeft - estimatedSyncTime;
			secondsLeft -= sleep;
			
			// compensate for 0.5% clock drift and 5% chip deviation
			sleep = compensateDrift(sleep);
			
			call TPMTimer32.start(sleep * estimatedBusClock);

			call DCF77.stop();
			
		//////////////////////////////////////////////////////////////////////////
		// CASE 4 
		// Sleeptime greater than the maximal sleep interval 
		// - set timer to the maximal sleep interval
		// - sleep with DCF77 turned off
		// - allow enough time for DCF77 synchronization
		//////////////////////////////////////////////////////////////////////////
		} else if (secondsLeft > maxSleepSeconds) {


			if (secondsLeft < (estimatedSyncTime + maxSleepSeconds) ) {

				sleep = secondsLeft - estimatedSyncTime;
				secondsLeft = estimatedSyncTime;
			} else {

				sleep = maxSleepSeconds;
				secondsLeft -= maxSleepSeconds;
			}

			// compensate for 0.5% clock drift and 5% chip deviation
			sleep = compensateDrift(sleep);

			call TPMTimer32.start(sleep * estimatedBusClock);

			call DCF77.stop();
		}

				
		atomic inSync = 0;
		currentMode = TIMER;

		return SUCCESS;
	}

	/////////////////////////////////////////////////////////////////////////////////
	// Synchronization complete
	//
	// Decide whether to continue hibernating or prepare to wake-up 
	/////////////////////////////////////////////////////////////////////////////////
	event result_t DCF77.inSync(uint32_t clock) {
		uint32_t now, sleep, msec;
	
		atomic inSync = 1;
		estimatedBusClock = clock;

		if (currentMode != DCF) {

			return SUCCESS;
		} else {

			call TPMTimer32.stop();

			now = call DCF77.getUnixTimestamp();

			if (now < wakeUpTime) {

				currentMode = TIMER;
				secondsLeft = wakeUpTime - now; 
			
				//////////////////////////////////////////////////////////////////////////
				// CASE 2 
				//////////////////////////////////////////////////////////////////////////
				if (secondsLeft <= 2) {
		
					msec = (secondsLeft * 1000) - call DCF77.getMilliseconds() + msecOffset;

					call TPMTimer32.start( (msec * estimatedBusClock) / 1000);
					secondsLeft = 0;

				//////////////////////////////////////////////////////////////////////////
				// CASE 3 
				//////////////////////////////////////////////////////////////////////////
				} else if (secondsLeft <= estimatedSyncTime) {

					msec = (call DCF77.getMilliseconds() * estimatedBusClock) / 2000;

					call TPMTimer32.start( (secondsLeft - 2) * estimatedBusClock - msec);
					secondsLeft = 2;

				//////////////////////////////////////////////////////////////////////////
				// CASE 4 
				//////////////////////////////////////////////////////////////////////////
				} else if (secondsLeft <= maxSleepSeconds) {

					sleep = secondsLeft - estimatedSyncTime;
					secondsLeft -= sleep;

					// compensate for 0.5% clock drift and 0.5% chip deviation
					sleep = compensateDrift(sleep);
					
					call TPMTimer32.start(sleep * estimatedBusClock);

					call DCF77.stop();

				//////////////////////////////////////////////////////////////////////////
				// CASE 5 
				//////////////////////////////////////////////////////////////////////////
				} else if (secondsLeft > maxSleepSeconds) {

					if (secondsLeft < (estimatedSyncTime + maxSleepSeconds) ) {

						sleep = secondsLeft - estimatedSyncTime;
						secondsLeft = estimatedSyncTime;
					} else {

						sleep = maxSleepSeconds;
						secondsLeft -= maxSleepSeconds;
					}

					// compensate for 0.5% clock drift and 5% chip deviation
					sleep = compensateDrift(sleep);

					call TPMTimer32.start(sleep * estimatedBusClock);

					call DCF77.stop();

				}
			} else {
				//////////////////////////////////////////////////////////////////////////
				// CASE 1 
				//////////////////////////////////////////////////////////////////////////

				currentMode = OFF;

				call TPMTimer32.start(estimatedBusClock);
				signal DCF77Hibernation.wakeUp(now - wakeUpTime);
			}
		}

		return SUCCESS;
	}

	event result_t DCF77.outSync() {

		atomic inSync = 0;

		return SUCCESS;
	}


	/////////////////////////////////////////////////////////////////////////////////
	// Timer fired
	//
	// Decide whether to wake-up or see what time it is 
	/////////////////////////////////////////////////////////////////////////////////
	async event result_t TPMTimer32.fired() {
		uint32_t sleep, msec, now;
	
		if (currentMode == TIMER) {

			//////////////////////////////////////////////////////////////////////////
			// CASE 1 
			//////////////////////////////////////////////////////////////////////////
			if (secondsLeft == 0) {

				currentMode = OFF;

				now = call DCF77.getUnixTimestamp();

				call TPMTimer32.start(estimatedBusClock);
				signal DCF77Hibernation.wakeUp(now - wakeUpTime);

			//////////////////////////////////////////////////////////////////////////
			// CASE 2 
			//////////////////////////////////////////////////////////////////////////
			} else if (secondsLeft <= 2) {

				currentMode = TIMER;

				msec = (secondsLeft * 1000) - call DCF77.getMilliseconds() + msecOffset;
				call TPMTimer32.start( (msec * estimatedBusClock) / 1000);
				secondsLeft = 0;

			//////////////////////////////////////////////////////////////////////////
			// CASE 3 & 4 
			//////////////////////////////////////////////////////////////////////////
			} else if (secondsLeft <= maxSleepSeconds) {

				currentMode = DCF;

				call TPMTimer32.start(estimatedSyncTime * estimatedBusClock);
				call DCF77.start(1);

			//////////////////////////////////////////////////////////////////////////
			// CASE 5 
			//////////////////////////////////////////////////////////////////////////
			} else if (secondsLeft > maxSleepSeconds) {

				currentMode = TIMER;

				if (secondsLeft < (estimatedSyncTime + maxSleepSeconds) ) {

					sleep = secondsLeft - estimatedSyncTime;
					secondsLeft = estimatedSyncTime;
				} else {

					sleep = maxSleepSeconds;
					secondsLeft -= maxSleepSeconds;
				}

				// compensate for 0.5% clock drift and 5% chip deviation
				sleep = compensateDrift(sleep);

				call TPMTimer32.start(sleep * estimatedBusClock);

				call DCF77.stop();

			}

		} else if (currentMode == DCF) {
		
			// panic!
			// DCF77 could not synchronize within allocated time
			// set wake-up solely on timer
			call DCF77.stop();

			if (secondsLeft == estimatedSyncTime) {
				currentMode = OFF;

				call TPMTimer32.start(estimatedBusClock);
				signal DCF77Hibernation.wakeUp(wakeUpTime);
				
			} else {

				currentMode = TIMER;

				secondsLeft -= estimatedSyncTime;

				call TPMTimer32.start(secondsLeft * estimatedBusClock);
				secondsLeft = 0;
			}

		} 


		return SUCCESS;
	}


	/////////////////////////////////////////////////////////////////////////////////
	// Internal function
	//
	// Reduces sleep with 1% 
	/////////////////////////////////////////////////////////////////////////////////
	uint32_t compensateDrift(uint32_t sleep) {
		uint32_t result;
	
		if (sleep < 1000) {

			result = (sleep * 990) / 1000;
		} else {

			result = (sleep / 1000) * 990;
		}

		return (result == 0) ? 1 : result;
	}
}



--- NEW FILE: DCF77C.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/


configuration DCF77C {
	provides {
		interface DCF77;
	}
}

implementation {
	components TPMM, 
		   DCF77M, 
		   PinControlM;

	DCF77 = DCF77M;
	
	DCF77M.TPMControl	-> TPMM;
	DCF77M.TPM		-> TPMM;
	DCF77M.LocalCounter	-> TPMM;
	DCF77M.TPMTimer16	-> TPMM.TPMTimer16;
	DCF77M.TPMTimer32	-> TPMM.TPMTimer32;
	DCF77M.ConradControl	-> PinControlM.StdControl[5];
	
}

--- NEW FILE: AMReceiverC.nc ---
/* Copyright (c) 2006, Marcus Chang
   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer. 

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution. 

    * Neither the name of the Dept. of Computer Science, University of 
      Copenhagen nor the names of its contributors may be used to endorse or 
      promote products derived from this software without specific prior 
      written permission. 

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   POSSIBILITY OF SUCH DAMAGE.
*/  

/*
	Author:		Marcus Chang <marcus at diku.dk>
	Last modified:	June, 2006
*/


configuration AMReceiverC {
	provides {
		interface AMReceiver;
	}
}

implementation {
	components TPMM, AMReceiverM, PinControlM;

	AMReceiver = AMReceiverM;

	AMReceiverM.AMRadioControl	-> PinControlM.StdControl[7];
	
	AMReceiverM.TPMControl		-> TPMM;
	AMReceiverM.TPM			-> TPMM;
}



More information about the Tinyos-contrib-commits mailing list