Merge pull request #792 from openmv/fix_softi2c

Fix softi2c
This commit is contained in:
Ibrahim Abd Elkader 2020-05-11 15:02:28 +02:00 committed by GitHub
commit b912fd6b64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 286 additions and 510 deletions

View File

@ -6,7 +6,7 @@
import image, time, fir import image, time, fir
# Initialize the thermal sensor # 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 # FPS clock
clock = time.clock() clock = time.clock()

View File

@ -6,7 +6,7 @@
import image, time, fir, lcd import image, time, fir, lcd
# Initialize the thermal sensor # 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. # Init the lcd.
lcd.init() lcd.init()

View File

@ -13,7 +13,7 @@ sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time = 2000) sensor.skip_frames(time = 2000)
# Initialize the thermal sensor # 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. # Allocate another frame buffer for smoother video.
extra_fb = sensor.alloc_extra_fb(sensor.width(), sensor.height(), sensor.RGB565) extra_fb = sensor.alloc_extra_fb(sensor.width(), sensor.height(), sensor.RGB565)

View File

@ -13,7 +13,7 @@ sensor.set_framesize(sensor.QQVGA2)
sensor.skip_frames(time = 2000) sensor.skip_frames(time = 2000)
# Initialize the thermal sensor # 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. # Init the lcd.
lcd.init() lcd.init()

View File

@ -13,7 +13,7 @@ sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time = 2000) sensor.skip_frames(time = 2000)
# Initialize the thermal sensor # 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. # Allocate another frame buffer for smoother video.
ir_buffer = image.Image(fir.width() * IR_SCALE, fir.height() * IR_SCALE, sensor.GRAYSCALE) ir_buffer = image.Image(fir.width() * IR_SCALE, fir.height() * IR_SCALE, sensor.GRAYSCALE)

View File

@ -18,8 +18,9 @@
#define _MLX90640_I2C_Driver_H_ #define _MLX90640_I2C_Driver_H_
#include <stdint.h> #include <stdint.h>
#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_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); int MLX90640_I2CWrite(uint8_t slaveAddr,uint16_t writeAddress, uint16_t data);
void MLX90640_I2CFreqSet(int freq); void MLX90640_I2CFreqSet(int freq);

View File

@ -64,7 +64,7 @@ int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData)
dataReady = statusRegister & 0x0008; dataReady = statusRegister & 0x0008;
} }
while(dataReady != 0 && cnt < 5) while(dataReady != 0 && cnt < 32)
{ {
error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030); error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030);
if(error == -1) if(error == -1)
@ -87,7 +87,7 @@ int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData)
cnt = cnt + 1; cnt = cnt + 1;
} }
if(cnt > 4) if(cnt > 31)
{ {
return -8; return -8;
} }

View File

@ -14,94 +14,38 @@
* limitations under the License. * limitations under the License.
* *
*/ */
/*#include "mbed.h" #include <stdio.h>
#include STM32_HAL_H
#include "cambus.h"
#include "MLX90640_I2C_Driver.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) int MLX90640_I2CRead(uint8_t slaveAddr, uint16_t startAddress, uint16_t nMemAddressRead, uint16_t *data)
{ {
uint8_t sa; uint8_t* p = (uint8_t*) data;
int ack = 0; if (cambus_readw_bytes(hi2c, (slaveAddr<<1), startAddress, p, nMemAddressRead*2) != 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)
{
return -1; return -1;
} }
sa = sa | 0x01; for(int cnt=0; cnt < nMemAddressRead*2; cnt+=2) {
ack = i2c.read(sa, i2cData, 2*nMemAddressRead, 0); uint8_t tempBuffer = p[cnt+1];
p[cnt+1] = p[cnt];
if (ack != 0x00) p[cnt] = tempBuffer;
{
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; return 0;
} }
void MLX90640_I2CFreqSet(int freq)
{
i2c.frequency(1000*freq);
}
int MLX90640_I2CWrite(uint8_t slaveAddr, uint16_t writeAddress, uint16_t data) int MLX90640_I2CWrite(uint8_t slaveAddr, uint16_t writeAddress, uint16_t data)
{ {
uint8_t sa; if (cambus_writew2(hi2c, (slaveAddr << 1), writeAddress, data) != 0) {
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)
{
return -1; return -1;
} }
i2c.stop();
MLX90640_I2CRead(slaveAddr,writeAddress,1, &dataCheck);
if ( dataCheck != data)
{
return -2;
}
return 0; return 0;
}*/ }

