Firmware SDK
twr_module_co2.c
1 #include <twr_module_co2.h>
2 #include <twr_scheduler.h>
3 #include <twr_i2c.h>
4 #include <twr_tca9534a.h>
5 #include <twr_sc16is740.h>
6 
7 #define _TWR_MODULE_CO2_I2C_GPIO_EXPANDER_ADDRESS 0x38
8 #define _TWR_MODULE_CO2_I2C_UART_ADDRESS 0x4d
9 #define _TWR_MODULE_CO2_PIN_DEFAULT (~(1 << 0) & ~(1 << 4))
10 #define _TWR_MODULE_CO2_PIN_CAP_ON (~(1 << 1))
11 #define _TWR_MODULE_CO2_PIN_VDD2_ON (~(1 << 2))
12 #define _TWR_MODULE_CO2_PIN_EN (~(1 << 3))
13 #define _TWR_MODULE_CO2_PIN_UART_RESET (~(1 << 6))
14 #define _TWR_MODULE_CO2_PIN_RDY TWR_TCA9534A_PIN_P7
15 
16 typedef enum
17 {
18  TWR_MODULE_CO2_STATE_ERROR = -1,
19  TWR_MODULE_CO2_STATE_INITIALIZE = 0,
20  TWR_MODULE_CO2_STATE_INITIALIZE1,
21  TWR_MODULE_CO2_STATE_INITIALIZE2,
22  TWR_MODULE_CO2_STATE_READY,
23  TWR_MODULE_CO2_STATE_CHARGE,
24  TWR_MODULE_CO2_STATE_BOOT,
25  TWR_MODULE_CO2_STATE_BOOT_READ,
26  TWR_MODULE_CO2_STATE_MEASURE,
27  TWR_MODULE_CO2_STATE_MEASURE_READ,
28 
29 } twr_module_co2_state_t;
30 
31 static bool _twr_module_co2_init(void);
32 static bool _twr_module_co2_charge_enable(bool state);
33 static bool _twr_module_co2_device_enable(bool state);
34 static bool _twr_module_co2_read_signal_rdy(int *value);
35 static bool _twr_module_co2_uart_enable(bool state);
36 static size_t _twr_module_co2_uart_write(uint8_t *buffer, size_t length);
37 static size_t _twr_module_co2_uart_read(uint8_t *buffer, size_t length);
38 
39 static struct
40 {
41  twr_tca9534a_t tca9534a;
42  twr_sc16is740_t sc16is740;
43  twr_lp8_t sensor;
44  const twr_lp8_driver_t driver;
45 
46 } _twr_module_co2 = {
47  .driver = {
48  .init = _twr_module_co2_init,
49  .charge_enable = _twr_module_co2_charge_enable,
50  .device_enable = _twr_module_co2_device_enable,
51  .read_signal_rdy = _twr_module_co2_read_signal_rdy,
52  .uart_enable = _twr_module_co2_uart_enable,
53  .uart_write = _twr_module_co2_uart_write,
54  .uart_read = _twr_module_co2_uart_read
55  }
56 };
57 
59 {
60  twr_lp8_init(&_twr_module_co2.sensor, &_twr_module_co2.driver);
61 }
62 
63 void twr_module_co2_set_event_handler(void (*event_handler)(twr_module_co2_event_t, void *), void *event_param)
64 {
65  twr_lp8_set_event_handler(&_twr_module_co2.sensor, (void (*)(twr_lp8_event_t, void *)) event_handler, event_param);
66 }
67 
69 {
70  twr_lp8_set_update_interval(&_twr_module_co2.sensor, interval);
71 }
72 
74 {
75  return twr_lp8_measure(&_twr_module_co2.sensor);
76 }
77 
79 {
80  return twr_lp8_get_concentration_ppm(&_twr_module_co2.sensor, ppm);
81 }
82 
83 bool twr_module_co2_get_error(twr_lp8_error_t *error)
84 {
85  return twr_lp8_get_error(&_twr_module_co2.sensor, error);
86 }
87 
89 {
90  twr_lp8_calibration(&_twr_module_co2.sensor, calibration);
91 }
92 
93 static bool _twr_module_co2_init(void)
94 {
95  if (!twr_tca9534a_init(&_twr_module_co2.tca9534a, TWR_I2C_I2C0, _TWR_MODULE_CO2_I2C_GPIO_EXPANDER_ADDRESS))
96  {
97  return false;
98  }
99 
100  if (!twr_tca9534a_write_port(&_twr_module_co2.tca9534a, 0x00))
101  {
102  return false;
103  }
104 
105  // Reset SC16IS740
106  if (!twr_tca9534a_set_port_direction(&_twr_module_co2.tca9534a, _TWR_MODULE_CO2_PIN_DEFAULT & _TWR_MODULE_CO2_PIN_UART_RESET))
107  {
108  return false;
109  }
110 
111  // Reset pulse width > 3us
112  for (volatile int i = 0; i < 100; i++)
113  {
114  continue;
115  }
116 
117  if (!twr_tca9534a_set_port_direction(&_twr_module_co2.tca9534a, _TWR_MODULE_CO2_PIN_DEFAULT))
118  {
119  return false;
120  }
121 
122  // Delay time width > 10us
123  for (volatile int i = 0; i < 1000; i++)
124  {
125  continue;
126  }
127 
128  if (!twr_sc16is740_init(&_twr_module_co2.sc16is740, TWR_I2C_I2C0, _TWR_MODULE_CO2_I2C_UART_ADDRESS))
129  {
130  return false;
131  }
132 
133  return true;
134 }
135 
136 static bool _twr_module_co2_charge_enable(bool state)
137 {
138  uint8_t direction = _TWR_MODULE_CO2_PIN_DEFAULT;
139 
140  if (state)
141  {
142  direction &= _TWR_MODULE_CO2_PIN_VDD2_ON & _TWR_MODULE_CO2_PIN_CAP_ON;
143  }
144 
145  return twr_tca9534a_set_port_direction(&_twr_module_co2.tca9534a, direction);
146 }
147 
148 static bool _twr_module_co2_device_enable(bool state)
149 {
150  uint8_t direction = _TWR_MODULE_CO2_PIN_DEFAULT;
151 
152  if (state)
153  {
154  direction &= _TWR_MODULE_CO2_PIN_VDD2_ON & _TWR_MODULE_CO2_PIN_CAP_ON & _TWR_MODULE_CO2_PIN_EN;
155  }
156 
157  return twr_tca9534a_set_port_direction(&_twr_module_co2.tca9534a, direction);
158 }
159 
160 static bool _twr_module_co2_read_signal_rdy(int *value)
161 {
162  if (!twr_tca9534a_read_pin(&_twr_module_co2.tca9534a, _TWR_MODULE_CO2_PIN_RDY, value))
163  {
164  return false;
165  }
166 
167  return true;
168 }
169 
170 static bool _twr_module_co2_uart_enable(bool state)
171 {
172  if (state)
173  {
174  return twr_sc16is740_reset_fifo(&_twr_module_co2.sc16is740, TWR_SC16IS740_FIFO_RX);
175  }
176 
177  return true;
178 }
179 
180 static size_t _twr_module_co2_uart_write(uint8_t *buffer, size_t length)
181 {
182  return twr_sc16is740_write(&_twr_module_co2.sc16is740, buffer, length);
183 }
184 
185 static size_t _twr_module_co2_uart_read(uint8_t *buffer, size_t length)
186 {
187  return twr_sc16is740_read(&_twr_module_co2.sc16is740, buffer, length, 0);
188 }
bool twr_tca9534a_write_port(twr_tca9534a_t *self, uint8_t state)
Write state to all pins.
Definition: twr_tca9534a.c:35
void twr_lp8_set_update_interval(twr_lp8_t *self, twr_tick_t interval)
Set measurement interval.
Definition: twr_lp8.c:42
twr_lp8_calibration_t
Calibration.
Definition: twr_lp8.h:25
twr_module_co2_event_t
Callback events.
void twr_lp8_set_event_handler(twr_lp8_t *self, void(*event_handler)(twr_lp8_event_t, void *), void *event_param)
Set callback function.
Definition: twr_lp8.c:36
void twr_module_co2_set_update_interval(twr_tick_t interval)
Set measurement interval.
void twr_module_co2_calibration(twr_lp8_calibration_t calibration)
Request sensor calibration.
bool twr_module_co2_measure(void)
Start measurement manually.
bool twr_tca9534a_read_pin(twr_tca9534a_t *self, twr_tca9534a_pin_t pin, int *state)
Read pin state.
Definition: twr_tca9534a.c:47
bool twr_tca9534a_init(twr_tca9534a_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize TCA9534A.
Definition: twr_tca9534a.c:8
void twr_lp8_calibration(twr_lp8_t *self, twr_lp8_calibration_t calibration)
Request sensor calibration.
Definition: twr_lp8.c:97
void twr_module_co2_set_event_handler(void(*event_handler)(twr_module_co2_event_t, void *), void *event_param)
Set callback function.
bool twr_lp8_get_concentration_ppm(twr_lp8_t *self, float *ppm)
Get CO2 concentration in ppm (parts per million)
Definition: twr_lp8.c:76
void twr_lp8_init(twr_lp8_t *self, const twr_lp8_driver_t *driver)
Initialize LP8.
Definition: twr_lp8.c:20
bool twr_sc16is740_reset_fifo(twr_sc16is740_t *self, twr_sc16is740_fifo_t fifo)
Reset FIFO.
Definition: twr_sc16is740.c:79
void twr_module_co2_init(void)
Initialize HARDWARIO CO2 Module.
bool twr_sc16is740_init(twr_sc16is740_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
SC16IS740 instance.
Definition: twr_sc16is740.c:23
bool twr_module_co2_get_concentration_ppm(float *ppm)
Get CO2 concentration in ppm (parts per million)
uint64_t twr_tick_t
Timestamp data type.
Definition: twr_tick.h:16
bool twr_module_co2_get_error(twr_lp8_error_t *error)
Get last error code.
Pin state.
Definition: twr_tca9534a.h:42
LP8 driver.
Definition: twr_lp8.h:53
twr_lp8_event_t
Callback events.
Definition: twr_lp8.h:13
struct twr_lp8_t twr_lp8_t
LP8 instance.
Definition: twr_lp8.h:49
I2C channel I2C0.
Definition: twr_i2c.h:18
bool twr_tca9534a_set_port_direction(twr_tca9534a_t *self, uint8_t direction)
Set direction of all pins.
Definition: twr_tca9534a.c:87
bool twr_lp8_get_error(twr_lp8_t *self, twr_lp8_error_t *error)
Get last error code.
Definition: twr_lp8.c:90
bool twr_lp8_measure(twr_lp8_t *self)
Start measurement manually.
Definition: twr_lp8.c:58
size_t twr_sc16is740_write(twr_sc16is740_t *self, uint8_t *buffer, size_t length)
Write.
size_t twr_sc16is740_read(twr_sc16is740_t *self, uint8_t *buffer, size_t length, twr_tick_t timeout)
Read.