/*---------------------------------------------------------------------------*/
static void
handle_dao_timer(void *ptr)
{
  rpl_instance_t *instance;
#if RPL_CONF_MULTICAST
  uip_mcast6_route_t *mcast_route;
  uint8_t i;
#endif

  instance = (rpl_instance_t *)ptr;

  if(!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) {
    PRINTF("RPL: Postpone DAO transmission\n");
    ctimer_set(&instance->dao_timer, CLOCK_SECOND, handle_dao_timer, instance);
    return;
  }

  /* Send the DAO to the DAO parent set -- the preferred parent in our case. */
  if(instance->current_dag->preferred_parent != NULL) {
    PRINTF("RPL: handle_dao_timer - sending DAO\n");
    /* Set the route lifetime to the default value. */
    dao_output(instance->current_dag->preferred_parent, instance->default_lifetime);

#if RPL_CONF_MULTICAST
    /* Send DAOs for multicast prefixes only if the instance is in MOP 3 */
    if(instance->mop == RPL_MOP_STORING_MULTICAST) {
      /* Send a DAO for own multicast addresses */
      for(i = 0; i < UIP_DS6_MADDR_NB; i++) {
        if(uip_ds6_if.maddr_list[i].isused
            && uip_is_addr_mcast_global(&uip_ds6_if.maddr_list[i].ipaddr)) {
          dao_output_target(instance->current_dag->preferred_parent,
              &uip_ds6_if.maddr_list[i].ipaddr, RPL_MCAST_LIFETIME);
        }
      }

      /* Iterate over multicast routes and send DAOs */
      mcast_route = uip_mcast6_route_list_head();
      while(mcast_route != NULL) {
        /* Don't send if it's also our own address, done that already */
        if(uip_ds6_maddr_lookup(&mcast_route->group) == NULL) {
          dao_output_target(instance->current_dag->preferred_parent,
                     &mcast_route->group, RPL_MCAST_LIFETIME);
        }
        mcast_route = list_item_next(mcast_route);
      }
    }
#endif
  } else {
    PRINTF("RPL: No suitable DAO parent\n");
  }

  ctimer_stop(&instance->dao_timer);

  if(etimer_expired(&instance->dao_lifetime_timer.etimer)) {
    set_dao_lifetime_timer(instance);
  }
}
Exemple #2
0
void
subscription_clean(void) {
	struct subscription_item *si;
	for (si = list_head(subscription_list);
			si != NULL; si = list_item_next(si)) {
		ctimer_stop(&si->t);
		subscription_init();
	}
}
/*---------------------------------------------------------------------------*/
void
stunicast_cancel(struct stunicast_conn *c)
{
  ctimer_stop(&c->t);
  if(c->buf != NULL) {
    queuebuf_free(c->buf);
    c->buf = NULL;
  }
}
Exemple #4
0
/*---------------------------------------------------------------------------*/
static void
rrep_packet_received(struct unicast_conn *uc, const rimeaddr_t *from)
{
    struct rrep_hdr *msg = packetbuf_dataptr();
    struct route_entry *rt;
    rimeaddr_t dest;
    struct route_discovery_conn *c = (struct route_discovery_conn *)
                                     ((char *)uc - offsetof(struct route_discovery_conn, rrepconn));

    PRINTF("%d.%d: rrep_packet_received from %d.%d towards %d.%d len %d\n",
           rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
           from->u8[0],from->u8[1],
           msg->dest.u8[0],msg->dest.u8[1],
           packetbuf_datalen());

    PRINTF("from %d.%d hops %d rssi %d lqi %d\n",
           from->u8[0], from->u8[1],
           msg->hops,
           packetbuf_attr(PACKETBUF_ATTR_RSSI),
           packetbuf_attr(PACKETBUF_ATTR_LINK_QUALITY));

    insert_route(&msg->originator, from, msg->hops);

    if(rimeaddr_cmp(&msg->dest, &rimeaddr_node_addr))
    {
        PRINTF("rrep for us!\n");
        rrep_pending = 0;
        ctimer_stop(&c->t);
        if(c->cb->new_route)
        {
            rimeaddr_t originator;

            /* If the callback modifies the packet, the originator address
               will be lost. Therefore, we need to copy it into a local
               variable before calling the callback. */
            rimeaddr_copy(&originator, &msg->originator);
            c->cb->new_route(c, &originator);
        }

    }
    else
    {
        rimeaddr_copy(&dest, &msg->dest);

        rt = route_lookup(&msg->dest);
        if(rt != NULL)
        {
            PRINTF("forwarding to %d.%d\n", rt->nexthop.u8[0], rt->nexthop.u8[1]);
            msg->hops++;
            unicast_send(&c->rrepconn, &rt->nexthop);
        }
        else
        {
            PRINTF("%d.%d: no route to %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], msg->dest.u8[0], msg->dest.u8[1]);
        }
    }
}
/*---------------------------------------------------------------------------*/
error_t bcpForwardingEngine_stdControlStop() {
	pmesg(200, "%s :: %s :: Line #%d\n", __FILE__, __func__, __LINE__);
	isRunningForwardingEngine = false;

	//Stop Beacons
	ctimer_stop(&beacon_timer);

	return SUCCESS;
}
Exemple #6
0
/*---------------------------------------------------------------------------*/
void
polite_cancel(struct polite_conn *c)
{
  ctimer_stop(&c->t);
  if(c->q != NULL) {
    queuebuf_free(c->q);
    c->q = NULL;
  }
}
void ota_mgr_timer_start(module_code_t msg_code, uint32_t interval, ota_timer_mode_t mode, void *handler)
{
	switch (msg_code)
	{
#if (OTA_COMMON_SUPPORT == 1)	
	case COMMON:
	{	
		if(ota_common_tmr_mode != TIMER_NONE)
		{
			ctimer_stop(&ota_common_tmr);
		}
	    ctimer_set(&ota_common_tmr,(interval*CLOCK_SECOND)/1000,handler,NULL);
		ota_common_tmr_hdlr = handler;
		if(TIMER_MODE_SINGLE == mode)
			ota_common_tmr_mode = TIMER_INTERVAL;
		else
		{
			ota_common_tmr_mode = TIMER_PERIODIC;
		}
	}
	break;
#endif		
#if (OTA_UPGRADE_SUPPORT == 1)		
	case UPGRADE:
	{
		if(ota_upgrade_tmr_mode != TIMER_NONE)
		{
			ctimer_stop(&ota_upgrade_tmr);
		}	
		ctimer_set(&ota_upgrade_tmr,(interval*CLOCK_SECOND)/1000,handler,NULL);
		ota_upgrade_tmr_hdlr = handler;
		if(TIMER_MODE_SINGLE == mode)
			ota_upgrade_tmr_mode = TIMER_INTERVAL;
		else
		{
			ota_upgrade_tmr_mode = TIMER_PERIODIC;		
		}
	}
	break;
#endif
	default:
		break;
	}
}
Exemple #8
0
/*---------------------------------------------------------------------------*/
void
polite_close(struct polite_conn *c)
{
  abc_close(&c->c);
  ctimer_stop(&c->t);
  if(c->q != NULL) {
    queuebuf_free(c->q);
    c->q = NULL;
  }
}
static void
transition(int state)
{
  if(state != deluge_state) {
    switch(deluge_state) {
    case DELUGE_STATE_MAINTAIN:
      ctimer_stop(&summary_timer);
      ctimer_stop(&profile_timer);
      break;
    case DELUGE_STATE_RX:
      ctimer_stop(&rx_timer);
      break;
    case DELUGE_STATE_TX:
      ctimer_stop(&tx_timer);
      break;
    }
    deluge_state = state;
  }
}
Exemple #10
0
/*---------------------------------------------------------------------------*/
void
neighbor_attr_set_timeout(uint16_t time)
{
  if(timeout == 0 && time > 0) {
    ctimer_set(&ct, TIMEOUT_SECONDS * CLOCK_SECOND, timeout_check, NULL);
  } else if(timeout > 0 && time == 0) {
    ctimer_stop(&ct);
  }
  timeout = time;
}
Exemple #11
0
/*---------------------------------------------------------------------------*/
void
uip_packetqueue_free(struct uip_packetqueue_handle *handle)
{
  PRINTF("uip_packetqueue_free %p\n", handle);
  if(handle->packet != NULL) {
    ctimer_stop(&handle->packet->lifetimer);
    memb_free(&packets_memb, handle->packet);
    handle->packet = NULL;
  }
}
/*---------------------------------------------------------------------------*/
void
ipolite_close(struct ipolite_conn *c)
{
  broadcast_close(&c->c);
  ctimer_stop(&c->t);
  if(c->q != NULL) {
    queuebuf_free(c->q);
    c->q = NULL;
  }
}
Exemple #13
0
void
rpl_free_dag(rpl_dag_t *dag)
{
  PRINTF("RPL: Leaving the DAG ");
  PRINT6ADDR(&dag->dag_id);
  PRINTF("\n");

  /* Remove routes installed by DAOs. */
  rpl_remove_routes(dag);

  /* Remove parents and the default route. */
  remove_parents(dag, 0);
  rpl_set_default_route(dag, NULL);

  ctimer_stop(&dag->dio_timer);
  ctimer_stop(&dag->dao_timer);

  dag->used = 0;
  dag->joined = 0;
}
void ota_mgr_timer_stop(module_code_t msg_code)
{
	switch (msg_code)
	{
#if (OTA_COMMON_SUPPORT == 1)	
		case COMMON:
			ctimer_stop(&ota_common_tmr);
			ota_common_tmr_mode = TIMER_NONE;
			break;
#endif		
#if (OTA_UPGRADE_SUPPORT == 1)			
		case UPGRADE:
			ctimer_stop(&ota_upgrade_tmr);
			ota_upgrade_tmr_mode = TIMER_NONE;
			break;
#endif
		default:
			break;
	}
}
Exemple #15
0
/*---------------------------------------------------------------------------*/
static void
remove_queued_packet(void *item)
{
    struct packetqueue_item *i = item;
    struct packetqueue *q = i->queue;

    list_remove(*q->list, i);
    queuebuf_free(i->buf);
    ctimer_stop(&i->lifetimer);
    memb_free(q->memb, i);
    /*  printf("removing queued packet due to timeout\n");*/
}
/*---------------------------------------------------------------------------*/
void remainingInterval() {
	pmesg(200, "%s :: %s :: Line #%d\n", __FILE__, __func__, __LINE__);
	static clock_time_t remaining = 0;
 	remaining = currentInterval;
	remaining -= t;
	tHasPassed = true;
	isBeaconTimerPeriodic = false;
	ctimer_stop(&beacon_timer);
  // Stop the tandem timer here, but can't because API doesnt provide that functionality
	ctimer_set(&beacon_timer, remaining, beacon_timer_fired, 0);
  	timer_reset(&beacon_timerTime);  // Reset the tandem timer
}
Exemple #17
0
/*---------------------------------------------------------------------------*/
static void
abort()
{
  PRINTF("Disco: Abort @ %lu\n", clock_seconds());
  n740_analog_deactivate();
  m25p16_dp();
  n740_analog_activate();
  state = DISCO_STATE_LISTENING;
  memset(&seed, 0, sizeof(seed));
  ctimer_stop(&disco_timer);
  batmon_log(LOG_TRIGGER_OAP_DISCO_ABORT);
}
Exemple #18
0
/**
 * Handles TCP events from Simple TCP
 */
static void
tcp_event(struct tcp_socket *s, void *ptr, tcp_socket_event_t event)
{
  struct mqtt_connection* conn = ptr;

  /* Take care of event */
  switch(event) {

    /* Fall through to manage different disconnect event the same way. */
    case TCP_SOCKET_CLOSED:
    case TCP_SOCKET_TIMEDOUT:
    case TCP_SOCKET_ABORTED: {

      ctimer_stop(&conn->keep_alive_timer);
      call_event(conn, MQTT_EVENT_DISCONNECTED, &event);

      /* If connecting retry */
      if(conn->state == MQTT_CONN_STATE_TCP_CONNECTING ||
         conn->auto_reconnect == 1) {
        DBG("MQTT - Disconnected by tcp event %d, reconnecting...",
            event);
        connect_tcp(conn);
      }
      else {
        conn->state = MQTT_CONN_STATE_NOT_CONNECTED;
      }
      break;
    }
    case TCP_SOCKET_CONNECTED: {
      DBG("MQTT - Got TCP_SOCKET_CONNECTED\r\n");
      conn->state = MQTT_CONN_STATE_TCP_CONNECTED;

      process_post(&mqtt_process, mqtt_do_connect_mqtt_event, conn);
      break;
    }
    case TCP_SOCKET_DATA_SENT: {
      DBG("MQTT - Got TCP_DATA_SENT\r\n");
      conn->out_buffer_sent = 1;
      conn->out_buffer_ptr = conn->out_buffer;

      ctimer_restart(&conn->keep_alive_timer);
      break;
    }

    default: {
      DBG("MQTT - TCP Event %d is currently not manged by the tcp event callback\r\n",
          event);
    }

  }

}
Exemple #19
0
/*---------------------------------------------------------------------------*/
void
packetqueue_dequeue(struct packetqueue *q)
{
	struct packetqueue_item *i;

	i = list_head(*q->list);
	if(i != NULL) {
		list_remove(*q->list, i);
		queuebuf_free(i->buf);
		ctimer_stop(&i->lifetimer);
		memb_free(q->memb, i);
	}
}
Exemple #20
0
/* if socket is not equipped with metering then calibration should stop automatically after some time */
void
metering_calibration_stop(void)
{
  //store calibration in EEPROM
  eeprom_write_word((uint16_t*) EE_METERING_REF, 0);

  //lock calibration by setting flag in eeprom
  eeprom_write_byte((uint8_t*) EE_METERING_CAL_FLAG, 0x00);

  metering_calibration_state = 0;
  metering_calibration = false;
  relay_leds();
  ctimer_stop(&metering_stop_timer);
}
Exemple #21
0
static void
handle_dao_timer(void *ptr)
{
  rpl_instance_t *instance;

  instance = (rpl_instance_t *)ptr;

  if(!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) {
    PRINTF("RPL: Postpone DAO transmission\n");
    ctimer_set(&instance->dao_timer, CLOCK_SECOND, handle_dao_timer, instance);
    return;
  }

  /* Send the DAO to the DAO parent set -- the preferred parent in our case. */
  if(instance->current_dag->preferred_parent != NULL) {
    PRINTF("RPL: handle_dao_timer - sending DAO\n");
    /* Set the route lifetime to the default value. */
    dao_output(instance->current_dag->preferred_parent, instance->default_lifetime, NULL);
#if UIP_IPV6_MULTICAST_RPL
    if(instance->mop == RPL_MOP_STORING_MULTICAST) {
      /* Send a DAO for own multicast addresses */
      for(i = 0; i < UIP_DS6_MADDR_NB; i++) {
        if(uip_ds6_if.maddr_list[i].isused
            && uip_is_addr_mcast_global(&uip_ds6_if.maddr_list[i].ipaddr)) {
          dao_output(instance->current_dag->preferred_parent, RPL_MCAST_LIFETIME,
              &uip_ds6_if.maddr_list[i].ipaddr);
        }
      }
      /* Iterate multicast routes and send DAOs */
      for(i = 0; i < UIP_DS6_MCAST_ROUTES; i++) {
        /* Don't send if it's also our own address, done that already */
        if(uip_ds6_mcast_table[i].isused) {
          if(uip_ds6_maddr_lookup(&uip_ds6_mcast_table[i].group) == NULL) {
            dao_output(instance->current_dag->preferred_parent, RPL_MCAST_LIFETIME,
                &uip_ds6_mcast_table[i].group);
          }
        }
      }
    }
#endif
  } else {
    PRINTF("RPL: No suitable DAO parent\n");
  }
  ctimer_stop(&instance->dao_timer);
}
Exemple #22
0
/*---------------------------------------------------------------------------*/
static void
free_packet(struct neighbor_queue *n, struct rdc_buf_list *p)
{
  if(p != NULL) {

//ADILA EDIT 09/02/14
//cc2420_set_channel(list_length(n->queued_packet_list) + 10);
//printf("%d BEFORE FREE Q %d\n", cc2420_get_channel(), list_length(n->queued_packet_list));
//-------------------

    /* Remove packet from list and deallocate */
    list_remove(n->queued_packet_list, p);

    queuebuf_free(p->buf);
    memb_free(&metadata_memb, p->ptr);
    memb_free(&packet_memb, p);

//ADILA EDIT 09/02/14
if((list_length(n->queued_packet_list)) == 0) {
cc2420_set_channel(26);
//printf("%d empty Q %d\n", cc2420_get_channel(), list_length(n->queued_packet_list));

}
//-------------------

    PRINTF("csma: free_queued_packet, queue length %d\n",
        list_length(n->queued_packet_list));
    if(list_head(n->queued_packet_list) != NULL) {
      /* There is a next packet. We reset current tx information */
      n->transmissions = 0;
      n->collisions = 0;
      n->deferrals = 0;
      /* Set a timer for next transmissions */
      ctimer_set(&n->transmit_timer, default_timebase(),
                 transmit_packet_list, n);
    } else {
      /* This was the last packet in the queue, we free the neighbor */
      ctimer_stop(&n->transmit_timer);
      list_remove(neighbor_list, n);
      memb_free(&neighbor_memb, n);
    }
  }
}
Exemple #23
0
static void
put_post_led_toggle_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
  static int led_state = 0;
  const uint8_t *request_content;
  int request_content_len;
  unsigned int accept = -1;

  /* Given the way the LEDs are connected to the DIO ports, the LEDs are controlled via direct DIO access. */
  content_len = 0;
  switch(led_state) {
  case (0):
    ctimer_stop(&ct);
    leds_set(LEDS_GREEN);            /* Only LEDS_GREEN on */
    CONTENT_PRINTF("Message from resource: Green LED on");
    led_state = 1;
    break;
  case (1):
    leds_set(LEDS_RED);              /* Only LEDS_RED on */
    CONTENT_PRINTF("Message from resource: Red LED on");
    led_state = 2;
    break;
  case (2):
    leds_set(0);                      /* All LEDS off */
    CONTENT_PRINTF("Message from resource: All LEDs off");
    led_state = 3;
    break;
  case 3:
    /* Both leds toggle */
    CONTENT_PRINTF("Message from resource: LEDs toggle");
    ctimer_restart(&ct);
    led_state = 0;
  default:
    break;
  }
  /* Return message */
  REST.get_header_accept(request, &accept);
  if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
    REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
    REST.set_response_payload(response, (uint8_t *)content, content_len);
  }
}
/**
 * \brief Configuration function for the MPU9250 sensor.
 *
 * \param type Activate, enable or disable the sensor. See below
 * \param enable
 *
 * When type == SENSORS_HW_INIT we turn on the hardware
 * When type == SENSORS_ACTIVE and enable==1 we enable the sensor
 * When type == SENSORS_ACTIVE and enable==0 we disable the sensor
 */