View File

@ -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;j<nBytes;j++)
{
Wait(freqCnt);
SDA_HIGH;
data = 0;
for(int i=0;i<8;i++){
Wait(freqCnt);
SCL_HIGH;
Wait(freqCnt);
data = data<<1;
if(sda == 1){
data = data+1;
}
Wait(freqCnt);
SCL_LOW;
Wait(freqCnt);
}
if(j == (nBytes-1))
{
I2CSendNack();
}
else
{
I2CSendACK();
}
*(dataP+j) = data;
}
}
void Wait(int freqCnt)
{
for(volatile int i = 0;i<freqCnt;i++);
}
void I2CStart(void)
{
SDA_HIGH;
SCL_HIGH;
Wait(freqCnt);
Wait(freqCnt);
SDA_LOW;
Wait(freqCnt);
SCL_LOW;
Wait(freqCnt);
}
void I2CStop(void)
{
SCL_LOW;
SDA_LOW;
Wait(freqCnt);
SCL_HIGH;
Wait(freqCnt);
SDA_HIGH;
Wait(freqCnt);
}
void I2CRepeatedStart(void)
{
SCL_LOW;
Wait(freqCnt);
SDA_HIGH;
Wait(freqCnt);
SCL_HIGH;
Wait(freqCnt);
SDA_LOW;
Wait(freqCnt);
SCL_LOW;
}
void I2CSendACK(void)
{
SDA_LOW;
Wait(freqCnt);
SCL_HIGH;
Wait(freqCnt);
Wait(freqCnt);
SCL_LOW;
Wait(freqCnt);
SDA_HIGH;
}
void I2CSendNack(void)
{
SDA_HIGH;
Wait(freqCnt);
SCL_HIGH;
Wait(freqCnt);
Wait(freqCnt);
SCL_LOW;
Wait(freqCnt);
SDA_HIGH;
}
int I2CReceiveAck(void)
{
int ack;
SDA_HIGH;
Wait(freqCnt);
SCL_HIGH;
Wait(freqCnt);
if(sda == 0)
{
ack = 0;
}
else
{
ack = 1;
}
Wait(freqCnt);
SCL_LOW;
SDA_LOW;
return ack;
}

View File

@ -108,6 +108,20 @@
#define SCCB_SCL_PIN (GPIO_PIN_8) #define SCCB_SCL_PIN (GPIO_PIN_8)
#define SCCB_SDA_PIN (GPIO_PIN_9) #define SCCB_SDA_PIN (GPIO_PIN_9)
#define SCCB_TIMING (I2C_TIMING_STANDARD) // ignored #define SCCB_TIMING (I2C_TIMING_STANDARD) // ignored
#define SCCB_FORCE_RESET() __HAL_RCC_I2C1_FORCE_RESET()
#define SCCB_RELEASE_RESET() __HAL_RCC_I2C1_RELEASE_RESET()
/* FIR I2C */
#define FIR_I2C (I2C2)
#define FIR_I2C_AF (GPIO_AF4_I2C2)
#define FIR_I2C_CLK_ENABLE() __I2C2_CLK_ENABLE()
#define FIR_I2C_CLK_DISABLE() __I2C2_CLK_DISABLE()
#define FIR_I2C_PORT (GPIOB)
#define FIR_I2C_SCL_PIN (GPIO_PIN_10)
#define FIR_I2C_SDA_PIN (GPIO_PIN_11)
#define FIR_I2C_TIMING (I2C_TIMING_FULL)
#define FIR_I2C_FORCE_RESET() __HAL_RCC_I2C2_FORCE_RESET()
#define FIR_I2C_RELEASE_RESET() __HAL_RCC_I2C2_RELEASE_RESET()
/* DCMI */ /* DCMI */
#define DCMI_TIM (TIM1) #define DCMI_TIM (TIM1)

View File

