Browse Source

initial commit

master
Franz Levin 2 years ago
commit
7f470fbb87
12 changed files with 1662 additions and 0 deletions
  1. +280
    -0
      bmp180.c
  2. +52
    -0
      bmp180.h
  3. +286
    -0
      bmp280.c
  4. +54
    -0
      bmp280.h
  5. +87
    -0
      drivers.h
  6. +58
    -0
      i2c.h
  7. +428
    -0
      i2c_master.c
  8. +22
    -0
      i2c_master.h
  9. +147
    -0
      tsl2561.c
  10. +40
    -0
      tsl2561.h
  11. +168
    -0
      ws2801.c
  12. +40
    -0
      ws2801.h

+ 280
- 0
bmp180.c View File

@ -0,0 +1,280 @@
/*
"THE BEER/MATE-WARE LICENSE":
<xil@xil.se> wrote this file. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you think
this stuff is worth it, you can buy us a ( > 0 ) beer/mate in return - The Xil TEAM
*/
#include <stdint.h>
#include "drivers/i2c.h"
#include "drivers/bmp180.h"
#include "drivers/drivers.h"
#define I2C_ADDRESS 0x77
#define BMP180_REG_ID 0xD0
#define BMP180_REG_CONTROL 0xF4
#define BMP180_REG_MSB 0xF6
#define BMP180_REG_LSB 0xF7
#define BMP180_REG_XLSB 0xF8
#define BMP180_ID 0x55
#define BMP180_TEMPERATURE 0x2E
#define BMP180_PRESSURE_OSS0 0x34
#define BMP180_PRESSURE_OSS1 0x74
#define BMP180_PRESSURE_OSS2 0xB4
#define BMP180_PRESSURE_OSS3 0xF4
#define BMP180_CONVERSION_TIME_TEMERATURE 4500 // us
#define BMP180_CONVERSION_TIME_PRESSURE_OSS0 4500 // us
#define BMP180_CONVERSION_TIME_PRESSURE_OSS1 7500 // us
#define BMP180_CONVERSION_TIME_PRESSURE_OSS2 13500 // us
#define BMP180_CONVERSION_TIME_PRESSURE_OSS3 25500 // us
static int32_t ICACHE_FLASH_ATTR read24_int(bmp180_t* bmp180, int reg, bool b24)
{
int res;
uint8_t val[3] = {0};
val[0] = reg;
res = i2c_transmit(bmp180->i2c, I2C_ADDRESS, val, 1);
if (res != 0)
{
return 0;
}
if (b24)
{
res = i2c_receive(bmp180->i2c, I2C_ADDRESS, val, 3);
}
else
{
res = i2c_receive(bmp180->i2c, I2C_ADDRESS, val, 2);
}
if (res != 0)
{
return 0;
}
if (b24)
return (val[0] << 16) | (val[1] << 8) | val[2];
else
return (val[0] << 8) | val[1];
}
static int16_t ICACHE_FLASH_ATTR read16(bmp180_t* bmp180, int reg)
{
return read24_int(bmp180, reg, false);
}
static int32_t ICACHE_FLASH_ATTR read24(bmp180_t* bmp180, int reg)
{
return read24_int(bmp180, reg, true);
}
int16_t ICACHE_FLASH_ATTR bmp180_read_temp_raw(bmp180_t* bmp180)
{
int res;
uint8_t buffer[2];
buffer[0] = BMP180_REG_CONTROL;
buffer[1] = BMP180_TEMPERATURE;
res = i2c_transmit(bmp180->i2c, I2C_ADDRESS, buffer, 2);
if (res != 0)
{
return 0;
}
os_delay_us(BMP180_CONVERSION_TIME_TEMERATURE);
return read16(bmp180, BMP180_REG_MSB);
}
int32_t ICACHE_FLASH_ATTR bmp180_read_pressure_raw(bmp180_t* bmp180, uint8_t oss)
{
int res;
int reg;
int delay;
uint8_t buffer[2];
switch (oss) {
case bmp180_pressure_sampling_accuracy_ultra_low_power:
reg = BMP180_PRESSURE_OSS0;
delay = BMP180_CONVERSION_TIME_PRESSURE_OSS0;
break;
case bmp180_pressure_sampling_accuracy_standard:
reg = BMP180_PRESSURE_OSS1;
delay = BMP180_CONVERSION_TIME_PRESSURE_OSS1;
break;
case bmp180_pressure_sampling_accuracy_high_resolution:
reg = BMP180_PRESSURE_OSS2;
delay = BMP180_CONVERSION_TIME_PRESSURE_OSS2;
break;
case bmp180_pressure_sampling_accuracy_ultra_high_resolution:
reg = BMP180_PRESSURE_OSS3;
delay = BMP180_CONVERSION_TIME_PRESSURE_OSS3;
break;
default:
return 0;
}
buffer[0] = BMP180_REG_CONTROL;
buffer[1] = reg;
res = i2c_transmit(bmp180->i2c, I2C_ADDRESS, buffer, 2);
if (res != 0)
{
return 0;
}
os_delay_us(delay);
return read24(bmp180, BMP180_REG_MSB) >> (8 - oss);
out:
return 0;
}
static int16_t ICACHE_FLASH_ATTR bmp180_read_temp(bmp180_t* bmp180)
{
uint16_t temp_raw;
int16_t temp;
int32_t x1;
int32_t x2;
if (!bmp180->initilized) {
return 0;
}
temp_raw = bmp180_read_temp_raw(bmp180);
x1 = (temp_raw - bmp180->ac6) * bmp180->ac5 / (2<<14);
x2 = bmp180->mc * (2<<10) / (x1 + bmp180->md);
bmp180->b5 = x1 + x2;
temp = (bmp180->b5 + 8) / (2<<3);
return temp;
}
static int32_t ICACHE_FLASH_ATTR bmp180_read_pressure(bmp180_t* bmp180)
{
int32_t pressure;
int32_t b6;
int32_t x1;
int32_t x2;
int32_t x3;
int32_t b3;
uint32_t b4;
uint32_t b7;
int32_t p;
uint8_t oss = bmp180->pressure_sampling_accuracy;
if (!bmp180->initilized) {
return 0;
}
pressure = bmp180_read_pressure_raw(bmp180, oss);
b6 = bmp180->b5 - 4000;
x1 = ((int32_t)bmp180->b2 * ((b6 * b6) >> 12)) >> 11;
x2 = ((int32_t)bmp180->ac2 * b6) >> 11;
x3 = x1 + x2;
b3 = (((((int32_t)bmp180->ac1 << 2) + x3) << oss) + 2) >> 2;
x1 = ((int32_t)bmp180->ac3 * b6) >> 13;
x2 = (int32_t)(bmp180->b1 * ((b6 * b6) >> 12)) >> 16;
x3 = (x1 + x2 + 2) >> 2;
b4 = ((uint32_t)bmp180->ac4 * ((uint32_t)(x3 + 32768)) >> 15);
b7 = (pressure - b3) * (50000 >> oss);
p = b7 < 0x80000000 ? (b7 << 1) / b4 : (b7 / b4) << 1;
x1 = (p >> 8) * (p >> 8);
x1 = (x1 * 3038) >> 16;
x2 = (-7357 * p) >> 16;
p = p + ((x1 + x2 + 3791) >> 4);
return p;
}
bool ICACHE_FLASH_ATTR bmp180_read(driver_params_t* params)
{
bmp180_t* bmp180 = &params->bmp180;
bmp180->temperature = bmp180_read_temp(bmp180);
bmp180->pressure = bmp180_read_pressure(bmp180);
return true;
}
bool ICACHE_FLASH_ATTR bmp180_print(driver_params_t* params, driver_print_data_t* print)
{
bmp180_t* bmp180 = &params->bmp180;
print->print_string(print->data, print->index, print->i, "driver", "bmp180");
print->print_value(print->data, print->index, print->i, "temp", &bmp180->temperature, sizeof(bmp180->temperature));
print->print_value(print->data, print->index, print->i, "pressure", &bmp180->pressure, sizeof(bmp180->pressure));
return true;
}
bool ICACHE_FLASH_ATTR bmp180_init(driver_params_t* params, driver_bus_t* bus)
{
bmp180_t* bmp180 = &params->bmp180;
i2c_t* i2c = &bus->params.i2c;
int res;
uint8_t id = 0;
uint8_t buffer[1];
bmp180->initilized = false;
bmp180->i2c = i2c;
buffer[1] = BMP180_REG_ID;
res = i2c_transmit(bmp180->i2c, I2C_ADDRESS, buffer, 1);
if (res != 0)
{
return false;
}
res = i2c_receive(bmp180->i2c, I2C_ADDRESS, &id, 1);
if (res != 0)
{
return false;
}
if (id != BMP180_ID) {
return false;
}
bmp180->ac1 = read16(bmp180, 0xAA);
bmp180->ac2 = read16(bmp180, 0xAC);
bmp180->ac3 = read16(bmp180, 0xAE);
bmp180->ac4 = read16(bmp180, 0xB0);
bmp180->ac5 = read16(bmp180, 0xB2);
bmp180->ac6 = read16(bmp180, 0xB4);
bmp180->b1 = read16(bmp180, 0xB6);
bmp180->b2 = read16(bmp180, 0xB8);
bmp180->mb = read16(bmp180, 0xBA);
bmp180->mc = read16(bmp180, 0xBC);
bmp180->md = read16(bmp180, 0xBE);
bmp180->initilized = true;
return true;
}
// Global variable with function pointers
const driver_sensor_t sensor_bmp180 = {
.init = bmp180_init,
.read = bmp180_read,
.print = bmp180_print,
};