static int
configure(int type, int enable)
{
  switch(type) {
  case SENSORS_HW_INIT:
    ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_MPU_INT);
    ti_lib_ioc_io_port_pull_set(BOARD_IOID_MPU_INT, IOC_IOPULL_DOWN);
    ti_lib_ioc_io_hyst_set(BOARD_IOID_MPU_INT, IOC_HYST_ENABLE);

    ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_MPU_POWER);
    ti_lib_ioc_io_drv_strength_set(BOARD_IOID_MPU_POWER, IOC_CURRENT_4MA,
                                   IOC_STRENGTH_MAX);
    ti_lib_gpio_clear_dio(BOARD_IOID_MPU_POWER);
    elements = MPU_9250_SENSOR_TYPE_NONE;
    break;
  case SENSORS_ACTIVE:
    if(((enable & MPU_9250_SENSOR_TYPE_ACC) != 0) ||
       ((enable & MPU_9250_SENSOR_TYPE_GYRO) != 0)) {
      PRINTF("MPU: Enabling\n");
      elements = enable & MPU_9250_SENSOR_TYPE_ALL;

      power_up();

      state = SENSOR_STATE_BOOTING;
    } else {
      PRINTF("MPU: Disabling\n");
      if(HWREG(GPIO_BASE + GPIO_O_DOUT31_0) & BOARD_MPU_POWER) {
        /* Then check our state */
        elements = MPU_9250_SENSOR_TYPE_NONE;
        ctimer_stop(&startup_timer);
        sensor_sleep();
        while(ti_lib_i2c_master_busy(I2C0_BASE));
        state = SENSOR_STATE_DISABLED;
        ti_lib_gpio_clear_dio(BOARD_IOID_MPU_POWER);
      }
    }
    break;
  default:
    break;
  }
  return state;
}
Exemple #25
0
/*---------------------------------------------------------------------------*/
static void
adv_packet_received(struct broadcast_conn *ibc, const rimeaddr_t *from)
{
  struct neighbor_discovery_conn *c = (struct neighbor_discovery_conn *)ibc;
  struct adv_msg *msg = packetbuf_dataptr();

  PRINTF("%d.%d: adv_packet_received from %d.%d with val %d\n",
	 rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1],
	 from->u8[RIMEADDR_SIZE-2], from->u8[RIMEADDR_SIZE-1], msg->val);

  /* If we receive an announcement with a lower value than ours, we
     cancel our own announcement. */
  if(msg->val < c->val) {
    ctimer_stop(&c->send_timer);
  }
  
  if(c->u->recv) {
    c->u->recv(c, from, msg->val);
  }
}
Exemple #26
0
PROCESS_THREAD(sensys_tx, ev, data)
{
 PROCESS_EXITHANDLER()
 PROCESS_BEGIN();
 
 // Initial configurations  on CC2420 and resetting the timer
 leds_off(LEDS_ALL);
 cc2420_set_txpower(POWER);
 cc2420_set_channel(CHANNEL_SENDER);
 unicast_open(&uc, RIME_SENDER, &unicast_callbacks); 
 ctimer_stop(&timer1);
  
 // Ready to send...
 leds_on(LEDS_BLUE); 
 
 while(1) {
	PROCESS_WAIT_EVENT();		
 }        
 PROCESS_END();
}
Exemple #27
0
static void remove_single_scope(struct scope *scope) {
	/* leave scope in case node is a member */
	if (HAS_STATUS(scope, SCOPES_STATUS_MEMBER)) {
		leave_scope(scope);
	}

	/* inform the owner */
	CALLBACK(scope->owner, remove(scope));

	/* inform the routing process */
	routing->remove(scope);

	/* remove the scope */
	list_remove(scopes, scope);

	/* stop the scope's TTL timer */
	ctimer_stop(&(scope->ttl_timer));

	/* deallocate scope memory */
	deallocate_scope(scope);
}
Exemple #28
0
/*---------------------------------------------------------------------------*/
static void
recv(struct abc_conn *abc)
{
  struct polite_conn *c = (struct polite_conn *)abc;
  if(c->q != NULL &&
     packetbuf_datalen() == queuebuf_datalen(c->q) &&
     memcmp(packetbuf_dataptr(), queuebuf_dataptr(c->q),
	    MIN(c->hdrsize, packetbuf_datalen())) == 0) {
    /* We received a copy of our own packet, so we do not send out
       packet. */
    queuebuf_free(c->q);
    c->q = NULL;
    ctimer_stop(&c->t);
    if(c->cb->dropped) {
      c->cb->dropped(c);
    }
  }
  if(c->cb->recv) {
    c->cb->recv(c);
  }
}
static void
advertise_summary(struct deluge_object *obj)
{
  struct deluge_msg_summary summary;

  if(recv_adv >= CONST_K) {
    ctimer_stop(&summary_timer);
    return;
  }

  summary.cmd = DELUGE_CMD_SUMMARY;
  summary.version = obj->update_version;
  summary.highest_available = highest_available_page(obj);
  summary.object_id = obj->object_id;

  PRINTF("Advertising summary for object id %u: version=%u, available=%u\n",
	(unsigned)obj->object_id, summary.version, summary.highest_available);

  packetbuf_copyfrom(&summary, sizeof(summary));
  broadcast_send(&deluge_broadcast);
}
Exemple #30
0
/**
 * \brief Callback registered with the GPIO module. Gets fired with a button
 * port/pin generates an interrupt
 * \param port The port number that generated the interrupt
 * \param pin The pin number that generated the interrupt. This is the pin
 * absolute number (i.e. 0, 1, ..., 7), not a mask
 */
static void
btn_callback(uint8_t port, uint8_t pin)
{
  if(!timer_expired(&debouncetimer)) {
    return;
  }

  timer_set(&debouncetimer, DEBOUNCE_DURATION);

  if(press_duration) {
    press_event_counter = 0;
    if(value(BUTTON_SENSOR_VALUE_TYPE_LEVEL) == BUTTON_SENSOR_PRESSED_LEVEL) {
      ctimer_set(&press_counter, press_duration, duration_exceeded_callback,
                 NULL);
    } else {
      ctimer_stop(&press_counter);
    }
  }

  sensors_changed(&button_sensor);
}