/* * Michael Fernandes * Shirley Gaw * CSE 466 Final Project - Shared Memory with I2C * * Implementation of the driver for the I2C Bus Controller * * Created: 12/16/2001 * Modified: 12/17/2001 * */ #include #include #include "I2C.h" #include "SharedMemory.h" // Holds the actual address (already shifted by a bit) unsigned char I2C_selfAddress; // Memory mapped inteface to the bus controller // A0 is represented by P2.4 // Use dest_reg for A0 = 0, use ctrl_reg for A0 = 1 unsigned char xdata dest_reg _at_ 0x0000; unsigned char xdata ctrl_reg _at_ 0x1000; // Holds all the bytes waiting to be received unsigned char * I2C_receiveBuffer; // Holds the number of bytes that have been received // -1 indicates that the address hasn't been received yet signed char I2C_numberBytes; // Read a byte with A0 = 0 unsigned char I2C_ReadByte() { return dest_reg; } // Read a byte with A0 = 1 unsigned char I2C_ReadCtrl() { return ctrl_reg; } // Send a byte with A0 = 0 void I2C_SendByte(unsigned char c) { dest_reg = c; } // Send a byte with A0 = 1 void I2C_SendCtrl(unsigned char c) { ctrl_reg = c; } // P1_0 is used to reset the bus controller // Reset the I2C Bus Controller for at least 30 clock cycles void I2C_Reset() { P1_0 = 0; _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); P1_0 = 1; } // Set the buffer that receives bytes // Reset the bus controller // Set address and clock frequencies void I2C_Init(unsigned char address, unsigned char* receiveBuffer) { P1_1 = 0; P1_2 = 0; P1_3 = 0; P1_4 = 0; P1_5 = 0; P1_6 = 0; P1_7 = 0; // Do not disable all interrupts EA = 1; // Enable external interrupt 0 EX0 = 1; // Store the address (after it has been shifted) I2C_selfAddress = address * 2; // Store the pointer to buffer used for receiving bytes I2C_receiveBuffer = receiveBuffer; // Initially, no bytes have been received I2C_numberBytes = -1; // Reset the bus controller I2C_Reset(); // Get ready to set our own address I2C_SendCtrl(0x00); // Adjusted address (after << 1) = address * 2 I2C_SendByte(address); // Get ready to set our clock I2C_SendCtrl(0x20); // Set internal clock to 12 MHz // Set SCL frequency to 90 KHz I2C_SendByte(0x1C); // Enable ESO, ENI, ACK I2C_SendCtrl(0x49); } // Tests if I2C bus is ready // If ready, START-condition and ACK will be enabled // Sets the I2C_inProgress bit // !!!!! DEBUGGING - check P1_1 for pulsing if stuck with bus busy void I2C_Start(unsigned char address) { // A0 high // Loop until bus is not busy while(!(I2C_ReadCtrl() & 0x01)) { // Check P1_1 for pulsing if stuck in this loop P1_1 = !P1_1; } P1_1 = 1; // I2C operation is now in progress P1_5 = 1; // Load slave address into S0 register I2C_SendByte(address); // Load C5H into S1, generates START condition and // clocks out slave address for acknowledgement I2C_SendCtrl(0xC5); } // Generates a STOP-condition // Clears the I2C_inProgress bit void I2C_Stop() { // Generate the STOP-condition I2C_SendCtrl(0xCB); // I2C operation is no longer in progress P1_5 = 0; } // This function will transmit 'bufferSize' bytes from 'buffer' to 'address' // !!!!! DEBUGGING - check P1_2 for pulsing if stuck with PIN != 0 void I2C_Transmit(unsigned char address, unsigned char* buffer, unsigned char bufferSize) { unsigned char i = 0; // Need to shift address by 1 bit I2C_Start(address*2); // A0 high // Poll for transmission finished while(1) { // Read byte from S1 register // Loop while PIN != 0 while(I2C_ReadCtrl() & 0x80) { // Check P1_2 for pulsing if stuck in this loop P1_2 = !P1_2; } P1_2 = 1; // Did the slave acknowledge the send? if(!(I2C_ReadCtrl() & 0x08)) { // Slave was found if(i < bufferSize) { I2C_SendByte(buffer[i]); i++; } else { I2C_Stop(); return; } } else { // Slave did not acknowledge! I2C_Stop(); return; } } } // Receives bytes from a transmit // !!!!! DEBUGGING - check P1_3 for pulsing if stuck with PIN != 0 void I2C_Interrupt() interrupt 0 { unsigned char control; if(I2C_numberBytes < 0) { // Read incoming address (could check for slave receiver mode) if(I2C_selfAddress == I2C_ReadByte()) { // Receive in progress P1_6 = 1; // Now ready to read data I2C_numberBytes = 0; } } else { // Read byte from S1 register // Loop while PIN != 0 do { control = I2C_ReadCtrl(); // Check P1_3 for pulsing if stuck in this loop P1_3 = !P1_3; } while(control & 0x80); P1_3 = 1; // Was stop signaled (STS = 1)? if(control & 0x20) { SharedMemory_Receive(I2C_receiveBuffer, I2C_numberBytes); I2C_numberBytes = -1; // Receive no longer in progress P1_6 = 0; } else { I2C_receiveBuffer[I2C_numberBytes] = I2C_ReadByte(); I2C_numberBytes++; } } }