+ 52
- 0
bmp180.h View File

@ -0,0 +1,52 @@
/*
"THE BEER/MATE-WARE LICENSE":
<xil@xil.se> wrote this file. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you think
this stuff is worth it, you can buy us a ( > 0 ) beer/mate in return - The Xil TEAM
*/
#ifndef BMP180_H
#define BMP180_H
#include <stdint.h>
#include <stdbool.h>
#include "drivers/i2c.h"
typedef enum {
bmp180_pressure_sampling_accuracy_ultra_low_power = 0,
bmp180_pressure_sampling_accuracy_standard = 1,
bmp180_pressure_sampling_accuracy_high_resolution = 2,
bmp180_pressure_sampling_accuracy_ultra_high_resolution = 3,
} bmp180_pressure_sampling_accuracy_t;
typedef struct {
// Configuration
bmp180_pressure_sampling_accuracy_t pressure_sampling_accuracy;
// Internal data
bool initilized;
// Calibration data
int16_t ac1;
int16_t ac2;
int16_t ac3;
uint16_t ac4;
uint16_t ac5;
uint16_t ac6;
int16_t b1;
int16_t b2;
int16_t mb;
int16_t mc;
int16_t md;
int32_t b5;
// Busses
i2c_t* i2c;
// Collected data
int16_t temperature;
int32_t pressure;
} bmp180_t;
#endif // BMP180_H

+ 286
- 0
bmp280.c View File

