DolphinV4 API  1.6.1.0
Sensor Application



Sensor Application file - main.c

#include "EO3100I_API.h"
#include "EO3100I_CFG.h"
//#include "EO3100I_API_DBG.h"
#include "main.h"
/************************************************************************-
EVA Board:
EVA320-2
Input PIN:
ADIO_0
Analog input for Light intensity or NTC measurement
ADIO_1
Analog input for POTI measurement
ADIO_2
Analog input for storage voltage measurement
WAKE_0
Wakes up the sensor. If a controller ID is learned in, the sensor makes
Data Reclaims than transmits a data telegram with the previous
Reclaim status.
WAKE_1
Wakes up the sensor and transmits a Learn Reclaim telegram.
Output PIN:
ADIO_7
LED indicating sending
Description:
The example shows how to create a SmartACK sensor application.
The Sensor wakes up periodicaly 1x hour and transmits a data telegram.
This data telegram in it's 1st byte contains the status of the PREVIOUS
telegram communication. The following states are possible:
0xFF - first data telegram from sensor after startup
0xEE - no controller ID learned in, watchdog reset
0xDD - no controller ID learned in, wake0 was pressed
0x01 - 0x03 - controller ID learned in, Data Acknowledge from Controller after 1,2 or 3 Data Reclaims
0x04 - controller ID learned in but there was no Data Acknowledge even after 3 Data Reclaims
0x05 - means that the mailbox of the controller is empty
The program has to send either 3 SmartACK learn request or EnOcean
standard telegrams using the radio_ulpSubTelTiming macro, and the
radio_PrepareTelegram and radio_ulpsendTelegram functions. During the pauses
it performs a short term sleep to save energy.
After all 3 sub telegrams are sent it also performs a short term sleep
(default response time is 200 ms), till the controller has the answer from
its backbone. For getting the reclaims from the post master the smack_reclaim functions
are used.
Every necessary timing constraints are handled inside this function.
If the reclaim was successful, the function returns the received telegram.
If it was not successful, then the reclaim function can be called again for
a further try as often as it is senseful for the application.
Notes:
Be sure not to initialize or use timer0 in EO3100I_CFG.h, because timer0
is used for receiving timeouts.
Use the macro SMART_TEST in order to transmit the result of the acknowledge
via serial port.
To save power during startuk the XTAL is started imediately after
power on with the help of the init_begin() function. This function
is called from the startup.a51.
The application uses a special UIDIV_F.a51 file. This routine is faster
than the classical division. For more information read
http://www.keil.com/support/docs/3412.htm.Be sure to place this file
before the EO3100I_API.LIB in the Project workspace, otherwise you will
get a warning: Module not unique.
-************************************************************************/
code uint8 VERSION_APP[] = {0xE0,'V','E','R','S','I','O','N',1,0,1,0,'A','S','M','A','C','K','S','E','N','S','O','R',0x00,0xE0};
#define MANUFACTURERID 0xff
#define EEP1 0xBB
#define EEP2 0xAA
#define EEP3 0xCC
#define RSSI_SENSOR 0
#define REPEATERID 0
#define STATUS_LRN_REQ 0x0F
#define MAX_RECLAIMS 6
#define RECLAIM_PAUSE 60
#define MAILBOX_INDEX 0
FLASH_DATA code u8gFlashData _at_ FLASH_START_DATA;
RAM0_SHADOW_STRUCT xdata ram0;
WAKE_TYPE u8Wake;
SMACK_RECLAIM_TYPE u8ReclaimType;
uint8 u8ReclaimCounter=0;
void sendMyTelegram()
{
// Initialize random generator for different series of random numbers for different sub telegram timings
misc_rndInit(ram0.seed.u16Seed);
do
{
ram0.seed.seed.u8SeedLo = misc_rndGet()+19;
ram0.seed.seed.u8SeedHi = misc_rndGet()+7;
} while (ram0.seed.u16Seed == 0);
mem_writeRAM0((uint8*)&ram0, 0x00, sizeof(RAM0_SHADOW_STRUCT));
pTel.p_tx.u8SubTelNum = 3;
pTel.p_tx.u32DestinationId = 0xffffffff;
io_setDigital(ADIO_7,0);
radio_sendTelegram(&rTel, &pTel);
time_wait(100);
io_setDigital(ADIO_7,1);
}
void sendSMACKLearnRequest()
{
// send a learn request telegram
rTel.sm_lrn_req.u8Choice = RADIO_CHOICE_SM_LRN_REQ;
rTel.sm_lrn_req.u11ManufacturerId = MANUFACTURERID;
rTel.sm_lrn_req.u5ReqCode = SENSOR_DEFAULT_REQ_CODE;
rTel.sm_lrn_req.u8EEP[0] = EEP1;
rTel.sm_lrn_req.u8EEP[1] = EEP2;
rTel.sm_lrn_req.u8EEP[2] = EEP3;
rTel.sm_lrn_req.u8RssiDbm = RSSI_SENSOR;
rTel.sm_lrn_req.u32RepeaterId = REPEATERID;
rTel.sm_lrn_req.u32SenderId = 0;
rTel.sm_lrn_req.u8Status = STATUS_LRN_REQ;
rTel.sm_lrn_req.u8Length = RADIO_DEC_LENGTH_SM_LRN_REQ;
sendMyTelegram();
u8ReclaimType = LEARN_RECLAIM;
}
void sendDataTelegram()
{
uint16 u16Value;
sint16 s16negref;
sint16 s16posref;
sint16 s16adio0value;
sint16 s16adio1value;
sint16 s16adio2value;
// send a data telegram, fill it with your measurement data
rTel.t4bs.u8Choice = RADIO_CHOICE_4BS;
rTel.t4bs.u8Data3 = ram0.u8ReclaimCounter;
//measurement from stm 300
io_enableAnalog(1); // configuring hardware for analog measurement no VGA, increase current to Analog current
io_ulpMeasAnalog(RVSS, RVDD, &s16negref); // measure negative reference against internal voltage
io_ulpMeasAnalog(RVDD, RVSS, &s16posref); // measure positive reference against internal voltage
io_ulpMeasAnalog(GPIO1_ADIO_0, RVSS, &s16adio0value); // measure ADIO_0 against internal voltage
io_ulpMeasAnalog(GPIO1_ADIO_1, RVSS, &s16adio1value); // measure ADIO_1 against internal voltage
io_ulpMeasAnalog(GPIO1_ADIO_2, RVSS, &s16adio2value); // measure ADIO_2 against internal voltage
io_enableAnalog(0); // restoring previous configuration for radio functionality and reduce current to CPU current*/
io_ulpScaleAnalog(s16posref, s16negref, 8, &u16Value); // scale and calculate result for ADIO_0
rTel.t4bs.u8Data0 = (uint8)(u16Value);
io_ulpScaleAnalog(s16posref, s16negref, 8, &u16Value); // scale and calculate result for ADIO_0
rTel.t4bs.u8Data1 = (uint8)(u16Value);
io_ulpScaleAnalog(s16posref, s16negref, 8, &u16Value); // scale and calculate result for ADIO_0
rTel.t4bs.u8Data2 = (uint8)(u16Value);
rTel.t4bs.u32Id = 0;
rTel.t4bs.u8Status = 0;
rTel.t4bs.u8Length = RADIO_DEC_LENGTH_4BS;
sendMyTelegram();
u8ReclaimType = DATA_RECLAIM;
}
void main()
{
RESET_TYPE u8ResetSrc;
uint8 u8state=0;
SMACK_RESULT u8Result;
bit bReclaim = FALSE;
uint32 u32WatchdogPeriode;
//Get the info where are we comming from
pwr_getSystemReset(&u8ResetSrc);
//Configuration in EO3100I_cfg
mainInit();
// Read back saved values of RAM0
mem_readRAM0((uint8*)&ram0, 0x00, sizeof(RAM0_SHADOW_STRUCT));
mem_readFlash((uint8*)&u8gFlashShadow, FLASH_START_DATA, sizeof(FLASH_DATA));
if (u8gFlashShadow.u16ResponseTime == 0xffff)
u8gFlashShadow.u16ResponseTime = MAX_RESPONSE_TIME; // it was deleted, so take default value
switch (u8ResetSrc)
{
case PIN_RESET:
case VDD_RESET:
//apply calibration factor - NOTE THE CHIP HAS TO BE CALIBRATED FOR WATCHDOG
u32WatchdogPeriode = CONV_TIME_TO_COUNTER(100, SEC, WATCHDOG_CLK);
u32WatchdogPeriode = u32WatchdogPeriode*gModArea.val.u16CalibWatchdog/WATCHDOG_CALIB_CONST;
//set the timer value
pwr_setSleepTimer(WATCHDOG_TIMER, u32WatchdogPeriode ,0);
ram0.u8ReclaimCounter = 0xff; // indicate power up or pin reset
ram0.seed.seed.u8SeedLo = misc_rndGet()+19;
ram0.seed.seed.u8SeedHi = misc_rndGet()+7;
mem_writeRAM0((uint8*)&ram0, 0x00, sizeof(RAM0_SHADOW_STRUCT));
// fall through
//when woken up by Watchdog or reset send a data telegram
sendDataTelegram();
// If we know a controller perform a reclaim
if (u8gFlashShadow.u32ControllerId != 0xffffffff)
bReclaim = TRUE;
else
{
ram0.u8ReclaimCounter = 0xEE; // if no controller learned, indicate in next 4BS telegram, that no reclaim was tried
mem_writeRAM0((uint8*)&ram0, 0x00, sizeof(RAM0_SHADOW_STRUCT));
}
break;
// Check the state of the wake pins, if the wake pin is pressed send a data telegram
io_getPort(GPIO2, &u8state);
if (!(u8state & 0x04))
{
// Send
sendDataTelegram();
// If we know a controller perform a reclaim
if (u8gFlashShadow.u32ControllerId != 0xffffffff)
bReclaim = TRUE;
else
{
ram0.u8ReclaimCounter = 0xDD; // if no controller learned, indicate in next 4BS telegram, that no reclaim was tried
mem_writeRAM0((uint8*)&ram0, 0x00, sizeof(RAM0_SHADOW_STRUCT));
}
}
// Be sure to start the counting from the beginning
break;
// Check the state of the wake pins
io_getPort(GPIO2, &u8state);
if (!(u8state & 0x08))
{
// only when wake1 is pressed
u8gFlashShadow.u16ResponseTime = MAX_RESPONSE_TIME; // for learning use always maximum resonse time
sendSMACKLearnRequest();
bReclaim = TRUE;
}
// Be sure to start the counting from the beginning
break;
default:
break;
}
if (bReclaim)
{
// pause till response is received in controller.
pwr_shortTermSleep((uint16)( ((uint32)u8gFlashShadow.u16ResponseTime * gModArea.val.u16CalibShortTerm) / SHORT_TERM_CALIB_CONST), NO_WAKE_FLAG);
// now its time to reclaim the answer
while (u8ReclaimCounter++ < MAX_RECLAIMS)
{
pTel.p_tx.u8SubTelNum = 3;
pTel.p_tx.u32DestinationId = 0xffffffff;
u8Result = smack_reclaim(u8ReclaimType, MAILBOX_INDEX, &rTel, &pTel);
// wait for next smack reclaim try.
//shortTermSleep(RECLAIM_PAUSE);
pwr_shortTermSleep((uint16)( ((uint32)RECLAIM_PAUSE * 100 * gModArea.val.u16CalibShortTerm) / SHORT_TERM_CALIB_CONST), NO_WAKE_FLAG);
if (u8Result == SMACK_OK)
{
// we received a response telegram in rTel/pTel
smartack_Evaluation();
break;
}
// Send information that the Reclaim sa succesfull
rTel.t1bs.u8Data = u8Result;//rTel.t1bs.u8Choice;
rTel.t1bs.u8Choice = RADIO_CHOICE_1BS;
rTel.sm_lrn_req.u8Length = RADIO_DEC_LENGTH_1BS;
sendMyTelegram();
}
// Save actual data in RAM0
ram0.u8ReclaimCounter = u8ReclaimCounter;
mem_writeRAM0((uint8*)&ram0, 0x00, sizeof(RAM0_SHADOW_STRUCT));
}
// Jump to deep sleep mode
// We should not get here
while(1)
{
io_togDigital(ADIO_7);
time_wait(100);
}
}



Sensor Application include file - main.h

/******************************************************************
Project version: $Name: 1.59 $
\file main.h
\ingroup SMACK sensor example
\version $Revision: 1.5 $
\date $Date: 2009/08/03 14:44:28 $
\author Armin Pelka
\brief Example of a smart ack sensor
Processor: EO3100I
Company: EnOcean Gmbh
******************************************************************/
#ifndef _MAIN_H_INCLUDED
#define _MAIN_H_INCLUDED
/****************************Defines*************************************/
#define FLASH_START_DATA 0x6000
/************************* TYPES/STRUCTURES/PARAMETERS ***************************/
typedef struct
{
uint8 u8ReclaimCounter;
union
{
uint16 u16Seed;
struct
{
uint8 u8SeedHi;
uint8 u8SeedLo;
} seed;
} seed;
} RAM0_SHADOW_STRUCT;
typedef struct
{
uint16 u16ResponseTime;
uint8 u8MailboxIndex;
uint32 u32ControllerId;
} FLASH_DATA;
/****************************Variables***********************************/
extern TEL_RADIO_TYPE rTel;
extern FLASH_DATA code u8gFlashData;
extern FLASH_DATA xdata u8gFlashShadow;
extern uint8 u8ReclaimCounter;
/****************************Functions**********************************/
void smartack_Evaluation();
#endif



