Commits

Anonymous committed 7462539 Draft

adding new module for I2C protocol

Comments (0)

Files changed (1)

src/platform/stm32f4/wire.py

+# this module allow communication with I2C peripheral
+# and STM32F4 board.
+# this module just wrap the work of Torrentula inside python
+# method. Like every time python is a glue :)
+# thx Torrentula
+# https://github.com/Torrentula/STM32F4-examples/blob/master/I2C%20Master/main.c
+# for the moment we only address I2C1 peripheral (this simplify argument work :)
+#
+# stm32F4 can have three peripheral I2C : I2C1, I2C2 and I2C3 as declared in
+# stm32f4xx.h !
+#
+
+
+# the slave address (example)
+SLAVE_ADDRESS = 0x3D 
+
+I2C_Direction_Transmitter  = 0x00
+I2C_Direction_Receiver  = 0x01
+
+"""__NATIVE__
+#include "plat.h"
+#include <stm32f4xx.h>
+#include <stm32f4xx_i2c.h>
+"""
+
+def init_I2C1()
+    """__NATIVE__
+    PmReturn_t retval = PM_RET_OK;
+	GPIO_InitTypeDef GPIO_InitStruct;
+	I2C_InitTypeDef I2C_InitStruct;
+
+	// enable APB1 peripheral clock for I2C1
+	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
+	// enable clock for SCL and SDA pins
+	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
+
+	/* setup SCL and SDA pins
+	 * You can connect I2C1 to two different
+	 * pairs of pins:
+	 * 1. SCL on PB6 and SDA on PB7 
+	 * 2. SCL on PB8 and SDA on PB9
+	 */
+	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // we are going to use PB6 and PB7
+	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;			// set pins to alternate function
+	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;		// set GPIO speed
+	GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;			// set output to open drain --> the line has to be only pulled low, not driven high
+	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;			// enable pull up resistors
+	GPIO_Init(GPIOB, &GPIO_InitStruct);					// init GPIOB
+
+	// Connect I2C1 pins to AF  
+	GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);	// SCL
+	GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1); // SDA
+
+	// configure I2C1 
+	I2C_InitStruct.I2C_ClockSpeed = 100000; 		// 100kHz
+	I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;			// I2C mode
+	I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;	// 50% duty cycle --> standard
+	I2C_InitStruct.I2C_OwnAddress1 = 0x00;			// own address, not relevant in master mode
+	I2C_InitStruct.I2C_Ack = I2C_Ack_Disable;		// disable acknowledge when reading (can be changed later on)
+	I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // set address length to 7 bit addresses
+	I2C_Init(I2C1, &I2C_InitStruct);				// init I2C1
+
+	// enable I2C1
+	I2C_Cmd(I2C1, ENABLE);
+    return retval;
+    """
+    pass
+
+# This function issues a start condition and 
+# transmits the slave address + R/W bit
+# 
+# Parameters:
+# 		I2Cx --> the I2C peripheral e.g. I2C1
+# 		address --> the 7 bit slave address
+# 		direction --> the tranmission direction can be:
+# 						I2C_Direction_Tranmitter for Master transmitter mode
+# 						I2C_Direction_Receiver for Master receiver
+def I2C_start(address, direction):
+    """__NATIVE__
+    PmReturn_t retval = PM_RET_OK;
+
+    pPmObj_t paddress;
+    pPmObj_t pdirection;
+
+    uint8_t address;
+    uint8_t direction;
+
+    if(NATIVE_GET_NUM_ARGS() != 2)
+    {
+      PM_RAISE(retval, PM_RET_EX_TYPE);
+      return retval;
+    }
+
+    paddress = NATIVE_GET_LOCAL(0);
+    if (OBJ_GET_TYPE(paddress) != OBJ_TYPE_INT)
+    {
+      PM_RAISE(retval, PM_RET_EX_TYPE);
+      return retval;
+    }
+    address = (uint8_t)((pPmInt_t)paddress)->val;
+
+    pdirection = NATIVE_GET_LOCAL(1);
+    if (OBJ_GET_TYPE(pdirection) != OBJ_TYPE_INT)
+    {
+      PM_RAISE(retval, PM_RET_EX_TYPE);
+      return retval;
+    }
+    direction = (uint8_t)((pPmInt_t)pdirection)->val;
+
+	// wait until I2C1 is not busy anymore
+	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
+  
+	// Send I2C1 START condition 
+	I2C_GenerateSTART(I2C1, ENABLE);
+
+	// wait for I2C1 EV5 --> Slave has acknowledged start condition
+	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
+
+	// Send slave Address for write 
+	I2C_Send7bitAddress(I2C1, address, direction);
+
+	/* wait for I2C1 EV6, check if 
+	 * either Slave has acknowledged Master transmitter or
+	 * Master receiver mode, depending on the transmission
+	 * direction
+	 */ 
+	if(direction == I2C_Direction_Transmitter){
+		while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
+	}
+	else if(direction == I2C_Direction_Receiver){
+		while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
+	}
+    return retval;
+    """
+    pass
+
+# This function transmits one byte to the slave device
+# Parameters:
+#		I2Cx --> the I2C peripheral e.g. I2C1 
+#		data --> the data byte to be transmitted
+# data should be an int !
+def I2C_write(data):
+    """__NATIVE__
+    PmReturn_t retval = PM_RET_OK;
+    pPmObj_t pdat;
+    uint8_t data;
+
+    if(NATIVE_GET_NUM_ARGS() != 1)
+    {
+      PM_RAISE(retval, PM_RET_EX_TYPE);
+      return retval;
+    }
+
+    pdat = NATIVE_GET_LOCAL(0);
+    if (OBJ_GET_TYPE(pdat) != OBJ_TYPE_INT)
+    {
+      PM_RAISE(retval, PM_RET_EX_TYPE);
+      return retval;
+    }
+    data = (uint8_t)((pPmInt_t)pdat)->val;
+ 
+	I2C_SendData(I2C1, data);
+	// wait for I2C1 EV8_2 --> byte has been transmitted
+	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
+    return retval;
+    """
+    pass
+
+# This function reads one byte from the slave device 
+# and acknowledges the byte (requests another byte)
+def I2C_read_ack():
+    """__NATIVE__
+	// enable acknowledge of recieved data
+	I2C_AcknowledgeConfig(I2C1, ENABLE);
+	// wait until one byte has been received
+	while( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) );
+	// read data from I2C data register and return data byte
+	uint8_t data = I2C_ReceiveData(I2C1);
+	return data;
+    """
+
+# This function reads one byte from the slave device
+# and doesn't acknowledge the recieved data 
+def I2C_read_nack():
+    """__NATIVE__
+	// disabe acknowledge of received data
+	I2C_AcknowledgeConfig(I2C1, DISABLE);
+	// wait until one byte has been received
+	while( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) );
+	// read data from I2C data register and return data byte
+	uint8_t data = I2C_ReceiveData(I2C1);
+	return data;
+    """
+    pass
+
+# This funtion issues a stop condition and therefore
+# releases the bus
+def I2C_stop():
+    """__NATIVE__
+    PmReturn_t retval = PM_RET_OK;
+	// Send I2C1 STOP Condition 
+	I2C_GenerateSTOP(ENABLE);
+    return retval;
+    """
+    pass
+
+def test(SLAVE_ADDRESS):
+    """
+    """
+    init_I2C1()
+    received_data=[]
+
+    while True :
+        # start a transmission in Master transmitter mode
+		I2C_start(SLAVE_ADDRESS, I2C_Direction_Transmitter)
+        # write one byte to the slave
+		I2C_write(0x20)
+        # write another byte to the slave
+		I2C_write(0x03) 
+        # stop the transmission
+		I2C_stop()
+
+        # start a transmission in Master receiver mode
+		I2C_start(SLAVE_ADDRESS, I2C_Direction_Receiver)
+        # read one byte and request another byte
+		received_data[0] = I2C_read_ack()
+        # read one byte and don't request another byte
+		received_data[1] = I2C_read_nack()
+        # stop the transmission
+		I2C_stop()
+        print received_data
+