@ -0,0 +1,286 @@
/*
"THE BEER/MATE-WARE LICENSE":
<xil@xil.se> wrote this file. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you think
this stuff is worth it, you can buy us a ( > 0 ) beer/mate in return - The Xil TEAM
*/
#include <stdint.h>
#include <stdbool.h>
#include "drivers/i2c.h"
#include "drivers/bmp280.h"
#include "drivers/drivers.h"
#define I2C_ADDRESS(bmp280) \
(0x76 | (bmp280->sdo_high ? 1 : 0))
#define BMP280_REG_ID 0xD0
#define BMP280_REG_CTRL_MEAS 0xF4
#define BMP280_REG_STATUS 0xF3
#define BMP280_REG_TEMP_MSB 0xFA
#define BMP280_REG_TEMP_LSB 0xFB
#define BMP280_REG_TEMP_XLSB 0xFC
#define BMP280_REG_PRESS_MSB 0xF7
#define BMP280_REG_PRESS_LSB 0xF8
#define BMP280_REG_PRESS_XLSB 0xF9
#define BMP280_ID 0x58
#define BMP280_POWER_MODE_SLEEP 0x00
#define BMP280_POWER_MODE_FORCED 0x01
#define BMP280_POWER_MODE_NORMAL 0x11
static uint16_t ICACHE_FLASH_ATTR byteswap16(uint16_t u16)
{
uint8_t* u8;
u8 = (uint8_t*)&u16;
return (u8[0] << 8) | (u8[1] << 0);
}
static int32_t ICACHE_FLASH_ATTR read24_int(bmp280_t* bmp280, int reg, bool b24)
{
int res;
uint8_t val[3] = {0};
val[0] = reg;
res = i2c_transmit(bmp280->i2c, I2C_ADDRESS(bmp280), val, 1);
if (res != 0)
{
return 0;
}
if (b24)
{
res = i2c_receive(bmp280->i2c, I2C_ADDRESS(bmp280), val, 3);
}
else
{
res = i2c_receive(bmp280->i2c, I2C_ADDRESS(bmp280), val, 2);
}
if (res != 0)
{
return 0;
}
if (b24)
return (val[0] << 16) | (val[1] << 8) | val[2];
else
return (val[0] << 8) | val[1];
}
static int16_t ICACHE_FLASH_ATTR read16(bmp280_t* bmp280, int reg)
{
return read24_int(bmp280, reg, false);
}
static int32_t ICACHE_FLASH_ATTR read24(bmp280_t* bmp280, int reg)
{
return read24_int(bmp280, reg, true);
}
static int16_t ICACHE_FLASH_ATTR bmp280_read_temp(bmp280_t* bmp280)
{
int16_t temp;
int32_t temp_raw;
int32_t var1;
int32_t var2;
if (!bmp280->initilized) {
return 0;
}
// 20 bit precison, skip last 4
temp_raw = read24(bmp280, BMP280_REG_TEMP_MSB) >> 4;
var1 = ((((temp_raw >> 3) - ((int32_t)bmp280->dig_T1 << 1))) * ((int32_t)bmp280->dig_T2)) >> 11;
var2 = (((((temp_raw >> 4) - ((int32_t)bmp280->dig_T1)) * ((temp_raw >> 4) - ((int32_t)bmp280->dig_T1))) >> 12) * ((int32_t)bmp280->dig_T3)) >> 14;
bmp280->t_fine = var1 + var2;
// temp will be in 0.01C
temp = (bmp280->t_fine * 5 + 128) >> 8;
// return value in 0.1C
return temp / 10;
}
static int32_t ICACHE_FLASH_ATTR bmp280_read_pressure(bmp280_t* bmp280)
{
int64_t pressure;
int32_t pressure_raw;
int64_t var1;
int64_t var2;
// 20 bit precison, skip last 4
pressure_raw = read24(bmp280, BMP280_REG_PRESS_MSB) >> 4;
var1 = ((int64_t)bmp280->t_fine) - 128000;
var2 = var1 * var1 * (int64_t)bmp280->dig_P6;
var2 = var2 + ((var1 * (int64_t)bmp280->dig_P5) << 17);
var2 = var2 + (((int64_t)bmp280->dig_P4) << 35);
var1 = ((var1 * var1 * (int64_t)bmp280->dig_P3) >> 8) +
((var1 * (int64_t)bmp280->dig_P2) << 12);
var1 = ((((int64_t)1) << 47) + var1) * ((int64_t)bmp280->dig_P1) >> 33;
if (var1 == 0)
{
return 0;
}
pressure = 1048576 - pressure_raw;
pressure = (((pressure << 31) - var2) * 3125) / var1;
var1 = (((int64_t)bmp280->dig_P9) * (pressure >> 13) * (pressure >> 13)) >> 25;
var2 = (((int64_t)bmp280->dig_P8) * pressure) >> 19;
// pressure will be in Pa, fixed point 24.8
pressure = ((pressure + var1 + var2) >> 8) + (((int64_t)bmp280->dig_P7) << 4);
// return value in Pa
return (int32_t)(pressure >> 8);
}
static bool ICACHE_FLASH_ATTR bmp280_start_measure(bmp280_t* bmp280)
{
int res;
uint8_t value;
uint8_t status;
uint8_t buffer[2];
bool rc = false;
int counter = 100;
if (!bmp280->initilized) {
return false;
}
value = ((0x07 & (bmp280->temp_oversampling + 1)) << 5) |
((0x07 & (bmp280->pressure_oversampling + 1)) << 2) |
((0x03 & BMP280_POWER_MODE_FORCED) << 0);
buffer[0] = BMP280_REG_CTRL_MEAS;
buffer[1] = value;
res = i2c_transmit(bmp280->i2c, I2C_ADDRESS(bmp280), buffer, 2);
if (res != 0)
{
return false;
}
do {
I2C_DELAY_US(10);
buffer[0] = BMP280_REG_STATUS;
res = i2c_transmit(bmp280->i2c, I2C_ADDRESS(bmp280), buffer, 1);
if (res != 0)
{
return false;
}
res = i2c_receive(bmp280->i2c, I2C_ADDRESS(bmp280), &status, 1);
if (res != 0)
{
return false;
}
} while ((status & 0x09) != 0 && counter-- > 0);
if (counter > 0) {
rc = true;
}
return rc;
}
bool ICACHE_FLASH_ATTR bmp280_read(driver_params_t* params)
{
bmp280_t* bmp280 = &params->bmp280;
bool status;
status = bmp280_start_measure(bmp280);
if (status == true) {
bmp280->temperature = bmp280_read_temp(bmp280);
bmp280->pressure = bmp280_read_pressure(bmp280);
} else {
bmp280->temperature = 0;
bmp280->pressure = 0;
}
return true;
}
bool ICACHE_FLASH_ATTR bmp280_print(driver_params_t* params, driver_print_data_t* print)
{
bmp280_t* bmp280 = &params->bmp280;
print->print_string(print->data, print->index, print->i, "driver", "bmp280");
print->print_value(print->data, print->index, print->i, "temp", &bmp280->temperature, sizeof(bmp280->temperature));
print->print_value(print->data, print->index, print->i, "pressure", &bmp280->pressure, sizeof(bmp280->pressure));
return true;
}
bool ICACHE_FLASH_ATTR bmp280_init(driver_params_t* params, driver_bus_t* bus)
{
bmp280_t* bmp280 = &params->bmp280;
i2c_t* i2c = &bus->params.i2c;
int res;
uint8_t buffer[1];
uint8_t id = 0;
bmp280->i2c = i2c;
buffer[0] = BMP280_REG_ID;
res = i2c_transmit(bmp280->i2c, I2C_ADDRESS(bmp280), buffer, 1);
if (res != 0)
{
return false;
}
res = i2c_receive(bmp280->i2c, I2C_ADDRESS(bmp280), &id, 1);
if (res != 0)
{
return false;
}
if (id != BMP280_ID) {
return false;
}
// Registers are LSB/MSB
bmp280->dig_T1 = byteswap16(read16(bmp280, 0x88));
bmp280->dig_T2 = byteswap16(read16(bmp280, 0x8A));
bmp280->dig_T3 = byteswap16(read16(bmp280, 0x8C));
bmp280->dig_P1 = byteswap16(read16(bmp280, 0x8E));
bmp280->dig_P2 = byteswap16(read16(bmp280, 0x90));
bmp280->dig_P3 = byteswap16(read16(bmp280, 0x92));
bmp280->dig_P4 = byteswap16(read16(bmp280, 0x94));
bmp280->dig_P5 = byteswap16(read16(bmp280, 0x96));
bmp280->dig_P6 = byteswap16(read16(bmp280, 0x98));
bmp280->dig_P7 = byteswap16(read16(bmp280, 0x9A));
bmp280->dig_P8 = byteswap16(read16(bmp280, 0x9C));
bmp280->dig_P9 = byteswap16(read16(bmp280, 0x9E));
bmp280->initilized = true;
return true;
}
// Global variable with function pointers
const driver_sensor_t sensor_bmp280 = {
.init = bmp280_init,
.read = bmp280_read,
.print = bmp280_print,
};