@ -106,6 +106,20 @@
#define SCCB_SCL_PIN (GPIO_PIN_8) #define SCCB_SCL_PIN (GPIO_PIN_8)
#define SCCB_SDA_PIN (GPIO_PIN_9) #define SCCB_SDA_PIN (GPIO_PIN_9)
#define SCCB_TIMING (I2C_TIMING_STANDARD) #define SCCB_TIMING (I2C_TIMING_STANDARD)
#define SCCB_FORCE_RESET() __HAL_RCC_I2C1_FORCE_RESET()
#define SCCB_RELEASE_RESET() __HAL_RCC_I2C1_RELEASE_RESET()
/* FIR I2C */
#define FIR_I2C (I2C2)
#define FIR_I2C_AF (GPIO_AF4_I2C2)
#define FIR_I2C_CLK_ENABLE() __I2C2_CLK_ENABLE()
#define FIR_I2C_CLK_DISABLE() __I2C2_CLK_DISABLE()
#define FIR_I2C_PORT (GPIOB)
#define FIR_I2C_SCL_PIN (GPIO_PIN_10)
#define FIR_I2C_SDA_PIN (GPIO_PIN_11)
#define FIR_I2C_TIMING (I2C_TIMING_FULL)
#define FIR_I2C_FORCE_RESET() __HAL_RCC_I2C2_FORCE_RESET()
#define FIR_I2C_RELEASE_RESET() __HAL_RCC_I2C2_RELEASE_RESET()
/* DCMI */ /* DCMI */
#define DCMI_TIM (TIM1) #define DCMI_TIM (TIM1)

View File

@ -155,6 +155,20 @@
#define SCCB_SCL_PIN (GPIO_PIN_8) #define SCCB_SCL_PIN (GPIO_PIN_8)
#define SCCB_SDA_PIN (GPIO_PIN_9) #define SCCB_SDA_PIN (GPIO_PIN_9)
#define SCCB_TIMING (I2C_TIMING_STANDARD) #define SCCB_TIMING (I2C_TIMING_STANDARD)
#define SCCB_FORCE_RESET() __HAL_RCC_I2C1_FORCE_RESET()
#define SCCB_RELEASE_RESET() __HAL_RCC_I2C1_RELEASE_RESET()
/* FIR I2C */
#define FIR_I2C (I2C2)
#define FIR_I2C_AF (GPIO_AF4_I2C2)
#define FIR_I2C_CLK_ENABLE() __I2C2_CLK_ENABLE()
#define FIR_I2C_CLK_DISABLE() __I2C2_CLK_DISABLE()
#define FIR_I2C_PORT (GPIOB)
#define FIR_I2C_SCL_PIN (GPIO_PIN_10)
#define FIR_I2C_SDA_PIN (GPIO_PIN_11)
#define FIR_I2C_TIMING (I2C_TIMING_FULL)
#define FIR_I2C_FORCE_RESET() __HAL_RCC_I2C2_FORCE_RESET()
#define FIR_I2C_RELEASE_RESET() __HAL_RCC_I2C2_RELEASE_RESET()
/* DCMI */ /* DCMI */
#define DCMI_TIM (TIM1) #define DCMI_TIM (TIM1)
@ -253,7 +267,7 @@
#define SOFT_I2C_SIOD_READ() HAL_GPIO_ReadPin (SOFT_I2C_PORT, SOFT_I2C_SIOD_PIN) #define SOFT_I2C_SIOD_READ() HAL_GPIO_ReadPin (SOFT_I2C_PORT, SOFT_I2C_SIOD_PIN)
#define SOFT_I2C_SIOD_WRITE(bit) HAL_GPIO_WritePin(SOFT_I2C_PORT, SOFT_I2C_SIOD_PIN, bit); #define SOFT_I2C_SIOD_WRITE(bit) HAL_GPIO_WritePin(SOFT_I2C_PORT, SOFT_I2C_SIOD_PIN, bit);
#define SOFT_I2C_SPIN_DELAY 32 #define SOFT_I2C_SPIN_DELAY 64
#define LEPTON_SPI (SPI3) #define LEPTON_SPI (SPI3)
#define LEPTON_SPI_AF (GPIO_AF6_SPI3) #define LEPTON_SPI_AF (GPIO_AF6_SPI3)

View File

