blob: 5c8f204b71be9497a7b1037ea861484eb48d9ca2 [file] [log] [blame]
/*
* ======== mon_ED.c ========
*/
#include <xdc/runtime/System.h>
#include <xdc/runtime/Log.h>
#include <xdc/runtime/Diags.h>
#include <local/runtime/utils/Stack.h>
#include <local/rf/Radio.h>
#include <local/rf/Bsp.h>
#include "msp430x22x4.h"
#define RED 1
#define GREEN 2
#define EVENT_SIZE 18
#define TEMP_OFFSET (*(Int *)0x10F4) /* temperature calibration offset */
#define FLASH_ADDR ((Bits8 *)0x10F0) /* Tag-Length-Value Table address */
Radio_LinkId sLinkID1 = 0;
void createRandomAddress();
void linkTo(void);
void measure(uint8_t msg[]);
/*
* ======== main ========
*/
void main(void)
{
Radio_Addr lAddr;
Radio_Status status;
volatile int i;
WDTCTL = WDTPW + WDTHOLD; /* Stop WDT */
/* delay loop to ensure proper startup before SimpliciTI increases DCO
* This is typically tailored to the power supply used, and in this case
* is overkill for safety due to wide distribution.
*/
for (i = 0; i < 0xFFFF; i++){}
if (CALBC1_8MHZ == 0xFF) { /* Do not run if cal values are erased */
P1DIR |= 0x03;
while (1) {
volatile int i;
for (i = 0; i < 0x5FFF; i++){}
Bsp_toggleLed(RED);
}
}
lAddr.addr[0] = FLASH_ADDR[0];
lAddr.addr[1] = FLASH_ADDR[1];
lAddr.addr[2] = FLASH_ADDR[2];
lAddr.addr[3] = FLASH_ADDR[3];
if (FLASH_ADDR[0] == 0xFF &&
FLASH_ADDR[1] == 0xFF &&
FLASH_ADDR[2] == 0xFF &&
FLASH_ADDR[3] == 0xFF) {
createRandomAddress(); /* set Random device address at startup */
}
BCSCTL1 = CALBC1_8MHZ; /* Set DCO after random function */
DCOCTL = CALDCO_8MHZ;
BCSCTL3 |= LFXT1S_2; /* LFXT1 = VLO */
/* Use timer interrupt to wake us from LPM once per second
* We use Timer_B since BSP uses Timer_A
*/
TBCCTL0 = CCIE; /* TBCCR0 interrupt enabled */
TBCCR0 = 12000; /* ~1 second (@ 8MHz) */
TBCTL = TASSEL_1 + MC_1; /* ACLK, upmode */
/* Keep trying to join until successful. toggle LEDs to indicate that
* joining has not occurred.
*/
Bsp_turnOnLed(GREEN);
while (Radio_SUCCESS != (status=Radio_start((Radio_CallBack)0, &lAddr))) {
System_printf("waiting to join (unused stack: %d, status %d) ...\r\n",
Stack_getUnused(), status);
if (Bsp_button(1)) { /* reset! */
Bsp_reset();
}
Bsp_toggleLed(RED);
Bsp_toggleLed(GREEN);
__bis_SR_register(LPM3_bits + GIE); /* LPM3 with ints enabled */
}
/* unconditional link to AP which is listening due to successful join. */
linkTo();
}
/*
* ======== createRandomAddress ========
*/
void createRandomAddress()
{
unsigned int rand, rand2;
extern int TI_getRandomIntegerFromVLO(void);
do { /* first byte can not be 0x00 or 0xFF */
rand = TI_getRandomIntegerFromVLO();
} while((rand & 0xFF00) == 0xFF00 || (rand & 0xFF00) == 0x0000);
rand2 = TI_getRandomIntegerFromVLO();
BCSCTL1 = CALBC1_1MHZ; /* Set DCO to 1MHz */
DCOCTL = CALDCO_1MHZ;
FCTL2 = FWKEY + FSSEL0 + FN1; /* MCLK/3 for Flash Timing Generator */
FCTL3 = FWKEY + LOCKA; /* Clear LOCK & LOCKA bits */
FCTL1 = FWKEY + WRT; /* Set WRT bit for write operation */
FLASH_ADDR[0] = (rand >> 8) & 0xFF;
FLASH_ADDR[1] = rand & 0xFF;
FLASH_ADDR[2] = (rand2 >> 8) & 0xFF;
FLASH_ADDR[3] = rand2 & 0xFF;
FCTL1 = FWKEY; /* Clear WRT bit */
FCTL3 = FWKEY + LOCKA + LOCK; /* Set LOCK & LOCKA bit */
}
/*
* ======== linkTo ========
*/
void linkTo()
{
uint8_t msg[3];
uint8_t traceFlag = 0;
/* turn off all LEDs */
Bsp_turnOffLed(RED);
Bsp_turnOffLed(GREEN);
/* keep trying to link... */
while (Radio_SUCCESS != Radio_link(&sLinkID1)) {
__bis_SR_register(LPM3_bits + GIE); /* LPM3 with interrupts enabled */
if (Bsp_button(1)) { /* reset! */
Bsp_reset();
}
Bsp_toggleLed(RED);
Bsp_toggleLed(GREEN);
}
/* turn off all LEDs */
Bsp_turnOffLed(RED);
Bsp_turnOffLed(GREEN);
Log_write4(Radio_ADDRESS, FLASH_ADDR[0], FLASH_ADDR[1],
FLASH_ADDR[2], FLASH_ADDR[3]);
Log_print1(Diags_USER1, "End Device: link id = %d", sLinkID1);
while (1) {
/* go into LPM3 with interrupts enabled, wait for timer to continue */
Radio_sleep();
__bis_SR_register(LPM3_bits + GIE);
/* time to wake up ... */
Radio_awake();
Bsp_turnOnLed(GREEN);
/* measure temp and voltage */
measure(msg);
if (traceFlag) {
Log_write1(Stack_UNUSED, Stack_getUnused());
}
if (Bsp_button(1)) {
traceFlag ^= 1;
if (traceFlag) {
Log_print0(Diags_USER1, "End Device: enabling trace ...");
}
else {
Log_print0(Diags_USER1, "End Device: trace disabled.");
}
Radio_Module_setMask(traceFlag ? Diags_ENTRY : 0);
}
/* send results to Access Point */
if (Radio_SUCCESS == Radio_send(sLinkID1, msg, sizeof(msg))) {
Bsp_turnOffLed(RED);
}
else {
Bsp_turnOnLed(RED);
}
Bsp_turnOffLed(GREEN);
}
}
/*
* ======== measure ========
*/
void measure(uint8_t msg[])
{
volatile long temp;
int degC, volt;
int results[2];
ADC10CTL1 = INCH_10 + ADC10DIV_4; /* Temp Sensor ADC10CLK/5 */
ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ADC10IE + ADC10SR;
/* delay to allow reference to settle */
for (degC = 240; degC > 0; degC--);
ADC10CTL0 |= ENC + ADC10SC; /* Sampling and conversion start */
__bis_SR_register(CPUOFF + GIE); /* LPM0 with interrupts enabled */
results[0] = ADC10MEM;
ADC10CTL0 &= ~ENC;
ADC10CTL1 = INCH_11; /* AVcc/2 */
ADC10CTL0 = SREF_1 + ADC10SHT_2 + REFON + ADC10ON + ADC10IE + REF2_5V;
/* delay to allow reference to settle */
for (degC = 240; degC > 0; degC--);
ADC10CTL0 |= ENC + ADC10SC; /* Sampling and conversion start */
__bis_SR_register(CPUOFF + GIE); /* LPM0 with interrupts enabled */
results[1] = ADC10MEM;
ADC10CTL0 &= ~ENC;
ADC10CTL0 &= ~(REFON + ADC10ON); /* turn off A/D to save power */
/* oC = ((A10/1024)*1500mV)-986mV)*1/3.55mV = A10*423/1024 - 278 */
/* the temperature is transmitted as an integer where 32.1 = 321 */
/* hence 4230 instead of 423 */
temp = results[0];
degC = ((temp - 673) * 4230) / 1024;
if (TEMP_OFFSET != 0xFFFF) {
degC += TEMP_OFFSET;
}
/* Encode event for transmission
*
* message format, UB = upper Byte, LB = lower Byte
* -------------------------------
* |degC LB | degC UB | volt LB |
* -------------------------------
* 0 1 2
*/
temp = results[1];
volt = (temp * 25) / 512;
msg[0] = degC & 0xFF;
msg[1] = (degC >> 8) & 0xFF;
msg[2] = volt;
}
/*
* ======== loggerCallback ========
*/
Void loggerCallback(Log_EventRec *erp)
{
UInt8 msg[EVENT_SIZE];
int len = EVENT_SIZE - 2;
UInt8 *src, *dst;
UInt16 mask;
/* Encode event for transmission
*
* message format:
* --------------------------------------
* | payload len | 0x80 | event payload ...
* --------------------------------------
* 0 1 2 ...
*/
msg[0] = len;
msg[1] = 0x80; /* sentinel for event message */
/* copy event into msg buffer */
for (dst = msg + 2, src = (UInt8 *)&erp->serial; len > 0; len--) {
*dst++ = *src++;
}
/* disable logging of Radio to prevent recursion */
mask = Radio_Module_getMask();
Radio_Module_setMask(0);
if (sLinkID1 && Radio_SUCCESS == Radio_send(sLinkID1, msg, sizeof(msg))) {
Bsp_turnOffLed(GREEN);
}
else {
Bsp_toggleLed(GREEN);
Bsp_toggleLed(RED);
}
/* restore logging of Radio */
Radio_Module_setMask(mask);
}
/* ----------------------------------------------------------------------------
* ADC10 interrupt service routine
* --------------------------------------------------------------------------*/
__asm("\t.global ADC10_ISR");
__asm("\t.sect \".adc10\"");
__asm("\t.align 2");
__asm("_ADC10_vector:\n\t.field ADC10_ISR, 16");
__interrupt void ADC10_ISR(void)
{
__bic_SR_register_on_exit(CPUOFF); /* Clear CPUOFF bit from 0(SR) */
}
/* ----------------------------------------------------------------------------
* Timer B0 interrupt service routine
* --------------------------------------------------------------------------*/
__asm("\t.global TIMER_B0_ISR");
__asm("\t.sect \".timer_b0\"");
__asm("\t.align 2");
__asm("_TIMER_B0_vector:\n\t.field TIMER_B0_ISR, 16");
__interrupt void TIMER_B0_ISR(void)
{
__bic_SR_register_on_exit(LPM3_bits); /* Clear LPM3 bits from 0(SR) */
}