+ 54
- 0
bmp280.h View File

@ -0,0 +1,54 @@
/*
"THE BEER/MATE-WARE LICENSE":
<xil@xil.se> wrote this file. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you think
this stuff is worth it, you can buy us a ( > 0 ) beer/mate in return - The Xil TEAM
*/
/*
* Connect CSB to VDD for i2c.
* SDO selects the address, low = 0x76, high = 0x77
*/
#ifndef BMP280_H
#define BMP280_H
#include <stdint.h>
#include <stdbool.h>
#include "drivers/i2c.h"
typedef struct {
// Configuration
bool sdo_high;
uint8_t temp_oversampling; // 2^temp_oversampling, max temp_oversampling is 5 (ei x16)
uint8_t pressure_oversampling; // 2^pressure_oversampling, max pressure_oversampling is 5 (ei x16)
// Internal data
bool initilized;
// calibration data
uint16_t dig_T1;
int16_t dig_T2;
int16_t dig_T3;
uint16_t dig_P1;
int16_t dig_P2;
int16_t dig_P3;
int16_t dig_P4;
int16_t dig_P5;
int16_t dig_P6;
int16_t dig_P7;
int16_t dig_P8;
int16_t dig_P9;
int32_t t_fine;
// busses
i2c_t* i2c;
// collected data
int16_t temperature;
int32_t pressure;
} bmp280_t;
#endif // BMP280_H

+ 87
- 0
drivers.h View File

@ -0,0 +1,87 @@
/*
"THE BEER/MATE-WARE LICENSE":
<xil@xil.se> wrote this file. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you think
this stuff is worth it, you can buy us a ( > 0 ) beer/mate in return - The Xil TEAM
*/
#ifndef DRIVERS_H
#define DRIVERS_H
#include <stdint.h>
#include <stdbool.h>
// Forward declare driver_bus for the drivers
typedef union driver_bus_params driver_bus_params_t;
typedef struct driver_bus driver_bus_t;
typedef union driver_params driver_params_t;
typedef struct driver driver_t;
typedef bool (*driver_print_value)(char* data, uint16_t* index, int i, const char* string, void* value, int size);
typedef bool (*driver_print_string)(char* data, uint16_t* index, int i, const char* string, const char* value);
typedef struct {
char* data;
uint16_t* index;
int i;
driver_print_value print_value;
driver_print_string print_string;
} driver_print_data_t;
typedef bool (*driver_bus_init)(driver_bus_params_t* params);
typedef bool (*driver_bus_print)(driver_bus_params_t* params, driver_print_data_t* data);
typedef bool (*driver_sensor_init)(driver_params_t* params, driver_bus_t* bus);
typedef bool (*driver_sensor_read)(driver_params_t* params);
typedef bool (*driver_sensor_print)(driver_params_t* params, driver_print_data_t* data);
typedef struct driver_bus_type {
const driver_bus_init init;
const driver_bus_print print;
} driver_bus_type_t;
typedef struct driver_sensor {
const driver_sensor_init init;
const driver_sensor_read read;
const driver_sensor_print print;
} driver_sensor_t;
#include "drivers/i2c.h"
#include "drivers/bmp180.h"
#include "drivers/bmp280.h"
#include "drivers/tsl2561.h"
// Global, constant variables for function pointers
// Busses
extern const driver_bus_type_t bus_i2c;
// Sensors
extern const driver_sensor_t sensor_bmp180;
extern const driver_sensor_t sensor_bmp280;
extern const driver_sensor_t sensor_tsl2561;
// Data buses
union driver_bus_params {
i2c_t i2c;
// spi_data spi;
};
struct driver_bus {
driver_bus_params_t params;
const driver_bus_type_t* bus;
};
// Sensor drivers
union driver_params {
bmp180_t bmp180;
bmp280_t bmp280;
tsl2561_t tsl2561;
};
struct driver {
driver_bus_t* bus;
driver_params_t params;
const driver_sensor_t* sensor;
};
#endif // DRIVERS_H

+ 58
- 0
i2c.h View File