@ -164,6 +164,20 @@
#define SCCB_SCL_PIN (GPIO_PIN_8) #define SCCB_SCL_PIN (GPIO_PIN_8)
#define SCCB_SDA_PIN (GPIO_PIN_9) #define SCCB_SDA_PIN (GPIO_PIN_9)
#define SCCB_TIMING (I2C_TIMING_STANDARD) #define SCCB_TIMING (I2C_TIMING_STANDARD)
#define SCCB_FORCE_RESET() __HAL_RCC_I2C1_FORCE_RESET()
#define SCCB_RELEASE_RESET() __HAL_RCC_I2C1_RELEASE_RESET()
/* FIR I2C */
#define FIR_I2C (I2C2)
#define FIR_I2C_AF (GPIO_AF4_I2C2)
#define FIR_I2C_CLK_ENABLE() __I2C2_CLK_ENABLE()
#define FIR_I2C_CLK_DISABLE() __I2C2_CLK_DISABLE()
#define FIR_I2C_PORT (GPIOB)
#define FIR_I2C_SCL_PIN (GPIO_PIN_10)
#define FIR_I2C_SDA_PIN (GPIO_PIN_11)
#define FIR_I2C_TIMING (I2C_TIMING_FULL)
#define FIR_I2C_FORCE_RESET() __HAL_RCC_I2C2_FORCE_RESET()
#define FIR_I2C_RELEASE_RESET() __HAL_RCC_I2C2_RELEASE_RESET()
/* DCMI */ /* DCMI */
#define DCMI_TIM (TIM1) #define DCMI_TIM (TIM1)
@ -262,7 +276,7 @@
#define SOFT_I2C_SIOD_READ() HAL_GPIO_ReadPin (SOFT_I2C_PORT, SOFT_I2C_SIOD_PIN) #define SOFT_I2C_SIOD_READ() HAL_GPIO_ReadPin (SOFT_I2C_PORT, SOFT_I2C_SIOD_PIN)
#define SOFT_I2C_SIOD_WRITE(bit) HAL_GPIO_WritePin(SOFT_I2C_PORT, SOFT_I2C_SIOD_PIN, bit); #define SOFT_I2C_SIOD_WRITE(bit) HAL_GPIO_WritePin(SOFT_I2C_PORT, SOFT_I2C_SIOD_PIN, bit);
#define SOFT_I2C_SPIN_DELAY 128 #define SOFT_I2C_SPIN_DELAY 64
#define LEPTON_SPI (SPI3) #define LEPTON_SPI (SPI3)
#define LEPTON_SPI_AF (GPIO_AF6_SPI3) #define LEPTON_SPI_AF (GPIO_AF6_SPI3)

View File

@ -152,6 +152,21 @@
#define SCCB_SCL_PIN (GPIO_PIN_6) #define SCCB_SCL_PIN (GPIO_PIN_6)
#define SCCB_SDA_PIN (GPIO_PIN_7) #define SCCB_SDA_PIN (GPIO_PIN_7)
#define SCCB_TIMING (I2C_TIMING_STANDARD) #define SCCB_TIMING (I2C_TIMING_STANDARD)
#define SCCB_FORCE_RESET() __HAL_RCC_I2C1_FORCE_RESET()
#define SCCB_RELEASE_RESET() __HAL_RCC_I2C1_RELEASE_RESET()
/* FIR I2C */
// TODO which I2C can be used for external sensors ?
#define FIR_I2C (I2C2)
#define FIR_I2C_AF (GPIO_AF4_I2C2)
#define FIR_I2C_CLK_ENABLE() __I2C2_CLK_ENABLE()
#define FIR_I2C_CLK_DISABLE() __I2C2_CLK_DISABLE()
#define FIR_I2C_PORT (GPIOB)
#define FIR_I2C_SCL_PIN (GPIO_PIN_10)
#define FIR_I2C_SDA_PIN (GPIO_PIN_11)
#define FIR_I2C_TIMING (I2C_TIMING_FULL)
#define FIR_I2C_FORCE_RESET() __HAL_RCC_I2C2_FORCE_RESET()
#define FIR_I2C_RELEASE_RESET() __HAL_RCC_I2C2_RELEASE_RESET()
#define DCMI_PWDN_PIN (GPIO_PIN_4) #define DCMI_PWDN_PIN (GPIO_PIN_4)
#define DCMI_PWDN_PORT (GPIOD) #define DCMI_PWDN_PORT (GPIOD)
@ -225,7 +240,7 @@
#define SOFT_I2C_SIOD_READ() HAL_GPIO_ReadPin (SOFT_I2C_PORT, SOFT_I2C_SIOD_PIN) #define SOFT_I2C_SIOD_READ() HAL_GPIO_ReadPin (SOFT_I2C_PORT, SOFT_I2C_SIOD_PIN)
#define SOFT_I2C_SIOD_WRITE(bit) HAL_GPIO_WritePin(SOFT_I2C_PORT, SOFT_I2C_SIOD_PIN, bit); #define SOFT_I2C_SIOD_WRITE(bit) HAL_GPIO_WritePin(SOFT_I2C_PORT, SOFT_I2C_SIOD_PIN, bit);
#define SOFT_I2C_SPIN_DELAY 32 #define SOFT_I2C_SPIN_DELAY 64
// Enable additional GPIO banks for DRAM... // Enable additional GPIO banks for DRAM...
#define OMV_ENABLE_GPIO_BANK_F #define OMV_ENABLE_GPIO_BANK_F

