Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_hdc2080.c
1 #include <bc_hdc2080.h>
2 
3 // TODO Clarify timing with TI
4 #define _BC_HDC2080_DELAY_RUN 50
5 #define _BC_HDC2080_DELAY_INITIALIZATION 50
6 #define _BC_HDC2080_DELAY_MEASUREMENT 50
7 
8 static void _bc_hdc2080_task_interval(void *param);
9 
10 static void _bc_hdc2080_task_measure(void *param);
11 
12 void bc_hdc2080_init(bc_hdc2080_t *self, bc_i2c_channel_t i2c_channel, uint8_t i2c_address)
13 {
14  memset(self, 0, sizeof(*self));
15 
16  self->_i2c_channel = i2c_channel;
17  self->_i2c_address = i2c_address;
18 
19  self->_task_id_interval = bc_scheduler_register(_bc_hdc2080_task_interval, self, BC_TICK_INFINITY);
20  self->_task_id_measure = bc_scheduler_register(_bc_hdc2080_task_measure, self, _BC_HDC2080_DELAY_RUN);
21 
22  self->_tick_ready = _BC_HDC2080_DELAY_RUN;
23 
24  bc_i2c_init(self->_i2c_channel, BC_I2C_SPEED_400_KHZ);
25 }
26 
27 void bc_hdc2080_set_event_handler(bc_hdc2080_t *self, void (*event_handler)(bc_hdc2080_t *, bc_hdc2080_event_t, void *), void *event_param)
28 {
29  self->_event_handler = event_handler;
30  self->_event_param = event_param;
31 }
32 
34 {
35  self->_update_interval = interval;
36 
37  if (self->_update_interval == BC_TICK_INFINITY)
38  {
39  bc_scheduler_plan_absolute(self->_task_id_interval, BC_TICK_INFINITY);
40  }
41  else
42  {
43  bc_scheduler_plan_relative(self->_task_id_interval, self->_update_interval);
44 
45  bc_hdc2080_measure(self);
46  }
47 }
48 
50 {
51  if (self->_measurement_active)
52  {
53  return false;
54  }
55 
56  self->_measurement_active = true;
57 
58  bc_scheduler_plan_absolute(self->_task_id_measure, self->_tick_ready);
59 
60  return true;
61 }
62 
63 bool bc_hdc2080_get_humidity_raw(bc_hdc2080_t *self, uint16_t *raw)
64 {
65  if (!self->_humidity_valid)
66  {
67  return false;
68  }
69 
70  *raw = self->_reg_humidity;
71 
72  return true;
73 }
74 
75 bool bc_hdc2080_get_humidity_percentage(bc_hdc2080_t *self, float *percentage)
76 {
77  uint16_t raw;
78 
79  if (!bc_hdc2080_get_humidity_raw(self, &raw))
80  {
81  return false;
82  }
83 
84  *percentage = (float) raw / 65536.f * 100.f;
85 
86  if (*percentage >= 100.f)
87  {
88  *percentage = 100.f;
89  }
90 
91  return true;
92 }
93 
94 bool bc_hdc2080_get_temperature_raw(bc_hdc2080_t *self, uint16_t *raw)
95 {
96  if (!self->_temperature_valid)
97  {
98  return false;
99  }
100 
101  *raw = self->_reg_temperature;
102 
103  return true;
104 }
105 
107 {
108  uint16_t raw;
109 
110  if (!bc_hdc2080_get_temperature_raw(self, &raw))
111  {
112  return false;
113  }
114 
115  *celsius = (float) raw / 65536.f * 165.f - 40.f;
116 
117  return true;
118 }
119 
120 static void _bc_hdc2080_task_interval(void *param)
121 {
122  bc_hdc2080_t *self = param;
123 
124  bc_hdc2080_measure(self);
125 
126  bc_scheduler_plan_current_relative(self->_update_interval);
127 }
128 
129 static void _bc_hdc2080_task_measure(void *param)
130 {
131  bc_hdc2080_t *self = param;
132 
133 start:
134 
135  switch (self->_state)
136  {
137  case BC_HDC2080_STATE_ERROR:
138  {
139  self->_humidity_valid = false;
140  self->_temperature_valid = false;
141 
142  self->_measurement_active = false;
143 
144  if (self->_event_handler != NULL)
145  {
146  self->_event_handler(self, BC_HDC2080_EVENT_ERROR, self->_event_param);
147  }
148 
149  self->_state = BC_HDC2080_STATE_INITIALIZE;
150 
151  return;
152  }
153  case BC_HDC2080_STATE_INITIALIZE:
154  {
155  self->_state = BC_HDC2080_STATE_ERROR;
156 
157  if (!bc_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x0e, 0x80))
158  {
159  goto start;
160  }
161 
162  self->_state = BC_HDC2080_STATE_MEASURE;
163 
164  self->_tick_ready = bc_tick_get() + _BC_HDC2080_DELAY_INITIALIZATION;
165 
166  if (self->_measurement_active)
167  {
168  bc_scheduler_plan_current_absolute(self->_tick_ready);
169  }
170 
171  return;
172  }
173  case BC_HDC2080_STATE_MEASURE:
174  {
175  self->_state = BC_HDC2080_STATE_ERROR;
176 
177  if (!bc_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x0f, 0x07))
178  {
179  goto start;
180  }
181 
182  self->_state = BC_HDC2080_STATE_READ;
183 
184  bc_scheduler_plan_current_from_now(_BC_HDC2080_DELAY_MEASUREMENT);
185 
186  return;
187  }
188  case BC_HDC2080_STATE_READ:
189  {
190  self->_state = BC_HDC2080_STATE_ERROR;
191 
192  uint8_t reg_interrupt;
193 
194  if (!bc_i2c_memory_read_8b(self->_i2c_channel, self->_i2c_address, 0x04, &reg_interrupt))
195  {
196  goto start;
197  }
198 
199  if ((reg_interrupt & 0x80) == 0)
200  {
201  goto start;
202  }
203 
204  if (!bc_i2c_memory_read_16b(self->_i2c_channel, self->_i2c_address, 0x02, &self->_reg_humidity))
205  {
206  goto start;
207  }
208 
209  if (!bc_i2c_memory_read_16b(self->_i2c_channel, self->_i2c_address, 0x00, &self->_reg_temperature))
210  {
211  goto start;
212  }
213 
214  self->_reg_temperature = self->_reg_temperature << 8 | self->_reg_temperature >> 8;
215  self->_reg_humidity = self->_reg_humidity << 8 | self->_reg_humidity >> 8;
216 
217  self->_temperature_valid = true;
218  self->_humidity_valid = true;
219 
220  self->_state = BC_HDC2080_STATE_UPDATE;
221 
222  goto start;
223  }
224  case BC_HDC2080_STATE_UPDATE:
225  {
226  self->_measurement_active = false;
227 
228  if (self->_event_handler != NULL)
229  {
230  self->_event_handler(self, BC_HDC2080_EVENT_UPDATE, self->_event_param);
231  }
232 
233  self->_state = BC_HDC2080_STATE_MEASURE;
234 
235  return;
236  }
237  default:
238  {
239  self->_state = BC_HDC2080_STATE_ERROR;
240 
241  goto start;
242  }
243  }
244 }
void bc_hdc2080_init(bc_hdc2080_t *self, bc_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize HDC2080.
Definition: bc_hdc2080.c:12
struct bc_hdc2080_t bc_hdc2080_t
HDC2080 instance.
Definition: bc_hdc2080.h:25
uint64_t bc_tick_t
Timestamp data type.
Definition: bc_tick.h:16
I2C communication speed is 400 kHz.
Definition: bc_i2c.h:36
void bc_scheduler_plan_absolute(bc_scheduler_task_id_t task_id, bc_tick_t tick)
Schedule specified task to absolute tick.
Definition: bc_scheduler.c:124
bc_scheduler_task_id_t bc_scheduler_register(void(*task)(void *), void *param, bc_tick_t tick)
Register task in scheduler.
Definition: bc_scheduler.c:56
bool bc_i2c_memory_read_8b(bc_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t *data)
Memory read 1 byte from I2C channel.
Definition: bc_i2c.c:431
void bc_scheduler_plan_current_absolute(bc_tick_t tick)
Schedule current task to absolute tick.
Definition: bc_scheduler.c:144
void bc_i2c_init(bc_i2c_channel_t channel, bc_i2c_speed_t speed)
Initialize I2C channel.
Definition: bc_i2c.c:54
bc_hdc2080_event_t
Callback events.
Definition: bc_hdc2080.h:13
bc_tick_t bc_tick_get(void)
Get absolute timestamp since start of program.
Definition: bc_tick.c:7
void bc_scheduler_plan_current_relative(bc_tick_t tick)
Schedule current task to tick relative from current spin.
Definition: bc_scheduler.c:149
void bc_hdc2080_set_event_handler(bc_hdc2080_t *self, void(*event_handler)(bc_hdc2080_t *, bc_hdc2080_event_t, void *), void *event_param)
Set callback function.
Definition: bc_hdc2080.c:27
void bc_scheduler_plan_relative(bc_scheduler_task_id_t task_id, bc_tick_t tick)
Schedule specified task to tick relative from current spin.
Definition: bc_scheduler.c:129
Error event.
Definition: bc_hdc2080.h:16
bool bc_hdc2080_get_humidity_raw(bc_hdc2080_t *self, uint16_t *raw)
Get measured humidity as raw value.
Definition: bc_hdc2080.c:63
bool bc_hdc2080_get_humidity_percentage(bc_hdc2080_t *self, float *percentage)
Get measured humidity as percentage.
Definition: bc_hdc2080.c:75
bool bc_hdc2080_measure(bc_hdc2080_t *self)
Start measurement manually.
Definition: bc_hdc2080.c:49
Update event.
Definition: bc_hdc2080.h:19
bc_i2c_channel_t
I2C channels.
Definition: bc_i2c.h:15
void bc_scheduler_plan_current_from_now(bc_tick_t tick)
Schedule current task to tick relative from now.
Definition: bc_scheduler.c:154
bool bc_hdc2080_get_temperature_raw(bc_hdc2080_t *self, uint16_t *raw)
Get measured temperature as raw value.
Definition: bc_hdc2080.c:94
#define BC_TICK_INFINITY
Maximum timestamp value.
Definition: bc_tick.h:12
bool bc_hdc2080_get_temperature_celsius(bc_hdc2080_t *self, float *celsius)
Get measured temperature in degrees of Celsius.
Definition: bc_hdc2080.c:106
void bc_hdc2080_set_update_interval(bc_hdc2080_t *self, bc_tick_t interval)
Set measurement interval.
Definition: bc_hdc2080.c:33
bool bc_i2c_memory_read_16b(bc_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint16_t *data)
Memory read 2 bytes from I2C channel.
Definition: bc_i2c.c:443
bool bc_i2c_memory_write_8b(bc_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t data)
Memory write 1 byte to I2C channel.
Definition: bc_i2c.c:402