This commit is contained in:
pvvx 2018-03-04 14:05:52 +03:00
parent 1c773d745a
commit 2bc9cc61b3
22 changed files with 1244 additions and 108 deletions

View file

@ -26,6 +26,10 @@
#include "hal_com_reg.h"
#ifndef mMIN
#define mMIN(a, b) ((a<b)?a:b)
#endif
#define MLX90614_I2CADDR 0x5A
// RAM
#define MLX90614_RAWIR1 0x04

View file

@ -51,13 +51,16 @@ extern void *pvPortMalloc(size_t xWantedSize);
#endif
//------------------------------------------------------------------------------
typedef union _adc_data {
unsigned short us;
typedef struct _adc_data {
uint16_t us0;
uint16_t us1;
} ADC_DATA, *PADC_DATA;
typedef struct _adc_drv {
signed char init; // флаг
unsigned char tmp;
unsigned char dcmf; // ADC_DECIMATION_FILTER
unsigned char xclk; // ADC_SAMPLE_XCLK
unsigned char audio; // Audio mode
unsigned short count; // счетчик считанных значений
unsigned short overrun; // счет переполнений буфера
@ -71,56 +74,95 @@ typedef struct _adc_drv {
#endif
} ADC_DRV, *PADC_DRV;
//#define mMIN(a, b) ((a<b)?a:b)
#define mMIN(a, b) ((a<b)?a:b)
//#define mMAX(a, b) ((a>b)?a:b)
ADC_DRV adc_drv = {
.buf_idx = (1460*2 - 80)/(sizeof(ADC_DATA)/2) // циклический буфер на ~1420 замеров (см. sizeof(ADC_DATA))
// Если шаг заполнения 1 ms -> буфер на 1.4 сек
// Оптимизация под TCP: (TCP_MSS*2 - 80)/2 = (1460*2 - 80)/2 = 1420
.dcmf = ADC_DECIMATION_FILTER,
.xclk = ADC_SAMPLE_XCLK,
// .audio = 0,
.buf_idx = 709 // (1460*2 - 80)/(sizeof(ADC_DATA)/2) // циклический буфер на ~1420 замеров (см. sizeof(ADC_DATA))
// Если шаг заполнения 1 ms -> буфер на 1.4 сек
// Оптимизация под TCP: (TCP_MSS*2 - 80)/2 = (1460*2 - 80)/2 = 1420
};
void adc_int_handler(void *par) {
union {
uint16_t w[4];
uint32_t d[2];
}buf;
PADC_DRV p = par; // &adc_drv
// uint32_t adc_isr = HAL_ADC_READ32(REG_ADC_INTR_STS);
buf.d[0] = HAL_ADC_READ32(REG_ADC_FIFO_READ);
buf.d[1] = HAL_ADC_READ32(REG_ADC_FIFO_READ);
if(p->pbuf) {
#ifndef ADC_USE_TIMER
int i = 4;
while(i--)
#endif
{
PADC_DATA pd = p->pbuf + p->buf_tx;
pd->us = HAL_ADC_READ32(REG_ADC_FIFO_READ); // 2 -> sample -> 24.4 kHz (if ADC irq!)
// (void)HAL_ADC_READ32(REG_ADC_FIFO_READ); // 4 sample -> 12.2 kHz (if ADC irq!)
// (void)HAL_ADC_READ32(REG_ADC_FIFO_READ); // 6 sample -> 8.133 kHz (if ADC irq!)
// (void)HAL_ADC_READ32(REG_ADC_FIFO_READ); // 8 sample -> 6.1 kHz (if ADC irq!)
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++;
};
}
/* Clear ADC Status */
(void)HAL_ADC_READ32(REG_ADC_INTR_STS);
PADC_DATA pd = p->pbuf + p->buf_tx;
pd->us0 = buf.w[3];
pd->us1 = buf.w[0];
if(p->buf_tx >= p->buf_idx) p->buf_tx = 0;
else p->buf_tx++;
if(p->buf_rx == p->buf_tx) {
p->overrun++;
if(p->overrun == 0) p->init = 2; // overrun
if(p->buf_rx >= p->buf_idx) p->buf_rx = 0;
else p->buf_rx++;
};
};
/* Clear ADC Status */
// HAL_ADC_WRITE32(REG_ADC_INTR_STS, adc_isr);
(void)HAL_ADC_READ32(REG_ADC_INTR_STS);
}
size_t adc_getdata(void *pd, uint16 cnt)
void adc_int_handler_audio(void *par) {
union {
uint16_t w[4];
uint32_t d[2];
}buf;
PADC_DRV p = par; // &adc_drv
buf.d[0] = HAL_ADC_READ32(REG_ADC_FIFO_READ);
buf.d[1] = HAL_ADC_READ32(REG_ADC_FIFO_READ);
if(p->pbuf) {
PADC_DATA pd = p->pbuf + p->buf_tx;
pd->us0 = buf.w[0];
pd->us1 = buf.w[1];
if(p->buf_tx >= p->buf_idx) p->buf_tx = 0;
else p->buf_tx++;
if(p->buf_rx == p->buf_tx) {
p->overrun++;
if(p->overrun == 0) p->init = 2; // overrun
if(p->buf_rx >= p->buf_idx) p->buf_rx = 0;
else p->buf_rx++;
};
pd = p->pbuf + p->buf_tx;
pd->us0 = buf.w[2];
pd->us1 = buf.w[3];
if(p->buf_tx >= p->buf_idx) p->buf_tx = 0;
else p->buf_tx++;
if(p->buf_rx == p->buf_tx) {
p->overrun++;
if(p->overrun == 0) p->init = 2; // overrun
if(p->buf_rx >= p->buf_idx) p->buf_rx = 0;
else p->buf_rx++;
};
};
/* Clear ADC Status */
(void)HAL_ADC_READ32(REG_ADC_INTR_STS);
}
size_t adc_getdata(void *pd, uint16_t cnt)
{
PADC_DRV p = &adc_drv;
if(p->init <= 0) return 0;
unsigned short *pus = (unsigned short *) pd;
uint16_t *pus = (uint16_t *) pd;
taskDISABLE_INTERRUPTS();
uint16 buf_rx = p->buf_rx;
uint16_t buf_rx = p->buf_rx;
*pus++ = cnt; // кол-во замеров
*pus++ = p->count + p->overrun; // индекс замера для анализа пропусков на стороне приемника
// если не пропущено, то равен прошлому + кол-во считанных замеров в прошлом блоке
p->count += cnt; // p->overrun = 0;
unsigned char *puc = (unsigned char *) pus;
uint8_t *puc = (uint8_t *) pus;
if(cnt) {
uint16 lend = buf_rx + cnt;
uint16_t lend = buf_rx + cnt;
if(lend > p->buf_idx) {
lend -= p->buf_idx + 1;
p->buf_rx = lend;
@ -136,13 +178,13 @@ size_t adc_getdata(void *pd, uint16 cnt)
return cnt * sizeof(ADC_DATA) + 4;
}
uint16 adc_chkdata(uint16 cnt)
uint16_t adc_chkdata(uint16_t cnt)
{
PADC_DRV p = &adc_drv;
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;
if(cnt > (uint16_t)len) cnt = (uint16_t)len;
return cnt;
}
@ -150,7 +192,47 @@ int adc_ws(TCP_SERV_CONN *ts_conn, char cmd)
{
PADC_DRV p = &adc_drv;
switch(cmd) {
case 'd': // deinit
case '*': // get_data
if(p->init <= 0) {
p->count = 0;
p->overrun = 0;
// p->errs = 0;
if(!p->pbuf) {
p->pbuf = zalloc((p->buf_idx + 1) * sizeof(ADC_DATA));
if(!p->pbuf) {
error_printf("Error create buffer!\n");
return -1;
};
p->buf_tx = 0;
p->buf_rx = 0;
};
ADCInit(p->audio, p->xclk, p->dcmf);
#ifdef ADC_USE_TIMER
// Initial a periodical timer
gtimer_init(&p->timer, ADC_USE_TIMER);
gtimer_start_periodical(&p->timer, 1000, (void*)adc_int_handler, (uint32_t)p);
rtl_printf("ADC Timer Period = %u us\n", &p->timer.hal_gtimer_adp.TimerLoadValueUs);
#else
if(p->audio)
ADCIrqInit(adc_int_handler_audio,(uint32)p, BIT_ADC_FIFO_FULL_EN | BIT_ADC_FIFO_RD_REQ_EN);
else
ADCIrqInit(adc_int_handler,(uint32)p, BIT_ADC_FIFO_FULL_EN | BIT_ADC_FIFO_RD_REQ_EN);
#endif
ADCEnable();
p->init = 1;
}
case 'g': // get_data
{
uint32_t i = adc_chkdata(p->buf_idx + 1);
if(i) {
WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
i = mMIN((web_conn->msgbufsize / sizeof(ADC_DATA)), i);
if(websock_tx_frame(ts_conn, WS_OPCODE_BINARY | WS_FRAGMENT_FIN, web_conn->msgbuf, adc_getdata(web_conn->msgbuf, i)) != ERR_OK)
return -1;
}
return i;
}
case 'z': // deinit
if(p->init > 0) {
#ifdef ADC_USE_TIMER
gtimer_stop(&p->timer);
@ -169,48 +251,40 @@ int adc_ws(TCP_SERV_CONN *ts_conn, char cmd)
return 0;
}
return 1;
case 'c': // get count
case '?': // get count
return adc_chkdata(p->buf_idx + 1);
case 'i': // init
case 'i': // info init
return p->init;
default: // get_data
if(p->init <= 0) {
p->count = 0;
p->overrun = 0;
// p->errs = 0;
if(!p->pbuf) {
p->pbuf = zalloc((p->buf_idx + 1) * sizeof(ADC_DATA));
if(!p->pbuf) {
error_printf("Error create buffer!\n");
return -1;
};
p->buf_tx = 0;
p->buf_rx = 0;
};
ADCInit(ADC2_SEL);
#ifdef ADC_USE_TIMER
// Initial a periodical timer
gtimer_init(&p->timer, ADC_USE_TIMER);
gtimer_start_periodical(&p->timer, 1000, (void*)adc_int_handler, (uint32_t)p);
rtl_printf("ADC Timer Period = %u us\n", &p->timer.hal_gtimer_adp.TimerLoadValueUs);
#else
ADCIrqInit(adc_int_handler,(uint32)p, BIT_ADC_FIFO_FULL_EN); // BIT_ADC_FIFO_RD_REQ_EN ?
#endif
ADCEnable();
p->init = 1;
// return 0;
}
case 'g': // get
{
uint32 i = adc_chkdata(p->buf_idx + 1);
if(i) {
WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
i = mMIN((web_conn->msgbufsize / sizeof(ADC_DATA)), i);
if(websock_tx_frame(ts_conn, WS_OPCODE_BINARY | WS_FRAGMENT_FIN, web_conn->msgbuf, adc_getdata(web_conn->msgbuf, i)) != ERR_OK)
return -1;
}
return i;
}
case '1': // set ADC_DECIMATION_1
p->dcmf = 1;
return 0;
case '2': // set ADC_DECIMATION_2
p->dcmf = 2;
return 0;
case '4': // set ADC_DECIMATION_4
p->dcmf = 3;
return 0;
case '8': // set ADC_DECIMATION_8
p->dcmf = 4;
return 0;
case 'a': // set ADC_SAMPLE_XCLK x1
p->xclk = 0;
return 0;
case 'b': // set ADC_SAMPLE_XCLK x2
p->xclk = 1;
return 0;
case 'c': // set ADC_SAMPLE_XCLK x4
p->xclk = 2;
return 0;
case 'd': // set ADC_SAMPLE_XCLK x8
p->xclk = 3;
return 0;
case 'x': // set Audio mode
p->audio = 1;
return 0;
case 'y': // set 4 channel mode
p->audio = 0;
return 0;
}
return -1;
}

View file

@ -82,7 +82,7 @@ static void ADCEnablePS(void)
}
#endif
void ADCInit(ADC_MODULE_SEL adc_idx) {
void ADCInit(unsigned char mode, unsigned char xclk, unsigned char dcmf) {
/* ADC Function and Clock Enable */
/* To release DAC delta sigma clock gating */
HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL2,
@ -97,10 +97,10 @@ void ADCInit(ADC_MODULE_SEL adc_idx) {
HAL_ADC_WRITE32(REG_ADC_CONTROL,
BIT_CTRL_ADC_COMP_ONLY(ADC_FEATURE_DISABLED) // compare mode only enable (without FIFO enable)
| BIT_CTRL_ADC_ONESHOT(ADC_FEATURE_DISABLED) // one-shot mode enable
| BIT_CTRL_ADC_OVERWRITE(ADC_FEATURE_DISABLED) // overwrite mode enable
| BIT_CTRL_ADC_OVERWRITE(ADC_FEATURE_ENABLED) // overwrite mode enable
| BIT_CTRL_ADC_ENDIAN(ADC_DATA_ENDIAN_LITTLE) // endian selection
| BIT_CTRL_ADC_BURST_SIZE(8) // DMA operation threshold
| BIT_CTRL_ADC_THRESHOLD(8) // one shot mode threshold
| BIT_CTRL_ADC_THRESHOLD(8) // one shot mode threshold
| BIT_CTRL_ADC_DBG_SEL(ADC_DBG_SEL_DISABLE));
#if 0
/* ADC compare value and compare method setting*/
@ -141,23 +141,25 @@ void ADCInit(ADC_MODULE_SEL adc_idx) {
& (~(1 << adc_idx))); // compare mode control : less than the compare threshold
#endif
/* ADC audio mode set-up */
#if 0
/* ADC enable manually setting */
HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD0,
HAL_ADC_READ32(REG_ADC_ANAPAR_AD0)
// & (~(BIT_ADC_AUDIO_EN)))
// & (~(BIT_ADC_EN_MANUAL))
| BIT_ADC_AUDIO_EN // ADC audio mode enable
// | BIT_ADC_AUDIO_EN // ADC audio mode enable
| BIT_ADC_EN_MANUAL // ADC enable manually
);
#endif
/* ADC analog parameter 0 */
HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD0,
(HAL_ADC_READ32(REG_ADC_ANAPAR_AD0)
// & (~BIT14) //ADC Input is internal?
| (BIT14))
& (~(BIT3|BIT2)));
HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD0, 0x00953b10
| BIT_CTRL_ADC_AUDIO_EN(mode)
| BIT_CTRL_ADC_SAMPLE_CLKL(xclk));
/* ADC analog parameter 1 */
HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD1,
(HAL_ADC_READ32(REG_ADC_ANAPAR_AD1) & (~BIT1)) | (BIT2|BIT0));
HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD1, BIT_ADC_DIGITAL_RST_BAR
| BIT_ADC_EXT_VREF_EN
| BIT_ADC_DECIMATION_FILTER_ORDER
| BIT_CTRL_DOWN_SAMPLE_RATE(dcmf));
/* ADC analog parameter 2 */
HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD2, 0x67884400);
/* ADC analog parameter 3 */

