Code Snippets Submitted by nemecep1
General library for debouncing (filtering) of digital inputs
/**************************************************************************************/
/* sample usage of the library */
/**************************************************************************************/
//Remark: sys_timer_ticks should be provided for timing by the user.
/* Simplest example with undefined CONFIG_DEBOUNCE_WITH_HANDLE and CONFIG_DEBOUNCE_SEPARATE_TIMES */
#include <debounce.h>
#define INPUTS_NUM 12
nl_debouce_time_t inp_times[ INPUTS_NUM ];
nl_debouce_time_t filt_time = 10; //same value will be used for t_on and t_off
int main(void)
{
nl_inp_t inp_state, filtered_inp_state;
debounce_init( inp_times, INPUTS_NUM, &filt_time, &filt_time,
(nl_ticks_t*)&sys_timer_ticks );
while(1)
{
//user defined function, which return actual state of all inputs as bit array
inp_state = get_input_state();
debounce_proc(&inp_state, &filtered_inp_state);
//do something with filtered_inp_state
//...............
//main program functionality
//...............
}
}
/* More complex example with defined CONFIG_DEBOUNCE_WITH_HANDLE and CONFIG_DEBOUNCE_SEPARATE_TIMES */
#include <debounce.h>
#define INPUTS_NUM 5
struct debounce_state_s inp_dbnc_s;
nl_debouce_time_t inp_times[ INPUTS_NUM ];
nl_debouce_time_t t_on[ INPUTS_NUM ] = {10,10,20,20,50};
nl_debouce_time_t t_off[ INPUTS_NUM ] = {5,5,10,10,50};
int main(void)
{
nl_inp_t inp_state, filtered_inp_state;
debounce_init( &inp_dbnc_s, inp_times, INPUTS_NUM,
t_on, t_off, (nl_ticks_t*)&sys_timer_ticks );
while(1)
{
//user defined function, which return actual state of all inputs as bit array
inp_state = get_input_state();
debounce_proc(&inp_dbnc_s, &inp_state, &filtered_inp_state);
//do something with filtered_inp_state
//...............
//main program functionality
//...............
}
}
/**************************************************************************************/
/* debounce library header file "debounce.h" */
/**************************************************************************************/
#ifndef _DEBOUNCE_H_
#define _DEBOUNCE_H_
#include <stdint.h>
/* because library is multiplatform, following types are defined in separate file */
#include "nlib_types.h"
/* examaple of types definition in "nlib_types.h" */
//typedef uint32_t nl_ticks_t;
//typedef int16_t nl_debouce_time_t; //so maximum filter time is 32767ms (considering period of ticks 1ms)
//typedef uint32_t nl_inp_t; //up to 32 inputs can be handled
/* in general case following macros should be provided in this header file, or can be defined directly */
#include <debounce_config.h>
//#define CONFIG_DEBOUNCE_WITH_HANDLE
//#define CONFIG_DEBOUNCE_SEPARATE_TIMES
#ifdef CONFIG_DEBOUNCE_WITH_HANDLE
#define DEBOUNCE_STRUCT_PAR struct debounce_state_s * debounce_state,
#else
#define DEBOUNCE_STRUCT_PAR
#endif
typedef struct debounce_state_s
{
const nl_ticks_t* ticks; //pointer to timing variable (is incremented e.g. each 1ms)
nl_ticks_t old_ticks;
uint_fast8_t inp_num; //number of inputs
const nl_debouce_time_t *debounce_on_time,*debounce_off_time; //tables with desired filter times
nl_debouce_time_t* inp_times; //actual time ON/OFF - non-negative values = ON, negative = OFF
}
debounce_state_t;
void debounce_init(DEBOUNCE_STRUCT_PAR nl_debouce_time_t* inp_tim, uint_fast8_t num, const nl_debouce_time_t *dton,const nl_debouce_time_t *dtoff, const nl_ticks_t* ticks);
uint_fast8_t debounce_proc(DEBOUNCE_STRUCT_PAR const nl_inp_t* act_inp_state, nl_inp_t* debounced_inp_state);
#endif /*_DEBOUNCE_H_*/
/**************************************************************************************/
/* debounce library source file "debounce.c" */
/**************************************************************************************/
#include "debounce.h"
#include <string.h>
//allow using multiple instances
#ifndef CONFIG_DEBOUNCE_WITH_HANDLE
struct debounce_state_s _debounce_state_;
struct debounce_state_s * debounce_state = &_debounce_state_;
#endif
/* allow different times for each input */
#ifndef CONFIG_DEBOUNCE_SEPARATE_TIMES
#define _debounce_times_idx_ 0
#else
#define _debounce_times_idx_ i
#endif
//maco trick to find maximum value of given signed integer type "http://www.fefe.de/intof.html"
#define __HALF_MAX_SIGNED(type) ((type)1 << (sizeof(type)*8-2))
#define __MAX_SIGNED(type) (__HALF_MAX_SIGNED(type) - 1 + __HALF_MAX_SIGNED(type))
/*
Init function of the library
DEBOUNCE_STRUCT_PAR - depending on "CONFIG_DEBOUNCE_WITH_HANDLE": nothing, or pointer to handle
inp_tim - array of variables for storing of state for each input (number of elements must be the same as number of inputs!)
num - number of inputs
dton - depending on "CONFIG_DEBOUNCE_SEPARATE_TIMES": pointer to sigle value (minimal ON time), or array of times
dtoff - depending on "CONFIG_DEBOUNCE_SEPARATE_TIMES": pointer to sigle value (minimal OFF time), or array of times
ticks - pointer to variable, which is periodicaly incremented
*/
void debounce_init(DEBOUNCE_STRUCT_PAR nl_debouce_time_t* inp_tim, uint_fast8_t num, const nl_debouce_time_t *dton, const nl_debouce_time_t *dtoff ,const nl_ticks_t* ticks)
{
debounce_state-> inp_times=inp_tim;
debounce_state-> inp_num=num;
debounce_state-> debounce_on_time=dton;
debounce_state-> debounce_off_time=dtoff;
debounce_state-> ticks=ticks;
debounce_state-> old_ticks=*ticks;
memset(inp_tim,0,sizeof(*inp_tim)*num);
inp_tim[0]=__MAX_SIGNED(nl_debouce_time_t); //this is used later to evaluate first iteration after start
}
/*
This is core function of the library
DEBOUNCE_STRUCT_PAR - depending on "CONFIG_DEBOUNCE_WITH_HANDLE": nothing, or pointer to handle
act_inp_state - pointer to variable with actual state of all inputs (1 bit for each input)
debounced_inp_state - resulting state after filtering
return - 0=no change, 1=some input(s) are changed
*/
uint_fast8_t debounce_proc(DEBOUNCE_STRUCT_PAR const nl_inp_t* act_inp_state, nl_inp_t* debounced_inp_state)
{
uint_fast8_t i,change=0;
nl_inp_t mask=1;
nl_ticks_t tic_diff;
tic_diff=(nl_ticks_t) (*(debounce_state-> ticks) - debounce_state-> old_ticks);
debounce_state-> old_ticks = *(debounce_state-> ticks);
if ((debounce_state-> inp_times)[0] == __MAX_SIGNED(nl_debouce_time_t)) //evaluate, if it is a first iteration
{
*debounced_inp_state=*act_inp_state;
for(i=0; i<debounce_state-> inp_num ;i++)
(debounce_state-> inp_times)[i]=0;
return 0;
}
for(i=0; i<debounce_state-> inp_num ;i++)
{
if ( *act_inp_state & mask) //actual state is ON
{
if ((debounce_state-> inp_times)[i] >= 0) //and last state was ON
{
if (((debounce_state-> inp_times)[i] + (nl_debouce_time_t) tic_diff) < debounce_state-> debounce_on_time[_debounce_times_idx_])
{
(debounce_state-> inp_times)[i] += (nl_debouce_time_t) tic_diff; //filter time not elapsed
}
else
{ //filter time elapsed
if (!( *debounced_inp_state & mask))
{
*debounced_inp_state |= mask;
change=1;
}
}
}
else (debounce_state-> inp_times)[i] = 0;
}
else //actual state is OFF
{
if (debounce_state-> inp_times[i] < 0) //and last state was OFF
{
if ( (nl_debouce_time_t)(((debounce_state-> inp_times)[i] - (nl_debouce_time_t) tic_diff)) >= (-1*debounce_state-> debounce_off_time[_debounce_times_idx_]))
{
(debounce_state-> inp_times)[i] -= (nl_debouce_time_t) tic_diff; //filter time not elapsed
}
else
{ //filter time elapsed
if ( *debounced_inp_state & mask)
{
*debounced_inp_state &= ~mask;
change=1;
}
}
}
else (debounce_state-> inp_times)[i] = -1;
}
mask=(nl_inp_t) mask<<1;
}
return change;
}
Very simple software timer framework
/*********************************************************************************/
/* sample usage */
/*********************************************************************************/
#include <lt_timer.h>
LT_TIMER_DEC(slow_timer) /* declaration */
LT_TIMER_IMP(slow_timer) /* implementation */
LT_TIMER_DEC(fast_timer) /* declaration */
LT_TIMER_IMP(fast_timer) /* implementation */
int main(void)
{
fast_timer_init();
slow_timer_init();
while(1)
{
if (slow_timer_expired(1000))
{
//do something each 1000ms
}
if (fast_timer_expired(10))
{
//do something each 10ms
}
//...............
//main program functionality
//...............
}
}
/*********************************************************************************/
/* lt_timer definition */
/*********************************************************************************/
#ifndef _LT_TIMER_H
#define _LT_TIMER_H
#include <stdint.h>
/* these definitions can vary on different platforms */
typedef unsigned int lt_ticks_t;
typedef int lt_tidiff_t;
typedef unsigned long lt_mstime_t;
typedef signed long lt_msdiff_t;
static lt_ticks_t last_ticks;
static lt_mstime_t actual_msec;
/* it is expected increment "sys_timer_ticks" variable in some timer interrupt */
/* alternatively some function which return ticks can be provided */
#define lt_get_ticks() (sys_timer_ticks)
/* in ms (SYS_TIMER_HZ must be provided by user)*/
#define lt_get_msbase() (1000/SYS_TIMER_HZ)
static inline void
lt_mstime_update()
{
lt_ticks_t act_ticks;
lt_mstime_t msec_diff;
act_ticks=lt_get_ticks();
msec_diff=((lt_tidiff_t)(act_ticks-last_ticks))*lt_get_msbase();
last_ticks=act_ticks;
actual_msec+=msec_diff;
}
#define LT_TIMER_DEC(cust_prefix) \
\
extern lt_mstime_t cust_prefix##_last_expired; \
static inline void \
cust_prefix##_init() \
{\
lt_mstime_update();\
cust_prefix##_last_expired=actual_msec;\
}\
static inline int \
cust_prefix##_expired(lt_mstime_t expiration) \
{\
lt_mstime_update();\
\
if ((lt_msdiff_t)(actual_msec-cust_prefix##_last_expired)>=expiration) {\
cust_prefix##_last_expired=actual_msec;\
return 1;\
}\
\
return 0;\
}
#define LT_TIMER_IMP(cust_prefix) \
\
lt_mstime_t cust_prefix##_last_expired; \
#endif /* _LT_TIMER_H */
SHT11 humidity sensor library (sensirion manufacture)
/*********** begin of library header file sht11.h ***************/
#ifndef _SHTXX_H
#define _SHTXX_H
#include <inttypes.h>
#define HUMIDITY_BYTE 0x05
#define TEMPERATURE_BYTE 0x03
//State machine states
#define SHT_DATA_WAIT_INITIAL_STATE 0
#define SHT_DATA_WAIT_TIMEOUT_STATE 1
#define SHT_PROC_RESET_COND_STATE 0
#define SHT_PROC_START_COND_STATE 1
#define SHT_PROC_SEND_STATE 2
#define SHT_PROC_WAIT_STATE 3
#define SHT_PROC_RETURN_STATE 4
#define SHT_RH_READ_TEMPERATURE_STATE 0
#define SHT_RH_READ_HUMIDITY_STATE 1
#define SHT_RH_CONVERT_RH_STATE 2
#include <sht_low_level_drv.h>
void shtxx_init(void);
int shtxx_proc(uint8_t sht_param,uint16_t *ret_value);
int shtxx_get_temp(uint16_t *ret_temperature);
int shtxx_get_temp_RH( int16_t *ret_temperature, int16_t *ret_humidity );
#endif /* _SHTXX_H */
/*********** begin of library source file sht11.c ***************/
#include "sht11.h"
void shtxx_init( void )
{
shtxx_set_db();
shtxx_set_cb();
}
void shtxx_wait( void ) //SHT_WAIT should be tuned acording to MCU clock
{
volatile int wait_cnt;
for ( wait_cnt = 0; wait_cnt < SHT_WAIT;wait_cnt )
{
wait_cnt++;
}
}
void shtxx_reset_condition( void )
{
uint8_t i;
shtxx_set_db();
shtxx_set_out_data_dir();
for ( i = 0;i < 12;i++ )
{
if ( i % 2 == 0 )
shtxx_set_cb();
else
shtxx_clr_cb();
shtxx_wait();
}
}
void shtxx_start_condition( void )
{
shtxx_set_db();
shtxx_set_out_data_dir();
shtxx_wait();
shtxx_set_cb();
shtxx_wait();
shtxx_clr_db();
shtxx_wait();
shtxx_clr_cb();
shtxx_wait();
shtxx_wait();
shtxx_set_cb();
shtxx_wait();
shtxx_set_db();
shtxx_wait();
shtxx_clr_cb();
shtxx_wait();
}
int shtxx_send_byte( uint8_t sht_data2send )
{
uint8_t i = 0;
while ( i <= 7 )
{
if ( ( ( sht_data2send << i++ ) & 0x80 ) == 0x80 )
shtxx_set_db();
else
shtxx_clr_db();
shtxx_set_out_data_dir();
shtxx_wait();
shtxx_set_cb();
shtxx_wait();
shtxx_clr_cb();
}
shtxx_set_in_data_dir();
shtxx_wait();
shtxx_set_cb();
shtxx_wait();
if ( shtxx_get_db() == 0 )
return 1;
else
return -1;
}
int shtxx_data_wait( sht_ticks_t sht_timeout )
{
static uint8_t sht_wait_state;
static sht_ticks_t sht_previous_ticks;
switch ( sht_wait_state )
{
case SHT_DATA_WAIT_INITIAL_STATE:
sht_previous_ticks = sht_msec_ticks;
sht_wait_state = SHT_DATA_WAIT_TIMEOUT_STATE;
shtxx_set_in_data_dir();
shtxx_clr_cb();
case SHT_DATA_WAIT_TIMEOUT_STATE:
if ( shtxx_get_db() == 0 )
{
sht_wait_state = SHT_DATA_WAIT_INITIAL_STATE;
return 1;
}
else
{
if ( ( sht_msec_ticks - sht_previous_ticks ) > sht_timeout )
{
sht_wait_state = SHT_DATA_WAIT_INITIAL_STATE;
return -1;
}
else
return 0;
}
}
}
uint8_t sht_read_byte( uint8_t sht_ack )
{
shtxx_set_in_data_dir();
uint8_t temp_rx_buff = 0;
int8_t i = 7;
while ( i >= 0 )
{
shtxx_wait();
shtxx_set_cb();
temp_rx_buff |= ( ( shtxx_get_db() & 0x01 ) << i );
i--;
shtxx_wait();
shtxx_clr_cb();
}
if ( sht_ack == 1 )
{
shtxx_clr_db();
shtxx_set_out_data_dir();
shtxx_wait();
shtxx_set_cb();
shtxx_wait();
shtxx_clr_cb();
shtxx_set_in_data_dir();
}
return temp_rx_buff;
}
int shtxx_proc( uint8_t sht_param, uint16_t *ret_value )
{
static uint8_t sht_proc_state = 0;
int8_t wait_status;
switch ( sht_proc_state )
{
case SHT_PROC_RESET_COND_STATE:
shtxx_reset_condition();
case SHT_PROC_START_COND_STATE:
shtxx_start_condition();
case SHT_PROC_SEND_STATE:
shtxx_send_byte( sht_param );
case SHT_PROC_WAIT_STATE:
wait_status = shtxx_data_wait( 300 );
if ( wait_status == -1 )
{
sht_proc_state = SHT_PROC_RESET_COND_STATE;
return -1;
}
if ( wait_status == 0 )
{
sht_proc_state = SHT_PROC_WAIT_STATE;
return 0;
}
else
sht_proc_state = SHT_PROC_RETURN_STATE;
case SHT_PROC_RETURN_STATE:
*ret_value = ( ( uint16_t ) sht_read_byte( 1 ) << 8 );
shtxx_wait();
*ret_value += sht_read_byte( 0 );
sht_proc_state = SHT_PROC_START_COND_STATE;
return 1;
}
}
int shtxx_get_temp( uint16_t *ret_temperature )
{
static uint16_t tmp_temp;
if ( shtxx_proc( TEMPERATURE_BYTE, &tmp_temp ) == 1 )
{
*ret_temperature = tmp_temp - 3965;
return 1;
}
else
return 0;
}
int shtxx_get_temp_RH( int16_t *ret_temperature, int16_t *ret_humidity )
{
static uint8_t sht_humidity_state;
static uint16_t sht_humidity_raw;
static uint16_t sht_temp_C;
static float RH_linear;
static float RH_compensated;
switch ( sht_humidity_state )
{
case SHT_RH_READ_TEMPERATURE_STATE:
if ( shtxx_get_temp( &sht_temp_C ) )
sht_humidity_state = SHT_RH_READ_HUMIDITY_STATE;
break;
case SHT_RH_READ_HUMIDITY_STATE:
if ( shtxx_proc( HUMIDITY_BYTE, &sht_humidity_raw ) )
sht_humidity_state = SHT_RH_CONVERT_RH_STATE;
break;
case SHT_RH_CONVERT_RH_STATE:
RH_linear = ( float ) ( ( 0.0405 * ( float ) sht_humidity_raw ) - ( 0.0000028 * ( float ) sht_humidity_raw * ( float ) sht_humidity_raw ) - 4 );
RH_compensated = ( float ) ( ( ( ( ( ( float ) sht_temp_C ) / 100 ) - 25 ) * ( 0.01 + ( 0.00008 * ( float ) sht_humidity_raw ) ) ) + RH_linear );
sht_humidity_state = SHT_RH_READ_TEMPERATURE_STATE;
*ret_temperature = sht_temp_C;
*ret_humidity = ( ( int16_t ) ( RH_compensated * 100 ) );
return 1;
default:
sht_humidity_state = SHT_RH_READ_TEMPERATURE_STATE;
}
return 0;
}
/*** sample low-level functions (platform dependent) sht_low_level_drv.h ***/
#ifndef _SHT_LOW_LEVEL_DRV_H
#define _SHT_LOW_LEVEL_DRV_H
#include <types.h>
#include <system_def.h> /* for concrete HW, SHT_PORT, SHT_DATA_BIT must be defined*/
#define SHT_MAX_CLK 100000
#define SHT_WAIT (CCLK/SHT_MAX_CLK) /* CCLK is MCU clock */
#define sht_ticks_t uint32_t
#define sht_msec_ticks sys_timer_ticks /* this variable should be defined in BSP and incremented each ms (usually in some timer interrupt routine) */
static inline void shtxx_set_db(void)
{
SET_OUT_PIN(SHT_PORT,SHT_DATA_BIT);
}
static inline void shtxx_clr_db(void)
{
CLR_OUT_PIN(SHT_PORT,SHT_DATA_BIT);
}
static inline void shtxx_set_cb(void)
{
SET_OUT_PIN(SHT_PORT,SHT_CLK_BIT);
}
static inline void shtxx_clr_cb(void)
{
CLR_OUT_PIN(SHT_PORT,SHT_CLK_BIT);
}
static inline uint8_t shtxx_get_db(void)
{
return( GET_IN_PIN(SHT_PORT,SHT_DATA_BIT) );
}
static inline void shtxx_set_in_data_dir(void)
{
IO0DIR &=~(SHT_DATA_BIT);
}
static inline void shtxx_set_out_data_dir(void)
{
IO0DIR |= SHT_DATA_BIT ;
}
#endif /* _SHT_LOW_LEVEL_DRV_H */
/********************* sample usage in main program ************************/
//..............
int16_t temperature, humidity;
while(1) //main loop of the user program
{
if (shtxx_get_temp_RH( &temperature, &humidity )
{
//do something
}
//do other operations
//.....................
}
Very simple software timer framework
/*********************************************************************************/
/* sample usage */
/*********************************************************************************/
#include <lt_timer.h>
LT_TIMER_DEC(slow_timer) /* declaration */
LT_TIMER_IMP(slow_timer) /* implementation */
LT_TIMER_DEC(fast_timer) /* declaration */
LT_TIMER_IMP(fast_timer) /* implementation */
int main(void)
{
fast_timer_init();
slow_timer_init();
while(1)
{
if (slow_timer_expired(1000))
{
//do something each 1000ms
}
if (fast_timer_expired(10))
{
//do something each 10ms
}
//...............
//main program functionality
//...............
}
}
/*********************************************************************************/
/* lt_timer definition */
/*********************************************************************************/
#ifndef _LT_TIMER_H
#define _LT_TIMER_H
#include <stdint.h>
/* these definitions can vary on different platforms */
typedef unsigned int lt_ticks_t;
typedef int lt_tidiff_t;
typedef unsigned long lt_mstime_t;
typedef signed long lt_msdiff_t;
static lt_ticks_t last_ticks;
static lt_mstime_t actual_msec;
/* it is expected increment "sys_timer_ticks" variable in some timer interrupt */
/* alternatively some function which return ticks can be provided */
#define lt_get_ticks() (sys_timer_ticks)
/* in ms (SYS_TIMER_HZ must be provided by user)*/
#define lt_get_msbase() (1000/SYS_TIMER_HZ)
static inline void
lt_mstime_update()
{
lt_ticks_t act_ticks;
lt_mstime_t msec_diff;
act_ticks=lt_get_ticks();
msec_diff=((lt_tidiff_t)(act_ticks-last_ticks))*lt_get_msbase();
last_ticks=act_ticks;
actual_msec+=msec_diff;
}
#define LT_TIMER_DEC(cust_prefix) \
\
extern lt_mstime_t cust_prefix##_last_expired; \
static inline void \
cust_prefix##_init() \
{\
lt_mstime_update();\
cust_prefix##_last_expired=actual_msec;\
}\
static inline int \
cust_prefix##_expired(lt_mstime_t expiration) \
{\
lt_mstime_update();\
\
if ((lt_msdiff_t)(actual_msec-cust_prefix##_last_expired)>=expiration) {\
cust_prefix##_last_expired=actual_msec;\
return 1;\
}\
\
return 0;\
}
#define LT_TIMER_IMP(cust_prefix) \
\
lt_mstime_t cust_prefix##_last_expired; \
#endif /* _LT_TIMER_H */
General library for debouncing (filtering) of digital inputs
/**************************************************************************************/
/* sample usage of the library */
/**************************************************************************************/
//Remark: sys_timer_ticks should be provided for timing by the user.
/* Simplest example with undefined CONFIG_DEBOUNCE_WITH_HANDLE and CONFIG_DEBOUNCE_SEPARATE_TIMES */
#include <debounce.h>
#define INPUTS_NUM 12
nl_debouce_time_t inp_times[ INPUTS_NUM ];
nl_debouce_time_t filt_time = 10; //same value will be used for t_on and t_off
int main(void)
{
nl_inp_t inp_state, filtered_inp_state;
debounce_init( inp_times, INPUTS_NUM, &filt_time, &filt_time,
(nl_ticks_t*)&sys_timer_ticks );
while(1)
{
//user defined function, which return actual state of all inputs as bit array
inp_state = get_input_state();
debounce_proc(&inp_state, &filtered_inp_state);
//do something with filtered_inp_state
//...............
//main program functionality
//...............
}
}
/* More complex example with defined CONFIG_DEBOUNCE_WITH_HANDLE and CONFIG_DEBOUNCE_SEPARATE_TIMES */
#include <debounce.h>
#define INPUTS_NUM 5
struct debounce_state_s inp_dbnc_s;
nl_debouce_time_t inp_times[ INPUTS_NUM ];
nl_debouce_time_t t_on[ INPUTS_NUM ] = {10,10,20,20,50};
nl_debouce_time_t t_off[ INPUTS_NUM ] = {5,5,10,10,50};
int main(void)
{
nl_inp_t inp_state, filtered_inp_state;
debounce_init( &inp_dbnc_s, inp_times, INPUTS_NUM,
t_on, t_off, (nl_ticks_t*)&sys_timer_ticks );
while(1)
{
//user defined function, which return actual state of all inputs as bit array
inp_state = get_input_state();
debounce_proc(&inp_dbnc_s, &inp_state, &filtered_inp_state);
//do something with filtered_inp_state
//...............
//main program functionality
//...............
}
}
/**************************************************************************************/
/* debounce library header file "debounce.h" */
/**************************************************************************************/
#ifndef _DEBOUNCE_H_
#define _DEBOUNCE_H_
#include <stdint.h>
/* because library is multiplatform, following types are defined in separate file */
#include "nlib_types.h"
/* examaple of types definition in "nlib_types.h" */
//typedef uint32_t nl_ticks_t;
//typedef int16_t nl_debouce_time_t; //so maximum filter time is 32767ms (considering period of ticks 1ms)
//typedef uint32_t nl_inp_t; //up to 32 inputs can be handled
/* in general case following macros should be provided in this header file, or can be defined directly */
#include <debounce_config.h>
//#define CONFIG_DEBOUNCE_WITH_HANDLE
//#define CONFIG_DEBOUNCE_SEPARATE_TIMES
#ifdef CONFIG_DEBOUNCE_WITH_HANDLE
#define DEBOUNCE_STRUCT_PAR struct debounce_state_s * debounce_state,
#else
#define DEBOUNCE_STRUCT_PAR
#endif
typedef struct debounce_state_s
{
const nl_ticks_t* ticks; //pointer to timing variable (is incremented e.g. each 1ms)
nl_ticks_t old_ticks;
uint_fast8_t inp_num; //number of inputs
const nl_debouce_time_t *debounce_on_time,*debounce_off_time; //tables with desired filter times
nl_debouce_time_t* inp_times; //actual time ON/OFF - non-negative values = ON, negative = OFF
}
debounce_state_t;
void debounce_init(DEBOUNCE_STRUCT_PAR nl_debouce_time_t* inp_tim, uint_fast8_t num, const nl_debouce_time_t *dton,const nl_debouce_time_t *dtoff, const nl_ticks_t* ticks);
uint_fast8_t debounce_proc(DEBOUNCE_STRUCT_PAR const nl_inp_t* act_inp_state, nl_inp_t* debounced_inp_state);
#endif /*_DEBOUNCE_H_*/
/**************************************************************************************/
/* debounce library source file "debounce.c" */
/**************************************************************************************/
#include "debounce.h"
#include <string.h>
//allow using multiple instances
#ifndef CONFIG_DEBOUNCE_WITH_HANDLE
struct debounce_state_s _debounce_state_;
struct debounce_state_s * debounce_state = &_debounce_state_;
#endif
/* allow different times for each input */
#ifndef CONFIG_DEBOUNCE_SEPARATE_TIMES
#define _debounce_times_idx_ 0
#else
#define _debounce_times_idx_ i
#endif
//maco trick to find maximum value of given signed integer type "http://www.fefe.de/intof.html"
#define __HALF_MAX_SIGNED(type) ((type)1 << (sizeof(type)*8-2))
#define __MAX_SIGNED(type) (__HALF_MAX_SIGNED(type) - 1 + __HALF_MAX_SIGNED(type))
/*
Init function of the library
DEBOUNCE_STRUCT_PAR - depending on "CONFIG_DEBOUNCE_WITH_HANDLE": nothing, or pointer to handle
inp_tim - array of variables for storing of state for each input (number of elements must be the same as number of inputs!)
num - number of inputs
dton - depending on "CONFIG_DEBOUNCE_SEPARATE_TIMES": pointer to sigle value (minimal ON time), or array of times
dtoff - depending on "CONFIG_DEBOUNCE_SEPARATE_TIMES": pointer to sigle value (minimal OFF time), or array of times
ticks - pointer to variable, which is periodicaly incremented
*/
void debounce_init(DEBOUNCE_STRUCT_PAR nl_debouce_time_t* inp_tim, uint_fast8_t num, const nl_debouce_time_t *dton, const nl_debouce_time_t *dtoff ,const nl_ticks_t* ticks)
{
debounce_state-> inp_times=inp_tim;
debounce_state-> inp_num=num;
debounce_state-> debounce_on_time=dton;
debounce_state-> debounce_off_time=dtoff;
debounce_state-> ticks=ticks;
debounce_state-> old_ticks=*ticks;
memset(inp_tim,0,sizeof(*inp_tim)*num);
inp_tim[0]=__MAX_SIGNED(nl_debouce_time_t); //this is used later to evaluate first iteration after start
}
/*
This is core function of the library
DEBOUNCE_STRUCT_PAR - depending on "CONFIG_DEBOUNCE_WITH_HANDLE": nothing, or pointer to handle
act_inp_state - pointer to variable with actual state of all inputs (1 bit for each input)
debounced_inp_state - resulting state after filtering
return - 0=no change, 1=some input(s) are changed
*/
uint_fast8_t debounce_proc(DEBOUNCE_STRUCT_PAR const nl_inp_t* act_inp_state, nl_inp_t* debounced_inp_state)
{
uint_fast8_t i,change=0;
nl_inp_t mask=1;
nl_ticks_t tic_diff;
tic_diff=(nl_ticks_t) (*(debounce_state-> ticks) - debounce_state-> old_ticks);
debounce_state-> old_ticks = *(debounce_state-> ticks);
if ((debounce_state-> inp_times)[0] == __MAX_SIGNED(nl_debouce_time_t)) //evaluate, if it is a first iteration
{
*debounced_inp_state=*act_inp_state;
for(i=0; i<debounce_state-> inp_num ;i++)
(debounce_state-> inp_times)[i]=0;
return 0;
}
for(i=0; i<debounce_state-> inp_num ;i++)
{
if ( *act_inp_state & mask) //actual state is ON
{
if ((debounce_state-> inp_times)[i] >= 0) //and last state was ON
{
if (((debounce_state-> inp_times)[i] + (nl_debouce_time_t) tic_diff) < debounce_state-> debounce_on_time[_debounce_times_idx_])
{
(debounce_state-> inp_times)[i] += (nl_debouce_time_t) tic_diff; //filter time not elapsed
}
else
{ //filter time elapsed
if (!( *debounced_inp_state & mask))
{
*debounced_inp_state |= mask;
change=1;
}
}
}
else (debounce_state-> inp_times)[i] = 0;
}
else //actual state is OFF
{
if (debounce_state-> inp_times[i] < 0) //and last state was OFF
{
if ( (nl_debouce_time_t)(((debounce_state-> inp_times)[i] - (nl_debouce_time_t) tic_diff)) >= (-1*debounce_state-> debounce_off_time[_debounce_times_idx_]))
{
(debounce_state-> inp_times)[i] -= (nl_debouce_time_t) tic_diff; //filter time not elapsed
}
else
{ //filter time elapsed
if ( *debounced_inp_state & mask)
{
*debounced_inp_state &= ~mask;
change=1;
}
}
}
else (debounce_state-> inp_times)[i] = -1;
}
mask=(nl_inp_t) mask<<1;
}
return change;
}
SHT11 humidity sensor library (sensirion manufacture)
/*********** begin of library header file sht11.h ***************/
#ifndef _SHTXX_H
#define _SHTXX_H
#include <inttypes.h>
#define HUMIDITY_BYTE 0x05
#define TEMPERATURE_BYTE 0x03
//State machine states
#define SHT_DATA_WAIT_INITIAL_STATE 0
#define SHT_DATA_WAIT_TIMEOUT_STATE 1
#define SHT_PROC_RESET_COND_STATE 0
#define SHT_PROC_START_COND_STATE 1
#define SHT_PROC_SEND_STATE 2
#define SHT_PROC_WAIT_STATE 3
#define SHT_PROC_RETURN_STATE 4
#define SHT_RH_READ_TEMPERATURE_STATE 0
#define SHT_RH_READ_HUMIDITY_STATE 1
#define SHT_RH_CONVERT_RH_STATE 2
#include <sht_low_level_drv.h>
void shtxx_init(void);
int shtxx_proc(uint8_t sht_param,uint16_t *ret_value);
int shtxx_get_temp(uint16_t *ret_temperature);
int shtxx_get_temp_RH( int16_t *ret_temperature, int16_t *ret_humidity );
#endif /* _SHTXX_H */
/*********** begin of library source file sht11.c ***************/
#include "sht11.h"
void shtxx_init( void )
{
shtxx_set_db();
shtxx_set_cb();
}
void shtxx_wait( void ) //SHT_WAIT should be tuned acording to MCU clock
{
volatile int wait_cnt;
for ( wait_cnt = 0; wait_cnt < SHT_WAIT;wait_cnt )
{
wait_cnt++;
}
}
void shtxx_reset_condition( void )
{
uint8_t i;
shtxx_set_db();
shtxx_set_out_data_dir();
for ( i = 0;i < 12;i++ )
{
if ( i % 2 == 0 )
shtxx_set_cb();
else
shtxx_clr_cb();
shtxx_wait();
}
}
void shtxx_start_condition( void )
{
shtxx_set_db();
shtxx_set_out_data_dir();
shtxx_wait();
shtxx_set_cb();
shtxx_wait();
shtxx_clr_db();
shtxx_wait();
shtxx_clr_cb();
shtxx_wait();
shtxx_wait();
shtxx_set_cb();
shtxx_wait();
shtxx_set_db();
shtxx_wait();
shtxx_clr_cb();
shtxx_wait();
}
int shtxx_send_byte( uint8_t sht_data2send )
{
uint8_t i = 0;
while ( i <= 7 )
{
if ( ( ( sht_data2send << i++ ) & 0x80 ) == 0x80 )
shtxx_set_db();
else
shtxx_clr_db();
shtxx_set_out_data_dir();
shtxx_wait();
shtxx_set_cb();
shtxx_wait();
shtxx_clr_cb();
}
shtxx_set_in_data_dir();
shtxx_wait();
shtxx_set_cb();
shtxx_wait();
if ( shtxx_get_db() == 0 )
return 1;
else
return -1;
}
int shtxx_data_wait( sht_ticks_t sht_timeout )
{
static uint8_t sht_wait_state;
static sht_ticks_t sht_previous_ticks;
switch ( sht_wait_state )
{
case SHT_DATA_WAIT_INITIAL_STATE:
sht_previous_ticks = sht_msec_ticks;
sht_wait_state = SHT_DATA_WAIT_TIMEOUT_STATE;
shtxx_set_in_data_dir();
shtxx_clr_cb();
case SHT_DATA_WAIT_TIMEOUT_STATE:
if ( shtxx_get_db() == 0 )
{
sht_wait_state = SHT_DATA_WAIT_INITIAL_STATE;
return 1;
}
else
{
if ( ( sht_msec_ticks - sht_previous_ticks ) > sht_timeout )
{
sht_wait_state = SHT_DATA_WAIT_INITIAL_STATE;
return -1;
}
else
return 0;
}
}
}
uint8_t sht_read_byte( uint8_t sht_ack )
{
shtxx_set_in_data_dir();
uint8_t temp_rx_buff = 0;
int8_t i = 7;
while ( i >= 0 )
{
shtxx_wait();
shtxx_set_cb();
temp_rx_buff |= ( ( shtxx_get_db() & 0x01 ) << i );
i--;
shtxx_wait();
shtxx_clr_cb();
}
if ( sht_ack == 1 )
{
shtxx_clr_db();
shtxx_set_out_data_dir();
shtxx_wait();
shtxx_set_cb();
shtxx_wait();
shtxx_clr_cb();
shtxx_set_in_data_dir();
}
return temp_rx_buff;
}
int shtxx_proc( uint8_t sht_param, uint16_t *ret_value )
{
static uint8_t sht_proc_state = 0;
int8_t wait_status;
switch ( sht_proc_state )
{
case SHT_PROC_RESET_COND_STATE:
shtxx_reset_condition();
case SHT_PROC_START_COND_STATE:
shtxx_start_condition();
case SHT_PROC_SEND_STATE:
shtxx_send_byte( sht_param );
case SHT_PROC_WAIT_STATE:
wait_status = shtxx_data_wait( 300 );
if ( wait_status == -1 )
{
sht_proc_state = SHT_PROC_RESET_COND_STATE;
return -1;
}
if ( wait_status == 0 )
{
sht_proc_state = SHT_PROC_WAIT_STATE;
return 0;
}
else
sht_proc_state = SHT_PROC_RETURN_STATE;
case SHT_PROC_RETURN_STATE:
*ret_value = ( ( uint16_t ) sht_read_byte( 1 ) << 8 );
shtxx_wait();
*ret_value += sht_read_byte( 0 );
sht_proc_state = SHT_PROC_START_COND_STATE;
return 1;
}
}
int shtxx_get_temp( uint16_t *ret_temperature )
{
static uint16_t tmp_temp;
if ( shtxx_proc( TEMPERATURE_BYTE, &tmp_temp ) == 1 )
{
*ret_temperature = tmp_temp - 3965;
return 1;
}
else
return 0;
}
int shtxx_get_temp_RH( int16_t *ret_temperature, int16_t *ret_humidity )
{
static uint8_t sht_humidity_state;
static uint16_t sht_humidity_raw;
static uint16_t sht_temp_C;
static float RH_linear;
static float RH_compensated;
switch ( sht_humidity_state )
{
case SHT_RH_READ_TEMPERATURE_STATE:
if ( shtxx_get_temp( &sht_temp_C ) )
sht_humidity_state = SHT_RH_READ_HUMIDITY_STATE;
break;
case SHT_RH_READ_HUMIDITY_STATE:
if ( shtxx_proc( HUMIDITY_BYTE, &sht_humidity_raw ) )
sht_humidity_state = SHT_RH_CONVERT_RH_STATE;
break;
case SHT_RH_CONVERT_RH_STATE:
RH_linear = ( float ) ( ( 0.0405 * ( float ) sht_humidity_raw ) - ( 0.0000028 * ( float ) sht_humidity_raw * ( float ) sht_humidity_raw ) - 4 );
RH_compensated = ( float ) ( ( ( ( ( ( float ) sht_temp_C ) / 100 ) - 25 ) * ( 0.01 + ( 0.00008 * ( float ) sht_humidity_raw ) ) ) + RH_linear );
sht_humidity_state = SHT_RH_READ_TEMPERATURE_STATE;
*ret_temperature = sht_temp_C;
*ret_humidity = ( ( int16_t ) ( RH_compensated * 100 ) );
return 1;
default:
sht_humidity_state = SHT_RH_READ_TEMPERATURE_STATE;
}
return 0;
}
/*** sample low-level functions (platform dependent) sht_low_level_drv.h ***/
#ifndef _SHT_LOW_LEVEL_DRV_H
#define _SHT_LOW_LEVEL_DRV_H
#include <types.h>
#include <system_def.h> /* for concrete HW, SHT_PORT, SHT_DATA_BIT must be defined*/
#define SHT_MAX_CLK 100000
#define SHT_WAIT (CCLK/SHT_MAX_CLK) /* CCLK is MCU clock */
#define sht_ticks_t uint32_t
#define sht_msec_ticks sys_timer_ticks /* this variable should be defined in BSP and incremented each ms (usually in some timer interrupt routine) */
static inline void shtxx_set_db(void)
{
SET_OUT_PIN(SHT_PORT,SHT_DATA_BIT);
}
static inline void shtxx_clr_db(void)
{
CLR_OUT_PIN(SHT_PORT,SHT_DATA_BIT);
}
static inline void shtxx_set_cb(void)
{
SET_OUT_PIN(SHT_PORT,SHT_CLK_BIT);
}
static inline void shtxx_clr_cb(void)
{
CLR_OUT_PIN(SHT_PORT,SHT_CLK_BIT);
}
static inline uint8_t shtxx_get_db(void)
{
return( GET_IN_PIN(SHT_PORT,SHT_DATA_BIT) );
}
static inline void shtxx_set_in_data_dir(void)
{
IO0DIR &=~(SHT_DATA_BIT);
}
static inline void shtxx_set_out_data_dir(void)
{
IO0DIR |= SHT_DATA_BIT ;
}
#endif /* _SHT_LOW_LEVEL_DRV_H */
/********************* sample usage in main program ************************/
//..............
int16_t temperature, humidity;
while(1) //main loop of the user program
{
if (shtxx_get_temp_RH( &temperature, &humidity )
{
//do something
}
//do other operations
//.....................
}