Firmware SDK
twr_hdc2080.c
1 #include <twr_hdc2080.h>
2 
3 // TODO Clarify timing with TI
4 #define _TWR_HDC2080_DELAY_RUN 50
5 #define _TWR_HDC2080_DELAY_INITIALIZATION 50
6 #define _TWR_HDC2080_DELAY_MEASUREMENT 50
7 
8 static void _twr_hdc2080_task_interval(void *param);
9 
10 static void _twr_hdc2080_task_measure(void *param);
11 
12 void twr_hdc2080_init(twr_hdc2080_t *self, twr_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 = twr_scheduler_register(_twr_hdc2080_task_interval, self, TWR_TICK_INFINITY);
20  self->_task_id_measure = twr_scheduler_register(_twr_hdc2080_task_measure, self, _TWR_HDC2080_DELAY_RUN);
21 
22  self->_tick_ready = _TWR_HDC2080_DELAY_RUN;
23 
24  twr_i2c_init(self->_i2c_channel, TWR_I2C_SPEED_400_KHZ);
25 }
26 
28 {
29  twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x0e, 0x80);
30 
31  twr_scheduler_unregister(self->_task_id_interval);
32 
33  twr_scheduler_unregister(self->_task_id_measure);
34 }
35 
36 void twr_hdc2080_set_event_handler(twr_hdc2080_t *self, void (*event_handler)(twr_hdc2080_t *, twr_hdc2080_event_t, void *), void *event_param)
37 {
38  self->_event_handler = event_handler;
39  self->_event_param = event_param;
40 }
41 
43 {
44  self->_update_interval = interval;
45 
46  if (self->_update_interval == TWR_TICK_INFINITY)
47  {
48  twr_scheduler_plan_absolute(self->_task_id_interval, TWR_TICK_INFINITY);
49  }
50  else
51  {
52  twr_scheduler_plan_relative(self->_task_id_interval, self->_update_interval);
53 
54  twr_hdc2080_measure(self);
55  }
56 }
57 
59 {
60  if (self->_measurement_active)
61  {
62  return false;
63  }
64 
65  self->_measurement_active = true;
66 
67  twr_scheduler_plan_absolute(self->_task_id_measure, self->_tick_ready);
68 
69  return true;
70 }
71 
72 bool twr_hdc2080_get_humidity_raw(twr_hdc2080_t *self, uint16_t *raw)
73 {
74  if (!self->_humidity_valid)
75  {
76  return false;
77  }
78 
79  *raw = self->_reg_humidity;
80 
81  return true;
82 }
83 
84 bool twr_hdc2080_get_humidity_percentage(twr_hdc2080_t *self, float *percentage)
85 {
86  uint16_t raw;
87 
88  if (!twr_hdc2080_get_humidity_raw(self, &raw))
89  {
90  return false;
91  }
92 
93  *percentage = (float) raw / 65536.f * 100.f;
94 
95  if (*percentage >= 100.f)
96  {
97  *percentage = 100.f;
98  }
99 
100  return true;
101 }
102 
104 {
105  if (!self->_temperature_valid)
106  {
107  return false;
108  }
109 
110  *raw = self->_reg_temperature;
111 
112  return true;
113 }
114 
116 {
117  uint16_t raw;
118 
119  if (!twr_hdc2080_get_temperature_raw(self, &raw))
120  {
121  return false;
122  }
123 
124  *celsius = (float) raw / 65536.f * 165.f - 40.f;
125 
126  return true;
127 }
128 
129 static void _twr_hdc2080_task_interval(void *param)
130 {
131  twr_hdc2080_t *self = param;
132 
133  twr_hdc2080_measure(self);
134 
135  twr_scheduler_plan_current_relative(self->_update_interval);
136 }
137 
138 static void _twr_hdc2080_task_measure(void *param)
139 {
140  twr_hdc2080_t *self = param;
141 
142 start:
143 
144  switch (self->_state)
145  {
146  case TWR_HDC2080_STATE_ERROR:
147  {
148  self->_humidity_valid = false;
149  self->_temperature_valid = false;
150 
151  self->_measurement_active = false;
152 
153  if (self->_event_handler != NULL)
154  {
155  self->_event_handler(self, TWR_HDC2080_EVENT_ERROR, self->_event_param);
156  }
157 
158  self->_state = TWR_HDC2080_STATE_INITIALIZE;
159 
160  return;
161  }
162  case TWR_HDC2080_STATE_INITIALIZE:
163  {
164  self->_state = TWR_HDC2080_STATE_ERROR;
165 
166  if (!twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x0e, 0x80))
167  {
168  goto start;
169  }
170 
171  self->_state = TWR_HDC2080_STATE_MEASURE;
172 
173  self->_tick_ready = twr_tick_get() + _TWR_HDC2080_DELAY_INITIALIZATION;
174 
175  if (self->_measurement_active)
176  {
177  twr_scheduler_plan_current_absolute(self->_tick_ready);
178  }
179 
180  return;
181  }
182  case TWR_HDC2080_STATE_MEASURE:
183  {
184  self->_state = TWR_HDC2080_STATE_ERROR;
185 
186  if (!twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x0f, 0x07))
187  {
188  goto start;
189  }
190 
191  self->_state = TWR_HDC2080_STATE_READ;
192 
193  twr_scheduler_plan_current_from_now(_TWR_HDC2080_DELAY_MEASUREMENT);
194 
195  return;
196  }
197  case TWR_HDC2080_STATE_READ:
198  {
199  self->_state = TWR_HDC2080_STATE_ERROR;
200 
201  uint8_t reg_interrupt;
202 
203  if (!twr_i2c_memory_read_8b(self->_i2c_channel, self->_i2c_address, 0x04, &reg_interrupt))
204  {
205  goto start;
206  }
207 
208  if ((reg_interrupt & 0x80) == 0)
209  {
210  goto start;
211  }
212 
213  if (!twr_i2c_memory_read_16b(self->_i2c_channel, self->_i2c_address, 0x02, &self->_reg_humidity))
214  {
215  goto start;
216  }
217 
218  if (!twr_i2c_memory_read_16b(self->_i2c_channel, self->_i2c_address, 0x00, &self->_reg_temperature))
219  {
220  goto start;
221  }
222 
223  self->_reg_temperature = self->_reg_temperature << 8 | self->_reg_temperature >> 8;
224  self->_reg_humidity = self->_reg_humidity << 8 | self->_reg_humidity >> 8;
225 
226  self->_temperature_valid = true;
227  self->_humidity_valid = true;
228 
229  self->_state = TWR_HDC2080_STATE_UPDATE;
230 
231  goto start;
232  }
233  case TWR_HDC2080_STATE_UPDATE:
234  {
235  self->_measurement_active = false;
236 
237  if (self->_event_handler != NULL)
238  {
239  self->_event_handler(self, TWR_HDC2080_EVENT_UPDATE, self->_event_param);
240  }
241 
242  self->_state = TWR_HDC2080_STATE_MEASURE;
243 
244  return;
245  }
246  default:
247  {
248  self->_state = TWR_HDC2080_STATE_ERROR;
249 
250  goto start;
251  }
252  }
253 }
twr_hdc2080_event_t
Callback events.
Definition: twr_hdc2080.h:14
struct twr_hdc2080_t twr_hdc2080_t
HDC2080 instance.
Definition: twr_hdc2080.h:25
void twr_hdc2080_init(twr_hdc2080_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize HDC2080.
Definition: twr_hdc2080.c:12
bool twr_hdc2080_get_temperature_celsius(twr_hdc2080_t *self, float *celsius)
Get measured temperature in degrees of Celsius.
Definition: twr_hdc2080.c:115
bool twr_hdc2080_get_temperature_raw(twr_hdc2080_t *self, uint16_t *raw)
Get measured temperature as raw value.
Definition: twr_hdc2080.c:103
void twr_hdc2080_deinit(twr_hdc2080_t *self)
Deinitialize HDC2080.
Definition: twr_hdc2080.c:27
bool twr_hdc2080_measure(twr_hdc2080_t *self)
Start measurement manually.
Definition: twr_hdc2080.c:58
bool twr_hdc2080_get_humidity_percentage(twr_hdc2080_t *self, float *percentage)
Get measured humidity as percentage.
Definition: twr_hdc2080.c:84
bool twr_hdc2080_get_humidity_raw(twr_hdc2080_t *self, uint16_t *raw)
Get measured humidity as raw value.
Definition: twr_hdc2080.c:72
void twr_hdc2080_set_update_interval(twr_hdc2080_t *self, twr_tick_t interval)
Set measurement interval.
Definition: twr_hdc2080.c:42
void twr_hdc2080_set_event_handler(twr_hdc2080_t *self, void(*event_handler)(twr_hdc2080_t *, twr_hdc2080_event_t, void *), void *event_param)
Set callback function.
Definition: twr_hdc2080.c:36
@ TWR_HDC2080_EVENT_UPDATE
Update event.
Definition: twr_hdc2080.h:19
@ TWR_HDC2080_EVENT_ERROR
Error event.
Definition: twr_hdc2080.h:16
void twr_i2c_init(twr_i2c_channel_t channel, twr_i2c_speed_t speed)
Initialize I2C channel.
Definition: twr_i2c.c:57
bool twr_i2c_memory_write_8b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t data)
Memory write 1 byte to I2C channel.
Definition: twr_i2c.c:408
bool twr_i2c_memory_read_16b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint16_t *data)
Memory read 2 bytes from I2C channel.
Definition: twr_i2c.c:449
bool twr_i2c_memory_read_8b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t *data)
Memory read 1 byte from I2C channel.
Definition: twr_i2c.c:437
twr_i2c_channel_t
I2C channels.
Definition: twr_i2c.h:16
@ TWR_I2C_SPEED_400_KHZ
I2C communication speed is 400 kHz.
Definition: twr_i2c.h:36
void twr_scheduler_plan_current_from_now(twr_tick_t tick)
Schedule current task to tick relative from now.
void twr_scheduler_plan_current_relative(twr_tick_t tick)
Schedule current task to tick relative from current spin.
void twr_scheduler_plan_current_absolute(twr_tick_t tick)
Schedule current task to absolute tick.
void twr_scheduler_plan_absolute(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to absolute tick.
void twr_scheduler_unregister(twr_scheduler_task_id_t task_id)
Unregister specified task.
Definition: twr_scheduler.c:77
void twr_scheduler_plan_relative(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to tick relative from current spin.
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
Definition: twr_scheduler.c:53
#define TWR_TICK_INFINITY
Maximum timestamp value.
Definition: twr_tick.h:12
twr_tick_t twr_tick_get(void)
Get absolute timestamp since start of program.
Definition: twr_tick.c:7
uint64_t twr_tick_t
Timestamp data type.
Definition: twr_tick.h:16