View File

@ -38,6 +38,16 @@ int cambus_init(I2C_HandleTypeDef *i2c, I2C_TypeDef *instance, uint32_t timing)
/* Initialization Error */ /* Initialization Error */
return -1; return -1;
} }
return 0;
}
int cambus_deinit(I2C_HandleTypeDef *i2c)
{
if (i2c->Instance) {
HAL_I2C_DeInit(i2c);
}
i2c->Instance = NULL;
return 0; return 0;
} }
@ -156,3 +166,51 @@ int cambus_writew2(I2C_HandleTypeDef *i2c, uint8_t slv_addr, uint16_t reg_addr,
__enable_irq(); __enable_irq();
return ret; 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;
}

View File

@ -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_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_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_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__ #endif // __CAMBUS_H__

View File

@ -10,6 +10,7 @@
*/ */
#include <stdbool.h> #include <stdbool.h>
#include "soft_i2c.h" #include "soft_i2c.h"
#include "cambus.h"
#include "MLX90640_I2C_Driver.h" #include "MLX90640_I2C_Driver.h"
#include "MLX90640_API.h" #include "MLX90640_API.h"
#include "omv_boardconfig.h" #include "omv_boardconfig.h"
@ -86,9 +87,6 @@
((((_OldValue-_OldMin)*(_NewMax-_NewMin))+((_OldMax-OldMin)/2)) / \ ((((_OldValue-_OldMin)*(_NewMax-_NewMin))+((_OldMax-OldMin)/2)) / \
(_OldMax-OldMin))+_NewMin; }) (_OldMax-OldMin))+_NewMin; })
// Grayscale to RGB565 conversion
extern const uint16_t rainbow_table[256];
// MLX variables // MLX variables
static float *a_ij = NULL; static float *a_ij = NULL;
static float *b_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 width = 0;
static uint8_t height = 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 IR_refresh_rate = 0;
static uint8_t ADC_resolution = 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) static void test_ack(int ret)
{ {
PY_ASSERT_TRUE_MSG(ret == 0, "I2C Bus communication error - missing ACK!"); PY_ASSERT_TRUE_MSG(ret == 0, "I2C Bus communication error - missing ACK!");
@ -197,18 +206,10 @@ static void calculate_To(float Ta, float *To)
static mp_obj_t py_fir_deinit() static mp_obj_t py_fir_deinit()
{ {
switch (type) {
case FIR_NONE:
return mp_const_none;
case FIR_SHIELD:
case FIR_MLX90640:
case FIR_AMG8833:
soft_i2c_deinit();
width = 0; width = 0;
height = 0; height = 0;
type = FIR_NONE;
IR_refresh_rate = 0;
ADC_resolution = 0; ADC_resolution = 0;
IR_refresh_rate = 0;
if (a_ij) { if (a_ij) {
a_ij = NULL; a_ij = NULL;
} }
@ -218,8 +219,19 @@ static mp_obj_t py_fir_deinit()
if (alpha_ij) { if (alpha_ij) {
alpha_ij = NULL; alpha_ij = NULL;
} }
return mp_const_none;
switch (fir_sensor) {
case FIR_NONE:
break;
case FIR_SHIELD:
soft_i2c_deinit();
break;
case FIR_MLX90640:
case FIR_AMG8833:
cambus_deinit(&fir_i2c);
break;
} }
fir_sensor = FIR_NONE;
return mp_const_none; return mp_const_none;
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_deinit_obj, py_fir_deinit); 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: calling:
fir.init() 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) mp_obj_t py_fir_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{ {
py_fir_deinit(); py_fir_deinit();
switch (py_helper_keyword_int(n_args, args, 0, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_type), FIR_SHIELD)) { 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; return mp_const_none;
} }
case FIR_SHIELD:
{ case FIR_SHIELD: {
width = 16; width = 16;
height = 4; height = 4;
type = FIR_SHIELD; fir_sensor = FIR_SHIELD;
soft_i2c_init(); soft_i2c_init();
// parse refresh rate and ADC resolution // 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(); fb_alloc_mark();
uint8_t *eeprom = fb_alloc(256 * sizeof(uint8_t), FB_ALLOC_NO_HINT); uint8_t *eeprom = fb_alloc(256 * sizeof(uint8_t), FB_ALLOC_NO_HINT);
// Read the whole eeprom. // Read the whole eeprom.
test_ack(soft_i2c_write_bytes(FIR_EEPROM_ADDR, test_ack(soft_i2c_write_bytes(FIR_EEPROM_ADDR, (uint8_t [1]){0x00}, 1, false));
(uint8_t [1]){0x00}, 1, false)); test_ack(soft_i2c_read_bytes(FIR_EEPROM_ADDR, eeprom, 256, true));
test_ack(soft_i2c_read_bytes(FIR_EEPROM_ADDR,
eeprom, 256, true));
// Write oscillator trimming value. // Write oscillator trimming value.
soft_i2c_write_bytes(FIR_MODULE_ADDR, 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(); fb_alloc_free_till_mark();
return mp_const_none; return mp_const_none;
} }
case FIR_MLX90640:
{ case FIR_MLX90640: {
width = 32; width = 32;
height = 24; height = 24;
type = FIR_MLX90640; fir_sensor = FIR_MLX90640;
soft_i2c_init(); 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 // 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 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)); alpha_ij = xalloc(sizeof(paramsMLX90640));
MLX90640_I2CFreqSet(SOFT_I2C_SPIN_DELAY);
MLX90640_I2CInit();
int error = 0; int error = 0;
error |= MLX90640_SetResolution(MLX90640_ADDR, ADC_resolution); error |= MLX90640_SetResolution(MLX90640_ADDR, ADC_resolution);
error |= MLX90640_SetRefreshRate(MLX90640_ADDR, IR_refresh_rate); 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_DumpEE(MLX90640_ADDR, eeprom);
error |= MLX90640_ExtractParameters(eeprom, (paramsMLX90640 *) alpha_ij); 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!"); PY_ASSERT_TRUE_MSG(error == 0, "Failed to init the MLX90640!");
fb_alloc_free_till_mark(); fb_alloc_free_till_mark();
return mp_const_none; return mp_const_none;
} }
case FIR_AMG8833:
{ case FIR_AMG8833: {
width = 8; width = 8;
height = 8; height = 8;
type = FIR_AMG8833; fir_sensor = FIR_AMG8833;
soft_i2c_init(); cambus_init(&fir_i2c, FIR_I2C, I2C_TIMING_STANDARD);
IR_refresh_rate = 10; IR_refresh_rate = 10;
ADC_resolution = 12; 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; 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() 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); return mp_obj_new_int(width);
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_width_obj, py_fir_width); STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_width_obj, py_fir_width);
static mp_obj_t py_fir_height() 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); return mp_obj_new_int(height);
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_height_obj, py_fir_height); STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_height_obj, py_fir_height);
static mp_obj_t py_fir_type() static mp_obj_t py_fir_type()
{ {
if (type == FIR_NONE) return mp_const_none; if (fir_sensor == FIR_NONE) return mp_const_none;
return mp_obj_new_int(type); return mp_obj_new_int(fir_sensor);
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_type_obj, py_fir_type); 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_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}; const int mlx_90640_refresh_rates[8] = {0, 1, 2, 4, 8, 16, 32, 64};
if (type == FIR_NONE) return mp_const_none; if (fir_sensor == FIR_NONE) return mp_const_none;
if (type == FIR_SHIELD) return mp_obj_new_int(mlx_90621_refresh_rates[IR_refresh_rate]); if (fir_sensor == 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 (fir_sensor == 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_AMG8833) return mp_obj_new_int(IR_refresh_rate);
return mp_const_none; return mp_const_none;
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_refresh_obj, py_fir_refresh); STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_refresh_obj, py_fir_refresh);
static mp_obj_t py_fir_resolution() static mp_obj_t py_fir_resolution()
{ {
if (type == FIR_NONE) return mp_const_none; if (fir_sensor == FIR_NONE) return mp_const_none;
if (type == FIR_SHIELD) return mp_obj_new_int(ADC_resolution + 15); if (fir_sensor == FIR_SHIELD) return mp_obj_new_int(ADC_resolution + 15);
if (type == FIR_MLX90640) return mp_obj_new_int(ADC_resolution + 16); if (fir_sensor == 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_AMG8833) return mp_obj_new_int(ADC_resolution);
return mp_const_none; return mp_const_none;
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_resolution_obj, py_fir_resolution); STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_fir_resolution_obj, py_fir_resolution);
mp_obj_t py_fir_read_ta() mp_obj_t py_fir_read_ta()
{ {
switch(type) { switch(fir_sensor) {
case FIR_NONE: return mp_const_none; case FIR_NONE: return mp_const_none;
case FIR_SHIELD: return mp_obj_new_float(calculate_Ta()); case FIR_SHIELD: return mp_obj_new_float(calculate_Ta());
case FIR_MLX90640: case FIR_MLX90640: {
{
fb_alloc_mark(); fb_alloc_mark();
uint16_t *data = fb_alloc(834 * sizeof(uint16_t), FB_ALLOC_NO_HINT); uint16_t *data = fb_alloc(834 * sizeof(uint16_t), FB_ALLOC_NO_HINT);
PY_ASSERT_TRUE_MSG(MLX90640_GetFrameData(MLX90640_ADDR, data) >= 0, 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(); fb_alloc_free_till_mark();
return result; return result;
} }
case FIR_AMG8833:
{ case FIR_AMG8833: {
test_ack(soft_i2c_write_bytes(AMG8833_ADDR, (uint8_t [1]){0x0E}, 1, true));
int16_t temp; 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; if ((temp >> 11) & 1) temp |= 1 << 15;
temp &= 0x87FF; temp &= 0x87FF;
return mp_obj_new_float(temp * 0.0625); 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() mp_obj_t py_fir_read_ir()
{ {
switch(type) { switch(fir_sensor) {
case FIR_NONE: return mp_const_none; case FIR_NONE: {
case FIR_SHIELD: return mp_const_none;
{ }
case FIR_SHIELD: {
fb_alloc_mark(); 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 *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(); float Ta = calculate_Ta();
@ -504,8 +515,8 @@ mp_obj_t py_fir_read_ir()
fb_alloc_free_till_mark(); fb_alloc_free_till_mark();
return mp_obj_new_tuple(4, tuple); return mp_obj_new_tuple(4, tuple);
} }
case FIR_MLX90640:
{ case FIR_MLX90640: {
fb_alloc_mark(); fb_alloc_mark();
uint16_t *data = fb_alloc(834 * sizeof(uint16_t), FB_ALLOC_NO_HINT); uint16_t *data = fb_alloc(834 * sizeof(uint16_t), FB_ALLOC_NO_HINT);
// Calculate 1st sub-frame... // Calculate 1st sub-frame...
@ -541,19 +552,17 @@ mp_obj_t py_fir_read_ir()
fb_alloc_free_till_mark(); fb_alloc_free_till_mark();
return mp_obj_new_tuple(4, tuple); return mp_obj_new_tuple(4, tuple);
} }
case FIR_AMG8833:
{ case FIR_AMG8833: {
test_ack(soft_i2c_write_bytes(AMG8833_ADDR, (uint8_t [1]){0x0E}, 1, true));
int16_t temp; 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; if ((temp >> 11) & 1) temp |= 1 << 15;
temp &= 0x87FF; temp &= 0x87FF;
float Ta = temp * 0.0625; float Ta = temp * 0.0625;
test_ack(soft_i2c_write_bytes(AMG8833_ADDR, (uint8_t [1]){0x80}, 1, true));
fb_alloc_mark(); fb_alloc_mark();
int16_t *data = fb_alloc(64 * sizeof(int16_t), FB_ALLOC_NO_HINT); 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; float To[64], min = FLT_MAX, max = FLT_MIN;
for (int i = 0; i < 64; i++) { for (int i = 0; i < 64; i++) {
if ((data[i] >> 11) & 1) data[i] |= 1 << 15; 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) 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]); image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
float Ta = mp_obj_get_float(args[1]); 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; y<arg_img->h; y++) { for (int y=0; y<arg_img->h; y++) {
for (int x=0; x<arg_img->w; x++) { for (int x=0; x<arg_img->w; x++) {
switch (arg_img->bpp) { 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)); 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 vgs = __PKHBT(pixel, gs_ta, 16);
uint32_t gs = __SMUAD(va, vgs)>>8; uint32_t gs = __SMUAD(va, vgs)>>8;
IMAGE_PUT_BINARY_PIXEL(arg_img, x, y, COLOR_GRAYSCALE_TO_BINARY(gs)); IMAGE_PUT_BINARY_PIXEL(arg_img, x, y, COLOR_GRAYSCALE_TO_BINARY(gs));
break; break;
} }
case IMAGE_BPP_GRAYSCALE:
{ case IMAGE_BPP_GRAYSCALE: {
uint8_t pixel = IMAGE_GET_GRAYSCALE_PIXEL(arg_img, x, y); uint8_t pixel = IMAGE_GET_GRAYSCALE_PIXEL(arg_img, x, y);
uint32_t vgs = __PKHBT(pixel, gs_ta, 16); uint32_t vgs = __PKHBT(pixel, gs_ta, 16);
uint32_t gs = __SMUAD(va, vgs)>>8; uint32_t gs = __SMUAD(va, vgs)>>8;
IMAGE_PUT_GRAYSCALE_PIXEL(arg_img, x, y, gs); IMAGE_PUT_GRAYSCALE_PIXEL(arg_img, x, y, gs);
break; break;
} }
case IMAGE_BPP_RGB565: { case IMAGE_BPP_RGB565: {
uint16_t pixel = IMAGE_GET_RGB565_PIXEL(arg_img, x, y); uint16_t pixel = IMAGE_GET_RGB565_PIXEL(arg_img, x, y);
uint32_t vr = __PKHBT(COLOR_RGB565_TO_R5(pixel), r_ta, 16); 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) 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]); image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
mp_obj_t *arg_To; 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 g_to = COLOR_RGB565_TO_G6(rainbow_table[gs_to]);
uint16_t b_to = COLOR_RGB565_TO_B5(rainbow_table[gs_to]); uint16_t b_to = COLOR_RGB565_TO_B5(rainbow_table[gs_to]);
switch (arg_img->bpp) { 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)); 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 vgs = __PKHBT(pixel, gs_to, 16);
uint32_t gs = __SMUAD(va, vgs)>>8; uint32_t gs = __SMUAD(va, vgs)>>8;
IMAGE_PUT_BINARY_PIXEL(arg_img, x, y, COLOR_GRAYSCALE_TO_BINARY(gs)); IMAGE_PUT_BINARY_PIXEL(arg_img, x, y, COLOR_GRAYSCALE_TO_BINARY(gs));
break; break;
} }
case IMAGE_BPP_GRAYSCALE:
{ case IMAGE_BPP_GRAYSCALE: {
uint8_t pixel = IMAGE_GET_GRAYSCALE_PIXEL(arg_img, x, y); uint8_t pixel = IMAGE_GET_GRAYSCALE_PIXEL(arg_img, x, y);
uint32_t vgs = __PKHBT(pixel, gs_to, 16); uint32_t vgs = __PKHBT(pixel, gs_to, 16);
uint32_t gs = __SMUAD(va, vgs)>>8; uint32_t gs = __SMUAD(va, vgs)>>8;
IMAGE_PUT_GRAYSCALE_PIXEL(arg_img, x, y, gs); IMAGE_PUT_GRAYSCALE_PIXEL(arg_img, x, y, gs);
break; break;
} }
case IMAGE_BPP_RGB565: { case IMAGE_BPP_RGB565: {
uint16_t pixel = IMAGE_GET_RGB565_PIXEL(arg_img, x, y); uint16_t pixel = IMAGE_GET_RGB565_PIXEL(arg_img, x, y);
uint32_t vr = __PKHBT(COLOR_RGB565_TO_R5(pixel), r_to, 16); 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) 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(); mp_obj_t ir = py_fir_read_ir();
size_t len; size_t len;
mp_obj_t *items; mp_obj_t *items;

View File

@ -172,13 +172,36 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
GPIO_InitStructure.Pin = SCCB_SDA_PIN; GPIO_InitStructure.Pin = SCCB_SDA_PIN;
HAL_GPIO_Init(SCCB_PORT, &GPIO_InitStructure); 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) void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c)
{ {
if (hi2c->Instance == SCCB_I2C) { if (hi2c->Instance == SCCB_I2C) {
SCCB_FORCE_RESET();
SCCB_RELEASE_RESET();
SCCB_CLK_DISABLE(); SCCB_CLK_DISABLE();
} else if (hi2c->Instance == FIR_I2C) {
FIR_I2C_FORCE_RESET();
FIR_I2C_RELEASE_RESET();
FIR_I2C_CLK_DISABLE();
} }
} }