@ -0,0 +1,58 @@
/*
"THE BEER/MATE-WARE LICENSE":
<xil@xil.se> wrote this file. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you think
this stuff is worth it, you can buy us a ( > 0 ) beer/mate in return - The Xil TEAM
*/
#ifndef I2C_H
#define I2C_H
#include <stdint.h>
#include <stdbool.h>
#if defined(TARGET_ESP8266)
#include "osapi.h"
#include "ets_sys.h"
#define I2C_DELAY_US(x) os_delay_us(x)
typedef struct {
// Configuration
uint8_t gpio_sda;
uint8_t gpio_scl;
// Internal data
uint8_t sda_last;
uint8_t scl_last;
} i2c_t;
#elif defined(TARGET_SMT32F0)
#include <stm32f0xx_hal.h>
#define I2C_DELAY_US(x) HAL_Delay(x)
typedef struct {
} i2c_t;
#elif defined(TARGET_RASPBERRY_PI)
#include <unistd.h>
#define I2C_DELAY_US(x) usleep(x)
typedef struct {
} i2c_t;
#else
#error "No target defined"
#endif
#ifndef ICACHE_FLASH_ATTR
#define ICACHE_FLASH_ATTR
#endif
/*
* address is 7 bit address
*/
int i2c_transmit(i2c_t* i2c, uint8_t address, uint8_t* data, uint8_t length);
int i2c_transmit_no_stop(i2c_t* i2c, uint8_t address, uint8_t* data, uint8_t length);
int i2c_receive(i2c_t* i2c, uint8_t address, uint8_t* data, uint8_t length);
#endif // I2C_H

+ 428
- 0
i2c_master.c View File