Sensor Application evaluation file - evaluation.c

#include "EO3100I_API.h"
#include "stdio.h"
#include "string.h"
#include "main.h"
#ifdef SMACK_TEST
char smack_sensor_buf[70];
#endif
FLASH_DATA xdata u8gFlashShadow;
// in this example evaluation we put all the information got in rTel telegram
// to uart interface to see it in terminal program when SMACK_TEST is defined
void smartack_Evaluation()
{
// This function will be called, when a telegram was received in rTel
// Here is the action to be done, f.e. update a display
switch (GET_CHOICE(rTel))
{
{
// usualy do some stuff, f.e. save response time, mailbox index and controller ID in flash
if ((rTel.sm_lrn_ans.u56Data.answer_acknowledge.u8AckCode & ACK_CODE_MAIN_MASK) == ACK_CODE_LEARN_IN)
{
u8gFlashShadow.u16ResponseTime = rTel.sm_lrn_ans.u56Data.answer_acknowledge.u16ResponseTime;
u8gFlashShadow.u8MailboxIndex = rTel.sm_lrn_ans.u56Data.answer_acknowledge.u8MailBoxIdx;
u8gFlashShadow.u32ControllerId = rTel.sm_lrn_ans.u32SenderId;
}
else
{
u8gFlashShadow.u16ResponseTime = 0xffff;
u8gFlashShadow.u8MailboxIndex = 0xff;
u8gFlashShadow.u32ControllerId = 0xffffffff;
}
mem_writeFlash((uint8*)(&u8gFlashShadow), FLASH_START_DATA, sizeof(FLASH_DATA));
#ifdef SMACK_TEST
sprintf(smack_sensor_buf, " Learn Acknowledge ");
uart_sendBuffer(&smack_sensor_buf, strlen(smack_sensor_buf));
time_wait(50); // to be sure, the data is sent
sprintf(smack_sensor_buf, " Response time %u ms ", rTel.sm_lrn_ans.u56Data.answer_acknowledge.u16ResponseTime);
uart_sendBuffer(&smack_sensor_buf, strlen(smack_sensor_buf));
time_wait(50); // to be sure, the data is sent
sprintf(smack_sensor_buf, " Mailbox index %u ", rTel.sm_lrn_ans.u56Data.answer_acknowledge.u8MailBoxIdx);
uart_sendBuffer(&smack_sensor_buf, strlen(smack_sensor_buf));
time_wait(50); // to be sure, the data is sent
sprintf(smack_sensor_buf, " Ack code %u ", rTel.sm_lrn_ans.u56Data.answer_acknowledge.u8AckCode);
uart_sendBuffer(&smack_sensor_buf, strlen(smack_sensor_buf));
time_wait(50); // to be sure, the data is sent
sprintf(smack_sensor_buf, " Controller-ID %u ", rTel.sm_lrn_ans.u32SenderId);
uart_sendBuffer(&smack_sensor_buf, strlen(smack_sensor_buf));
time_wait(50); // to be sure, the data is sent
#endif
break;
}
{
SIGNAL_INDEX u8SignalIdx = rTel.sig.u8SignalIdx;
u8ReclaimCounter = 0x05;
#ifdef SMACK_TEST
switch (u8SignalIdx)
{
{
sprintf(smack_sensor_buf, " Mailbox empty ");
uart_sendBuffer(&smack_sensor_buf, strlen(smack_sensor_buf));
time_wait(50); // to be sure, the data is sent
break;
}
{
sprintf(smack_sensor_buf, " Mailbox does not exist ");
uart_sendBuffer(&smack_sensor_buf, strlen(smack_sensor_buf));
time_wait(50); // to be sure, the data is sent
break;
}
case RESET:
{
sprintf(smack_sensor_buf, " Reset signal ");
uart_sendBuffer(&smack_sensor_buf, strlen(smack_sensor_buf));
time_wait(50); // to be sure, the data is sent
break;
}
default:
{
sprintf(smack_sensor_buf, " Unknown signal msg %d ", u8SignalIdx);
uart_sendBuffer(&smack_sensor_buf, strlen(smack_sensor_buf));
time_wait(50); // to be sure, the data is sent
break;
}
}
#endif
break;
}
default:
{
#ifdef SMACK_TEST
uint8 i;
char * pBuf = smack_sensor_buf;
char tmp[4];
sprintf(smack_sensor_buf, " Data Telegramm ");
uart_sendBuffer(&smack_sensor_buf, strlen(smack_sensor_buf));
time_wait(50); // to be sure, the data is sent
// print whole telegram to uart
for (i=0; i<rTel.raw.u8Length; i++)
{
sprintf(tmp, "%2x ", rTel.raw.bytes[i]);
*pBuf++=tmp[0];
*pBuf++=tmp[1];
*pBuf++=0x20; // Blank
}
*pBuf=0; // end of string
uart_sendBuffer(&smack_sensor_buf, strlen(smack_sensor_buf));
time_wait(50); // to be sure, the data is sent
#endif
break;
}
}
}



