Skip to content
Snippets Groups Projects
Select Git revision
  • master
  • schneider/ir
  • rahix/user-space-ctx
  • schneider/iaq-python
  • schneider/ble-mini-demo
  • schneider/ble-ecg-stream-visu
  • schneider/mp-exception-print
  • schneider/sleep-display
  • schneider/deepsleep4
  • schneider/deepsleep2
  • schneider/deepsleep
  • schneider/ble-central
  • rahix/bluetooth-app-favorite
  • schneider/v1.17-changelog
  • schneider/ancs
  • schneider/png
  • schneider/freertos-list-debug
  • schneider/212-reset-hardware-when-entering-repl
  • schneider/bonding-fail-if-full
  • schneider/ble-fixes-2020-3
  • v1.18
  • v1.17
  • v1.16
  • v1.15
  • v1.14
  • v1.13
  • v1.12
  • v1.11
  • v1.10
  • v1.9
  • v1.8
  • v1.7
  • v1.6
  • v1.5
  • v1.4
  • v1.3
  • v1.2
  • v1.1
  • v1.0
  • release-1
40 results

personal_state.c

Blame
  • user avatar
    schneider authored
    This reduces the power consumption of the system by around .1 mA when
    the personal state is not active.
    4ac704af
    History
    personal_state.c 3.64 KiB
    #include "epicardium.h"
    #include "leds.h"
    #include "modules.h"
    
    #include "os/work_queue.h"
    
    #include "FreeRTOS.h"
    #include "timers.h"
    
    #include <math.h>
    
    static uint8_t _personal_state_enabled   = 0;
    static uint8_t personal_state            = STATE_NONE;
    static uint8_t personal_state_persistent = 0;
    
    static int led_animation_ticks = 0;
    static int led_animation_state = 0;
    
    static TimerHandle_t led_timer;
    static StaticTimer_t led_timer_buffer;
    static void worktick(void *data);
    
    static const int led_animation_rate = 1000 / 25; /* 25Hz -> 40ms*/
    
    int personal_state_enabled()
    {
    	return _personal_state_enabled;
    }
    
    static void tick(TimerHandle_t xTimer)
    {
    	workqueue_schedule(worktick, NULL);
    }
    
    int epic_personal_state_set(uint8_t state, bool persistent)
    {
    	if (state > STATE_CAMP)
    		return -EINVAL;
    
    	led_animation_state = 0;
    	led_animation_ticks = 0;
    	personal_state      = state;
    
    	uint8_t was_enabled = _personal_state_enabled;
    
    	_personal_state_enabled   = (state != STATE_NONE);
    	personal_state_persistent = persistent;
    
    	if (!was_enabled && _personal_state_enabled) {
    		// Activate
    		if (!led_timer) {
    			led_timer = xTimerCreateStatic(
    				"personal state",
    				led_animation_rate / portTICK_PERIOD_MS,
    				pdTRUE,
    				NULL,
    				tick,
    				&led_timer_buffer
    			);
    			// since &poll_timer_buffer is not NULL, xTimerCreateStatic should allways succeed, so
    			// we don't need to check for poll_timer being NULL.
    		}
    
    		if (xTimerIsTimerActive(led_timer) == pdFALSE) {
    			xTimerStart(led_timer, 0);
    		}
    
    	} else if (was_enabled && !_personal_state_enabled) {
    		// Deactivate
    		xTimerStop(led_timer, 0);
    		// TODO: we might need a lock here to avoid a race condition
    		leds_prep(PERSONAL_STATE_LED, 0, 0, 0);
    		epic_leds_update();
    	}
    
    	return 0;
    }
    
    int epic_personal_state_get()
    {
    	return personal_state;
    }
    
    int epic_personal_state_is_persistent()
    {
    	return personal_state_persistent;
    }
    
    static void worktick(void *data)
    {
    	if (_personal_state_enabled) {
    		led_animation_ticks++;
    		if (personal_state == STATE_NO_CONTACT) {
    			leds_prep(PERSONAL_STATE_LED, 255, 0, 0);
    		} else if (personal_state == STATE_CHAOS) {
    			if (led_animation_state == 0) {
    				leds_prep(PERSONAL_STATE_LED, 0, 0, 255);
    				if (led_animation_ticks >
    				    (200 / led_animation_rate)) {
    					led_animation_ticks = 0;
    					led_animation_state = 1;
    				}
    			} else if (led_animation_state == 1) {
    				leds_prep(PERSONAL_STATE_LED, 0, 0, 0);
    				if (led_animation_ticks >
    				    (300 / led_animation_rate)) {
    					led_animation_ticks = 0;
    					led_animation_state = 2;
    				}
    			} else if (led_animation_state == 2) {
    				leds_prep(PERSONAL_STATE_LED, 0, 0, 255);
    				if (led_animation_ticks >
    				    (1000 / led_animation_rate)) {
    					led_animation_ticks = 0;
    					led_animation_state = 3;
    				}
    			} else if (led_animation_state == 3) {
    				leds_prep(PERSONAL_STATE_LED, 0, 0, 0);
    				if (led_animation_ticks >
    				    (300 / led_animation_rate)) {
    					led_animation_ticks = 0;
    					led_animation_state = 0;
    				}
    			}
    		} else if (personal_state == STATE_COMMUNICATION) {
    			if (led_animation_state == 0) {
    				leds_prep(PERSONAL_STATE_LED, 255, 255, 0);
    				if (led_animation_ticks >
    				    (1000 / led_animation_rate)) {
    					led_animation_ticks = 0;
    					led_animation_state = 1;
    				}
    			} else if (led_animation_state == 1) {
    				leds_prep(PERSONAL_STATE_LED, 0, 0, 0);
    				if (led_animation_ticks >
    				    (300 / led_animation_rate)) {
    					led_animation_ticks = 0;
    					led_animation_state = 0;
    				}
    			}
    		} else if (personal_state == STATE_CAMP) {
    			leds_prep_hsv(
    				PERSONAL_STATE_LED,
    				120.0f,
    				1.0f,
    				fabs(sin(
    					led_animation_ticks /
    					(float)(1000 / led_animation_rate))));
    		}
    
    		epic_leds_update();
    	}
    }