From e8940d3dd9a3c23e904ac75c40cf1f8e546f52fe Mon Sep 17 00:00:00 2001 From: Kevin Townsend Date: Fri, 25 May 2012 11:33:11 +0200 Subject: [PATCH] New drivers --- ChangeLog.txt | 3 + Makefile | 4 + build/crossworks/LPC1343_CodeBase.hzp | 4 + build/crossworks/LPC1343_CodeBase.hzs | 19 +- core/i2c/i2c.h | 4 +- drivers/dac/mcp4725/mcp4725.h | 3 +- drivers/displays/tft/hw/hx8347d.c | 689 +++++++++++++------------- drivers/displays/tft/hw/hx8347d.h | 24 +- drivers/sensors/ina219/ina219.c | 569 +++++++++++++++++++++ drivers/sensors/ina219/ina219.h | 137 +++++ 10 files changed, 1087 insertions(+), 369 deletions(-) create mode 100644 drivers/sensors/ina219/ina219.c create mode 100644 drivers/sensors/ina219/ina219.h diff --git a/ChangeLog.txt b/ChangeLog.txt index 39c59ec..830c427 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -2,6 +2,8 @@ v1.1.2 - ongoing ============================================================================== NEW FEATURES ------------------------------------------------------------------------------ +- Added drivers/sensors/ina219/ina219.c (work in progress!) +- Added drivers/displays/tft/hw/hx8347d.C (courtesy tauonteilchen again) - Added drivers/dac/mcp4901 (courtesy tauonteilchen, thanks!) - Cleaned up /tools/testfirmware to include more recent blinky, etc. - Added basic TEA5767 drive @@ -17,6 +19,7 @@ BUG FIXES/OPTIMISATIONS/ETC. ------------------------------------------------------------------------------ - Minor accuracy improvement to pwm.c (off by 1 error) - Fixed typos in cmd_pwm.c and cmd_tbl.h +- Changed I2C default speed to 400kHz (from 100kHz) v1.1.1 - 14 April 2012 ============================================================================== diff --git a/Makefile b/Makefile index b3573c5..a3aa928 100644 --- a/Makefile +++ b/Makefile @@ -144,6 +144,10 @@ OBJS += w25q16bv.o VPATH += drivers/audio/tea5767 OBJS += tea5767.o +# IN219 Current Sensor +VPATH += drivers/sensors/ina219 +OBJS += ina219.o + ########################################################################## # Library files ########################################################################## diff --git a/build/crossworks/LPC1343_CodeBase.hzp b/build/crossworks/LPC1343_CodeBase.hzp index 02e59b4..636619f 100644 --- a/build/crossworks/LPC1343_CodeBase.hzp +++ b/build/crossworks/LPC1343_CodeBase.hzp @@ -171,6 +171,10 @@ + + + + diff --git a/build/crossworks/LPC1343_CodeBase.hzs b/build/crossworks/LPC1343_CodeBase.hzs index 74e2cf0..61c5d6a 100644 --- a/build/crossworks/LPC1343_CodeBase.hzs +++ b/build/crossworks/LPC1343_CodeBase.hzs @@ -25,9 +25,8 @@ - - - + + @@ -63,10 +62,14 @@ - - - - + + + + + + + + - + diff --git a/core/i2c/i2c.h b/core/i2c/i2c.h index 5e16c82..bdf5b70 100644 --- a/core/i2c/i2c.h +++ b/core/i2c/i2c.h @@ -89,8 +89,8 @@ Fast Mode (400KHz) = CFG_CPU_CCLK / 800000 Fast- Mode Plus (1MHz) = CFG_CPU_CCLK / 2000000 */ -#define I2SCLH_SCLH CFG_CPU_CCLK / 200000 /* Standard Mode I2C SCL Duty Cycle High (400KHz) */ -#define I2SCLL_SCLL CFG_CPU_CCLK / 200000 /* Fast Mode I2C SCL Duty Cycle Low (400KHz) */ +#define I2SCLH_SCLH CFG_CPU_CCLK / 800000 /* Standard Mode I2C SCL Duty Cycle High (400KHz) */ +#define I2SCLL_SCLL CFG_CPU_CCLK / 800000 /* Fast Mode I2C SCL Duty Cycle Low (400KHz) */ #define I2SCLH_HS_SCLH CFG_CPU_CCLK / 2000000 /* Fast Plus I2C SCL Duty Cycle High Reg */ #define I2SCLL_HS_SCLL CFG_CPU_CCLK / 2000000 /* Fast Plus I2C SCL Duty Cycle Low Reg */ diff --git a/drivers/dac/mcp4725/mcp4725.h b/drivers/dac/mcp4725/mcp4725.h index 71100cc..bb91b3e 100644 --- a/drivers/dac/mcp4725/mcp4725.h +++ b/drivers/dac/mcp4725/mcp4725.h @@ -39,7 +39,8 @@ #include "projectconfig.h" -#define MCP4725_ADDRESS (0xC0) // 1100000x - Assumes A0 is GND and A2,A1 are 0 (MCP4725A0T-E/CH) +//#define MCP4725_ADDRESS (0xC0) // 1100000x - Assumes A0 is GND and A2,A1 are 00 (MCP4725A0T-E/CH) +#define MCP4725_ADDRESS (0xC4) // 1100010x - Assumes A0 is GND and A2,A1 are 01 (MCP4725A1T-E/CH) #define MCP4725_READ (0x01) #define MCP4726_CMD_WRITEDAC (0x40) // Writes data to the DAC #define MCP4726_CMD_WRITEDACEEPROM (0x60) // Writes data to the DAC and the EEPROM (persisting the assigned value after reset) diff --git a/drivers/displays/tft/hw/hx8347d.c b/drivers/displays/tft/hw/hx8347d.c index 48da4d3..dd115f6 100644 --- a/drivers/displays/tft/hw/hx8347d.c +++ b/drivers/displays/tft/hw/hx8347d.c @@ -14,90 +14,91 @@ Software License Agreement (BSD License) Copyright (c) 2012, TauonTeilchen - ---------------------------------------------------------------------------- - "THE ClubMate-WARE LICENSE" (Revision 42): - JID: wrote this file. As long as you retain this notice you - can do whatever you want with this stuff. If we meet some day, and you think - this stuff is worth it, you can buy me a ClubMate in return Tauon - ---------------------------------------------------------------------------- - ---------------------------------------------------------------------------- - "THE ClubMate-WARE LICENSE" (Revision 42): - JID: schrieb diese Datei. Solange Sie diesen Vermerk nicht entfernen, k�nnen - Sie mit dem Material machen, was Sie m�chten. Wenn wir uns eines Tages treffen und Sie - denken, das Material ist es wert, k�nnen Sie mir daf�r ein ClubMate ausgeben. Tauon - ---------------------------------------------------------------------------- - + ---------------------------------------------------------------------------- + "THE ClubMate-WARE LICENSE" (Revision 42): + JID: wrote this file. As long as you retain this notice you + can do whatever you want with this stuff. If we meet some day, and you think + this stuff is worth it, you can buy me a ClubMate in return Tauon + ---------------------------------------------------------------------------- + ---------------------------------------------------------------------------- + "THE ClubMate-WARE LICENSE" (Revision 42): + JID: schrieb diese Datei. Solange Sie diesen Vermerk nicht entfernen, k�nnen + Sie mit dem Material machen, was Sie m�chten. Wenn wir uns eines Tages treffen und Sie + denken, das Material ist es wert, k�nnen Sie mir daf�r ein ClubMate ausgeben. Tauon + ---------------------------------------------------------------------------- + */ /**************************************************************************/ #include "drivers/displays/tft/hw/hx8347d.h" -#define LCD_ID (0x00) -#define LCD_DATA ((0x72)|(LCD_ID<<2)) -#define LCD_REGISTER ((0x70)|(LCD_ID<<2)) +#define LCD_ID (0x00) +#define LCD_DATA ((0x72)|(LCD_ID<<2)) +#define LCD_REGISTER ((0x70)|(LCD_ID<<2)) -#define LCD_BACK_LIGHT 6 -#define LCD_RST 5 -#define LCD_CS 4 +#define LCD_BACK_LIGHT 6 +#define LCD_RST 5 +#define LCD_CS 4 // Macros for control line state -#define LCD_CS_ENABLE() GPIO_GPIO2DATA &= ~0x10 // gpioSetValue(2, 4, 0) -#define LCD_CS_DISABLE() GPIO_GPIO2DATA |= 0x10 // gpioSetValue(2, 4, 1) -#define LCD_RST_ENABLE() GPIO_GPIO2DATA &= ~0x20 // gpioSetValue(2, 5, 0) -#define LCD_RST_DISABLE() GPIO_GPIO2DATA |= 0x20 // gpioSetValue(2, 5, 1) - -#define Himax ID 0x00 -#define Display_Mode_Control 0x01 - -#define Column_Address_Start_2 0x02 -#define Column_Address_Start_1 0x03 -#define Column_Address_End_2 0x04 -#define Column_Address_End_1 0x05 - -#define Row_Address_Start_2 0x06 -#define Row_Address_Start_1 0x07 -#define Row_Address_End_2 0x08 -#define Row_Address_End_1 0x09 - -#define Partial_Area_Start_Row_2 0x0A -#define Partial_Area_Start_Row_1 0x0B -#define Partial_Area_End_Row_2 0x0C -#define Partial_Area_End_Row_1 0x0D - -#define TFA_REGISTER 0x0E -#define VSA_REGISTER 0x10 -#define BFA_REGISTER 0x12 -#define VSP_REGISTER 0x14 - -#define COLMOD 0x17 -#define OSC_Control_1 0x18 -#define OSC_Control_2 0x19 -#define Power_Control_1 0x1A -#define Power_Control_2 0x1B -#define Power_Control_3 0x1C -#define Power_Control_4 0x1D -#define Power_Control_5 0x1E -#define Power_Control_6 0x1F -#define VCOM_Control_1 0x23 -#define VCOM_Control_2 0x24 -#define VCOM_Control_3 0x25 -#define Display_Control_1 0x26 -#define Display_Control_2 0x27 -#define Display_Control_3 0x28 -#define Source_OP_Control_Normal 0xE8 -#define Source_OP_Control_IDLE 0xE9 -#define Power_Control_Internal_1 0xEA -#define Power_Control_Internal_2 0xEB -#define Source_Control_Internal_1 0xEC -#define Source_Control_Internal_2 0xED - -#define OSC_Control_2_OSC_EN 0x01 -#define Display_Control_3_GON 0x20 -#define Display_Control_3_DTE 0x10 -#define Display_Control_3_D0 0x04 -#define Display_Control_3_D1 0x08 -#define Power_Control_6_STB 0x01 +#define LCD_CS_ENABLE() GPIO_GPIO2DATA &= ~0x10 // gpioSetValue(2, 4, 0) +#define LCD_CS_DISABLE() GPIO_GPIO2DATA |= 0x10 // gpioSetValue(2, 4, 1) +#define LCD_RST_ENABLE() GPIO_GPIO2DATA &= ~0x20 // gpioSetValue(2, 5, 0) +#define LCD_RST_DISABLE() GPIO_GPIO2DATA |= 0x20 // gpioSetValue(2, 5, 1) + +#define Himax ID 0x00 +#define Display_Mode_Control 0x01 + +#define Column_Address_Start_2 0x02 +#define Column_Address_Start_1 0x03 +#define Column_Address_End_2 0x04 +#define Column_Address_End_1 0x05 + +#define Row_Address_Start_2 0x06 +#define Row_Address_Start_1 0x07 +#define Row_Address_End_2 0x08 +#define Row_Address_End_1 0x09 + +#define Partial_Area_Start_Row_2 0x0A +#define Partial_Area_Start_Row_1 0x0B +#define Partial_Area_End_Row_2 0x0C +#define Partial_Area_End_Row_1 0x0D + +#define TFA_REGISTER 0x0E +#define VSA_REGISTER 0x10 +#define BFA_REGISTER 0x12 +#define VSP_REGISTER 0x14 + +#define COLMOD 0x17 +#define OSC_Control_1 0x18 +#define OSC_Control_2 0x19 +#define Power_Control_1 0x1A +#define Power_Control_2 0x1B +#define Power_Control_3 0x1C +#define Power_Control_4 0x1D +#define Power_Control_5 0x1E +#define Power_Control_6 0x1F +#define VCOM_Control_1 0x23 +#define VCOM_Control_2 0x24 +#define VCOM_Control_3 0x25 +#define Display_Control_1 0x26 +#define Display_Control_2 0x27 +#define Display_Control_3 0x28 +#define Source_OP_Control_Normal 0xE8 +#define Source_OP_Control_IDLE 0xE9 +#define Power_Control_Internal_1 0xEA +#define Power_Control_Internal_2 0xEB +#define Source_Control_Internal_1 0xEC +#define Source_Control_Internal_2 0xED + +#define OSC_Control_2_OSC_EN 0x01 +#define Display_Control_3_GON 0x20 +#define Display_Control_3_DTE 0x10 +#define Display_Control_3_D0 0x04 +#define Display_Control_3_D1 0x08 +#define Power_Control_6_STB 0x01 #define Display_Mode_Control_DP_STB_S 0x40 -#define Display_Mode_Control_DP_STB 0x80 +#define Display_Mode_Control_DP_STB 0x80 + uint16_t offset; /*************************************************/ @@ -116,54 +117,55 @@ void lcd_area(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); void hx8347d_Scroll(uint16_t tfa,uint16_t vsa,uint16_t bfa, uint16_t vsp) { - lcd_cmd(TFA_REGISTER , tfa >> 8); - lcd_cmd(TFA_REGISTER + 1, tfa & 0xFF); + lcd_cmd(TFA_REGISTER , tfa >> 8); + lcd_cmd(TFA_REGISTER + 1, tfa & 0xFF); - lcd_cmd(VSA_REGISTER , vsa >> 8); - lcd_cmd(VSA_REGISTER + 1, vsa & 0xFF); + lcd_cmd(VSA_REGISTER , vsa >> 8); + lcd_cmd(VSA_REGISTER + 1, vsa & 0xFF); - lcd_cmd(BFA_REGISTER , bfa >> 8); - lcd_cmd(BFA_REGISTER + 1, bfa & 0xFF); + lcd_cmd(BFA_REGISTER , bfa >> 8); + lcd_cmd(BFA_REGISTER + 1, bfa & 0xFF); - lcd_cmd(VSP_REGISTER , vsp>> 8); - lcd_cmd(VSP_REGISTER + 1, vsp & 0xFF); - lcd_cmd(0x01, 0x08); //scroll on + lcd_cmd(VSP_REGISTER , vsp>> 8); + lcd_cmd(VSP_REGISTER + 1, vsp & 0xFF); + lcd_cmd(0x01, 0x08); //scroll on } void displayOnFlow(void) { - lcd_cmd(Display_Control_3, 0x0038); - systickDelay(4); - lcd_cmd(Display_Control_3, 0x003C); + lcd_cmd(Display_Control_3, 0x0038); + systickDelay(4); + lcd_cmd(Display_Control_3, 0x003C); } void displayOffFlow(void) { - lcd_cmd(Display_Control_3, Display_Control_3_GON | Display_Control_3_DTE | Display_Control_3_D1); - systickDelay(4); - lcd_cmd(Display_Control_3, Display_Control_3_D0); + lcd_cmd(Display_Control_3, Display_Control_3_GON | Display_Control_3_DTE | Display_Control_3_D1); + systickDelay(4); + lcd_cmd(Display_Control_3, Display_Control_3_D0); } void lcd_cmd(uint16_t reg, uint16_t param) { - uint8_t b_first[2]; - uint8_t b_sec[2]; - LCD_CS_ENABLE(); + uint8_t b_first[2]; + uint8_t b_sec[2]; + LCD_CS_ENABLE(); - b_first[0] = LCD_REGISTER; - b_first[1] = reg; + b_first[0] = LCD_REGISTER; + b_first[1] = reg; - sspSend(0, b_first, 2); - LCD_CS_DISABLE(); + sspSend(0, b_first, 2); + LCD_CS_DISABLE(); - b_sec[0] = LCD_DATA; - b_sec[1] = param; - LCD_CS_ENABLE(); + b_sec[0] = LCD_DATA; + b_sec[1] = param; + LCD_CS_ENABLE(); - sspSend(0, b_sec, 2); - LCD_CS_DISABLE(); + sspSend(0, b_sec, 2); + LCD_CS_DISABLE(); return; } + void lcd_clear(uint16_t color) { unsigned int i; @@ -189,97 +191,98 @@ void lcd_clear(uint16_t color) void lcd_draw(uint16_t color) { - // Writing data in 16Bit mode for saving a lot of time - /* Move on only if NOT busy and TX FIFO not full. */ - while ((SSP_SSP0SR & (SSP_SSP0SR_TNF_NOTFULL | SSP_SSP0SR_BSY_BUSY)) != SSP_SSP0SR_TNF_NOTFULL); - SSP_SSP0DR = color; - - while ( (SSP_SSP0SR & (SSP_SSP0SR_BSY_BUSY|SSP_SSP0SR_RNE_NOTEMPTY)) != SSP_SSP0SR_RNE_NOTEMPTY ); - /* Whenever a byte is written, MISO FIFO counter increments, Clear FIFO - on MISO. Otherwise, when SSP0Receive() is called, previous data byte - is left in the FIFO. */ - uint8_t Dummy = SSP_SSP0DR; - return; + // Writing data in 16Bit mode for saving a lot of time + /* Move on only if NOT busy and TX FIFO not full. */ + while ((SSP_SSP0SR & (SSP_SSP0SR_TNF_NOTFULL | SSP_SSP0SR_BSY_BUSY)) != SSP_SSP0SR_TNF_NOTFULL); + SSP_SSP0DR = color; + + while ( (SSP_SSP0SR & (SSP_SSP0SR_BSY_BUSY|SSP_SSP0SR_RNE_NOTEMPTY)) != SSP_SSP0SR_RNE_NOTEMPTY ); + /* Whenever a byte is written, MISO FIFO counter increments, Clear FIFO + on MISO. Otherwise, when SSP0Receive() is called, previous data byte + is left in the FIFO. */ + uint8_t Dummy = SSP_SSP0DR; + return; } void lcd_drawstop(void) { - while ((SSP_SSP0SR & SSP_SSP0SR_TFE_MASK ) != SSP_SSP0SR_TFE_EMPTY ); - LCD_CS_DISABLE(); + while ((SSP_SSP0SR & SSP_SSP0SR_TFE_MASK ) != SSP_SSP0SR_TFE_EMPTY ); + LCD_CS_DISABLE(); - // init 8Bit SPI Mode - SSP_SSP0CR0 &= ~SSP_SSP0CR0_DSS_MASK; - SSP_SSP0CR0 |= SSP_SSP0CR0_DSS_8BIT; + // init 8Bit SPI Mode + SSP_SSP0CR0 &= ~SSP_SSP0CR0_DSS_MASK; + SSP_SSP0CR0 |= SSP_SSP0CR0_DSS_8BIT; - return; + return; } + void lcd_drawstart(void) { - LCD_CS_ENABLE(); - uint8_t b_first[2]; - uint8_t b_sec[1]; - b_first[0] = LCD_REGISTER; - b_first[1] = 0x22; - sspSend(0, b_first, 2); - LCD_CS_DISABLE(); + LCD_CS_ENABLE(); + uint8_t b_first[2]; + uint8_t b_sec[1]; + b_first[0] = LCD_REGISTER; + b_first[1] = 0x22; + sspSend(0, b_first, 2); + LCD_CS_DISABLE(); - LCD_CS_ENABLE(); - b_sec[0] = LCD_DATA; - sspSend(0, b_sec, 1); + LCD_CS_ENABLE(); + b_sec[0] = LCD_DATA; + sspSend(0, b_sec, 1); - // Assign config values to SSP0CR0 - // init 16Bit SPI Mode for fast data transmitting - SSP_SSP0CR0 &= ~SSP_SSP0CR0_DSS_MASK; - SSP_SSP0CR0 |= SSP_SSP0CR0_DSS_16BIT; + // Assign config values to SSP0CR0 + // init 16Bit SPI Mode for fast data transmitting + SSP_SSP0CR0 &= ~SSP_SSP0CR0_DSS_MASK; + SSP_SSP0CR0 |= SSP_SSP0CR0_DSS_16BIT; - return; + return; } - void lcd_area(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { - if(hx8347dPOrientation == LCD_ORIENTATION_PORTRAIT) - { - y0 = ((320-offset)+ y0) % 320; - y1 = ((320-offset)+ y1) % 320; - } - else - { - x0 = ((320-offset)+ x0) % 320; - x1 = ((320-offset)+ x1) % 320; - } - lcd_cmd(Column_Address_Start_1, (x0>>0)); //set x0 - lcd_cmd(Column_Address_Start_2, (x0>>8)); //set x0 - lcd_cmd(Column_Address_End_1 , (x1>>0)); //set x1 - lcd_cmd(Column_Address_End_2 , (x1>>8)); //set x1 - lcd_cmd(Row_Address_Start_1 , (y0>>0)); //set y0 - lcd_cmd(Row_Address_Start_2 , (y0>>8)); //set y0 - lcd_cmd(Row_Address_End_1 , (y1>>0)); //set y1 - lcd_cmd(Row_Address_End_2 , (y1>>8)); //set y1 + if(hx8347dPOrientation == LCD_ORIENTATION_PORTRAIT) + { + y0 = ((320-offset)+ y0) % 320; + y1 = ((320-offset)+ y1) % 320; + } + else + { + x0 = ((320-offset)+ x0) % 320; + x1 = ((320-offset)+ x1) % 320; + } + lcd_cmd(Column_Address_Start_1, (x0>>0)); //set x0 + lcd_cmd(Column_Address_Start_2, (x0>>8)); //set x0 + lcd_cmd(Column_Address_End_1 , (x1>>0)); //set x1 + lcd_cmd(Column_Address_End_2 , (x1>>8)); //set x1 + lcd_cmd(Row_Address_Start_1 , (y0>>0)); //set y0 + lcd_cmd(Row_Address_Start_2 , (y0>>8)); //set y0 + lcd_cmd(Row_Address_End_1 , (y1>>0)); //set y1 + lcd_cmd(Row_Address_End_2 , (y1>>8)); //set y1 return; } + void lcd_cursor(uint16_t x, uint16_t y) { lcd_area(x, y, x, y); return; } + void lcd_data(uint16_t c) { - LCD_CS_ENABLE(); - uint8_t b[3]; - b[0] = LCD_DATA; - b[1] = c>>8; - b[2] = c; - sspSend(0, b, 3); + LCD_CS_ENABLE(); + uint8_t b[3]; + b[0] = LCD_DATA; + b[1] = c>>8; + b[2] = c; + sspSend(0, b, 3); - LCD_CS_DISABLE(); + LCD_CS_DISABLE(); return; } - void fillRect(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color) { uint32_t size; @@ -353,67 +356,67 @@ void fillRect(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color /**************************************************************************/ void lcdInit(void) { - sspInit(0,0,0); - - gpioSetDir(2, LCD_CS, gpioDirection_Output); - gpioSetDir(2, LCD_RST, gpioDirection_Output); - gpioSetDir(2, LCD_BACK_LIGHT, gpioDirection_Output); - - //reset - LCD_CS_DISABLE(); - systickDelay(1); - LCD_RST_ENABLE(); - systickDelay(50); - LCD_RST_DISABLE(); - systickDelay(50); - - //driving ability - lcd_cmd(Power_Control_Internal_1 , 0x0000); - lcd_cmd(Power_Control_Internal_2 , 0x0020); - lcd_cmd(Source_Control_Internal_1, 0x000C); - lcd_cmd(Source_Control_Internal_2, 0x00C4); - lcd_cmd(Source_OP_Control_Normal , 0x0040); - lcd_cmd(Source_OP_Control_IDLE , 0x0038); - lcd_cmd(0xF1, 0x0001); - lcd_cmd(0xF2, 0x0010); - lcd_cmd(0x27, 0x00A3); - - //power voltage - lcd_cmd(Power_Control_2, 0x001B); - lcd_cmd(Power_Control_1, 0x0001); - lcd_cmd(VCOM_Control_2 , 0x002F); - lcd_cmd(VCOM_Control_3 , 0x0057); - - //VCOM offset - lcd_cmd(VCOM_Control_1, 0x008D); //for flicker adjust - - //power on - lcd_cmd(OSC_Control_1 , 0x0036); - lcd_cmd(OSC_Control_2 , 0x0001); //start osc - lcd_cmd(Display_Mode_Control, 0x0000); //wakeup - lcd_cmd(Power_Control_6 , 0x0088); - systickDelay(5); - lcd_cmd(Power_Control_6, 0x0080); - systickDelay(5); - lcd_cmd(Power_Control_6, 0x0090); - systickDelay(5); - lcd_cmd(Power_Control_6, 0x00D0); - systickDelay(5); - - //color selection - lcd_cmd(COLMOD, 0x0005); //0x0005=65k, 0x0006=262k - - //panel characteristic - lcd_cmd(0x36, 0x0000); - - //display on - lcd_cmd(0x28, 0x0038); - systickDelay(40); - lcd_cmd(0x28, 0x003C); - - lcdSetOrientation(hx8347dPOrientation); - offset = 0; - return; + sspInit(0,0,0); + + gpioSetDir(2, LCD_CS, gpioDirection_Output); + gpioSetDir(2, LCD_RST, gpioDirection_Output); + gpioSetDir(2, LCD_BACK_LIGHT, gpioDirection_Output); + + //reset + LCD_CS_DISABLE(); + systickDelay(1); + LCD_RST_ENABLE(); + systickDelay(50); + LCD_RST_DISABLE(); + systickDelay(50); + + //driving ability + lcd_cmd(Power_Control_Internal_1 , 0x0000); + lcd_cmd(Power_Control_Internal_2 , 0x0020); + lcd_cmd(Source_Control_Internal_1, 0x000C); + lcd_cmd(Source_Control_Internal_2, 0x00C4); + lcd_cmd(Source_OP_Control_Normal , 0x0040); + lcd_cmd(Source_OP_Control_IDLE , 0x0038); + lcd_cmd(0xF1, 0x0001); + lcd_cmd(0xF2, 0x0010); + lcd_cmd(0x27, 0x00A3); + + //power voltage + lcd_cmd(Power_Control_2, 0x001B); + lcd_cmd(Power_Control_1, 0x0001); + lcd_cmd(VCOM_Control_2 , 0x002F); + lcd_cmd(VCOM_Control_3 , 0x0057); + + //VCOM offset + lcd_cmd(VCOM_Control_1, 0x008D); //for flicker adjust + + //power on + lcd_cmd(OSC_Control_1 , 0x0036); + lcd_cmd(OSC_Control_2 , 0x0001); //start osc + lcd_cmd(Display_Mode_Control, 0x0000); //wakeup + lcd_cmd(Power_Control_6 , 0x0088); + systickDelay(5); + lcd_cmd(Power_Control_6, 0x0080); + systickDelay(5); + lcd_cmd(Power_Control_6, 0x0090); + systickDelay(5); + lcd_cmd(Power_Control_6, 0x00D0); + systickDelay(5); + + //color selection + lcd_cmd(COLMOD, 0x0005); //0x0005=65k, 0x0006=262k + + //panel characteristic + lcd_cmd(0x36, 0x0000); + + //display on + lcd_cmd(0x28, 0x0038); + systickDelay(40); + lcd_cmd(0x28, 0x003C); + + lcdSetOrientation(hx8347dPOrientation); + offset = 0; + return; } /**************************************************************************/ /*! @@ -422,7 +425,7 @@ void lcdInit(void) /**************************************************************************/ void lcdBacklight(bool state) { - gpioSetValue(2, LCD_BACK_LIGHT, state); + gpioSetValue(2, LCD_BACK_LIGHT, state); } /**************************************************************************/ @@ -432,8 +435,7 @@ void lcdBacklight(bool state) /**************************************************************************/ void lcdTest(void) { - lcdFillRGB(COLOR_CYAN); - + lcdFillRGB(COLOR_CYAN); } /**************************************************************************/ @@ -443,7 +445,7 @@ void lcdTest(void) /**************************************************************************/ void lcdFillRGB(uint16_t data) { - lcd_clear(data); + lcd_clear(data); } /**************************************************************************/ @@ -453,15 +455,15 @@ void lcdFillRGB(uint16_t data) /**************************************************************************/ void lcdDrawPixel(uint16_t x, uint16_t y, uint16_t color) { - if((x >= hx8347dProperties.width) || - (y >= hx8347dProperties.height)) - { - return; - } + if((x >= hx8347dProperties.width) || + (y >= hx8347dProperties.height)) + { + return; + } - fillRect(x,y,x,y,color); + fillRect(x,y,x,y,color); - return; + return; } /**************************************************************************/ @@ -472,16 +474,15 @@ void lcdDrawPixel(uint16_t x, uint16_t y, uint16_t color) /**************************************************************************/ void lcdDrawPixels(uint16_t x, uint16_t y, uint16_t *data, uint32_t len) { - lcd_area(x, y, x + len, y); - int i; - lcd_drawstart(); - for(i = 0; i < len; i++) - { - - lcd_draw(*data); - data++; - } - lcd_drawstop(); + lcd_area(x, y, x + len, y); + int i; + lcd_drawstart(); + for(i = 0; i < len; i++) + { + lcd_draw(*data); + data++; + } + lcd_drawstop(); } /**************************************************************************/ @@ -492,31 +493,29 @@ void lcdDrawPixels(uint16_t x, uint16_t y, uint16_t *data, uint32_t len) /**************************************************************************/ void lcdDrawHLine(uint16_t x0, uint16_t x1, uint16_t y, uint16_t color) { + if (x1 < x0) + { + // Switch x1 and x0 + uint16_t x; + x = x1; + x1 = x0; + x0 = x; + } - if (x1 < x0) - { - // Switch x1 and x0 - uint16_t x; - x = x1; - x1 = x0; - x0 = x; - } - - if(x0 >= hx8347dProperties.width) - { - x0 = hx8347dProperties.width-1; - } - if(x1 >= hx8347dProperties.width) - { - x1 = hx8347dProperties.width-1; - } - if(y >= hx8347dProperties.height) - { - y = hx8347dProperties.height-1; - } - - fillRect(x0, y, x1, y, color); + if(x0 >= hx8347dProperties.width) + { + x0 = hx8347dProperties.width-1; + } + if(x1 >= hx8347dProperties.width) + { + x1 = hx8347dProperties.width-1; + } + if(y >= hx8347dProperties.height) + { + y = hx8347dProperties.height-1; + } + fillRect(x0, y, x1, y, color); } /**************************************************************************/ @@ -527,31 +526,30 @@ void lcdDrawHLine(uint16_t x0, uint16_t x1, uint16_t y, uint16_t color) /**************************************************************************/ void lcdDrawVLine(uint16_t x, uint16_t y0, uint16_t y1, uint16_t color) { + if (y1 < y0) + { + // Switch y1 and y0 + uint16_t y; + y = y1; + y1 = y0; + y0 = y; + } + + if(x >= hx8347dProperties.width) + { + x = hx8347dProperties.width-1; + } + + if(y0 >= hx8347dProperties.height) + { + y0 = hx8347dProperties.height-1; + } + if(y1 >= hx8347dProperties.height) + { + y1 = hx8347dProperties.height-1; + } - if (y1 < y0) - { - // Switch y1 and y0 - uint16_t y; - y = y1; - y1 = y0; - y0 = y; - } - - if(x >= hx8347dProperties.width) - { - x = hx8347dProperties.width-1; - } - - if(y0 >= hx8347dProperties.height) - { - y0 = hx8347dProperties.height-1; - } - if(y1 >= hx8347dProperties.height) - { - y1 = hx8347dProperties.height-1; - } - - fillRect(x, y0, x, y1, color); + fillRect(x, y0, x, y1, color); } /**************************************************************************/ @@ -561,7 +559,7 @@ void lcdDrawVLine(uint16_t x, uint16_t y0, uint16_t y1, uint16_t color) /**************************************************************************/ uint16_t lcdGetPixel(uint16_t x, uint16_t y) { - return 0; + return 0; } /**************************************************************************/ @@ -571,21 +569,21 @@ uint16_t lcdGetPixel(uint16_t x, uint16_t y) /**************************************************************************/ void lcdSetOrientation(lcdOrientation_t orientation) { - if(orientation == LCD_ORIENTATION_LANDSCAPE) - { - lcd_cmd(0x16, 0x00A8); //MY=1 MX=0 MV=1 ML=0 BGR=1 - hx8347dProperties.width = 320; - hx8347dProperties.height = 240; - } - else - { - //lcd_cmd(0x16, 0x0008); //MY=0 MX=0 MV=0 ML=0 BGR=1 - lcd_cmd(0x16, 0x00C8); //MY=1 MX=0 MV=1 ML=0 BGR=1 - hx8347dProperties.width = 240; - hx8347dProperties.height = 320; - } - hx8347dPOrientation = orientation; - lcd_area(0, 0, (hx8347dProperties.width-1), (hx8347dProperties.height-1)); + if(orientation == LCD_ORIENTATION_LANDSCAPE) + { + lcd_cmd(0x16, 0x00A8); //MY=1 MX=0 MV=1 ML=0 BGR=1 + hx8347dProperties.width = 320; + hx8347dProperties.height = 240; + } + else + { + //lcd_cmd(0x16, 0x0008); //MY=0 MX=0 MV=0 ML=0 BGR=1 + lcd_cmd(0x16, 0x00C8); //MY=1 MX=0 MV=1 ML=0 BGR=1 + hx8347dProperties.width = 240; + hx8347dProperties.height = 320; + } + hx8347dPOrientation = orientation; + lcd_area(0, 0, (hx8347dProperties.width-1), (hx8347dProperties.height-1)); } /**************************************************************************/ @@ -595,7 +593,7 @@ void lcdSetOrientation(lcdOrientation_t orientation) /**************************************************************************/ lcdOrientation_t lcdGetOrientation(void) { - return hx8347dPOrientation; + return hx8347dPOrientation; } /**************************************************************************/ @@ -606,7 +604,7 @@ lcdOrientation_t lcdGetOrientation(void) /**************************************************************************/ uint16_t lcdGetWidth(void) { - return hx8347dProperties.width; + return hx8347dProperties.width; } /**************************************************************************/ @@ -617,7 +615,7 @@ uint16_t lcdGetWidth(void) /**************************************************************************/ uint16_t lcdGetHeight(void) { - return hx8347dProperties.height; + return hx8347dProperties.height; } /**************************************************************************/ @@ -629,17 +627,16 @@ uint16_t lcdGetHeight(void) void lcdScroll(int16_t pixels, uint16_t fillColor) { - - hx8347d_Scroll(0,320,0,(offset + pixels) % 320); - if(hx8347dPOrientation == LCD_ORIENTATION_PORTRAIT) - { - fillRect(0, hx8347dProperties.height-pixels, hx8347dProperties.width, hx8347dProperties.height, fillColor); - } - else - { - fillRect(hx8347dProperties.width-pixels, 0, hx8347dProperties.width, hx8347dProperties.height, fillColor); - } - offset = (offset + pixels) % 320; + hx8347d_Scroll(0,320,0,(offset + pixels) % 320); + if(hx8347dPOrientation == LCD_ORIENTATION_PORTRAIT) + { + fillRect(0, hx8347dProperties.height-pixels, hx8347dProperties.width, hx8347dProperties.height, fillColor); + } + else + { + fillRect(hx8347dProperties.width-pixels, 0, hx8347dProperties.width, hx8347dProperties.height, fillColor); + } + offset = (offset + pixels) % 320; } /**************************************************************************/ /*! @@ -649,14 +646,14 @@ void lcdScroll(int16_t pixels, uint16_t fillColor) /**************************************************************************/ void hx8347d_Standby(bool deep) { - displayOffFlow(); - lcd_cmd(Power_Control_6 , Power_Control_6_STB); - if(deep) - { - lcd_cmd(Display_Mode_Control,Display_Mode_Control_DP_STB_S); - lcd_cmd(Display_Mode_Control, Display_Mode_Control_DP_STB); - } - lcd_cmd(OSC_Control_2, ~OSC_Control_2_OSC_EN); + displayOffFlow(); + lcd_cmd(Power_Control_6 , Power_Control_6_STB); + if(deep) + { + lcd_cmd(Display_Mode_Control,Display_Mode_Control_DP_STB_S); + lcd_cmd(Display_Mode_Control, Display_Mode_Control_DP_STB); + } + lcd_cmd(OSC_Control_2, ~OSC_Control_2_OSC_EN); } /**************************************************************************/ /*! @@ -666,21 +663,21 @@ void hx8347d_Standby(bool deep) /**************************************************************************/ void hx8347d_Wakeup(bool deep) { - lcd_cmd(OSC_Control_2, OSC_Control_2_OSC_EN); - - if(deep) - { - lcd_cmd(Display_Mode_Control,0x0000); - systickDelay(20); - lcd_cmd(Display_Mode_Control, 0x0000); - } - else - { - systickDelay(5); - } - - lcd_cmd(Power_Control_6, 0x00D0); - displayOnFlow(); + lcd_cmd(OSC_Control_2, OSC_Control_2_OSC_EN); + + if(deep) + { + lcd_cmd(Display_Mode_Control,0x0000); + systickDelay(20); + lcd_cmd(Display_Mode_Control, 0x0000); + } + else + { + systickDelay(5); + } + + lcd_cmd(Power_Control_6, 0x00D0); + displayOnFlow(); } /**************************************************************************/ @@ -690,7 +687,7 @@ void hx8347d_Wakeup(bool deep) /**************************************************************************/ uint16_t lcdGetControllerID(void) { - return 0x0; + return 0x0; } /**************************************************************************/ @@ -701,6 +698,6 @@ uint16_t lcdGetControllerID(void) /**************************************************************************/ lcdProperties_t lcdGetProperties(void) { - return hx8347dProperties; + return hx8347dProperties; } diff --git a/drivers/displays/tft/hw/hx8347d.h b/drivers/displays/tft/hw/hx8347d.h index 33b089d..e86a984 100644 --- a/drivers/displays/tft/hw/hx8347d.h +++ b/drivers/displays/tft/hw/hx8347d.h @@ -8,18 +8,18 @@ Software License Agreement (BSD License) Copyright (c) 2012, TauonTeilchen - ---------------------------------------------------------------------------- - "THE BEER-WARE LICENSE" (Revision 42): - JID: wrote this file. As long as you retain this notice you - can do whatever you want with this stuff. If we meet some day, and you think - this stuff is worth it, you can buy me a ClubMate in return Tauon - ---------------------------------------------------------------------------- - ---------------------------------------------------------------------------- - "THE ClubMate-WARE LICENSE" (Revision 42): - JID: schrieb diese Datei. Solange Sie diesen Vermerk nicht entfernen, koennen - Sie mit dem Material machen, was Sie möechten. Wenn wir uns eines Tages treffen und Sie - denken, das Material ist es wert, koennen Sie mir dafuer ein ClubMate ausgeben. Tauon - ---------------------------------------------------------------------------- + ---------------------------------------------------------------------------- + "THE BEER-WARE LICENSE" (Revision 42): + JID: wrote this file. As long as you retain this notice you + can do whatever you want with this stuff. If we meet some day, and you think + this stuff is worth it, you can buy me a ClubMate in return Tauon + ---------------------------------------------------------------------------- + ---------------------------------------------------------------------------- + "THE ClubMate-WARE LICENSE" (Revision 42): + JID: schrieb diese Datei. Solange Sie diesen Vermerk nicht entfernen, koennen + Sie mit dem Material machen, was Sie möechten. Wenn wir uns eines Tages treffen und Sie + denken, das Material ist es wert, koennen Sie mir dafuer ein ClubMate ausgeben. Tauon + ---------------------------------------------------------------------------- */ /**************************************************************************/ diff --git a/drivers/sensors/ina219/ina219.c b/drivers/sensors/ina219/ina219.c new file mode 100644 index 0000000..da56762 --- /dev/null +++ b/drivers/sensors/ina219/ina219.c @@ -0,0 +1,569 @@ +/**************************************************************************/ +/*! + @file ina219.c + @author K. Townsend (microBuilder.eu) + + @brief Driver for the TI INA219 current/power monitor + + @section DESCRIPTION + + The INA219 is an I2C-based current/power monitor that monitors the + voltage drop across a shunt resistor, as well as the supply voltage. + + @section EXAMPLE + @code + ina219Init(); + + int16_t current = 0; + int16_t power = 0; + int16_t current_mA = 0; + int16_t power_mW = 0; + int16_t busvoltage = 0; + int16_t shuntvoltage = 0; + int16_t loadVoltage = 0; + + while(1) + { + shuntvoltage = ina219GetShuntVoltage(); + busvoltage = ina219GetBusVoltage(); + power = ina219GetPower(); + current = ina219GetCurrent(); + power_mW = ina219GetPower_mW(); + current_mA = ina219GetCurrent_mA(); + loadVoltage = busvoltage + (shuntvoltage / 100); + printf("%-15s %6d = %d.%dmV (%duV) \r\n", "Shunt Voltage:", shuntvoltage, shuntvoltage / 100, shuntvoltage % 100, shuntvoltage * 10); + printf("%-15s %6d = %d.%dV \r\n", "Bus Voltage:", busvoltage, busvoltage / 1000, busvoltage % 1000); + printf("%-15s %6d = %d.%dV \r\n", "Load Voltage:", loadVoltage, loadVoltage / 1000, loadVoltage % 1000); + printf("%-15s %6d = %dmW \r\n", "Power:", power, power_mW); + printf("%-15s %6d = %dmA \r\n", "Current:", current, current_mA); + printf("\r\n"); + systickDelay(5000); + } + @endcode + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2012 Kevin Townsend + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/**************************************************************************/ +#include "ina219.h" +#include "core/systick/systick.h" + +extern volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE]; +extern volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE]; + +// The following multipliers are used to convert raw current and power +// values to mA and mW, taking into account the current config settings +uint32_t ina219_currentDivider_mA = 0; +uint32_t ina219_powerDivider_mW = 0; + +/**************************************************************************/ +/*! + @brief Sends a single command byte over I2C +*/ +/**************************************************************************/ +static void ina219WriteRegister (uint8_t reg, uint16_t value) +{ + // Clear write buffers + uint32_t i; + for ( i = 0; i < I2C_BUFSIZE; i++ ) + { + I2CMasterBuffer[i] = 0x00; + } + + I2CWriteLength = 4; + I2CReadLength = 0; + I2CMasterBuffer[0] = INA219_ADDRESS; // I2C device address + I2CMasterBuffer[1] = reg; // Register + I2CMasterBuffer[2] = value >> 8; // Upper 8-bits + I2CMasterBuffer[3] = value & 0xFF; // Lower 8-bits + i2cEngine(); +} + +/**************************************************************************/ +/*! + @brief Reads a 16 bit values over I2C +*/ +/**************************************************************************/ +static void ina219Read16(uint8_t reg, uint16_t *value) +{ + // Clear write buffers + uint32_t i; + for ( i = 0; i < I2C_BUFSIZE; i++ ) + { + I2CMasterBuffer[i] = 0x00; + } + + I2CWriteLength = 2; + I2CReadLength = 2; + I2CMasterBuffer[0] = INA219_ADDRESS; // I2C device address + I2CMasterBuffer[1] = reg; // Command register + // Append address w/read bit + I2CMasterBuffer[2] = INA219_ADDRESS | INA219_READ; + i2cEngine(); + + // Shift values to create properly formed integer + *value = ((I2CSlaveBuffer[0] << 8) | I2CSlaveBuffer[1]); +} + +/**************************************************************************/ +/*! + @brief Configures to INA219 to be able to measure up to 32V and 2A + of current. Each unit of current corresponds to 100uA, and + each unit of power corresponds to 2mW. Counter overflow + occurs at 3.2A. + + @note These calculations assume a 0.1 ohm resistor is present +*/ +/**************************************************************************/ +static void ina219SetCalibration_32V_2A(void) +{ + // By default we use a pretty huge range for the input voltage, + // which probably isn't the most appropriate choice for system + // that don't use a lot of power. But all of the calculations + // are shown below if you want to change the settings. You will + // also need to change any relevant register settings, such as + // setting the VBUS_MAX to 16V instead of 32V, etc. + + // VBUS_MAX = 32V (Assumes 32V, can also be set to 16V) + // VSHUNT_MAX = 0.32 (Assumes Gain 8, 320mV, can also be 0.16, 0.08, 0.04) + // RSHUNT = 0.1 (Resistor value in ohms) + + // 1. Determine max possible current + // MaxPossible_I = VSHUNT_MAX / RSHUNT + // MaxPossible_I = 3.2A + + // 2. Determine max expected current + // MaxExpected_I = 2.0A + + // 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit) + // MinimumLSB = MaxExpected_I/32767 + // MinimumLSB = 0.000061 (61µA per bit) + // MaximumLSB = MaxExpected_I/4096 + // MaximumLSB = 0,000488 (488µA per bit) + + // 4. Choose an LSB between the min and max values + // (Preferrably a roundish number close to MinLSB) + // CurrentLSB = 0.0001 (100µA per bit) + + // 5. Compute the calibration register + // Cal = trunc (0.04096 / (Current_LSB * RSHUNT)) + // Cal = 4096 (0x1000) + + // 6. Calculate the power LSB + // PowerLSB = 20 * CurrentLSB + // PowerLSB = 0.002 (2mW per bit) + + // 7. Compute the maximum current and shunt voltage values before overflow + // + // Max_Current = Current_LSB * 32767 + // Max_Current = 3.2767A before overflow + // + // If Max_Current > Max_Possible_I then + // Max_Current_Before_Overflow = MaxPossible_I + // Else + // Max_Current_Before_Overflow = Max_Current + // End If + // + // Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT + // Max_ShuntVoltage = 0.32V + // + // If Max_ShuntVoltage >= VSHUNT_MAX + // Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX + // Else + // Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage + // End If + + // 8. Computer the Maximum Power + // MaximumPower = Max_Current_Before_Overflow * VBUS_MAX + // MaximumPower = 3.2 * 32V + // MaximumPower = 102.4W + + // Set multipliers to convert raw current/power values + ina219_currentDivider_mA = 10; // Current LSB = 100uA per bit (1000/100 = 10) + ina219_powerDivider_mW = 2; // Power LSB = 1mW per bit (2/1) + + // Set Calibration register to 'Cal' calculated above + ina219WriteRegister(INA219_REG_CALIBRATION, 0x1000); + + // Set Config register to take into account the settings above + uint16_t config = INA219_CONFIG_BVOLTAGERANGE_32V | + INA219_CONFIG_GAIN_8_320MV | + INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_1S_532US | + INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + ina219WriteRegister(INA219_REG_CONFIG, config); +} + +/**************************************************************************/ +/*! + @brief Configures to INA219 to be able to measure up to 32V and 1A + of current. Each unit of current corresponds to 40uA, and each + unit of power corresponds to 800µW. Counter overflow occurs at + 1.3A. + + @note These calculations assume a 0.1 ohm resistor is present +*/ +/**************************************************************************/ +static void ina219SetCalibration_32V_1A(void) +{ + // By default we use a pretty huge range for the input voltage, + // which probably isn't the most appropriate choice for system + // that don't use a lot of power. But all of the calculations + // are shown below if you want to change the settings. You will + // also need to change any relevant register settings, such as + // setting the VBUS_MAX to 16V instead of 32V, etc. + + // VBUS_MAX = 32V (Assumes 32V, can also be set to 16V) + // VSHUNT_MAX = 0.32 (Assumes Gain 8, 320mV, can also be 0.16, 0.08, 0.04) + // RSHUNT = 0.1 (Resistor value in ohms) + + // 1. Determine max possible current + // MaxPossible_I = VSHUNT_MAX / RSHUNT + // MaxPossible_I = 3.2A + + // 2. Determine max expected current + // MaxExpected_I = 1.0A + + // 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit) + // MinimumLSB = MaxExpected_I/32767 + // MinimumLSB = 0.0000305 (30.5µA per bit) + // MaximumLSB = MaxExpected_I/4096 + // MaximumLSB = 0.000244 (244µA per bit) + + // 4. Choose an LSB between the min and max values + // (Preferrably a roundish number close to MinLSB) + // CurrentLSB = 0.0000400 (40µA per bit) + + // 5. Compute the calibration register + // Cal = trunc (0.04096 / (Current_LSB * RSHUNT)) + // Cal = 10240 (0x2800) + + // 6. Calculate the power LSB + // PowerLSB = 20 * CurrentLSB + // PowerLSB = 0.0008 (800µW per bit) + + // 7. Compute the maximum current and shunt voltage values before overflow + // + // Max_Current = Current_LSB * 32767 + // Max_Current = 1.31068A before overflow + // + // If Max_Current > Max_Possible_I then + // Max_Current_Before_Overflow = MaxPossible_I + // Else + // Max_Current_Before_Overflow = Max_Current + // End If + // + // ... In this case, we're good though since Max_Current is less than MaxPossible_I + // + // Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT + // Max_ShuntVoltage = 0.131068V + // + // If Max_ShuntVoltage >= VSHUNT_MAX + // Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX + // Else + // Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage + // End If + + // 8. Computer the Maximum Power + // MaximumPower = Max_Current_Before_Overflow * VBUS_MAX + // MaximumPower = 1.31068 * 32V + // MaximumPower = 41.94176W + + // Set multipliers to convert raw current/power values + ina219_currentDivider_mA = 25; // Current LSB = 40uA per bit (1000/40 = 25) + ina219_powerDivider_mW = 1; // Power LSB = 800µW per bit + + // Set Calibration register to 'Cal' calculated above + ina219WriteRegister(INA219_REG_CALIBRATION, 0x2800); + + // Set Config register to take into account the settings above + uint16_t config = INA219_CONFIG_BVOLTAGERANGE_32V | + INA219_CONFIG_GAIN_8_320MV | + INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_1S_532US | + INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + ina219WriteRegister(INA219_REG_CONFIG, config); +} + +/**************************************************************************/ +/*! + @brief Configures to INA219 to be able to measure up to 16V and 500mA + of current. Each unit of current corresponds to 25uA, and each + unit of power corresponds to 500µW. Counter overflow occurs at + 800mA. + + @note These calculations assume a 0.1 ohm resistor is present +*/ +/**************************************************************************/ +static void ina219SetCalibration_16V_500mA(void) +{ + // VBUS_MAX = 16V + // VSHUNT_MAX = 0.08 (Assumes Gain 2, 80mV, can also be 0.32, 0.16, 0.04) + // RSHUNT = 0.1 (Resistor value in ohms) + + // 1. Determine max possible current + // MaxPossible_I = VSHUNT_MAX / RSHUNT + // MaxPossible_I = 0.8A + + // 2. Determine max expected current + // MaxExpected_I = 0.5A + + // 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit) + // MinimumLSB = MaxExpected_I/32767 + // MinimumLSB = 0.0000153 (15.3µA per bit) + // MaximumLSB = MaxExpected_I/4096 + // MaximumLSB = 0.0001221 (122µA per bit) + + // 4. Choose an LSB between the min and max values + // (Preferrably a roundish number close to MinLSB) + // CurrentLSB = 0.0000250 (25µA per bit) + + // 5. Compute the calibration register + // Cal = trunc (0.04096 / (Current_LSB * RSHUNT)) + // Cal = 16384 (0x4000) + + // 6. Calculate the power LSB + // PowerLSB = 20 * CurrentLSB + // PowerLSB = 0.0005 (500µW per bit) + + // 7. Compute the maximum current and shunt voltage values before overflow + // + // Max_Current = Current_LSB * 32767 + // Max_Current = 0.819175 (819 mA before overflow) + // + // If Max_Current > Max_Possible_I then + // Max_Current_Before_Overflow = MaxPossible_I + // Else + // Max_Current_Before_Overflow = Max_Current + // End If + // + // Max_Current_Before_Overflow = 0.8A + // + // Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT + // Max_ShuntVoltage = 0.8 * 0.1 + // Max_ShuntVoltage = 0.08V + // + // If Max_ShuntVoltage >= VSHUNT_MAX + // Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX + // Else + // Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage + // End If + + // 8. Computer the Maximum Power + // MaximumPower = Max_Current_Before_Overflow * VBUS_MAX + // MaximumPower = 0.8 * 16V + // MaximumPower = 12.8W + + // Set multipliers to convert raw current/power values + ina219_currentDivider_mA = 40; // Current LSB = 25uA per bit (1000/25 = 40) + ina219_powerDivider_mW = 1; // Power LSB = 500µW per bit + + // Set Calibration register to 'Cal' calculated above + ina219WriteRegister(INA219_REG_CALIBRATION, 0x4000); + + // Set Config register to take into account the settings above + uint16_t config = INA219_CONFIG_BVOLTAGERANGE_16V | + INA219_CONFIG_GAIN_2_80MV | + INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_1S_532US | + INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + ina219WriteRegister(INA219_REG_CONFIG, config); +} + +/**************************************************************************/ +/*! + @brief Configures to INA219 to be able to measure up to 16V and 200mA + of current. Each unit of current corresponds to 10uA, and each + unit of power corresponds to 200µW. Counter overflow occurs at + 327mA. + + @note These calculations assume a 0.1 ohm resistor is present +*/ +/**************************************************************************/ +static void ina219SetCalibration_16V_200mA(void) +{ + // VBUS_MAX = 16V + // VSHUNT_MAX = 0.04 (Assumes Gain 1, 40mV, can also be 0.32, 0.16, 0.08) + // RSHUNT = 0.1 (Resistor value in ohms) + + // 1. Determine max possible current + // MaxPossible_I = VSHUNT_MAX / RSHUNT + // MaxPossible_I = 0.4A + + // 2. Determine max expected current + // MaxExpected_I = 0.2A + + // 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit) + // MinimumLSB = MaxExpected_I/32767 + // MinimumLSB = 0.000006104 (6.104µA per bit) + // MaximumLSB = MaxExpected_I/4096 + // MaximumLSB = 0,000048828 (48.82µA per bit) + + // 4. Choose an LSB between the min and max values + // CurrentLSB = 0.000010 (10µA per bit) + + // 5. Compute the calibration register + // Cal = trunc (0.04096 / (Current_LSB * RSHUNT)) + // Cal = 40960 (0xA000) + + // 6. Calculate the power LSB + // PowerLSB = 20 * CurrentLSB + // PowerLSB = 0.0002 (200µW per bit) + + // 7. Compute the maximum current and shunt voltage values before overflow + // + // Max_Current = Current_LSB * 32767 + // Max_Current = 0.32767 (328 mA before overflow) + // + // If Max_Current > Max_Possible_I then + // Max_Current_Before_Overflow = MaxPossible_I + // Else + // Max_Current_Before_Overflow = Max_Current + // End If + // + // Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT + // Max_ShuntVoltage = 0.032767V + // + // If Max_ShuntVoltage >= VSHUNT_MAX + // Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX + // Else + // Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage + // End If + + // 8. Computer the Maximum Power + // MaximumPower = Max_Current_Before_Overflow * VBUS_MAX + // MaximumPower = 0.32767 * 16V + // MaximumPower = 5.24W + + // Set multipliers to convert raw current/power values + ina219_currentDivider_mA = 100; // Current LSB = 10uA per bit (1000/10 = 100) + ina219_powerDivider_mW = 1; // Power LSB = 200µW per bit + + // Set Calibration register to 'Cal' calculated above + ina219WriteRegister(INA219_REG_CALIBRATION, 0xA000); + + // Set Config register to take into account the settings above + uint16_t config = INA219_CONFIG_BVOLTAGERANGE_16V | + INA219_CONFIG_GAIN_1_40MV | + INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_1S_532US | + INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + ina219WriteRegister(INA219_REG_CONFIG, config); +} + +/**************************************************************************/ +/*! + @brief Initialises the I2C block +*/ +/**************************************************************************/ +void ina219Init(void) +{ + // Reset INA219 (set to default values) + ina219WriteRegister(INA219_REG_CONFIG, INA219_CONFIG_RESET); + + // Setup chip for 32V and 2A by default + ina219SetCalibration_32V_2A(); +} + +/**************************************************************************/ +/*! + @brief Gets the shunt voltage (16-bit signed integer, so +-32767) +*/ +/**************************************************************************/ +int16_t ina219GetShuntVoltage(void) +{ + uint16_t value; + ina219Read16(INA219_REG_SHUNTVOLTAGE, &value); + return value; +} + +/**************************************************************************/ +/*! + @brief Gets the shunt voltage (16-bit signed integer, so +-32767) +*/ +/**************************************************************************/ +int16_t ina219GetBusVoltage(void) +{ + uint16_t value; + ina219Read16(INA219_REG_BUSVOLTAGE, &value); + // Shift to the right 3 to drop CNVR and OVF and then multiply by LSB + return (value >> 3) * 4; +} + +/**************************************************************************/ +/*! + @brief Gets the raw power value (16-bit signed integer, so +-32767) +*/ +/**************************************************************************/ +int16_t ina219GetPower(void) +{ + uint16_t value; + ina219Read16(INA219_REG_POWER, &value); + return value; +} + +/**************************************************************************/ +/*! + @brief Gets the power value in mW, taking into account the config + settings and power LSB +*/ +/**************************************************************************/ +int16_t ina219GetPower_mW(void) +{ + uint16_t value; + ina219Read16(INA219_REG_POWER, &value); + return value / ina219_powerDivider_mW; +} + +/**************************************************************************/ +/*! + @brief Gets the raw current value (16-bit signed integer, so +-32767) +*/ +/**************************************************************************/ +int16_t ina219GetCurrent(void) +{ + uint16_t value; + ina219Read16(INA219_REG_CURRENT, &value); + return value; +} + +/**************************************************************************/ +/*! + @brief Gets the current value in mA, taking into account the + config settings and current LSB +*/ +/**************************************************************************/ +int16_t ina219GetCurrent_mA(void) +{ + uint16_t value; + ina219Read16(INA219_REG_CURRENT, &value); + return value / ina219_currentDivider_mA; +} + + diff --git a/drivers/sensors/ina219/ina219.h b/drivers/sensors/ina219/ina219.h new file mode 100644 index 0000000..69dfdbc --- /dev/null +++ b/drivers/sensors/ina219/ina219.h @@ -0,0 +1,137 @@ +/**************************************************************************/ +/*! + @file ina219.h + @author K. Townsend (microBuilder.eu) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2012 Kevin Townsend + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/**************************************************************************/ + +#ifndef _INA219_H_ +#define _INS219_H_ + +#include "projectconfig.h" +#include "core/i2c/i2c.h" + +/*========================================================================= + I2C ADDRESS/BITS + -----------------------------------------------------------------------*/ + #define INA219_ADDRESS (0x80) // 1000000x (A0+A1=GND) + #define INA219_READ (0x01) +/*=========================================================================*/ + +/*========================================================================= + CONFIG REGISTER (R/W) + -----------------------------------------------------------------------*/ + #define INA219_REG_CONFIG (0x00) + /*---------------------------------------------------------------------*/ + #define INA219_CONFIG_RESET (0x8000) // Reset Bit + + #define INA219_CONFIG_BVOLTAGERANGE_MASK (0x4000) // Bus Voltage Range Mask + #define INA219_CONFIG_BVOLTAGERANGE_16V (0x0000) // 0-16V Range + #define INA219_CONFIG_BVOLTAGERANGE_32V (0x4000) // 0-32V Range + + #define INA219_CONFIG_GAIN_MASK (0x1800) // Gain Mask + #define INA219_CONFIG_GAIN_1_40MV (0x0000) // Gain 1, 40mV Range + #define INA219_CONFIG_GAIN_2_80MV (0x0800) // Gain 2, 80mV Range + #define INA219_CONFIG_GAIN_4_160MV (0x1000) // Gain 4, 160mV Range + #define INA219_CONFIG_GAIN_8_320MV (0x1800) // Gain 8, 320mV Range + + #define INA219_CONFIG_BADCRES_MASK (0x0780) // Bus ADC Resolution Mask + #define INA219_CONFIG_BADCRES_9BIT (0x0080) // 9-bit bus res = 0..511 + #define INA219_CONFIG_BADCRES_10BIT (0x0100) // 10-bit bus res = 0..1023 + #define INA219_CONFIG_BADCRES_11BIT (0x0200) // 11-bit bus res = 0..2047 + #define INA219_CONFIG_BADCRES_12BIT (0x0400) // 12-bit bus res = 0..4097 + + #define INA219_CONFIG_SADCRES_MASK (0x0078) // Shunt ADC Resolution and Averaging Mask + #define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0000) // 1 x 9-bit shunt sample + #define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x0008) // 1 x 10-bit shunt sample + #define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x0010) // 1 x 11-bit shunt sample + #define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x0018) // 1 x 12-bit shunt sample + #define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x0048) // 2 x 12-bit shunt samples averaged together + #define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0x0050) // 4 x 12-bit shunt samples averaged together + #define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0x0058) // 8 x 12-bit shunt samples averaged together + #define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0x0060) // 16 x 12-bit shunt samples averaged together + #define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0x0068) // 32 x 12-bit shunt samples averaged together + #define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0x0070) // 64 x 12-bit shunt samples averaged together + #define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0x0078) // 128 x 12-bit shunt samples averaged together + + #define INA219_CONFIG_MODE_MASK (0x0007) // Operating Mode Mask + #define INA219_CONFIG_MODE_POWERDOWN (0x0000) + #define INA219_CONFIG_MODE_SVOLT_TRIGGERED (0x0001) + #define INA219_CONFIG_MODE_BVOLT_TRIGGERED (0x0002) + #define INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED (0x0003) + #define INA219_CONFIG_MODE_ADCOFF (0x0004) + #define INA219_CONFIG_MODE_SVOLT_CONTINUOUS (0x0005) + #define INA219_CONFIG_MODE_BVOLT_CONTINUOUS (0x0006) + #define INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS (0x0007) +/*=========================================================================*/ + +/*========================================================================= + SHUNT VOLTAGE REGISTER (R) + -----------------------------------------------------------------------*/ + #define INA219_REG_SHUNTVOLTAGE (0x01) +/*=========================================================================*/ + +/*========================================================================= + BUS VOLTAGE REGISTER (R) + -----------------------------------------------------------------------*/ + #define INA219_REG_BUSVOLTAGE (0x02) +/*=========================================================================*/ + +/*========================================================================= + POWER REGISTER (R) + -----------------------------------------------------------------------*/ + #define INA219_REG_POWER (0x03) +/*=========================================================================*/ + +/*========================================================================= + CURRENT REGISTER (R) + -----------------------------------------------------------------------*/ + #define INA219_REG_CURRENT (0x04) +/*=========================================================================*/ + +/*========================================================================= + CALIBRATION REGISTER (R/W) + -----------------------------------------------------------------------*/ + #define INA219_REG_CALIBRATION (0x05) +/*=========================================================================*/ + +void ina219Init(void); +int16_t ina219GetShuntVoltage(void); +int16_t ina219GetBusVoltage(void); +int16_t ina219GetPower(void); +int16_t ina219GetPower_mW(void); +int16_t ina219GetCurrent(void); +int16_t ina219GetCurrent_mA(void); + +#endif + + -- 2.20.1