diff --git a/ExampleHTM/dygraph/ws_test_mlx90614.html b/ExampleHTM/dygraph/ws_test_mlx90614.html
new file mode 100644
index 0000000..9d477e1
--- /dev/null
+++ b/ExampleHTM/dygraph/ws_test_mlx90614.html
@@ -0,0 +1,67 @@
+
+
+
+
+ Get data MLX90614
+
+
+
+
+ Read regs Ta & Tobj1 MLX90614
+
+
+
+
diff --git a/project.mk b/project.mk
index e87d6d8..edc0215 100644
--- a/project.mk
+++ b/project.mk
@@ -1,7 +1,8 @@
#=============================================
# SDK CONFIG
#=============================================
-WEB_INA219_DRV = 1
+#WEB_INA219_DRV = 1
+WEB_MLX90614_DRV = 1
#WEB_ADC_DRV = 1
#USE_SDCARD = 1
#USE_UVC = 1
@@ -62,6 +63,13 @@ ADD_SRC_C += project/src/ina219/ina219drv.c
CFLAGS += -DWEB_INA219_DRV=1
endif
+ifdef WEB_MLX90614_DRV
+ADD_SRC_C += project/src/driver/i2c_drv.c
+CFLAGS += -DUSE_I2C_CONSOLE=1
+ADD_SRC_C += project/src/MLX90614/MLX90614.c
+CFLAGS += -DWEB_MLX90614_DRV=1
+endif
+
ifdef WEB_ADC_DRV
ADD_SRC_C += project/src/driver/adc_drv.c
ADD_SRC_C += project/src/adc_ws/adc_ws.c
diff --git a/project/src/MLX90614/MLX90614.c b/project/src/MLX90614/MLX90614.c
new file mode 100644
index 0000000..554d902
--- /dev/null
+++ b/project/src/MLX90614/MLX90614.c
@@ -0,0 +1,421 @@
+/*
+ * MLX90614drv.c
+ *
+ * Created on: 02/09/2017
+ * Author: pvvx
+ */
+#include
+#include "rtl8195a.h"
+#include "device.h"
+#include "PinNames.h"
+
+#include "basic_types.h"
+#include "diag.h"
+#include "osdep_api.h"
+#include "timer_api.h"
+
+//#include "i2c_api.h"
+//#include "i2c_ex_api.h"
+#include "pinmap.h"
+#include "rtl_lib.h"
+#include "rtl8195a/rtl_libc.h"
+#include "driver/i2c_drv.h"
+#include "platform_stdlib.h"
+#include "web_websocket.h"
+#include "tcpsrv/tcp_srv_conn.h"
+
+#include "hal_com_reg.h"
+
+#define MLX90614_I2CADDR 0x5A
+// RAM
+#define MLX90614_RAWIR1 0x04
+#define MLX90614_RAWIR2 0x05
+#define MLX90614_TA 0x06
+#define MLX90614_TOBJ1 0x07
+#define MLX90614_TOBJ2 0x08
+// EEPROM
+#define MLX90614_TOMAX 0x20
+#define MLX90614_TOMIN 0x21
+#define MLX90614_PWMCTRL 0x22
+#define MLX90614_TARANGE 0x23
+#define MLX90614_EMISS 0x24
+#define MLX90614_CONFIG 0x25
+#define MLX90614_ADDR 0x0E
+#define MLX90614_ID1 0x3C
+#define MLX90614_ID2 0x3D
+#define MLX90614_ID3 0x3E
+#define MLX90614_ID4 0x3F
+#define MLX90614_SLEEP 0xFF
+
+typedef struct _MLX90614_data {
+ union {
+ signed short to1; // Tobj1
+ unsigned char uc[2];
+ } o;
+ union {
+ signed short ta; // Ta
+ unsigned char uc[2];
+ } a;
+} MLX90614DATA, *PMLX90614DATA;
+
+typedef struct _MLX90614drv {
+ unsigned char status;
+ unsigned char addr; // адрес MLX90614 на шине I2C (формат 7 bit)
+ signed char init;
+ unsigned char tmp;
+
+ unsigned short config; // регистр конфигурации MLX90614
+ unsigned short timetik; // время опроса таймером (в us)
+
+ unsigned short count; // счетчик считанных значений
+ unsigned short overrun; // счет переполнений буфера
+
+ unsigned short errs; // счет ошибок на I2C
+ unsigned short buf_idx; // объем буфера pbuf[buf_idx+1], максимальный индекс-номер замера
+ unsigned short buf_rx; // индекс-номер ещё не считанного замера
+ unsigned short buf_tx; // индекс-номер для записи следующего замера
+ PMLX90614DATA pbuf;
+ gtimer_t timer;
+ union { // буфер
+ unsigned char uc[4];
+ unsigned short us[2];
+ signed short ss[2];
+ unsigned int ui;
+ } buf_i2c;
+ i2c_drv_t i2c;
+} MLX90614DRV, *PMLX90614DRV;
+
+
+#define MLX90614_I2C_PIN_SDA PC_4
+#define MLX90614_I2C_PIN_SCL PC_5
+#define MLX90614_I2C_BUS_CLK 50000 // The maximum frequency of the MLX90614 SMBus is 100 KHz and the minimum is 10 KHz.
+#define MLX90614_TIMER TIMER3 // используемый таймер
+
+//#define ReadTSF_Lo32() (*((volatile unsigned int *)(WIFI_REG_BASE + REG_TSFTR)))
+//#define ReadTSF_Hi32() (*((volatile unsigned int *)(WIFI_REG_BASE + REG_TSFTR1)))
+
+MLX90614DRV mlx90614drv = {
+ .addr = MLX90614_I2CADDR,
+ .timetik = 10000, // Время опроса таймером: 10000 us
+ .buf_idx = 709, // циклический буфер на 710 замеров (по 4 байт -> sizeof(MLX90614DATA))
+ // Если шаг заполнения 1 ms -> буфер на 0.71 сек
+ // Оптимизация под TCP: (TCP_MSS*2 - 80)/4 = (1460*2 - 80)/4 = 710
+ .i2c.status = DRV_I2C_OFF,
+ .i2c.idx = 1, // I2C1
+ .i2c.io_sel = S0, // PC_4, PC_5
+ .i2c.mode = DRV_I2C_SS_MODE // DRV_I2C_FS_MODE // DRV_I2C_HS_MODE
+};
+/*
+void mlx90614_write(unsigned char reg, unsigned short data)
+{
+ PMLX90614DRV p = &mlx90614drv;
+ p->buf_i2c.uc[0] = reg;
+ p->buf_i2c.uc[1] = (unsigned char)((unsigned short)(data >> 8));
+ p->buf_i2c.uc[2] = (unsigned char)data;
+ _i2c_write(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 3, 1);
+ UBaseType_t f;
+ portBASE_TYPE d;
+}
+
+unsigned int mlx90614_read(unsigned char reg)
+{
+ PMLX90614DRV p = &mlx90614drv;
+ p->buf_i2c.uc[0] = reg;
+ _i2c_write(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 1, 1);
+ p->buf_i2c.ui = 0;
+ _i2c_read(&p->i2c, p->addr, (const char *)p->buf_i2c.uc, 2, 1);
+ return (p->buf_i2c.uc[0] << 8) | p->buf_i2c.uc[1];
+}
+*/
+
+#define i2c_reg(r) *((volatile uint32 *)(pi2c->base_regs + r))
+
+/* Пример непрерывного чтения регистров Tobj1 и Tobj2
+ * MLX90614 по прерыванию таймера */
+void mlx_tick_handler(void *par) {
+ PMLX90614DRV p = &mlx90614drv;
+ i2c_drv_t *pi2c = &p->i2c;
+ switch(p->status) {
+ default:
+ // Disable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = 0;
+ p->status = 1;
+ break;
+ case 1:
+ // Master Target Address
+ i2c_reg(REG_DW_I2C_IC_TAR) = p->addr;
+ // Enable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE;
+ p->status = 3; // = 2;
+ break;
+ case 2:
+ // Заполним FIFO ic I2C командами инициализации MLX90614 ?
+/*
+ // Заполним FIFO ic I2C командами чтения RAW данных
+ // Write Command.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = MLX90614_RAWIR1 | BIT_IC_DATA_CMD_RESTART;
+ // Read command & data (3 bytes).
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
+ // Write Command.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = MLX90614_RAWIR2 | BIT_IC_DATA_CMD_RESTART;
+ // Read command & data (3 bytes).
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP; // | BIT_IC_DATA_CMD_RESTART
+*/
+ p->status = 3;
+ break;
+ case 4:
+ if (i2c_reg(REG_DW_I2C_IC_RAW_INTR_STAT) & BIT_IC_RAW_INTR_STAT_TX_ABRT) {
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_CLR_INTR);
+ p->errs++;
+ p->status = 0;
+ break;
+ } else {
+ if(p->pbuf) {
+ PMLX90614DATA pd = p->pbuf + p->buf_tx;
+ // Считаем готовые значения из FIFO ic I2C
+ pd->o.uc[0] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ pd->o.uc[1] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ pd->a.uc[0] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ pd->a.uc[1] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ if(p->buf_tx >= p->buf_idx) p->buf_tx = 0;
+ else p->buf_tx++;
+ if(p->buf_rx == p->buf_tx) {
+ p->overrun++; // todo: if(p->overrun++ > 100000) deinit() ?
+ if(p->buf_rx >= p->buf_idx) p->buf_rx = 0;
+ else p->buf_rx++;
+ };
+ } else {
+ // удаление из FIFO 6-ти байт данных
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ (volatile uint32)i2c_reg(REG_DW_I2C_IC_DATA_CMD);
+ };
+ }
+ case 3:
+ // Заполним FIFO ic I2C командами чтения
+ // Write Command.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = MLX90614_TOBJ1; // | BIT_IC_DATA_CMD_RESTART;
+ // Read command & data (3 bytes).
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_RESTART;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
+ // Write Command.
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = MLX90614_TA; // | BIT_IC_DATA_CMD_RESTART;
+ // Read command & data (3 bytes).
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_RESTART;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP; // | BIT_IC_DATA_CMD_RESTART
+ p->status = 4;
+ break;
+ }
+}
+
+uint16 mlx90614_chkdata(uint16 cnt)
+{
+ PMLX90614DRV p = &mlx90614drv;
+ if(p->init <= 0) return 0;
+ int len = p->buf_tx - p->buf_rx;
+ if(len < 0) len += p->buf_idx + 1;
+ if(cnt > (uint16)len) cnt = (uint16)len;
+ return cnt;
+}
+
+size_t mlx90614_getdata(void *pd, uint16 cnt)
+{
+ PMLX90614DRV p = &mlx90614drv;
+ if(p->init <= 0) return 0;
+// cnt = mlx90614_chkdata(cnt);
+ unsigned short *pus = (unsigned short *) pd;
+ taskDISABLE_INTERRUPTS();
+ uint16 buf_rx = p->buf_rx;
+ *pus++ = cnt; // кол-во замеров
+ *pus++ = p->count + p->overrun; // индекс замера для анализа пропусков на стороне приемника
+ // если не пропущено, то равен прошлому + кол-во считанных замеров в прошлом блоке
+ p->count += cnt; // p->overrun = 0;
+ unsigned char *puc = (unsigned char *) pus;
+ if(cnt) {
+ uint16 lend = buf_rx + cnt;
+ if(lend > p->buf_idx) {
+ lend -= p->buf_idx + 1;
+ p->buf_rx = lend;
+ } else {
+ p->buf_rx = lend;
+ lend = 0;
+ };
+ size_t len = (cnt - lend) *sizeof(MLX90614DATA);
+ if(len) memcpy(puc, (void *)(p->pbuf + buf_rx), len);
+ if(lend) memcpy(puc + len, (void *)p->pbuf, lend *sizeof(MLX90614DATA));
+ }
+ taskENABLE_INTERRUPTS();
+ return cnt * sizeof(MLX90614DATA) + 4;
+}
+
+//#define mMIN(a, b) ((ab)?a:b)
+
+#include "web_srv.h"
+#include "websock.h"
+
+int mlx90614_ws(TCP_SERV_CONN *ts_conn, char cmd)
+{
+ PMLX90614DRV p = &mlx90614drv;
+ switch(cmd) {
+ case 'd': // deinit
+ if(p->init > 0) {
+ gtimer_stop(&p->timer);
+ gtimer_deinit(&p->timer);
+ _i2c_deinit(&p->i2c);
+ if(p->pbuf) {
+ free(p->pbuf);
+ p->pbuf = NULL;
+ }
+ p->init = -1;
+ return 0;
+ }
+ return 1;
+ case 'c': // get count
+ return mlx90614_chkdata(p->buf_idx + 1);
+ case 'i': // init
+ return p->init;
+ default: // get_data
+ if(p->init <= 0) {
+ p->status = 0;
+ p->count = 0;
+ p->overrun = 0;
+ p->errs = 0;
+ if(!p->pbuf) {
+ p->pbuf = zalloc((p->buf_idx + 1) * sizeof(MLX90614DATA));
+ if(!p->pbuf) {
+ error_printf("Error create buffer!\n");
+ return -1;
+ };
+ p->buf_tx = 0;
+ p->buf_rx = 0;
+ };
+ _i2c_init(&p->i2c);
+ gtimer_init(&p->timer, MLX90614_TIMER);
+ gtimer_start_periodical(&p->timer, p->timetik, (void*)mlx_tick_handler, (uint32_t)&mlx90614drv);
+ p->init = 1;
+// return 0;
+ }
+ case 'g': // get
+ {
+ uint32 i = mlx90614_chkdata(p->buf_idx + 1);
+ if(i) {
+ WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
+ i = mMIN((web_conn->msgbufsize / sizeof(MLX90614DATA)), i);
+ if(websock_tx_frame(ts_conn, WS_OPCODE_BINARY | WS_FRAGMENT_FIN, web_conn->msgbuf, mlx90614_getdata(web_conn->msgbuf, i)) != ERR_OK)
+ return -1;
+ }
+ return i;
+ }
+ }
+ return -1;
+}
+
+void mlx90614_init(void)
+{
+ PMLX90614DRV p = &mlx90614drv;
+ if(p->init <= 0) {
+ rtl_printf("Init MLX90614\n");
+ p->status = 0;
+ p->count = 0;
+ p->errs = 0;
+ if(!p->pbuf) {
+ p->pbuf = zalloc((p->buf_idx + 1) * sizeof(MLX90614DATA));
+ if(!p->pbuf) {
+ error_printf("Error create buffer!\n");
+ return;
+ };
+ p->buf_tx = 0;
+ p->buf_rx = 0;
+ };
+// (!) Установки драйвера I2C заданы в структуре mlx90614drv
+// _i2c_setup(&p->i2c, MLX90614_I2C_PIN_SDA , MLX90614_I2C_PIN_SCL, DRV_I2C_FS_MODE); // == DRV_I2C_OK?
+ _i2c_init(&p->i2c);
+// _i2c_set_speed(&p->i2c, MLX90614_I2C_BUS_CLK);
+ rtl_printf("I2C%d mode = %d, drvStatus = %d\n", p->i2c.idx, p->i2c.mode, p->i2c.status);
+// (!) Инициализация MLX90614 перенесена в прерывание таймера
+ // Initial a periodical timer
+ gtimer_init(&p->timer, MLX90614_TIMER);
+ // Tick every 0.001 sec (p->timetik)
+ gtimer_start_periodical(&p->timer, p->timetik, (void*)mlx_tick_handler, (uint32_t)&mlx90614drv);
+ rtl_printf("MLX90614 Timer Period = %u us\n", p->timetik);
+ p->init = 1;
+ }
+}
+
+void mlx90614_deinit(void)
+{
+ PMLX90614DRV p = &mlx90614drv;
+ i2c_drv_t *pi2c = &p->i2c;
+ if(p->init > 0) {
+ rtl_printf("Deinit MLX90614\n");
+ gtimer_stop(&p->timer);
+ gtimer_deinit(&p->timer);
+// (!) Не используется mlx90614_write / mlx90614_read для сокращения кода
+// mlx90614_write(MLX90614_REG_CONFIG, MLX90614_CONFIG_MODE_POWERDOWN);
+ // Break controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) |= 2;
+ vTaskDelay(2); // +WDT
+ // Disable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = 0;
+/* Exit from Sleep Mode > 250 ms !
+ vTaskDelay(2); // +WDT
+ // Master Target Address
+ i2c_reg(REG_DW_I2C_IC_TAR) = p->addr;
+ // Enable controller.
+ i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE;
+ // Заполним FIFO ic I2C командой sleep MLX90614
+ vTaskDelay(2); // +WDT
+ // MLX90614 Enter Sleep Mode
+ i2c_reg(REG_DW_I2C_IC_DATA_CMD) = MLX90614_SLEEP | BIT_IC_DATA_CMD_STOP;
+*/
+ vTaskDelay(2); // +WDT
+ _i2c_deinit(&p->i2c);
+ if(p->pbuf) {
+ free(p->pbuf);
+ p->pbuf = NULL;
+ }
+ }
+ p->init = 0;
+}
+
+LOCAL void ShowMlx(void)
+{
+ PMLX90614DRV p = &mlx90614drv;
+ rtl_printf("MLX90614: %d, %d\n", p->buf_i2c.us[0], p->buf_i2c.ss[1]);
+ rtl_printf("MLX90614: Cnt = %u, Err = %u\n", p->count, p->errs);
+}
+
+LOCAL void fATMLX(int argc, char *argv[])
+{
+ if(argc > 1) {
+ if(atoi(argv[1])) {
+ mlx90614_init();
+ vTaskDelay(10); // +WDT
+ }
+ else mlx90614_deinit();
+ }
+ ShowMlx();
+}
+
+
+MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_mlx90614[] = {
+ {"ATMLX", 0, fATMLX, "=[0/1]: MLX90614 =1 start, =0 stop"}
+};
+/*
+ * Test i2c:
+ * ati2c i
+ * ati2c g 5a 1 6 3
+ * ati2c d
+ */
diff --git a/project/src/web/web_int_callbacks.c b/project/src/web/web_int_callbacks.c
index 708c2eb..7ca3fe7 100644
--- a/project/src/web/web_int_callbacks.c
+++ b/project/src/web/web_int_callbacks.c
@@ -455,6 +455,16 @@ extern int ina219_ws(TCP_SERV_CONN *ts_conn, char cmd);
}
}
#endif
+#ifdef WEB_MLX90614_DRV
+ else ifcmp("mlx90614") {
+ if(CheckSCB(SCB_WEBSOC)) {
+extern int mlx90614_ws(TCP_SERV_CONN *ts_conn, char cmd);
+ int x = mlx90614_ws(ts_conn, cstr[6]);
+ if(x < 0) SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
+ else tcp_puts("%d", x);
+ }
+ }
+#endif
#ifdef WEB_ADC_DRV
else ifcmp("adc") {
if(CheckSCB(SCB_WEBSOC)) {
diff --git a/project/src/web/web_websocket.c b/project/src/web/web_websocket.c
index d1e752d..18ecf22 100644
--- a/project/src/web/web_websocket.c
+++ b/project/src/web/web_websocket.c
@@ -136,6 +136,7 @@ websock_rx_data(TCP_SERV_CONN *ts_conn)
case sw_frs_text:
#if DEBUGSOO > 1
os_printf("ws:txt ");
+
#if DEBUGSOO > 2
if(ws->frame_len != 0) {
uint8 tt = pstr[len];