forked from ossw/ossw-firmware-s120
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vibration.c
102 lines (89 loc) · 3.03 KB
/
vibration.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <math.h>
#include "vibration.h"
#include "nordic_common.h"
#include "app_timer.h"
#include "app_scheduler.h"
#include "board.h"
#include "nrf_gpio.h"
#include "ext_ram.h"
#include "rtc.h"
// 32bit pattern format: VVNNNNTT TTTTTTTT PPPPPPPP PPPPPPPP
// V - reserved for future use - just 0,
// N - number of steps 1-16 (0 means all 16 steps),
// T - length of a single step in milliseconds
// P - steps where 1 means vibration motor should be on, 0 means it should be off
static app_timer_id_t m_vibration_pattern_timer_id;
static uint32_t m_pattern;
static int16_t step_counter;
static uint8_t m_next_step;
static void vibration_motor_on(void) {
nrf_gpio_pin_set(VIBRATION_MOTOR);
}
static void vibration_motor_off(void) {
nrf_gpio_pin_clear(VIBRATION_MOTOR);
}
void vibration_next_step(void * p_event_data, uint16_t event_size) {
if (--step_counter <= 0) {
vibration_motor_off();
uint32_t err_code = app_timer_stop(m_vibration_pattern_timer_id);
APP_ERROR_CHECK(err_code);
return;
}
if (m_pattern >> (15 - m_next_step) & 0x1) {
vibration_motor_on();
} else {
vibration_motor_off();
}
m_next_step++;
uint8_t steps_no = (m_pattern >> 26)&0xF;
if (steps_no == 0) {
steps_no = 16;
}
if (m_next_step >= steps_no) {
m_next_step = 0;
}
}
static void vibration_pattern_change_handler(void * p_context) {
UNUSED_PARAMETER(p_context);
uint32_t err_code = app_sched_event_put(NULL, NULL, vibration_next_step);
APP_ERROR_CHECK(err_code);
}
void vibration_init(void) {
nrf_gpio_cfg_output(VIBRATION_MOTOR);
nrf_gpio_pin_clear(VIBRATION_MOTOR);
uint32_t err_code;
err_code = app_timer_create(&m_vibration_pattern_timer_id,
APP_TIMER_MODE_REPEATED,
vibration_pattern_change_handler);
APP_ERROR_CHECK(err_code);
uint8_t s_hour1 = get_ext_ram_byte(EXT_RAM_SILENT_HOURS);
uint8_t s_hour2 = get_ext_ram_byte(EXT_RAM_SILENT_HOURS + 1);
if (s_hour1 > 23 || s_hour2 > 23)
put_ext_ram_short(EXT_RAM_SILENT_HOURS, 0);
}
void vibration_vibrate(uint32_t pattern, uint16_t timeout, bool force) {
uint8_t hour1 = get_ext_ram_byte(EXT_RAM_SILENT_HOURS);
uint8_t hour2 = get_ext_ram_byte(EXT_RAM_SILENT_HOURS + 1);
uint8_t curr = rtc_get_current_hour_24();
if (!force && ((hour1 <= curr && curr < hour2) ||
(hour2 < hour1 && (curr < hour2 || hour1 <= curr))))
return;
m_pattern = pattern;
m_next_step = 0;
uint32_t step_length = (pattern >> 16) & 0x3FF;
if (step_length == 0) {
vibration_motor_off();
return;
}
step_counter = CEIL(timeout, step_length);
vibration_next_step(NULL, 0);
uint32_t err_code;
err_code = app_timer_start(m_vibration_pattern_timer_id, APP_TIMER_TICKS(step_length, APP_TIMER_PRESCALER), NULL);
APP_ERROR_CHECK(err_code);
}
void vibration_stop() {
uint32_t err_code;
err_code = app_timer_stop(m_vibration_pattern_timer_id);
APP_ERROR_CHECK(err_code);
vibration_motor_off();
}