diff --git a/scripts/examples/12-Thermopile-Shield/MLX90640_camera.py b/scripts/examples/12-Thermopile-Shield/MLX90640_camera.py index a3e5819cb..3ef426857 100644 --- a/scripts/examples/12-Thermopile-Shield/MLX90640_camera.py +++ b/scripts/examples/12-Thermopile-Shield/MLX90640_camera.py @@ -6,7 +6,7 @@ import image, time, fir # Initialize the thermal sensor -fir.init(type=fir.FIR_MLX90640, refresh=16) # Hz (higher end OpenMV Cam's may be able to run faster) +fir.init(type=fir.FIR_MLX90640, refresh=32) # 16Hz, 32Hz or 64Hz. # FPS clock clock = time.clock() diff --git a/scripts/examples/12-Thermopile-Shield/MLX90640_camera_lcd.py b/scripts/examples/12-Thermopile-Shield/MLX90640_camera_lcd.py index 33818f95a..1d1714d37 100644 --- a/scripts/examples/12-Thermopile-Shield/MLX90640_camera_lcd.py +++ b/scripts/examples/12-Thermopile-Shield/MLX90640_camera_lcd.py @@ -6,7 +6,7 @@ import image, time, fir, lcd # Initialize the thermal sensor -fir.init(type=fir.FIR_MLX90640, refresh=16) # Hz (higher end OpenMV Cam's may be able to run faster) +fir.init(type=fir.FIR_MLX90640, refresh=32) # 16Hz, 32Hz or 64Hz. # Init the lcd. lcd.init() diff --git a/scripts/examples/12-Thermopile-Shield/MLX90640_overlay.py b/scripts/examples/12-Thermopile-Shield/MLX90640_overlay.py index 76ad3ae01..57a8ecae6 100644 --- a/scripts/examples/12-Thermopile-Shield/MLX90640_overlay.py +++ b/scripts/examples/12-Thermopile-Shield/MLX90640_overlay.py @@ -13,7 +13,7 @@ sensor.set_framesize(sensor.QQVGA) sensor.skip_frames(time = 2000) # Initialize the thermal sensor -fir.init(type=fir.FIR_MLX90640, refresh=16) # Hz (higher end OpenMV Cam's may be able to run faster) +fir.init(type=fir.FIR_MLX90640, refresh=32) # 16Hz, 32Hz or 64Hz. # Allocate another frame buffer for smoother video. extra_fb = sensor.alloc_extra_fb(sensor.width(), sensor.height(), sensor.RGB565) diff --git a/scripts/examples/12-Thermopile-Shield/MLX90640_overlay_lcd.py b/scripts/examples/12-Thermopile-Shield/MLX90640_overlay_lcd.py index 297f045f9..5dd8ad319 100644 --- a/scripts/examples/12-Thermopile-Shield/MLX90640_overlay_lcd.py +++ b/scripts/examples/12-Thermopile-Shield/MLX90640_overlay_lcd.py @@ -13,7 +13,7 @@ sensor.set_framesize(sensor.QQVGA2) sensor.skip_frames(time = 2000) # Initialize the thermal sensor -fir.init(type=fir.FIR_MLX90640, refresh=16) # Hz (higher end OpenMV Cam's may be able to run faster) +fir.init(type=fir.FIR_MLX90640, refresh=32) # 16Hz, 32Hz or 64Hz. # Init the lcd. lcd.init() diff --git a/scripts/examples/12-Thermopile-Shield/MLX90640_overlay_smoothed.py b/scripts/examples/12-Thermopile-Shield/MLX90640_overlay_smoothed.py index 04c004281..ddaaeb33f 100644 --- a/scripts/examples/12-Thermopile-Shield/MLX90640_overlay_smoothed.py +++ b/scripts/examples/12-Thermopile-Shield/MLX90640_overlay_smoothed.py @@ -13,7 +13,7 @@ sensor.set_framesize(sensor.QQVGA) sensor.skip_frames(time = 2000) # Initialize the thermal sensor -fir.init(type=fir.FIR_MLX90640, refresh=16) # Hz (higher end OpenMV Cam's may be able to run faster) +fir.init(type=fir.FIR_MLX90640, refresh=32) # 16Hz, 32Hz or 64Hz. # Allocate another frame buffer for smoother video. ir_buffer = image.Image(fir.width() * IR_SCALE, fir.height() * IR_SCALE, sensor.GRAYSCALE) diff --git a/src/mlx/include/MLX90640_I2C_Driver.h b/src/mlx/include/MLX90640_I2C_Driver.h index ef795d597..1159af596 100644 --- a/src/mlx/include/MLX90640_I2C_Driver.h +++ b/src/mlx/include/MLX90640_I2C_Driver.h @@ -18,9 +18,10 @@ #define _MLX90640_I2C_Driver_H_ #include +#include STM32_HAL_H - void MLX90640_I2CInit(void); + void MLX90640_I2CInit(I2C_HandleTypeDef *i2c); int MLX90640_I2CRead(uint8_t slaveAddr,uint16_t startAddress, uint16_t nMemAddressRead, uint16_t *data); int MLX90640_I2CWrite(uint8_t slaveAddr,uint16_t writeAddress, uint16_t data); void MLX90640_I2CFreqSet(int freq); -#endif \ No newline at end of file +#endif diff --git a/src/mlx/src/MLX90640_API.c b/src/mlx/src/MLX90640_API.c index 52a3e1158..0032323f2 100644 --- a/src/mlx/src/MLX90640_API.c +++ b/src/mlx/src/MLX90640_API.c @@ -64,7 +64,7 @@ int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData) dataReady = statusRegister & 0x0008; } - while(dataReady != 0 && cnt < 5) + while(dataReady != 0 && cnt < 32) { error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030); if(error == -1) @@ -87,7 +87,7 @@ int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData) cnt = cnt + 1; } - if(cnt > 4) + if(cnt > 31) { return -8; } diff --git a/src/mlx/src/MLX90640_I2C_Driver.c b/src/mlx/src/MLX90640_I2C_Driver.c index 5eae81d38..fb57224ed 100644 --- a/src/mlx/src/MLX90640_I2C_Driver.c +++ b/src/mlx/src/MLX90640_I2C_Driver.c @@ -14,94 +14,38 @@ * limitations under the License. * */ -/*#include "mbed.h" +#include +#include STM32_HAL_H +#include "cambus.h" #include "MLX90640_I2C_Driver.h" -I2C i2c(p9, p10); +static I2C_HandleTypeDef *hi2c; -void MLX90640_I2CInit() +void MLX90640_I2CInit(I2C_HandleTypeDef *i2c) { - i2c.stop(); + hi2c = i2c; } int MLX90640_I2CRead(uint8_t slaveAddr, uint16_t startAddress, uint16_t nMemAddressRead, uint16_t *data) { - uint8_t sa; - int ack = 0; - int cnt = 0; - int i = 0; - char cmd[2] = {0,0}; - char i2cData[1664] = {0}; - uint16_t *p; - - p = data; - sa = (slaveAddr << 1); - cmd[0] = startAddress >> 8; - cmd[1] = startAddress & 0x00FF; - - i2c.stop(); - wait_us(5); - ack = i2c.write(sa, cmd, 2, 1); - - if (ack != 0x00) - { + uint8_t* p = (uint8_t*) data; + if (cambus_readw_bytes(hi2c, (slaveAddr<<1), startAddress, p, nMemAddressRead*2) != 0) { return -1; - } - - sa = sa | 0x01; - ack = i2c.read(sa, i2cData, 2*nMemAddressRead, 0); - - if (ack != 0x00) - { - return -1; - } - i2c.stop(); - - for(cnt=0; cnt < nMemAddressRead; cnt++) - { - i = cnt << 1; - *p++ = (uint16_t)i2cData[i]*256 + (uint16_t)i2cData[i+1]; - } - - return 0; -} + } -void MLX90640_I2CFreqSet(int freq) -{ - i2c.frequency(1000*freq); -} + for(int cnt=0; cnt < nMemAddressRead*2; cnt+=2) { + uint8_t tempBuffer = p[cnt+1]; + p[cnt+1] = p[cnt]; + p[cnt] = tempBuffer; + } + + return 0; +} int MLX90640_I2CWrite(uint8_t slaveAddr, uint16_t writeAddress, uint16_t data) { - uint8_t sa; - int ack = 0; - char cmd[4] = {0,0,0,0}; - uint16_t dataCheck; - - - sa = (slaveAddr << 1); - cmd[0] = writeAddress >> 8; - cmd[1] = writeAddress & 0x00FF; - cmd[2] = data >> 8; - cmd[3] = data & 0x00FF; - - i2c.stop(); - wait_us(5); - ack = i2c.write(sa, cmd, 4, 0); - - if (ack != 0x00) - { + if (cambus_writew2(hi2c, (slaveAddr << 1), writeAddress, data) != 0) { return -1; - } - i2c.stop(); - - MLX90640_I2CRead(slaveAddr,writeAddress,1, &dataCheck); - - if ( dataCheck != data) - { - return -2; - } - - return 0; -}*/ - + } + return 0; +} diff --git a/src/mlx/src/MLX90640_SWI2C_Driver.c b/src/mlx/src/MLX90640_SWI2C_Driver.c deleted file mode 100644 index 5070f5431..000000000 --- a/src/mlx/src/MLX90640_SWI2C_Driver.c +++ /dev/null @@ -1,334 +0,0 @@ -/** - * @copyright (C) 2017 Melexis N.V. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - /** - * As the timings depend heavily on the MCU in use, it is recommended - * to make sure that the proper timings are achieved. For that purpose - * an oscilloscope might be needed to strobe the SCL and SDA signals. - * The Wait(int) function could be modified in order to better - * trim the frequency. For coarse setting of the frequency or - * dynamic frequency change using the default function implementation, - * ‘freqCnt’ argument should be changed – lower value results in - * higher frequency. - */ - -//#include "mbed.h" -#include "MLX90640_I2C_Driver.h" -#include STM32_HAL_H -#include "omv_boardconfig.h" - -//DigitalInOut sda(p9); -#define sda SOFT_I2C_SIOD_READ() -//DigitalOut scl(p10); - -#define LOW 0; -#define HIGH 1; - -//#define SCL_HIGH scl = HIGH; -#define SCL_HIGH SOFT_I2C_SIOC_H() -//#define SCL_LOW scl = LOW; -#define SCL_LOW SOFT_I2C_SIOC_L() -//#define SDA_HIGH sda.input(); -#define SDA_HIGH SOFT_I2C_SIOD_H() -//#define SDA_LOW sda.output(); sda = LOW; -#define SDA_LOW SOFT_I2C_SIOD_L() - -int I2CSendByte(int8_t); -void I2CReadBytes(int, char *); -void I2CStart(void); -void I2CStop(void); -void I2CRepeatedStart(void); -void I2CSendACK(void); -void I2CSendNack(void); -int I2CReceiveAck(void); -void Wait(int); - -static int freqCnt; - -void MLX90640_I2CInit() -{ - I2CStop(); -} - -int MLX90640_I2CRead(uint8_t slaveAddr, uint16_t startAddress,uint16_t nMemAddressRead, uint16_t *data) -{ - uint8_t sa; - int ack = 0; - int cnt = 0; - int i = 0; - char cmd[2] = {0,0}; - char i2cData[1664] = {0}; - uint16_t *p; - - p = data; - sa = (slaveAddr << 1); - cmd[0] = startAddress >> 8; - cmd[1] = startAddress & 0x00FF; - - I2CStop(); - Wait(freqCnt); - I2CStart(); - Wait(freqCnt); - - ack = I2CSendByte(sa)!=0; - if(ack != 0) - { - return -1; - } - - ack = I2CSendByte(cmd[0])!=0; - if(ack != 0) - { - return -1; - } - - ack = I2CSendByte(cmd[1])!=0; - if(ack != 0) - { - return -1; - } - - I2CRepeatedStart(); - - sa = sa | 0x01; - - ack = I2CSendByte(sa); - if(ack != 0) - { - return -1; - } - - I2CReadBytes((nMemAddressRead << 1), i2cData); - - I2CStop(); - - for(cnt=0; cnt < nMemAddressRead; cnt++) - { - i = cnt << 1; - *p++ = (int)i2cData[i]*256 + (int)i2cData[i+1]; - } - return 0; - -} - -void MLX90640_I2CFreqSet(int freq) -{ - freqCnt = freq>>1; -} - -int MLX90640_I2CWrite(uint8_t slaveAddr, uint16_t writeAddress, uint16_t data) -{ - uint8_t sa; - int ack = 0; - char cmd[4] = {0,0,0,0}; - uint16_t dataCheck; - - sa = (slaveAddr << 1); - cmd[0] = writeAddress >> 8; - cmd[1] = writeAddress & 0x00FF; - cmd[2] = data >> 8; - cmd[3] = data & 0x00FF; - - I2CStop(); - Wait(freqCnt); - I2CStart(); - ack = I2CSendByte(sa); - if (ack != 0x00) - { - return 1; - } - - for(int i = 0; i<4; i++) - { - ack = I2CSendByte(cmd[i]); - - if (ack != 0x00) - { - return -1; - } - } - I2CStop(); - - MLX90640_I2CRead(slaveAddr,writeAddress,1, &dataCheck); - - if ( dataCheck != data) - { - return -2; - } - - return 0; -} - -int I2CSendByte(int8_t data) -{ - int ack = 1; - int8_t byte = data; - - for(int i=0;i<8;i++) - { - Wait(freqCnt); - - if(byte & 0x80) - { - SDA_HIGH; - } - else - { - SDA_LOW; - } - Wait(freqCnt); - SCL_HIGH; - Wait(freqCnt); - Wait(freqCnt); - SCL_LOW; - byte = byte<<1; - } - - Wait(freqCnt); - ack = I2CReceiveAck(); - - return ack; -} - -void I2CReadBytes(int nBytes, char *dataP) -{ - char data; - for(int j=0;jInstance) { + HAL_I2C_DeInit(i2c); + } + i2c->Instance = NULL; return 0; } @@ -156,3 +166,51 @@ int cambus_writew2(I2C_HandleTypeDef *i2c, uint8_t slv_addr, uint16_t reg_addr, __enable_irq(); return ret; } + +int cambus_read_bytes(I2C_HandleTypeDef *i2c, uint8_t slv_addr, uint8_t reg_addr, uint8_t *buf, int len) +{ + int ret=0; + __disable_irq(); + if (HAL_I2C_Mem_Read(i2c, slv_addr, reg_addr, + I2C_MEMADD_SIZE_8BIT, buf, len, I2C_TIMEOUT) != HAL_OK) { + ret = -1; + } + __enable_irq(); + return ret; +} + +int cambus_write_bytes(I2C_HandleTypeDef *i2c, uint8_t slv_addr, uint8_t reg_addr, uint8_t *buf, int len) +{ + int ret=0; + __disable_irq(); + if (HAL_I2C_Mem_Write(i2c, slv_addr, reg_addr, + I2C_MEMADD_SIZE_8BIT, buf, len, I2C_TIMEOUT) != HAL_OK) { + ret = -1; + } + __enable_irq(); + return ret; +} + +int cambus_readw_bytes(I2C_HandleTypeDef *i2c, uint8_t slv_addr, uint16_t reg_addr, uint8_t *buf, int len) +{ + int ret=0; + __disable_irq(); + if (HAL_I2C_Mem_Read(i2c, slv_addr, reg_addr, + I2C_MEMADD_SIZE_16BIT, buf, len, I2C_TIMEOUT) != HAL_OK) { + ret = -1; + } + __enable_irq(); + return ret; +} + +int cambus_writew_bytes(I2C_HandleTypeDef *i2c, uint8_t slv_addr, uint16_t reg_addr, uint8_t *buf, int len) +{ + int ret=0; + __disable_irq(); + if (HAL_I2C_Mem_Write(i2c, slv_addr, reg_addr, + I2C_MEMADD_SIZE_16BIT, buf, len, I2C_TIMEOUT) != HAL_OK) { + ret = -1; + } + __enable_irq(); + return ret; +} diff --git a/src/omv/cambus.h b/src/omv/cambus.h index 126e556b9..5504083bf 100644 --- a/src/omv/cambus.h +++ b/src/omv/cambus.h @@ -41,4 +41,8 @@ int cambus_readw(I2C_HandleTypeDef *i2c, uint8_t slv_addr, uint8_t reg_addr, ui int cambus_writew(I2C_HandleTypeDef *i2c, uint8_t slv_addr, uint8_t reg_addr, uint16_t reg_data); int cambus_readw2(I2C_HandleTypeDef *i2c, uint8_t slv_addr, uint16_t reg_addr, uint16_t *reg_data); int cambus_writew2(I2C_HandleTypeDef *i2c, uint8_t slv_addr, uint16_t reg_addr, uint16_t reg_data); +int cambus_read_bytes(I2C_HandleTypeDef *i2c, uint8_t slv_addr, uint8_t reg_addr, uint8_t *buf, int len); +int cambus_write_bytes(I2C_HandleTypeDef *i2c, uint8_t slv_addr, uint8_t reg_addr, uint8_t *buf, int len); +int cambus_readw_bytes(I2C_HandleTypeDef *i2c, uint8_t slv_addr, uint16_t reg_addr, uint8_t *buf, int len); +int cambus_writew_bytes(I2C_HandleTypeDef *i2c, uint8_t slv_addr, uint16_t reg_addr, uint8_t *buf, int len); #endif // __CAMBUS_H__ diff --git a/src/omv/py/py_fir.c b/src/omv/py/py_fir.c index b910ca3e5..ed66ea824 100644 --- a/src/omv/py/py_fir.c +++ b/src/omv/py/py_fir.c @@ -10,6 +10,7 @@ */ #include #include "soft_i2c.h" +#include "cambus.h" #include "MLX90640_I2C_Driver.h" #include "MLX90640_API.h" #include "omv_boardconfig.h" @@ -86,9 +87,6 @@ ((((_OldValue-_OldMin)*(_NewMax-_NewMin))+((_OldMax-OldMin)/2)) / \ (_OldMax-OldMin))+_NewMin; }) -// Grayscale to RGB565 conversion -extern const uint16_t rainbow_table[256]; - // MLX variables static float *a_ij = NULL; static float *b_ij = NULL; @@ -97,10 +95,21 @@ static float v_th, k_t1, k_t2, tgc, emissivity, ksta, alpha_cp, ks4, a_cp, b_cp; static uint8_t width = 0; static uint8_t height = 0; -static enum { FIR_NONE, FIR_SHIELD, FIR_MLX90640, FIR_AMG8833 } type = FIR_NONE; static uint8_t IR_refresh_rate = 0; static uint8_t ADC_resolution = 0; +static I2C_HandleTypeDef fir_i2c = {0}; // SCCB/I2C bus. + +static enum { + FIR_NONE, + FIR_SHIELD, + FIR_MLX90640, + FIR_AMG8833 +} fir_sensor = FIR_NONE; + +// Grayscale to RGB565 conversion +extern const uint16_t rainbow_table[256]; + static void test_ack(int ret) { PY_ASSERT_TRUE_MSG(ret == 0, "I2C Bus communication error - missing ACK!"); @@ -197,29 +206,32 @@ static void calculate_To(float Ta, float *To) static mp_obj_t py_fir_deinit() { - switch (type) { + width = 0; + height = 0; + ADC_resolution = 0; + IR_refresh_rate = 0; + if (a_ij) { + a_ij = NULL; + } + if (b_ij) { + b_ij = NULL; + } + if (alpha_ij) { + alpha_ij = NULL; + } + + switch (fir_sensor) { case FIR_NONE: - return mp_const_none; + break; case FIR_SHIELD: + soft_i2c_deinit(); + break; case FIR_MLX90640: case FIR_AMG8833: - soft_i2c_deinit(); - width = 0; - height = 0; - type = FIR_NONE; - IR_refresh_rate = 0; - ADC_resolution = 0; - if (a_ij) { - a_ij = NULL; - } - if (b_ij) { - b_ij = NULL; - } - if (alpha_ij) { - alpha_ij = NULL; - } - return mp_const_none; + cambus_deinit(&fir_i2c); + break; } + fir_sensor = FIR_NONE; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_deinit_obj, py_fir_deinit); @@ -234,21 +246,20 @@ ADC 18-bits: max scene temperature ~450C, 15-bits: max scene temperature ~950C calling: fir.init() - fir.init(type=1, refresh=64, resolution=18) + fir.init(fir_sensor=1, refresh=64, resolution=18) */ mp_obj_t py_fir_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { py_fir_deinit(); switch (py_helper_keyword_int(n_args, args, 0, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_type), FIR_SHIELD)) { - case FIR_NONE: - { + case FIR_NONE: { return mp_const_none; } - case FIR_SHIELD: - { + + case FIR_SHIELD: { width = 16; height = 4; - type = FIR_SHIELD; + fir_sensor = FIR_SHIELD; soft_i2c_init(); // parse refresh rate and ADC resolution @@ -266,10 +277,8 @@ mp_obj_t py_fir_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) fb_alloc_mark(); uint8_t *eeprom = fb_alloc(256 * sizeof(uint8_t), FB_ALLOC_NO_HINT); // Read the whole eeprom. - test_ack(soft_i2c_write_bytes(FIR_EEPROM_ADDR, - (uint8_t [1]){0x00}, 1, false)); - test_ack(soft_i2c_read_bytes(FIR_EEPROM_ADDR, - eeprom, 256, true)); + test_ack(soft_i2c_write_bytes(FIR_EEPROM_ADDR, (uint8_t [1]){0x00}, 1, false)); + test_ack(soft_i2c_read_bytes(FIR_EEPROM_ADDR, eeprom, 256, true)); // Write oscillator trimming value. soft_i2c_write_bytes(FIR_MODULE_ADDR, @@ -342,12 +351,14 @@ mp_obj_t py_fir_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) fb_alloc_free_till_mark(); return mp_const_none; } - case FIR_MLX90640: - { + + case FIR_MLX90640: { width = 32; height = 24; - type = FIR_MLX90640; - soft_i2c_init(); + fir_sensor = FIR_MLX90640; + MLX90640_I2CInit(&fir_i2c); + // The EEPROM must be read at <= 400KHz. + cambus_init(&fir_i2c, FIR_I2C, I2C_TIMING_FULL); // parse refresh rate and ADC resolution IR_refresh_rate = py_helper_keyword_int(n_args, args, 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_refresh), 32); // 32Hz @@ -359,11 +370,7 @@ mp_obj_t py_fir_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) alpha_ij = xalloc(sizeof(paramsMLX90640)); - MLX90640_I2CFreqSet(SOFT_I2C_SPIN_DELAY); - MLX90640_I2CInit(); - int error = 0; - error |= MLX90640_SetResolution(MLX90640_ADDR, ADC_resolution); error |= MLX90640_SetRefreshRate(MLX90640_ADDR, IR_refresh_rate); @@ -372,22 +379,26 @@ mp_obj_t py_fir_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) error |= MLX90640_DumpEE(MLX90640_ADDR, eeprom); error |= MLX90640_ExtractParameters(eeprom, (paramsMLX90640 *) alpha_ij); + // Switch to FAST speed + cambus_deinit(&fir_i2c); + cambus_init(&fir_i2c, FIR_I2C, I2C_TIMING_FAST); + PY_ASSERT_TRUE_MSG(error == 0, "Failed to init the MLX90640!"); fb_alloc_free_till_mark(); return mp_const_none; } - case FIR_AMG8833: - { + + case FIR_AMG8833: { width = 8; height = 8; - type = FIR_AMG8833; - soft_i2c_init(); + fir_sensor = FIR_AMG8833; + cambus_init(&fir_i2c, FIR_I2C, I2C_TIMING_STANDARD); IR_refresh_rate = 10; ADC_resolution = 12; - test_ack(soft_i2c_write_bytes(AMG8833_ADDR, (uint8_t [2]){0x01, 0x3F}, 2, true)); + test_ack(cambus_write_bytes(&fir_i2c, AMG8833_ADDR, 0x01, (uint8_t [1]){0x3F}, 1)); return mp_const_none; } @@ -398,22 +409,22 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_fir_init_obj, 0, py_fir_init); static mp_obj_t py_fir_width() { - if (type == FIR_NONE) return mp_const_none; + if (fir_sensor == FIR_NONE) return mp_const_none; return mp_obj_new_int(width); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_width_obj, py_fir_width); static mp_obj_t py_fir_height() { - if (type == FIR_NONE) return mp_const_none; + if (fir_sensor == FIR_NONE) return mp_const_none; return mp_obj_new_int(height); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_height_obj, py_fir_height); static mp_obj_t py_fir_type() { - if (type == FIR_NONE) return mp_const_none; - return mp_obj_new_int(type); + if (fir_sensor == FIR_NONE) return mp_const_none; + return mp_obj_new_int(fir_sensor); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_type_obj, py_fir_type); @@ -421,31 +432,30 @@ static mp_obj_t py_fir_refresh() { const int mlx_90621_refresh_rates[16] = {512, 512, 512, 512, 512, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0}; const int mlx_90640_refresh_rates[8] = {0, 1, 2, 4, 8, 16, 32, 64}; - if (type == FIR_NONE) return mp_const_none; - if (type == FIR_SHIELD) return mp_obj_new_int(mlx_90621_refresh_rates[IR_refresh_rate]); - if (type == FIR_MLX90640) return mp_obj_new_int(mlx_90640_refresh_rates[IR_refresh_rate]); - if (type == FIR_AMG8833) return mp_obj_new_int(IR_refresh_rate); + if (fir_sensor == FIR_NONE) return mp_const_none; + if (fir_sensor == FIR_SHIELD) return mp_obj_new_int(mlx_90621_refresh_rates[IR_refresh_rate]); + if (fir_sensor == FIR_MLX90640) return mp_obj_new_int(mlx_90640_refresh_rates[IR_refresh_rate]); + if (fir_sensor == FIR_AMG8833) return mp_obj_new_int(IR_refresh_rate); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_refresh_obj, py_fir_refresh); static mp_obj_t py_fir_resolution() { - if (type == FIR_NONE) return mp_const_none; - if (type == FIR_SHIELD) return mp_obj_new_int(ADC_resolution + 15); - if (type == FIR_MLX90640) return mp_obj_new_int(ADC_resolution + 16); - if (type == FIR_AMG8833) return mp_obj_new_int(ADC_resolution); + if (fir_sensor == FIR_NONE) return mp_const_none; + if (fir_sensor == FIR_SHIELD) return mp_obj_new_int(ADC_resolution + 15); + if (fir_sensor == FIR_MLX90640) return mp_obj_new_int(ADC_resolution + 16); + if (fir_sensor == FIR_AMG8833) return mp_obj_new_int(ADC_resolution); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_resolution_obj, py_fir_resolution); mp_obj_t py_fir_read_ta() { - switch(type) { + switch(fir_sensor) { case FIR_NONE: return mp_const_none; case FIR_SHIELD: return mp_obj_new_float(calculate_Ta()); - case FIR_MLX90640: - { + case FIR_MLX90640: { fb_alloc_mark(); uint16_t *data = fb_alloc(834 * sizeof(uint16_t), FB_ALLOC_NO_HINT); PY_ASSERT_TRUE_MSG(MLX90640_GetFrameData(MLX90640_ADDR, data) >= 0, @@ -454,11 +464,10 @@ mp_obj_t py_fir_read_ta() fb_alloc_free_till_mark(); return result; } - case FIR_AMG8833: - { - test_ack(soft_i2c_write_bytes(AMG8833_ADDR, (uint8_t [1]){0x0E}, 1, true)); + + case FIR_AMG8833: { int16_t temp; - test_ack(soft_i2c_read_bytes(AMG8833_ADDR, (uint8_t *) &temp, 2, true)); + test_ack(cambus_read_bytes(&fir_i2c, AMG8833_ADDR, 0x0E, (uint8_t *) &temp, 2)); if ((temp >> 11) & 1) temp |= 1 << 15; temp &= 0x87FF; return mp_obj_new_float(temp * 0.0625); @@ -470,10 +479,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_read_ta_obj, py_fir_read_ta); mp_obj_t py_fir_read_ir() { - switch(type) { - case FIR_NONE: return mp_const_none; - case FIR_SHIELD: - { + switch(fir_sensor) { + case FIR_NONE: { + return mp_const_none; + } + + case FIR_SHIELD: { fb_alloc_mark(); float *To = fb_alloc(64 * sizeof(float), FB_ALLOC_NO_HINT), *To_rot = fb_alloc(64 * sizeof(float), FB_ALLOC_NO_HINT); float Ta = calculate_Ta(); @@ -504,8 +515,8 @@ mp_obj_t py_fir_read_ir() fb_alloc_free_till_mark(); return mp_obj_new_tuple(4, tuple); } - case FIR_MLX90640: - { + + case FIR_MLX90640: { fb_alloc_mark(); uint16_t *data = fb_alloc(834 * sizeof(uint16_t), FB_ALLOC_NO_HINT); // Calculate 1st sub-frame... @@ -541,19 +552,17 @@ mp_obj_t py_fir_read_ir() fb_alloc_free_till_mark(); return mp_obj_new_tuple(4, tuple); } - case FIR_AMG8833: - { - test_ack(soft_i2c_write_bytes(AMG8833_ADDR, (uint8_t [1]){0x0E}, 1, true)); + + case FIR_AMG8833: { int16_t temp; - test_ack(soft_i2c_read_bytes(AMG8833_ADDR, (uint8_t *) &temp, 2, true)); + test_ack(cambus_read_bytes(&fir_i2c, AMG8833_ADDR, 0x0E, (uint8_t *) &temp, 2)); if ((temp >> 11) & 1) temp |= 1 << 15; temp &= 0x87FF; float Ta = temp * 0.0625; - test_ack(soft_i2c_write_bytes(AMG8833_ADDR, (uint8_t [1]){0x80}, 1, true)); fb_alloc_mark(); int16_t *data = fb_alloc(64 * sizeof(int16_t), FB_ALLOC_NO_HINT); - test_ack(soft_i2c_read_bytes(AMG8833_ADDR, (uint8_t *) data, 128, true)); + test_ack(cambus_read_bytes(&fir_i2c, AMG8833_ADDR, 0x80, (uint8_t *) data, 128)); float To[64], min = FLT_MAX, max = FLT_MIN; for (int i = 0; i < 64; i++) { if ((data[i] >> 11) & 1) data[i] |= 1 << 15; @@ -585,7 +594,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_read_ir_obj, py_fir_read_ir); mp_obj_t py_fir_draw_ta(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { - if (type == FIR_NONE) return mp_const_none; + if (fir_sensor == FIR_NONE) return mp_const_none; image_t *arg_img = py_helper_arg_to_image_mutable(args[0]); float Ta = mp_obj_get_float(args[1]); @@ -611,22 +620,22 @@ mp_obj_t py_fir_draw_ta(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) for (int y=0; yh; y++) { for (int x=0; xw; x++) { switch (arg_img->bpp) { - case IMAGE_BPP_BINARY: - { + case IMAGE_BPP_BINARY: { uint8_t pixel = COLOR_BINARY_TO_GRAYSCALE(IMAGE_GET_BINARY_PIXEL(arg_img, x, y)); uint32_t vgs = __PKHBT(pixel, gs_ta, 16); uint32_t gs = __SMUAD(va, vgs)>>8; IMAGE_PUT_BINARY_PIXEL(arg_img, x, y, COLOR_GRAYSCALE_TO_BINARY(gs)); break; } - case IMAGE_BPP_GRAYSCALE: - { + + case IMAGE_BPP_GRAYSCALE: { uint8_t pixel = IMAGE_GET_GRAYSCALE_PIXEL(arg_img, x, y); uint32_t vgs = __PKHBT(pixel, gs_ta, 16); uint32_t gs = __SMUAD(va, vgs)>>8; IMAGE_PUT_GRAYSCALE_PIXEL(arg_img, x, y, gs); break; } + case IMAGE_BPP_RGB565: { uint16_t pixel = IMAGE_GET_RGB565_PIXEL(arg_img, x, y); uint32_t vr = __PKHBT(COLOR_RGB565_TO_R5(pixel), r_ta, 16); @@ -648,7 +657,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_fir_draw_ta_obj, 2, py_fir_draw_ta); mp_obj_t py_fir_draw_ir(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { - if (type == FIR_NONE) return mp_const_none; + if (fir_sensor == FIR_NONE) return mp_const_none; image_t *arg_img = py_helper_arg_to_image_mutable(args[0]); mp_obj_t *arg_To; @@ -687,22 +696,22 @@ mp_obj_t py_fir_draw_ir(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) uint16_t g_to = COLOR_RGB565_TO_G6(rainbow_table[gs_to]); uint16_t b_to = COLOR_RGB565_TO_B5(rainbow_table[gs_to]); switch (arg_img->bpp) { - case IMAGE_BPP_BINARY: - { + case IMAGE_BPP_BINARY: { uint8_t pixel = COLOR_BINARY_TO_GRAYSCALE(IMAGE_GET_BINARY_PIXEL(arg_img, x, y)); uint32_t vgs = __PKHBT(pixel, gs_to, 16); uint32_t gs = __SMUAD(va, vgs)>>8; IMAGE_PUT_BINARY_PIXEL(arg_img, x, y, COLOR_GRAYSCALE_TO_BINARY(gs)); break; } - case IMAGE_BPP_GRAYSCALE: - { + + case IMAGE_BPP_GRAYSCALE: { uint8_t pixel = IMAGE_GET_GRAYSCALE_PIXEL(arg_img, x, y); uint32_t vgs = __PKHBT(pixel, gs_to, 16); uint32_t gs = __SMUAD(va, vgs)>>8; IMAGE_PUT_GRAYSCALE_PIXEL(arg_img, x, y, gs); break; } + case IMAGE_BPP_RGB565: { uint16_t pixel = IMAGE_GET_RGB565_PIXEL(arg_img, x, y); uint32_t vr = __PKHBT(COLOR_RGB565_TO_R5(pixel), r_to, 16); @@ -725,7 +734,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_fir_draw_ir_obj, 2, py_fir_draw_ir); mp_obj_t py_fir_snapshot(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { - if (type == FIR_NONE) return mp_const_none; + if (fir_sensor == FIR_NONE) return mp_const_none; mp_obj_t ir = py_fir_read_ir(); size_t len; mp_obj_t *items; diff --git a/src/omv/stm32fxxx_hal_msp.c b/src/omv/stm32fxxx_hal_msp.c index 95bc80de3..15594c718 100644 --- a/src/omv/stm32fxxx_hal_msp.c +++ b/src/omv/stm32fxxx_hal_msp.c @@ -172,13 +172,36 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) GPIO_InitStructure.Pin = SCCB_SDA_PIN; HAL_GPIO_Init(SCCB_PORT, &GPIO_InitStructure); + } else if (hi2c->Instance == FIR_I2C) { + /* Enable I2C clock */ + FIR_I2C_CLK_ENABLE(); + + /* Configure FIR I2C GPIOs */ + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_LOW; + GPIO_InitStructure.Mode = GPIO_MODE_AF_OD; + GPIO_InitStructure.Alternate = FIR_I2C_AF; + + GPIO_InitStructure.Pin = FIR_I2C_SCL_PIN; + HAL_GPIO_Init(FIR_I2C_PORT, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = FIR_I2C_SDA_PIN; + HAL_GPIO_Init(FIR_I2C_PORT, &GPIO_InitStructure); } + } void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c) { if (hi2c->Instance == SCCB_I2C) { + SCCB_FORCE_RESET(); + SCCB_RELEASE_RESET(); SCCB_CLK_DISABLE(); + } else if (hi2c->Instance == FIR_I2C) { + FIR_I2C_FORCE_RESET(); + FIR_I2C_RELEASE_RESET(); + FIR_I2C_CLK_DISABLE(); } }