Added BMP180 and I2C driver and example
Fixed reference to unknown environment var Moved drivers into extras folder and added additional documentations. Changed LOCAL to static and renamed DEBUG to BMP180_DEBUG
This commit is contained in:
		
							parent
							
								
									22d35ed5f2
								
							
						
					
					
						commit
						fd1081a0cc
					
				
					 14 changed files with 996 additions and 0 deletions
				
			
		
							
								
								
									
										3
									
								
								examples/bmp180_i2c/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								examples/bmp180_i2c/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| PROGRAM=BMP180_Reader | ||||
| EXTRA_COMPONENTS = extras/i2c extras/bmp180 | ||||
| include ../../common.mk | ||||
							
								
								
									
										7
									
								
								examples/bmp180_i2c/README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								examples/bmp180_i2c/README.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| # I2C / BMP180 Example | ||||
| 
 | ||||
| This example references two addtional drivers [i2c](https://github.com/kanflo/esp-open-rtos-driver-i2c) and [bmp180](https://github.com/Angus71/esp-open-rtos-driver-bmp180), which are provided in the `../../extras` folder. | ||||
| 
 | ||||
| If you plan to use one or both of this drivers in your own projects, please check the main development pages for updated versions or reported issues. | ||||
| 
 | ||||
| To run this example connect the BMP085/BMP180 SCL to GPIO0 and SDA to GPIO2. | ||||
							
								
								
									
										132
									
								
								examples/bmp180_i2c/bmp180_i2c.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								examples/bmp180_i2c/bmp180_i2c.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,132 @@ | |||
| /* Simple example for I2C / BMP180 / Timer & Event Handling
 | ||||
|  * | ||||
|  * This sample code is in the public domain. | ||||
|  */ | ||||
| #include "espressif/esp_common.h" | ||||
| #include "espressif/sdk_private.h" | ||||
| 
 | ||||
| #include "FreeRTOS.h" | ||||
| #include "task.h" | ||||
| #include "timers.h" | ||||
| #include "queue.h" | ||||
| 
 | ||||
| // BMP180 driver
 | ||||
| #include "bmp180/bmp180.h" | ||||
| 
 | ||||
| #define MY_EVT_TIMER  0x01 | ||||
| #define MY_EVT_BMP180 0x02 | ||||
| 
 | ||||
| #define SCL_PIN GPIO_ID_PIN((0)) | ||||
| #define SDA_PIN GPIO_ID_PIN((2)) | ||||
| 
 | ||||
| typedef struct | ||||
| { | ||||
|     uint8_t event_type; | ||||
|     bmp180_result_t bmp180_data; | ||||
| } my_event_t; | ||||
| 
 | ||||
| // Communication Queue
 | ||||
| static xQueueHandle mainqueue; | ||||
| static xTimerHandle timerHandle; | ||||
| 
 | ||||
| // Own BMP180 User Inform Implementation
 | ||||
| bool bmp180_i2c_informUser(const xQueueHandle* resultQueue, uint8_t cmd, bmp180_temp_t temperatue, bmp180_press_t pressure) | ||||
| { | ||||
|     my_event_t ev; | ||||
| 
 | ||||
|     ev.event_type = MY_EVT_BMP180; | ||||
|     ev.bmp180_data.cmd = cmd; | ||||
|     ev.bmp180_data.temperatue = temperatue; | ||||
|     ev.bmp180_data.pressure = pressure; | ||||
| 
 | ||||
|     return (xQueueSend(*resultQueue, &ev, 0) == pdTRUE); | ||||
| } | ||||
| 
 | ||||
| // Timer call back
 | ||||
| static void bmp180_i2c_timer_cb(xTimerHandle xTimer) | ||||
| { | ||||
|     my_event_t ev; | ||||
|     ev.event_type = MY_EVT_TIMER; | ||||
| 
 | ||||
|     xQueueSend(mainqueue, &ev, 0); | ||||
| } | ||||
| 
 | ||||
| // Check for communiction events
 | ||||
| void bmp180_task(void *pvParameters) | ||||
| { | ||||
|     // Received pvParameters is communication queue
 | ||||
|     xQueueHandle *com_queue = (xQueueHandle *)pvParameters; | ||||
| 
 | ||||
|     printf("%s: Started user interface task\n", __FUNCTION__); | ||||
| 
 | ||||
|     while(1) | ||||
|     { | ||||
|         my_event_t ev; | ||||
| 
 | ||||
|         xQueueReceive(*com_queue, &ev, portMAX_DELAY); | ||||
| 
 | ||||
|         switch(ev.event_type) | ||||
|         { | ||||
|         case MY_EVT_TIMER: | ||||
|             printf("%s: Received Timer Event\n", __FUNCTION__); | ||||
| 
 | ||||
|             bmp180_trigger_measurement(com_queue); | ||||
|             break; | ||||
|         case MY_EVT_BMP180: | ||||
|             printf("%s: Received BMP180 Event temp:=%ld.%d°C press=%ld.%02ldhPa\n", __FUNCTION__, \ | ||||
|                        (int32_t)ev.bmp180_data.temperatue, abs((int32_t)(ev.bmp180_data.temperatue*10)%10), \ | ||||
|                        ev.bmp180_data.pressure/100, ev.bmp180_data.pressure%100 ); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Setup HW
 | ||||
| void user_setup(void) | ||||
| { | ||||
|     // Set UART Parameter
 | ||||
|     sdk_uart_div_modify(0, UART_CLK_FREQ / 115200); | ||||
| 
 | ||||
|     // Give the UART some time to settle
 | ||||
|     sdk_os_delay_us(500); | ||||
| } | ||||
| 
 | ||||
| void user_init(void) | ||||
| { | ||||
|     // Setup HW
 | ||||
|     user_setup(); | ||||
| 
 | ||||
|     // Just some infomations
 | ||||
|     printf("\n"); | ||||
|     printf("SDK version : %s\n", sdk_system_get_sdk_version()); | ||||
|     printf("GIT version : %s\n", GITSHORTREV); | ||||
| 
 | ||||
|     // Use our user inform implementation
 | ||||
|     bmp180_informUser = bmp180_i2c_informUser; | ||||
| 
 | ||||
|     // Init BMP180 Interface
 | ||||
|     bmp180_init(SCL_PIN, SDA_PIN); | ||||
| 
 | ||||
|     // Create Main Communication Queue
 | ||||
|     mainqueue = xQueueCreate(10, sizeof(my_event_t)); | ||||
| 
 | ||||
|     // Create user interface task
 | ||||
|     xTaskCreate(bmp180_task, (signed char *)"bmp180_task", 256, &mainqueue, 2, NULL); | ||||
| 
 | ||||
|     // Create Timer (Trigger a measurement every second)
 | ||||
|     timerHandle = xTimerCreate((signed char *)"BMP180 Trigger", 1000/portTICK_RATE_MS, pdTRUE, NULL, bmp180_i2c_timer_cb); | ||||
| 
 | ||||
|     if (timerHandle != NULL) | ||||
|     { | ||||
|         if (xTimerStart(timerHandle, 0) != pdPASS) | ||||
|         { | ||||
|             printf("%s: Unable to start Timer ...\n", __FUNCTION__); | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         printf("%s: Unable to create Timer ...\n", __FUNCTION__); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										10
									
								
								extras/README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								extras/README.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| # extras | ||||
| 
 | ||||
| This folder contains supportive source code. | ||||
| 
 | ||||
| For current versions or reporting issues etc. please check the main development pages. | ||||
| 
 | ||||
| - [bmp180](https://github.com/Angus71/esp-open-rtos-driver-bmp180) | ||||
| - [i2c](https://github.com/kanflo/esp-open-rtos-driver-i2c) | ||||
| - [rboot-ota](http://richard.burtons.org/) | ||||
| 
 | ||||
							
								
								
									
										22
									
								
								extras/bmp180/LICENSE
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								extras/bmp180/LICENSE
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2015 Frank Bargstedt | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
| 
 | ||||
							
								
								
									
										56
									
								
								extras/bmp180/README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								extras/bmp180/README.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,56 @@ | |||
| # Driver for BMP085/BMP180 digital pressure sensor | ||||
| 
 | ||||
| This driver is written for usage with the ESP8266 and FreeRTOS ([esp-open-rtos](https://github.com/SuperHouse/esp-open-rtos) and [esp-open-rtos-driver-i2c](https://github.com/kanflo/esp-open-rtos-driver-i2c)). | ||||
| 
 | ||||
| ### Usage | ||||
| 
 | ||||
| Before using the BMP180 module, the function `bmp180_init(SCL_PIN, SDA_PIN)` needs to be called to setup the I2C interface and do validation if the BMP180/BMP085 is accessible. | ||||
| 
 | ||||
| If the setup is sucessfully and a measurement is triggered, the result of the measurement is provided to the user as an event send via the `qQueue` provided with `bmp180_trigger_*measurement(pQueue);`  | ||||
| 
 | ||||
| #### Example  | ||||
| 
 | ||||
| ``` | ||||
| #define SCL_PIN GPIO_ID_PIN(0) | ||||
| #define SDA_PIN GPIO_ID_PIN(2) | ||||
| ... | ||||
| 
 | ||||
| if (!bmp180_init(SCL_PIN, SDA_PIN)) { | ||||
| // An error occured, while dong the init (E.g device not found etc.) | ||||
| } | ||||
| 
 | ||||
| // Trigger a measurement | ||||
| bmp180_trigger_measurement(pQueue); | ||||
| 
 | ||||
| ``` | ||||
| 
 | ||||
| #### Change queue event | ||||
| 
 | ||||
| Per default the event send to the user via the provided queue is of the type `bmp180_result_t`. As this might not always be desired, a way is provided so that the user can provide a function, which creates and sends the event via the provided queue. | ||||
| 
 | ||||
| As all data aqquired from the BMP180/BMP085 is provided to the `bmp180_informUser` function, it is also possible to calculate new informations (E.g altitude etc.) | ||||
| 
 | ||||
| ##### Example | ||||
| 
 | ||||
| ``` | ||||
| // Own BMP180 User Inform Implementation | ||||
| bool my_informUser(const xQueueHandle* resultQueue, uint8_t cmd, bmp180_temp_t temperatue, bmp180_press_t pressure) { | ||||
| 	my_event_t ev; | ||||
| 
 | ||||
| 	ev.event_type = MY_EVT_BMP180; | ||||
| 	ev.bmp180_data.cmd = cmd; | ||||
| 	ev.bmp180_data.temperatue = temperatue; | ||||
| 	ev.bmp180_data.pressure = pressure; | ||||
| 
 | ||||
| 	return (xQueueSend(*resultQueue, &ev, 0) == pdTRUE); | ||||
| } | ||||
| 
 | ||||
| ... | ||||
| 
 | ||||
| // Use our user inform implementation | ||||
| // needs to be set before first measurement is triggered | ||||
| bmp180_informUser = my_informUser; | ||||
| 
 | ||||
| 
 | ||||
| ```  | ||||
| 
 | ||||
							
								
								
									
										351
									
								
								extras/bmp180/bmp180.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										351
									
								
								extras/bmp180/bmp180.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,351 @@ | |||
| #include "bmp180.h" | ||||
| 
 | ||||
| #include "FreeRTOS.h" | ||||
| #include "queue.h" | ||||
| #include "task.h" | ||||
| 
 | ||||
| #include "espressif/esp_common.h" | ||||
| #include "espressif/sdk_private.h" | ||||
| 
 | ||||
| #include "i2c/i2c.h" | ||||
| 
 | ||||
| #define BMP180_RX_QUEUE_SIZE      10 | ||||
| #define BMP180_TASK_PRIORITY      9 | ||||
| 
 | ||||
| #define BMP180_DEVICE_ADDRESS     0x77 | ||||
| 
 | ||||
| #define BMP180_VERSION_REG        0xD0 | ||||
| #define BMP180_CONTROL_REG        0xF4 | ||||
| #define BMP180_RESET_REG          0xE0 | ||||
| #define BMP180_OUT_MSB_REG        0xF6 | ||||
| #define BMP180_OUT_LSB_REG        0xF7 | ||||
| #define BMP180_OUT_XLSB_REG       0xF8 | ||||
| 
 | ||||
| #define BMP180_CALIBRATION_REG    0xAA | ||||
| 
 | ||||
| //
 | ||||
| // Values for BMP180_CONTROL_REG
 | ||||
| //
 | ||||
| #define BMP180_MEASURE_TEMP       0x2E | ||||
| #define BMP180_MEASURE_PRESS_OSS0 0x34 | ||||
| #define BMP180_MEASURE_PRESS_OSS1 0x74 | ||||
| #define BMP180_MEASURE_PRESS_OSS2 0xB4 | ||||
| #define BMP180_MEASURE_PRESS_OSS3 0xF4 | ||||
| 
 | ||||
| #define BMP180_DEFAULT_CONV_TIME  5000 | ||||
| 
 | ||||
| //
 | ||||
| // CHIP ID stored in BMP180_VERSION_REG
 | ||||
| //
 | ||||
| #define BMP180_CHIP_ID            0x55 | ||||
| 
 | ||||
| //
 | ||||
| // Reset value for BMP180_RESET_REG
 | ||||
| //
 | ||||
| #define BMP180_RESET_VALUE        0xB6 | ||||
| 
 | ||||
| 
 | ||||
| // BMP180_Event_Command
 | ||||
| typedef struct | ||||
| { | ||||
|     uint8_t cmd; | ||||
|     const xQueueHandle* resultQueue; | ||||
| } bmp180_command_t; | ||||
| 
 | ||||
| // Just works due to the fact that xQueueHandle is a "void *"
 | ||||
| static xQueueHandle bmp180_rx_queue = NULL; | ||||
| static xTaskHandle  bmp180_task_handle = NULL; | ||||
| 
 | ||||
| // Calibration constants
 | ||||
| static int16_t  AC1; | ||||
| static int16_t  AC2; | ||||
| static int16_t  AC3; | ||||
| static uint16_t AC4; | ||||
| static uint16_t AC5; | ||||
| static uint16_t AC6; | ||||
| 
 | ||||
| static int16_t  B1; | ||||
| static int16_t  B2; | ||||
| 
 | ||||
| static int16_t  MB; | ||||
| static int16_t  MC; | ||||
| static int16_t  MD; | ||||
| 
 | ||||
| //
 | ||||
| // Forward declarations
 | ||||
| //
 | ||||
| static void bmp180_meassure(const bmp180_command_t* command); | ||||
| static bool bmp180_informUser_Impl(const xQueueHandle* resultQueue, uint8_t cmd, bmp180_temp_t temperatue, bmp180_press_t pressure); | ||||
| 
 | ||||
| // Set default implementation .. User gets result as bmp180_result_t event
 | ||||
| bool (*bmp180_informUser)(const xQueueHandle* resultQueue, uint8_t cmd, bmp180_temp_t temperatue, bmp180_press_t pressure) = bmp180_informUser_Impl; | ||||
| 
 | ||||
| // I2C Driver Task
 | ||||
| static void bmp180_driver_task(void *pvParameters) | ||||
| { | ||||
|     // Data to be received from user
 | ||||
|     bmp180_command_t current_command; | ||||
| 
 | ||||
| #ifdef BMP180_DEBUG | ||||
|     // Wait for commands from the outside
 | ||||
|     printf("%s: Started Task\n", __FUNCTION__); | ||||
| #endif | ||||
| 
 | ||||
|     while(1) | ||||
|     { | ||||
|         // Wait for user to insert commands
 | ||||
|         if (xQueueReceive(bmp180_rx_queue, ¤t_command, portMAX_DELAY) == pdTRUE) | ||||
|         { | ||||
| #ifdef BMP180_DEBUG | ||||
|             printf("%s: Received user command %d 0x%p\n", __FUNCTION__, current_command.cmd, current_command.resultQueue); | ||||
| #endif | ||||
|             // use user provided queue
 | ||||
|             if (current_command.resultQueue != NULL) | ||||
|             { | ||||
|                 // Work on it ...
 | ||||
|                 bmp180_meassure(¤t_command); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static uint8_t bmp180_readRegister8(uint8_t reg) | ||||
| { | ||||
|     uint8_t r = 0; | ||||
| 
 | ||||
|     if (!i2c_slave_read(BMP180_DEVICE_ADDRESS, reg, &r, 1)) | ||||
|     { | ||||
|         r = 0; | ||||
|     } | ||||
|     return r; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int16_t bmp180_readRegister16(uint8_t reg) | ||||
| { | ||||
|     uint8_t d[] = { 0, 0 }; | ||||
|     int16_t r = 0; | ||||
| 
 | ||||
|     if (i2c_slave_read(BMP180_DEVICE_ADDRESS, reg, d, 2)) | ||||
|     { | ||||
|         r = ((int16_t)d[0]<<8) | (d[1]); | ||||
|     } | ||||
|     return r; | ||||
| } | ||||
| 
 | ||||
| static void bmp180_start_Messurement(uint8_t cmd) | ||||
| { | ||||
|     uint8_t d[] = { BMP180_CONTROL_REG, cmd }; | ||||
| 
 | ||||
|     i2c_slave_write(BMP180_DEVICE_ADDRESS, d, 2); | ||||
| } | ||||
| 
 | ||||
| static int16_t bmp180_getUncompensatedMessurement(uint8_t cmd) | ||||
| { | ||||
|     // Write Start Code into reg 0xF4 (Currently without oversampling ...)
 | ||||
|     bmp180_start_Messurement((cmd==BMP180_TEMPERATURE)?BMP180_MEASURE_TEMP:BMP180_MEASURE_PRESS_OSS0); | ||||
| 
 | ||||
|     // Wait 5ms Datasheet states 4.5ms
 | ||||
|     sdk_os_delay_us(BMP180_DEFAULT_CONV_TIME); | ||||
| 
 | ||||
|     return (int16_t)bmp180_readRegister16(BMP180_OUT_MSB_REG); | ||||
| } | ||||
| 
 | ||||
| static void bmp180_fillInternalConstants(void) | ||||
| { | ||||
|     AC1 = bmp180_readRegister16(BMP180_CALIBRATION_REG+0); | ||||
|     AC2 = bmp180_readRegister16(BMP180_CALIBRATION_REG+2); | ||||
|     AC3 = bmp180_readRegister16(BMP180_CALIBRATION_REG+4); | ||||
|     AC4 = bmp180_readRegister16(BMP180_CALIBRATION_REG+6); | ||||
|     AC5 = bmp180_readRegister16(BMP180_CALIBRATION_REG+8); | ||||
|     AC6 = bmp180_readRegister16(BMP180_CALIBRATION_REG+10); | ||||
| 
 | ||||
|     B1 = bmp180_readRegister16(BMP180_CALIBRATION_REG+12); | ||||
|     B2 = bmp180_readRegister16(BMP180_CALIBRATION_REG+14); | ||||
| 
 | ||||
|     MB = bmp180_readRegister16(BMP180_CALIBRATION_REG+16); | ||||
|     MC = bmp180_readRegister16(BMP180_CALIBRATION_REG+18); | ||||
|     MD = bmp180_readRegister16(BMP180_CALIBRATION_REG+20); | ||||
| 
 | ||||
| #ifdef BMP180_DEBUG | ||||
|     printf("%s: AC1:=%d AC2:=%d AC3:=%d AC4:=%u AC5:=%u AC6:=%u \n", __FUNCTION__, AC1, AC2, AC3, AC4, AC5, AC6); | ||||
|     printf("%s: B1:=%d B2:=%d\n", __FUNCTION__, B1, B2); | ||||
|     printf("%s: MB:=%d MC:=%d MD:=%d\n", __FUNCTION__, MB, MC, MD); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| static bool bmp180_create_communication_queues() | ||||
| { | ||||
|     // Just create them once
 | ||||
|     if (bmp180_rx_queue==NULL) | ||||
|     { | ||||
|         bmp180_rx_queue = xQueueCreate(BMP180_RX_QUEUE_SIZE, sizeof(bmp180_result_t)); | ||||
|     } | ||||
| 
 | ||||
|     return (bmp180_rx_queue!=NULL); | ||||
| } | ||||
| 
 | ||||
| static bool bmp180_is_avaialble() | ||||
| { | ||||
|     return (bmp180_readRegister8(BMP180_VERSION_REG)==BMP180_CHIP_ID); | ||||
| } | ||||
| 
 | ||||
| static bool bmp180_createTask() | ||||
| { | ||||
|     // We already have a task
 | ||||
|     portBASE_TYPE x = pdPASS; | ||||
| 
 | ||||
|     if (bmp180_task_handle==NULL) | ||||
|     { | ||||
|         x = xTaskCreate(bmp180_driver_task, (signed char *)"bmp180_driver_task", 256, NULL, BMP180_TASK_PRIORITY, &bmp180_task_handle); | ||||
|     } | ||||
|     return (x==pdPASS); | ||||
| } | ||||
| 
 | ||||
| static void bmp180_meassure(const bmp180_command_t* command) | ||||
| { | ||||
|     int32_t T, P; | ||||
| 
 | ||||
|     // Init result to 0
 | ||||
|     T = P = 0; | ||||
| 
 | ||||
|     if (command->resultQueue != NULL) | ||||
|     { | ||||
|         int32_t UT, X1, X2, B5; | ||||
| 
 | ||||
|         //
 | ||||
|         // Temperature is always needed ... Also required for pressure only
 | ||||
|         //
 | ||||
|         // Calculation taken from BMP180 Datasheet
 | ||||
|         UT = (int32_t)bmp180_getUncompensatedMessurement(BMP180_TEMPERATURE); | ||||
| 
 | ||||
|         X1 = (UT - (int32_t)AC6) * ((int32_t)AC5) >> 15; | ||||
|         X2 = ((int32_t)MC << 11) / (X1 + (int32_t)MD); | ||||
|         B5 = X1 + X2; | ||||
| 
 | ||||
|         T = (B5 + 8) >> 4; | ||||
| 
 | ||||
| #ifdef BMP180_DEBUG | ||||
|         printf("%s: T:= %ld.%d\n", __FUNCTION__, T/10, abs(T%10)); | ||||
| #endif | ||||
| 
 | ||||
|         // Do we also need pressure?
 | ||||
|         if (command->cmd & BMP180_PRESSURE) | ||||
|         { | ||||
|             int32_t X3, B3, B6; | ||||
|             uint32_t B4, B7, UP; | ||||
| 
 | ||||
|             UP = ((uint32_t)bmp180_getUncompensatedMessurement(BMP180_PRESSURE) & 0xFFFF); | ||||
| 
 | ||||
|             // Calculation taken from BMP180 Datasheet
 | ||||
|             B6 = B5 - 4000; | ||||
|             X1 = ((int32_t)B2 * ((B6 * B6) >> 12)) >> 11; | ||||
|             X2 = ((int32_t)AC2 * B6) >> 11; | ||||
|             X3 = X1 + X2; | ||||
| 
 | ||||
|             B3 = (((int32_t)AC1 * 4 + X3) + 2) >> 2; | ||||
|             X1 = ((int32_t)AC3 * B6) >> 13; | ||||
|             X2 = ((int32_t)B1 * ((B6 * B6) >> 12)) >> 16; | ||||
|             X3 = ((X1 + X2) + 2) >> 2; | ||||
|             B4 = ((uint32_t)AC4 * (uint32_t)(X3 + 32768)) >> 15; | ||||
|             B7 = (UP - B3) * (uint32_t)(50000UL); | ||||
| 
 | ||||
|             if (B7 < 0x80000000) | ||||
|             { | ||||
|                 P = (B7 * 2) / B4; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 P = (B7 / B4) * 2; | ||||
|             } | ||||
| 
 | ||||
|             X1 = (P >> 8) * (P >> 8); | ||||
|             X1 = (X1 * 3038) >> 16; | ||||
|             X2 = (-7357 * P) >> 16; | ||||
|             P = P + ((X1 + X2 + (int32_t)3791) >> 4); | ||||
| 
 | ||||
| #ifdef BMP180_DEBUG | ||||
|             printf("%s: P:= %ld\n", __FUNCTION__, P); | ||||
| #endif | ||||
|         } | ||||
| 
 | ||||
|         // Inform the user ...
 | ||||
|         if (!bmp180_informUser(command->resultQueue, command->cmd, ((bmp180_temp_t)T)/10.0, (bmp180_press_t)P)) | ||||
|         { | ||||
|             // Failed to send info to user
 | ||||
|             printf("%s: Unable to inform user bmp180_informUser returned \"false\"\n", __FUNCTION__); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Default user inform implementation
 | ||||
| static bool bmp180_informUser_Impl(const xQueueHandle* resultQueue, uint8_t cmd, bmp180_temp_t temperatue, bmp180_press_t pressure) | ||||
| { | ||||
|     bmp180_result_t result; | ||||
| 
 | ||||
|     result.cmd = cmd; | ||||
|     result.temperatue = temperatue; | ||||
|     result.pressure = pressure; | ||||
| 
 | ||||
|     return (xQueueSend(*resultQueue, &result, 0) == pdTRUE); | ||||
| } | ||||
| 
 | ||||
| // Just init all needed queues
 | ||||
| bool bmp180_init(uint8_t scl, uint8_t sda) | ||||
| { | ||||
|     // 1. Create required queues
 | ||||
|     bool result = false; | ||||
| 
 | ||||
|     if (bmp180_create_communication_queues()) | ||||
|     { | ||||
|         // 2. Init i2c driver
 | ||||
|         i2c_init(scl, sda); | ||||
| 
 | ||||
|         // 3. Check for bmp180 ...
 | ||||
|         if (bmp180_is_avaialble()) | ||||
|         { | ||||
|             // 4. Init all internal constants ...
 | ||||
|             bmp180_fillInternalConstants(); | ||||
| 
 | ||||
|             // 5. Start driver task
 | ||||
|             if (bmp180_createTask()) | ||||
|             { | ||||
|                 // We are finished
 | ||||
|                 result = true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| void bmp180_trigger_measurement(const xQueueHandle* resultQueue) | ||||
| { | ||||
|     bmp180_command_t c; | ||||
| 
 | ||||
|     c.cmd = BMP180_PRESSURE + BMP180_TEMPERATURE; | ||||
|     c.resultQueue = resultQueue; | ||||
| 
 | ||||
|     xQueueSend(bmp180_rx_queue, &c, 0); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void bmp180_trigger_pressure_measurement(const xQueueHandle* resultQueue) | ||||
| { | ||||
|     bmp180_command_t c; | ||||
| 
 | ||||
|     c.cmd = BMP180_PRESSURE; | ||||
|     c.resultQueue = resultQueue; | ||||
| 
 | ||||
|     xQueueSend(bmp180_rx_queue, &c, 0); | ||||
| } | ||||
| 
 | ||||
| void bmp180_trigger_temperature_measurement(const xQueueHandle* resultQueue) | ||||
| { | ||||
|     bmp180_command_t c; | ||||
| 
 | ||||
|     c.cmd = BMP180_TEMPERATURE; | ||||
|     c.resultQueue = resultQueue; | ||||
| 
 | ||||
|     xQueueSend(bmp180_rx_queue, &c, 0); | ||||
| } | ||||
							
								
								
									
										55
									
								
								extras/bmp180/bmp180.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								extras/bmp180/bmp180.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | |||
| /*
 | ||||
|  * bmp180.h | ||||
|  * | ||||
|  *  Created on: 23.08.2015 | ||||
|  *      Author: fbargste | ||||
|  */ | ||||
| 
 | ||||
| #ifndef DRIVER_BMP180_H_ | ||||
| #define DRIVER_BMP180_H_ | ||||
| 
 | ||||
| #include "stdint.h" | ||||
| #include "stdbool.h" | ||||
| 
 | ||||
| #include "FreeRTOS.h" | ||||
| #include "queue.h" | ||||
| 
 | ||||
| // Uncomment to enable debug output
 | ||||
| //#define BMP180_DEBUG
 | ||||
| 
 | ||||
| #define BMP180_TEMPERATURE (1<<0) | ||||
| #define BMP180_PRESSURE    (1<<1) | ||||
| 
 | ||||
| //
 | ||||
| // Create bmp180_types
 | ||||
| //
 | ||||
| 
 | ||||
| // temperature in °C
 | ||||
| typedef float bmp180_temp_t; | ||||
| // pressure in mPa (To get hPa divide by 100)
 | ||||
| typedef uint32_t bmp180_press_t; | ||||
| 
 | ||||
| // BMP180_Event_Result
 | ||||
| typedef struct | ||||
| { | ||||
|     uint8_t cmd; | ||||
|     bmp180_temp_t  temperatue; | ||||
|     bmp180_press_t pressure; | ||||
| } bmp180_result_t; | ||||
| 
 | ||||
| // Init bmp180 driver ...
 | ||||
| bool bmp180_init(uint8_t scl, uint8_t sda); | ||||
| 
 | ||||
| // Trigger a "complete" measurement (temperature and pressure will be valid when given to "bmp180_informUser)
 | ||||
| void bmp180_trigger_measurement(const xQueueHandle* resultQueue); | ||||
| 
 | ||||
| // Trigger a "temperature only" measurement (only temperature will be valid when given to "bmp180_informUser)
 | ||||
| void bmp180_trigger_temperature_measurement(const xQueueHandle* resultQueue); | ||||
| 
 | ||||
| // Trigger a "pressure only" measurement (only pressure will be valid when given to "bmp180_informUser)
 | ||||
| void bmp180_trigger_pressure_measurement(const xQueueHandle* resultQueue); | ||||
| 
 | ||||
| // Give the user the chance to create it's own handler
 | ||||
| extern bool (*bmp180_informUser)(const xQueueHandle* resultQueue, uint8_t cmd, bmp180_temp_t temperatue, bmp180_press_t pressure); | ||||
| 
 | ||||
| #endif /* DRIVER_BMP180_H_ */ | ||||
							
								
								
									
										9
									
								
								extras/bmp180/component.mk
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								extras/bmp180/component.mk
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| # Component makefile for extras/bmp180
 | ||||
| 
 | ||||
| INC_DIRS += $(ROOT)extras | ||||
| 
 | ||||
| # args for passing into compile rule generation
 | ||||
| extras/bmp180_INC_DIR =  $(ROOT)extras | ||||
| extras/bmp180_SRC_DIR =  $(ROOT)extras/bmp180 | ||||
| 
 | ||||
| $(eval $(call component_compile_rules,extras/bmp180)) | ||||
							
								
								
									
										22
									
								
								extras/i2c/LICENSE
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								extras/i2c/LICENSE
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2015 Johan Kanflo | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
| 
 | ||||
							
								
								
									
										40
									
								
								extras/i2c/README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								extras/i2c/README.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | |||
| # Yet another I2C driver for the ESP8266 | ||||
| 
 | ||||
| This time a driver for the excellent esp-open-rtos. This is a bit banging I2C driver based on the Wikipedia pesudo C code [1]. | ||||
| 
 | ||||
| ### Adding to your project | ||||
| 
 | ||||
| Add the driver to your project as a submodule rather than cloning it: | ||||
| 
 | ||||
| ```` | ||||
| % git submodule add https://github.com/kanflo/esp-open-rtos-driver-i2c.git i2c | ||||
| ```` | ||||
| The esp-open-rtos makefile-fu will make sure the driver is built. | ||||
| 
 | ||||
| ### Usage | ||||
| 
 | ||||
| 
 | ||||
| ```` | ||||
| #include <i2c.h> | ||||
| 
 | ||||
| #define SCL_PIN (0) | ||||
| #define SDA_PIN (2) | ||||
| 
 | ||||
| uint8_t slave_addr = 0x20; | ||||
| uint8_t reg_addr = 0x1f; | ||||
| uint8_t reg_data; | ||||
| uint8_t data[] = {reg_addr, 0xc8}; | ||||
| 
 | ||||
| i2c_init(SCL_PIN, SDA_PIN); | ||||
| 
 | ||||
| // Write data to slave | ||||
| bool success = i2c_slave_write(slave_addr, data, sizeof(data)); | ||||
| 
 | ||||
| // Issue write to slave, sending reg_addr, followed by reading 1 byte | ||||
| success = i2c_slave_read(slave_addr, ®_addr, reg_data, 1); | ||||
| 
 | ||||
| ```` | ||||
| 
 | ||||
| The driver is released under the MIT license. | ||||
| 
 | ||||
| [1] https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I.C2.B2C_Master_protocol | ||||
							
								
								
									
										9
									
								
								extras/i2c/component.mk
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								extras/i2c/component.mk
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| # Component makefile for extras/i2c
 | ||||
| 
 | ||||
| INC_DIRS += $(ROOT)extras | ||||
| 
 | ||||
| # args for passing into compile rule generation
 | ||||
| extras/i2c_INC_DIR =  $(ROOT)extras | ||||
| extras/i2c_SRC_DIR =  $(ROOT)extras/i2c | ||||
| 
 | ||||
| $(eval $(call component_compile_rules,extras/i2c)) | ||||
							
								
								
									
										229
									
								
								extras/i2c/i2c.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										229
									
								
								extras/i2c/i2c.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,229 @@ | |||
| /* 
 | ||||
|  * The MIT License (MIT) | ||||
|  *  | ||||
|  * Copyright (c) 2015 Johan Kanflo (github.com/kanflo) | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <esp8266.h> | ||||
| #include <espressif/esp_misc.h> // sdk_os_delay_us | ||||
| #include "i2c.h" | ||||
| 
 | ||||
| 
 | ||||
| // I2C driver for ESP8266 written for use with esp-open-rtos
 | ||||
| // Based on https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I.C2.B2C_Master_protocol
 | ||||
| 
 | ||||
| // With calling overhead, we end up at ~100kbit/s
 | ||||
| #define CLK_HALF_PERIOD_US (1) | ||||
| 
 | ||||
| #define CLK_STRETCH  (10) | ||||
| 
 | ||||
| static bool started; | ||||
| static uint8_t g_scl_pin; | ||||
| static uint8_t g_sda_pin; | ||||
| 
 | ||||
| void i2c_init(uint8_t scl_pin, uint8_t sda_pin) | ||||
| { | ||||
|     started = false; | ||||
|     g_scl_pin = scl_pin; | ||||
|     g_sda_pin = sda_pin; | ||||
| } | ||||
| 
 | ||||
| static void i2c_delay(void) | ||||
| { | ||||
|     sdk_os_delay_us(CLK_HALF_PERIOD_US); | ||||
| } | ||||
| 
 | ||||
| // Set SCL as input and return current level of line, 0 or 1
 | ||||
| static bool read_scl(void) | ||||
| { | ||||
|     gpio_enable(g_scl_pin, GPIO_INPUT); | ||||
|     return gpio_read(g_scl_pin); // Clock high, valid ACK
 | ||||
| } | ||||
| 
 | ||||
| // Set SDA as input and return current level of line, 0 or 1
 | ||||
| static bool read_sda(void) | ||||
| { | ||||
|     gpio_enable(g_sda_pin, GPIO_INPUT); | ||||
|     // TODO: Without this delay we get arbitration lost in i2c_stop
 | ||||
|     i2c_delay(); | ||||
|     return gpio_read(g_sda_pin); // Clock high, valid ACK
 | ||||
| } | ||||
| 
 | ||||
| // Actively drive SCL signal low
 | ||||
| static void clear_scl(void) | ||||
| { | ||||
|     gpio_enable(g_scl_pin, GPIO_OUTPUT); | ||||
|     gpio_write(g_scl_pin, 0); | ||||
| } | ||||
| 
 | ||||
| // Actively drive SDA signal low
 | ||||
| static void clear_sda(void) | ||||
| { | ||||
|     gpio_enable(g_sda_pin, GPIO_OUTPUT); | ||||
|     gpio_write(g_sda_pin, 0); | ||||
| } | ||||
| 
 | ||||
| // Output start condition
 | ||||
| void i2c_start(void) | ||||
| { | ||||
|     uint32_t clk_stretch = CLK_STRETCH; | ||||
|     if (started) { // if started, do a restart cond
 | ||||
|         // Set SDA to 1
 | ||||
|         (void) read_sda(); | ||||
|         i2c_delay(); | ||||
|         while (read_scl() == 0 && clk_stretch--) ; | ||||
|         // Repeated start setup time, minimum 4.7us
 | ||||
|         i2c_delay(); | ||||
|     } | ||||
|     if (read_sda() == 0) { | ||||
|         printf("I2C: arbitration lost in i2c_start\n"); | ||||
|     } | ||||
|     // SCL is high, set SDA from 1 to 0.
 | ||||
|     clear_sda(); | ||||
|     i2c_delay(); | ||||
|     clear_scl(); | ||||
|     started = true; | ||||
| } | ||||
| 
 | ||||
| // Output stop condition
 | ||||
| void i2c_stop(void) | ||||
| { | ||||
|     uint32_t clk_stretch = CLK_STRETCH; | ||||
|     // Set SDA to 0
 | ||||
|     clear_sda(); | ||||
|     i2c_delay(); | ||||
|     // Clock stretching
 | ||||
|     while (read_scl() == 0 && clk_stretch--) ; | ||||
|     // Stop bit setup time, minimum 4us
 | ||||
|     i2c_delay(); | ||||
|     // SCL is high, set SDA from 0 to 1
 | ||||
|     if (read_sda() == 0) { | ||||
|         printf("I2C: arbitration lost in i2c_stop\n"); | ||||
|     } | ||||
|     i2c_delay(); | ||||
|     started = false; | ||||
| } | ||||
| 
 | ||||
| // Write a bit to I2C bus
 | ||||
| static void i2c_write_bit(bool bit) | ||||
| { | ||||
|     uint32_t clk_stretch = CLK_STRETCH; | ||||
|     if (bit) { | ||||
|         (void) read_sda(); | ||||
|     } else { | ||||
|         clear_sda(); | ||||
|     } | ||||
|     i2c_delay(); | ||||
|     // Clock stretching
 | ||||
|     while (read_scl() == 0 && clk_stretch--) ; | ||||
|     // SCL is high, now data is valid
 | ||||
|     // If SDA is high, check that nobody else is driving SDA
 | ||||
|     if (bit && read_sda() == 0) { | ||||
|         printf("I2C: arbitration lost in i2c_write_bit\n"); | ||||
|     } | ||||
|     i2c_delay(); | ||||
|     clear_scl(); | ||||
| } | ||||
| 
 | ||||
| // Read a bit from I2C bus
 | ||||
| static bool i2c_read_bit(void) | ||||
| { | ||||
|     uint32_t clk_stretch = CLK_STRETCH; | ||||
|     bool bit; | ||||
|     // Let the slave drive data
 | ||||
|     (void) read_sda(); | ||||
|     i2c_delay(); | ||||
|     // Clock stretching
 | ||||
|     while (read_scl() == 0 && clk_stretch--) ; | ||||
|     // SCL is high, now data is valid
 | ||||
|     bit = read_sda(); | ||||
|     i2c_delay(); | ||||
|     clear_scl(); | ||||
|     return bit; | ||||
| } | ||||
| 
 | ||||
| bool i2c_write(uint8_t byte) | ||||
| { | ||||
|     bool nack; | ||||
|     uint8_t bit; | ||||
|     for (bit = 0; bit < 8; bit++) { | ||||
|         i2c_write_bit((byte & 0x80) != 0); | ||||
|         byte <<= 1; | ||||
|     } | ||||
|     nack = i2c_read_bit(); | ||||
|     return !nack; | ||||
| } | ||||
| 
 | ||||
| uint8_t i2c_read(bool ack) | ||||
| { | ||||
|     uint8_t byte = 0; | ||||
|     uint8_t bit; | ||||
|     for (bit = 0; bit < 8; bit++) { | ||||
|         byte = (byte << 1) | i2c_read_bit(); | ||||
|     } | ||||
|     i2c_write_bit(ack); | ||||
|     return byte; | ||||
| } | ||||
| 
 | ||||
| bool i2c_slave_write(uint8_t slave_addr, uint8_t *data, uint8_t len) | ||||
| { | ||||
|     bool success = false; | ||||
|     do { | ||||
|         i2c_start(); | ||||
|         if (!i2c_write(slave_addr << 1)) | ||||
|             break; | ||||
|         while (len--) { | ||||
|             if (!i2c_write(*data++)) | ||||
|                 break; | ||||
|         } | ||||
|         i2c_stop(); | ||||
|         success = true; | ||||
|     } while(0); | ||||
|     return success; | ||||
| } | ||||
| 
 | ||||
| bool i2c_slave_read(uint8_t slave_addr, uint8_t data, uint8_t *buf, uint32_t len) | ||||
| { | ||||
|     bool success = false; | ||||
|     do { | ||||
|         i2c_start(); | ||||
|         if (!i2c_write(slave_addr << 1)) { | ||||
|             break; | ||||
|         } | ||||
|         i2c_write(data); | ||||
|         i2c_stop(); | ||||
|         i2c_start(); | ||||
|         if (!i2c_write(slave_addr << 1 | 1)) { // Slave address + read
 | ||||
|             break; | ||||
|         } | ||||
|         while(len) { | ||||
|             *buf = i2c_read(len == 1); | ||||
|             buf++; | ||||
|             len--; | ||||
|         } | ||||
|         success = true; | ||||
|     } while(0); | ||||
|     i2c_stop(); | ||||
|     if (!success) { | ||||
|         printf("I2C: write error\n"); | ||||
|     } | ||||
|     return success; | ||||
| } | ||||
							
								
								
									
										51
									
								
								extras/i2c/i2c.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								extras/i2c/i2c.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | |||
| /* 
 | ||||
|  * The MIT License (MIT) | ||||
|  *  | ||||
|  * Copyright (c) 2015 Johan Kanflo (github.com/kanflo) | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef __I2C_H__ | ||||
| #define __I2C_H__ | ||||
| #endif | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include <stdbool.h> | ||||
| 
 | ||||
| // Init bitbanging I2C driver on given pins
 | ||||
| void i2c_init(uint8_t scl_pin, uint8_t sda_pin); | ||||
| 
 | ||||
| // Write a byte to I2C bus. Return true if slave acked.
 | ||||
| bool i2c_write(uint8_t byte); | ||||
| 
 | ||||
| // Read a byte from I2C bus. Return true if slave acked.
 | ||||
| uint8_t i2c_read(bool ack); | ||||
| 
 | ||||
| // Write 'len' bytes from 'buf' to slave. Return true if slave acked.
 | ||||
| bool i2c_slave_write(uint8_t slave_addr, uint8_t *buf, uint8_t len); | ||||
| 
 | ||||
| // Issue a read operation and send 'data', followed by reading 'len' bytes
 | ||||
| // from slave into 'buf'. Return true if slave acked.
 | ||||
| bool i2c_slave_read(uint8_t slave_addr, uint8_t data, uint8_t *buf, uint32_t len); | ||||
| 
 | ||||
| // Send start and stop conditions. Only needed when implementing protocols for
 | ||||
| // devices where the i2c_slave_[read|write] functions above are of no use.
 | ||||
| void i2c_start(void); | ||||
| void i2c_stop(void); | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue