2021-08-01 18:40:42 -04:00

194 lines
4.9 KiB
C

#include <stdio.h>
#include <string.h>
#include "app.h"
// these are implemented in main.c, just want to have access to them here.
void uart_putc(char c);
void uart_puts(char *s);
typedef enum ApplicationMode {
MODE_TIME,
MODE_SENSE,
MODE_SET_HOUR,
MODE_SET_MINUTE,
MODE_SET_SECOND
} ApplicationMode;
typedef struct ApplicationState {
ApplicationMode mode;
bool light_pressed;
bool mode_pressed;
bool alarm_pressed;
bool light_on;
uint16_t dig_T1; /**< dig_T1 cal register. */
int16_t dig_T2; /**< dig_T2 cal register. */
int16_t dig_T3; /**< dig_T3 cal register. */
} ApplicationState;
ApplicationState applicationState;
void cb_light_pressed() {
applicationState.light_pressed = true;
}
void cb_mode_pressed() {
applicationState.mode_pressed = true;
}
void cb_alarm_pressed() {
applicationState.alarm_pressed = true;
}
void cb_tick() {
;
}
#define BMP280_REGISTER_DIG_T1 0x88
#define BMP280_REGISTER_DIG_T2 0x8A
#define BMP280_REGISTER_DIG_T3 0x8C
#define BMP280_REGISTER_SOFTRESET 0xE0
#define BMP280_REGISTER_STATUS 0xF3
#define BMP280_REGISTER_CONTROL 0xF4
#define BMP280_REGISTER_CONFIG 0xF5
#define BMP280_REGISTER_PRESSUREDATA 0xF7
#define BMP280_REGISTER_TEMPDATA 0xFA
uint16_t read8(uint8_t reg) {
uint8_t val;
watch_i2c_send(0x77, &reg, 1);
watch_i2c_receive(0x77, &val, 1);
return val;
}
uint16_t read16(uint8_t reg) {
uart_puts("\nReading 2 bytes... ");
uint8_t buf[2];
watch_i2c_send(0x77, &reg, 1);
watch_i2c_receive(0x77, (uint8_t *)&buf, 2);
uart_puts("received!\n");
char buf2[32] = {0};
sprintf(buf2, "buf has values: %#02x, %#02x", buf[0], buf[1]);
uart_puts(buf2);
return (buf[0] << 8) | buf[1];
}
uint32_t read24(uint8_t reg) {
uart_puts("\nReading 3 bytes... ");
uint32_t value;
uint8_t buf[3];
watch_i2c_send(0x77, &reg, 1);
watch_i2c_receive(0x77, (uint8_t *)&buf, 3);
uart_puts("received!\n");
char buf2[33] = {0};
sprintf(buf2, "buf has values: %#02x, %#02x, %#02x", buf[0], buf[1], buf[2]);
uart_puts(buf2);
value = buf[0];
value <<= 8;
value |= buf[1];
value <<= 8;
value |= buf[2];
return value;
}
uint16_t read16_LE(uint8_t reg) {
uint16_t temp = read16(reg);
return (temp >> 8) | (temp << 8);
}
int16_t readS16(uint8_t reg) {
return (int16_t)read16(reg);
}
int16_t readS16_LE(uint8_t reg) {
return (int16_t)read16_LE(reg);
}
void print_temperature() {
int32_t var1, var2;
int32_t t_fine;
int32_t adc_T = read24(BMP280_REGISTER_TEMPDATA);
adc_T >>= 4;
var1 = ((((adc_T >> 3) - ((int32_t)applicationState.dig_T1 << 1))) *
((int32_t)applicationState.dig_T2)) >>
11;
var2 = (((((adc_T >> 4) - ((int32_t)applicationState.dig_T1)) *
((adc_T >> 4) - ((int32_t)applicationState.dig_T1))) >>
12) *
((int32_t)applicationState.dig_T3)) >>
14;
t_fine = var1 + var2;
float T = ((t_fine * 5 + 128) >> 8) / 100.0;
char buf[32] = {0};
sprintf(buf, "\n\nTemp is %3.2f degrees C", T);
uart_puts(buf);
}
/**
* @brief the app_init function is like setup() in Arduino. It is called once when the
* program begins. You should set pin modes and enable any peripherals you want to
* set up (real-time clock, I2C, etc.)
*
* @note If your app enters the ultra-low power BACKUP sleep mode, this function will
* be called again when it wakes from that deep sleep state. In this state, the RTC will
* still be configured with the correct date and time.
*/
void app_init() {
memset(&applicationState, 0, sizeof(applicationState));
watch_enable_buttons();
watch_register_button_callback(BTN_LIGHT, cb_light_pressed);
watch_enable_date_time();
watch_enable_tick_callback(cb_tick);
watch_enable_display();
watch_enable_led();
watch_enable_i2c();
uart_puts("\n\nI2C Driver Test\n");
uint8_t reset_cmd[] = {0xE0, 0xB6};
watch_i2c_send(0x77, reset_cmd, 2);
uart_puts("Reset BMP280\n");
applicationState.dig_T1 = read16_LE(BMP280_REGISTER_DIG_T1);
applicationState.dig_T2 = readS16_LE(BMP280_REGISTER_DIG_T2);
applicationState.dig_T3 = readS16_LE(BMP280_REGISTER_DIG_T3);
uint8_t ctrl_cmd[] = {0xF4, 0xA3};
watch_i2c_send(0x77, ctrl_cmd, 2);
}
/**
* @brief the app_prepare_for_sleep function is called before the watch goes into the
* STANDBY sleep mode. In STANDBY mode, most peripherals are shut down, and no code
* will run until the watch receives an interrupt (generally either the 1Hz tick or
* a press on one of the buttons).
*/
void app_prepare_for_sleep() {
applicationState.light_pressed = false;
applicationState.mode_pressed = false;
applicationState.alarm_pressed = false;
}
/**
* @brief the app_wake_from_sleep function is called after the watch wakes from the
* STANDBY sleep mode.
*/
void app_wake_from_sleep() {
}
void app_loop() {
if (applicationState.light_pressed) {
print_temperature();
}
uart_putc('.');
}