Config file - EO3100I_CFG.h

// Generated on 2013-06-07 15:41:32 by DolphinAPIConfigurator 1.1.0.20
#ifndef _EO3100I_CFG_H_INCLUDED
#define _EO3100I_CFG_H_INCLUDED
void startupInit();
void mainInit();
//*********************RADIO PARAM***************************
#define RADIO_BUFF_NUM 10
#define RADIO_MATURITY_TIME 100
extern volatile RADIO_BUFFER_TYPE xdata gRadioBuff[RADIO_BUFF_NUM];
//*********************FILTER PARAM***************************
#define FILTER_NUM 1
extern volatile uint32 xdata u32gFilterValue[FILTER_NUM];
extern volatile uint8 xdata u8gFilterCfg[FILTER_NUM];
//*********************IO PARAM******************************
extern uint8 code io_param[];
#endif //_EO3100I_CFG_H_INCLUDED



Config file - EO3100I_CFG.c

// Generated on 2013-06-07 15:41:51 by DolphinAPIConfigurator 1.1.0.20
#include "EO3100I_API.h"
#include "EO3100I_CFG.h"
//*********************API INIT***************************
//Note: Function is called from startup.a51. Global variables are not yet initialized!
void startupInit()
{
io_init(io_param);
}
void mainInit()
{
radio_init(RADIO_BUFF_NUM, RADIO_MATURITY_TIME);
}
//*********************RADIO PARAM***************************
volatile RADIO_BUFFER_TYPE xdata gRadioBuff[RADIO_BUFF_NUM];
//*********************FILTER PARAM***************************
volatile uint32 xdata u32gFilterValue[FILTER_NUM];
volatile uint8 xdata u8gFilterCfg[FILTER_NUM];
//*********************IO PARAM******************************
uint8 code io_param[] = {
0x07, //IDX_GPIO_CONF
0x00, //IDX_GPIO0_CONF
0x0F, //IDX_GPIO0_PULL_CONF
0x00, //IDX_GPIO0_DIR
0x07, //IDX_GPIO1_AN
0x00, //IDX_GPIO1_CONF0
0x00, //IDX_GPIO1_CONF1
0x03, //IDX_GPIO1_DIG_CONF
0x80, //IDX_GPIO1_DIR
0x7F, //IDX_GPIO1_PULL
0x0C, //IDX_GPIO2_CONF
0x00, //IDX_GPIO2_DIR
0x00, //IDX_GPIO0
0x00, //IDX_GPIO1
0x00, //IDX_GPIO2
};
// I/O Configuration overview
//
// Pin : Interface Direction Pull InitValue Interrupt
// SCSEDIO0 : Digital I/O In Up 0 No
// SCLKDIO1 : Digital I/O In Up 0 No
// WSDADIO2 : Digital I/O In Up 0 No
// RSDADIO3 : Digital I/O In Up 0 No
// ADIO0 : Analogue I/O In Up 0 No
// ADIO1 : Analogue I/O In Up 0 No
// ADIO2 : Analogue I/O In Up 0 No
// ADIO3 : Digital I/O In Up 0 No
// ADIO4 : Digital I/O In Up 0 No
// ADIO5 : Digital I/O In Up 0 No
// ADIO6 : Digital I/O In Up 0 No
// ADIO7 : Digital I/O Out None 0 No
// WXIDIO : Digital I/O In Up 0 No
// WXODIO : Digital I/O In Up 0 No
// WAKE0 : Digital I/O In None 0 No
// WAKE1 : Digital I/O In None 0 No