@ -0,0 +1,428 @@
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: i2c_master.c
*
* Description: i2c master API
*
* Modification history:
* 2014/3/12, v1.0 create this file.
*******************************************************************************/
#include "ets_sys.h"
#include "osapi.h"
#include "gpio.h"
#include "drivers/i2c.h"
#include "drivers/i2c_master.h"
#define I2C_MASTER_SDA_HIGH_SCL_HIGH(x) \
gpio_output_set(1<<(x->gpio_sda) | 1<<(x->gpio_scl), 0, 1<<(x->gpio_sda) | 1<<(x->gpio_scl), 0)
#define I2C_MASTER_SDA_HIGH_SCL_LOW(x) \
gpio_output_set(1<<(x->gpio_sda), 1<<(x->gpio_scl), 1<<(x->gpio_sda) | 1<<(x->gpio_scl), 0)
#define I2C_MASTER_SDA_LOW_SCL_HIGH(x) \
gpio_output_set(1<<(x->gpio_scl), 1<<(x->gpio_sda), 1<<(x->gpio_sda) | 1<<(x->gpio_scl), 0)
#define I2C_MASTER_SDA_LOW_SCL_LOW(x) \
gpio_output_set(0, 1<<(x->gpio_sda) | 1<<(x->gpio_scl), 1<<(x->gpio_sda) | 1<<(x->gpio_scl), 0)
static uint32_t ICACHE_FLASH_ATTR i2c_master_getGpioMux(uint8_t gpio)
{
switch (gpio) {
case 0: return PERIPHS_IO_MUX_GPIO0_U;
case 1: return PERIPHS_IO_MUX_U0TXD_U;
case 2: return PERIPHS_IO_MUX_GPIO2_U;
case 3: return PERIPHS_IO_MUX_U0RXD_U;
case 4: return PERIPHS_IO_MUX_GPIO4_U;
case 5: return PERIPHS_IO_MUX_GPIO5_U;
// case 6: return PERIPHS_IO_MUX_SD_CLK_U;
// case 7: return PERIPHS_IO_MUX_SD_DATA0_U;
// case 8: return PERIPHS_IO_MUX_SD_DATA1_U;
// case 9: return PERIPHS_IO_MUX_SD_DATA2_U;
// case 10: return PERIPHS_IO_MUX_SD_DATA3_U;
// case 11: return PERIPHS_IO_MUX_SD_CMD_U;
case 12: return PERIPHS_IO_MUX_MTDI_U;
case 13: return PERIPHS_IO_MUX_MTCK_U;
case 14: return PERIPHS_IO_MUX_MTMS_U;
case 15: return PERIPHS_IO_MUX_MTDO_U;
// case 16: return PERIPHS_IO_MUX_XPD_DCDC;
default: return 0x0;
}
}
static uint32_t ICACHE_FLASH_ATTR i2c_master_getGpioFunc(uint8_t gpio)
{
switch (gpio) {
// CLKOUT
case 0: return FUNC_GPIO0;
// UART0 TX
case 1: return FUNC_GPIO1;
case 2: return FUNC_GPIO2;
// UART0 RX
case 3: return FUNC_GPIO3;
case 4: return FUNC_GPIO4;
case 5: return FUNC_GPIO5;
// Typically used to interface flash memory IC on most esp8266 modules
// case 6: return FUNC_GPIO6;
// case 7: return FUNC_GPIO7;
// case 8: return FUNC_GPIO8;
// case 9: return FUNC_GPIO9;
// case 10: return FUNC_GPIO10;
// case 11: return FUNC_GPIO11;
// SPI MISO
case 12: return FUNC_GPIO12;
// SPI MOSI
case 13: return FUNC_GPIO13;
// SPI CLK
case 14: return FUNC_GPIO14;
// SPI CS
case 15: return FUNC_GPIO15;
// Not available as gpio
case 16:
default: return 0x0;
}
}
/******************************************************************************
* FunctionName : i2c_master_setDC
* Description : Internal used function -
* set i2c SDA and SCL bit value for half clk cycle
* Parameters : uint8_t SDA
* uint8_t SCL
* Returns : NONE
*******************************************************************************/
static void ICACHE_FLASH_ATTR
i2c_master_setDC(i2c_t* i2c, uint8_t SDA, uint8_t SCL)
{
SDA &= 0x01;
SCL &= 0x01;
i2c->sda_last = SDA;
i2c->scl_last = SCL;
if ((0 == SDA) && (0 == SCL)) {
I2C_MASTER_SDA_LOW_SCL_LOW(i2c);
} else if ((0 == SDA) && (1 == SCL)) {
I2C_MASTER_SDA_LOW_SCL_HIGH(i2c);
} else if ((1 == SDA) && (0 == SCL)) {
I2C_MASTER_SDA_HIGH_SCL_LOW(i2c);
} else {
I2C_MASTER_SDA_HIGH_SCL_HIGH(i2c);
}
}
/******************************************************************************
* FunctionName : i2c_master_getDC
* Description : Internal used function -
* get i2c SDA bit value
* Parameters : NONE
* Returns : uint8_t - SDA bit value
*******************************************************************************/
static uint8_t ICACHE_FLASH_ATTR
i2c_master_getDC(i2c_t* i2c)
{
uint8_t sda_out;
sda_out = GPIO_INPUT_GET(GPIO_ID_PIN(i2c->gpio_sda));
return sda_out;
}
/******************************************************************************
* FunctionName : i2c_master_init_internal
* Description : initilize I2C bus to enable i2c operations
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
static void ICACHE_FLASH_ATTR
i2c_master_init_internal(i2c_t* i2c)
{
uint8_t i;
i2c_master_setDC(i2c, 1, 0);
i2c_master_wait(5);
// when SCL = 0, toggle SDA to clear up
i2c_master_setDC(i2c, 0, 0) ;
i2c_master_wait(5);
i2c_master_setDC(i2c, 1, 0) ;
i2c_master_wait(5);
// set data_cnt to max value
for (i = 0; i < 28; i++) {
i2c_master_setDC(i2c, 1, 0);
i2c_master_wait(5); // sda 1, scl 0
i2c_master_setDC(i2c, 1, 1);
i2c_master_wait(5); // sda 1, scl 1
}
// reset all
i2c_master_stop(i2c);
return;
}
/******************************************************************************
* FunctionName : i2c_master_gpio_init
* Description : config SDA and SCL gpio to open-drain output mode,
* mux and gpio num defined in i2c_master.h
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
static void ICACHE_FLASH_ATTR
i2c_master_gpio_init(i2c_t* i2c, uint8_t sda, uint8_t scl)
{
i2c->gpio_sda = sda;
i2c->gpio_scl = scl;
ETS_GPIO_INTR_DISABLE() ;
// ETS_INTR_LOCK();
PIN_FUNC_SELECT(i2c_master_getGpioMux(i2c->gpio_sda),
i2c_master_getGpioFunc(i2c->gpio_sda));
PIN_FUNC_SELECT(i2c_master_getGpioMux(i2c->gpio_scl),
i2c_master_getGpioFunc(i2c->gpio_scl));
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(i2c->gpio_sda)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(i2c->gpio_sda))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain;
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << i2c->gpio_sda));
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(i2c->gpio_scl)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(i2c->gpio_scl))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain;
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << i2c->gpio_scl));
I2C_MASTER_SDA_HIGH_SCL_HIGH(i2c);
ETS_GPIO_INTR_ENABLE() ;
// ETS_INTR_UNLOCK();
i2c_master_init_internal(i2c);
}
/******************************************************************************
* FunctionName : i2c_master_init
* Description : initialize i2c and gpios
* Parameters : params
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_init(driver_bus_params_t* params)
{
i2c_t* i2c = &params->i2c;
i2c_master_gpio_init(i2c, i2c->gpio_sda, i2c->gpio_scl);
}
/******************************************************************************
* FunctionName : i2c_master_print
* Description : print data with specified function
* Parameters :
* Returns : NONE
*******************************************************************************/
bool ICACHE_FLASH_ATTR
i2c_master_print(driver_bus_params_t* params, driver_print_data_t* print)
{
i2c_t* i2c = &params->i2c;
print->print_string(print->data, print->index, print->i, "bus", "i2c");
print->print_value(print->data, print->index, print->i, "sda", &i2c->gpio_sda, sizeof(i2c->gpio_sda));
print->print_value(print->data, print->index, print->i, "scl", &i2c->gpio_scl, sizeof(i2c->gpio_scl));
return true;
}
/******************************************************************************
* FunctionName : i2c_master_start
* Description : set i2c to send state
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_start(i2c_t* i2c)
{
i2c_master_setDC(i2c, 1, i2c->scl_last);
i2c_master_wait(5);
i2c_master_setDC(i2c, 1, 1);
i2c_master_wait(5); // sda 1, scl 1
i2c_master_setDC(i2c, 0, 1);
i2c_master_wait(5); // sda 0, scl 1
}
/******************************************************************************
* FunctionName : i2c_master_stop
* Description : set i2c to stop sending state
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_stop(i2c_t* i2c)
{
i2c_master_wait(5);
i2c_master_setDC(i2c, 0, i2c->scl_last);
i2c_master_wait(5); // sda 0
i2c_master_setDC(i2c, 0, 1);
i2c_master_wait(5); // sda 0, scl 1
i2c_master_setDC(i2c, 1, 1);
i2c_master_wait(5); // sda 1, scl 1
}
/******************************************************************************
* FunctionName : i2c_master_setAck
* Description : set ack to i2c bus as level value
* Parameters : uint8_t level - 0 or 1
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_setAck(i2c_t* i2c, uint8_t level)
{
i2c_master_setDC(i2c, i2c->sda_last, 0);
i2c_master_wait(5);
i2c_master_setDC(i2c, level, 0);
i2c_master_wait(5); // sda level, scl 0
i2c_master_setDC(i2c, level, 1);
i2c_master_wait(8); // sda level, scl 1
i2c_master_setDC(i2c, level, 0);
i2c_master_wait(5); // sda level, scl 0
i2c_master_setDC(i2c, 1, 0);
i2c_master_wait(5);
}
/******************************************************************************
* FunctionName : i2c_master_getAck
* Description : confirm if peer send ack
* Parameters : NONE
* Returns : uint8_t - ack value, 0 or 1
*******************************************************************************/
uint8_t ICACHE_FLASH_ATTR
i2c_master_getAck(i2c_t* i2c)
{
uint8_t retVal;
i2c_master_setDC(i2c, i2c->sda_last, 0);
i2c_master_wait(5);
i2c_master_setDC(i2c, 1, 0);
i2c_master_wait(5);
i2c_master_setDC(i2c, 1, 1);
i2c_master_wait(5);
retVal = i2c_master_getDC(i2c);
i2c_master_wait(5);
i2c_master_setDC(i2c, 1, 0);
i2c_master_wait(5);
return retVal;
}
/******************************************************************************
* FunctionName : i2c_master_checkAck
* Description : get dev response
* Parameters : NONE
* Returns : true : get ack ; false : get nack
*******************************************************************************/
bool ICACHE_FLASH_ATTR
i2c_master_checkAck(i2c_t* i2c)
{
if(i2c_master_getAck(i2c)){
return FALSE;
}else{
return TRUE;
}
}
/******************************************************************************
* FunctionName : i2c_master_send_ack
* Description : response ack
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_send_ack(i2c_t* i2c)
{
i2c_master_setAck(i2c, 0x0);
}
/******************************************************************************
* FunctionName : i2c_master_send_nack
* Description : response nack
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_send_nack(i2c_t* i2c)
{
i2c_master_setAck(i2c, 0x1);
}
/******************************************************************************
* FunctionName : i2c_master_readByte
* Description : read Byte from i2c bus
* Parameters : NONE
* Returns : uint8_t - readed value
*******************************************************************************/
uint8_t ICACHE_FLASH_ATTR
i2c_master_readByte(i2c_t* i2c)
{
uint8_t retVal = 0;
uint8_t k, i;
i2c_master_wait(5);
i2c_master_setDC(i2c, i2c->sda_last, 0);
i2c_master_wait(5); // sda 1, scl 0
for (i = 0; i < 8; i++) {
i2c_master_wait(5);
i2c_master_setDC(i2c, 1, 0);
i2c_master_wait(5); // sda 1, scl 0
i2c_master_setDC(i2c, 1, 1);
i2c_master_wait(5); // sda 1, scl 1
k = i2c_master_getDC(i2c);
i2c_master_wait(5);
if (i == 7) {
i2c_master_wait(3); ////
}
k <<= (7 - i);
retVal |= k;
}
i2c_master_setDC(i2c, 1, 0);
i2c_master_wait(5); // sda 1, scl 0
return retVal;
}
/******************************************************************************
* FunctionName : i2c_master_writeByte
* Description : write wrdata value(one byte) into i2c
* Parameters : uint8_t wrdata - write value
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_writeByte(i2c_t* i2c, uint8_t wrdata)
{
uint8_t dat;
int8_t i;
i2c_master_wait(5);
i2c_master_setDC(i2c, i2c->sda_last, 0);
i2c_master_wait(5);
for (i = 7; i >= 0; i--) {
dat = wrdata >> i;
i2c_master_setDC(i2c, dat, 0);
i2c_master_wait(5);
i2c_master_setDC(i2c, dat, 1);
i2c_master_wait(5);
if (i == 0) {
i2c_master_wait(3); ////
}
i2c_master_setDC(i2c, dat, 0);
i2c_master_wait(5);
}
}
// Global variable with function pointers
const driver_bus_type_t const bus_i2c = {
.init = i2c_master_init,
.print = i2c_master_print,
};

+ 22
- 0
i2c_master.h View File

@ -0,0 +1,22 @@
#ifndef __I2C_MASTER_H__
#define __I2C_MASTER_H__
#include <stdbool.h>
// Global structs
#include "drivers/drivers.h"
#define i2c_master_wait os_delay_us
void i2c_master_stop(i2c_t* i2c);
void i2c_master_start(i2c_t* i2c);
void i2c_master_setAck(i2c_t* i2c, uint8_t level);
uint8_t i2c_master_getAck(i2c_t* i2c);
uint8_t i2c_master_readByte(i2c_t* i2c);
void i2c_master_writeByte(i2c_t* i2c, uint8_t wrdata);
bool i2c_master_checkAck(i2c_t* i2c);
void i2c_master_send_ack(i2c_t* i2c);
void i2c_master_send_nack(i2c_t* i2c);
#endif

+ 147
- 0
tsl2561.c View File

@ -0,0 +1,147 @@
/*
"THE BEER/MATE-WARE LICENSE":
<xil@xil.se> wrote this file. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you think
this stuff is worth it, you can buy us a ( > 0 ) beer/mate in return - The Xil TEAM
*/
#include <stdint.h>
#include <stdbool.h>
#include "drivers/i2c.h"
#include "drivers/tsl2561.h"
#include "drivers/drivers.h"
#define I2C_ADDRESS(tsl2561) i2c_address(tsl2561)
#define TSL2561_REG_ID 0xA
#define TSL2561_ID 0x10
static i2c_address(tsl2561_t* tsl2561)
{
uint8_t addr = 0x29;
switch (tsl2561->addr_select)
{
case tsl2561_address_select_high:
addr += 0x10;
case tsl2561_address_select_float:
addr += 0x10;
case tsl2561_address_select_low:
break;
}
return addr;
}
static uint16_t ICACHE_FLASH_ATTR byteswap16(uint16_t u16)
{
uint8_t* u8;
u8 = (uint8_t*)&u16;
return (u8[0] << 8) | (u8[1] << 0);
}
static int16_t ICACHE_FLASH_ATTR tsl2651_read(tsl2561_t* tsl2561)
{
if (!tsl2561->initilized) {
return 0;
}
return 0;
}
bool ICACHE_FLASH_ATTR tsl2561_init(driver_params_t* params, driver_bus_t* bus);
bool ICACHE_FLASH_ATTR tsl2561_read(driver_params_t* params)
{
tsl2561_t* tsl2561 = &params->tsl2561;
tsl2561_init(params, NULL);
return true;
}
bool ICACHE_FLASH_ATTR tsl2561_print(driver_params_t* params, driver_print_data_t* print)
{
tsl2561_t* tsl2561 = &params->tsl2561;
print->print_string(print->data, print->index, print->i, "driver", "tsl2561");
print->print_value(print->data, print->index, print->i, "id", &tsl2561->id, sizeof(tsl2561->id));
print->print_value(print->data, print->index, print->i, "inits", &tsl2561->inits, sizeof(tsl2561->inits));
return true;
}
bool ICACHE_FLASH_ATTR tsl2561_init(driver_params_t* params, driver_bus_t* bus)
{
tsl2561_t* tsl2561 = &params->tsl2561;
#if 0 // temp
i2c_t* i2c = &bus->params.i2c;
#endif
int res;
uint8_t id;
uint8_t buffer[1];
uint8_t command;
tsl2561->inits++;
#if 0 // temp
#else
i2c_t* i2c;
if (bus != NULL)
{
i2c = &bus->params.i2c;
}
else
{
i2c = tsl2561->i2c;
}
#endif
tsl2561->i2c = i2c;
command = 0;
command |= (1 << 7);
command |= (TSL2561_REG_ID << 0);
buffer[0] = command;
res = i2c_transmit(tsl2561->i2c, I2C_ADDRESS(tsl2561), buffer, 1);
if (res != 0)
{
return false;
}
res = i2c_receive(tsl2561->i2c, I2C_ADDRESS(tsl2561), &id, 1);
if (res != 0)
{
return false;
}
tsl2561->id = id;
tsl2561->id = 0x11;
if (id & 0xf0!= TSL2561_ID) {
tsl2561->id = 0x34;
return false;
}
tsl2561->initilized = true;
tsl2561->id = 0x35;
return true;
}
// Global variable with function pointers
const driver_sensor_t sensor_tsl2561 = {
.init = tsl2561_init,
.read = tsl2561_read,
.print = tsl2561_print,
};

+ 40
- 0
tsl2561.h View File

@ -0,0 +1,40 @@
/*
"THE BEER/MATE-WARE LICENSE":
<xil@xil.se> wrote this file. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you think
this stuff is worth it, you can buy us a ( > 0 ) beer/mate in return - The Xil TEAM
*/
#ifndef TSL2561_H
#define TSL2561_H
#include <stdint.h>
#include <stdbool.h>
#include "drivers/i2c.h"
typedef enum {
tsl2561_address_select_low,
tsl2561_address_select_float,
tsl2561_address_select_high,
} tsl2561_address_select_t;
typedef struct {
// Configuration
tsl2561_address_select_t addr_select;
// Internal data
bool initilized;
// calibration data
// busses
i2c_t* i2c;
// collected data
int32_t light;
uint8_t id;
uint8_t inits;
} tsl2561_t;
#endif // TSL2561_H

+ 168
- 0
ws2801.c View File

@ -0,0 +1,168 @@
/*
"THE BEER/MATE-WARE LICENSE":
<xil@xil.se> wrote this file. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you think
this stuff is worth it, you can buy us a ( > 0 ) beer/mate in return - The Xil TEAM
*/
#include <stdint.h>
#include "ets_sys.h"
#include "osapi.h"
#include "gpio.h"
#include "drivers/ws2801.h"
static uint32_t ICACHE_FLASH_ATTR gpio_mux(uint8_t gpio)
{
switch (gpio) {
case 0: return PERIPHS_IO_MUX_GPIO0_U;
case 1: return PERIPHS_IO_MUX_U0TXD_U;
case 2: return PERIPHS_IO_MUX_GPIO2_U;
case 3: return PERIPHS_IO_MUX_U0RXD_U;
case 4: return PERIPHS_IO_MUX_GPIO4_U;
case 5: return PERIPHS_IO_MUX_GPIO5_U;
// case 6: return PERIPHS_IO_MUX_SD_CLK_U;
// case 7: return PERIPHS_IO_MUX_SD_DATA0_U;
// case 8: return PERIPHS_IO_MUX_SD_DATA1_U;
// case 9: return PERIPHS_IO_MUX_SD_DATA2_U;
// case 10: return PERIPHS_IO_MUX_SD_DATA3_U;
// case 11: return PERIPHS_IO_MUX_SD_CMD_U;
case 12: return PERIPHS_IO_MUX_MTDI_U;
case 13: return PERIPHS_IO_MUX_MTCK_U;
case 14: return PERIPHS_IO_MUX_MTMS_U;
case 15: return PERIPHS_IO_MUX_MTDO_U;
// case 16: return PERIPHS_IO_MUX_XPD_DCDC;
default: return 0x0;
}
}
static uint32_t ICACHE_FLASH_ATTR gpio_func(uint8_t gpio)
{
switch (gpio) {
// CLKOUT
case 0: return FUNC_GPIO0;
// UART0 TX
case 1: return FUNC_GPIO1;
case 2: return FUNC_GPIO2;
// UART0 RX
case 3: return FUNC_GPIO3;
case 4: return FUNC_GPIO4;
case 5: return FUNC_GPIO5;
// Typically used to interface flash memory IC on most esp8266 modules
// case 6: return FUNC_GPIO6;
// case 7: return FUNC_GPIO7;
// case 8: return FUNC_GPIO8;
// case 9: return FUNC_GPIO9;
// case 10: return FUNC_GPIO10;
// case 11: return FUNC_GPIO11;
// SPI MISO
case 12: return FUNC_GPIO12;
// SPI MOSI
case 13: return FUNC_GPIO13;
// SPI CLK
case 14: return FUNC_GPIO14;
// SPI CS
case 15: return FUNC_GPIO15;
// Not available as gpio
case 16:
default: return 0x0;
}
}
static void ICACHE_FLASH_ATTR write_clock(int pin)
{
GPIO_OUTPUT_SET(pin, 1);
os_delay_us(10);
GPIO_OUTPUT_SET(pin, 0);
}
static void ICACHE_FLASH_ATTR write_bit(ws2801_color_t* led, uint32_t bit, uint32_t pin)
{
int data;
data = led->c.c & (1<<(3*8-1-bit));
if (data == 0) {
GPIO_OUTPUT_SET(pin, 0);
} else {
GPIO_OUTPUT_SET(pin, 1);
}
}
bool ICACHE_FLASH_ATTR ws2801_write(ws2801_data_t* ws2801)
{
int chain;
int leds_max = 0;
int led;
for (chain = 0; chain < ws2801->chains; chain++) {
if (leds_max < ws2801->chain[chain].leds) {
leds_max = ws2801->chain[chain].leds;
}
}
for (led = 0; led < leds_max; led++) {
uint32_t bit;
for (bit = 0; bit < 3*8; bit++) {
for (chain = 0; chain < ws2801->chains; chain++) {
if (ws2801->chain[chain].leds >= led) {
write_bit(&ws2801->chain[chain].led[led], bit, ws2801->chain[chain].pin_data);
}
}
for (chain = 0; chain < ws2801->chains; chain++) {
if (chain == 0) {
write_clock(ws2801->chain[chain].pin_clock);
#if 0
} else {
int c;
bool written = false;
for (c = chain-1; c >= 0; c--) {
if (ws2801->chain[chain].pin_clock ==
ws2801->chain[c].pin_clock)
{
written = true;
}
}
if (!written) {
write_clock(ws2801->chain[chain].pin_clock);
}
#endif
}
}
}
}
return true;
}
bool ICACHE_FLASH_ATTR ws2801_init(ws2801_data_t* ws2801)
{
int i;
ETS_GPIO_INTR_DISABLE();
for (i = 0; i < ws2801->chains; i++) {
int pin_clock = ws2801->chain[i].pin_clock;
int pin_data = ws2801->chain[i].pin_data;
PIN_FUNC_SELECT(gpio_mux(pin_clock),
gpio_func(pin_clock));