View file

@ -47,8 +47,8 @@ INA219DRV ina219drv = {
// Если шаг заполнения 1 ms -> буфер на 0.71 сек
// Оптимизация под TCP: (TCP_MSS*2 - 80)/4 = (1460*2 - 80)/4 = 710
.i2c.status = DRV_I2C_OFF,
.i2c.idx = 1, // =1: I2C1
.i2c.io_sel = S0, // =S0: PC_4, PC_5
.i2c.idx = 3, //1, // =1: I2C1, =2: I2C2, =3: I2C3
.i2c.io_sel = S0, // =S0: PC_4, PC_5; PB_6, PB_7; PB_2, PB_3
.i2c.mode = DRV_I2C_FS_MODE // DRV_I2C_FS_MODE
};
/*

View file

@ -466,7 +466,7 @@ extern int ina219_ws(TCP_SERV_CONN *ts_conn, char cmd);
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]);
int x = mlx90614_ws(ts_conn, cstr[8]);
if(x < 0) SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
else tcp_puts("%d", x);
}
@ -476,7 +476,7 @@ extern int mlx90614_ws(TCP_SERV_CONN *ts_conn, char cmd);
else ifcmp("adc") {
if(CheckSCB(SCB_WEBSOC)) {
extern int adc_ws(TCP_SERV_CONN *ts_conn, char cmd);
int x = adc_ws(ts_conn, cstr[6]);
int x = adc_ws(ts_conn, cstr[3]);
if(x < 0) SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
else tcp_puts("%d", x);
}