#include "SharedMemory.h"
#include "Serial.h"
#include "I2C.h"
// Count MAX_WAIT times before timing out
#define MAX_WAIT 16383
// If greater than 0, it holds the number of bytes received from I2C level
unsigned char SharedMemory_receivedSize;
// True if a read is being attempted
// False if read causes time out or read is returned successfully
bit SharedMemory_attemptingRead;
// True if responding to a read
bit SharedMemory_respondingToRead;
// True if a chat message has been received
bit SharedMemory_receivedChatMessage;
// Holds the size of a transmitted chat command
unsigned char SharedMemory_transmitSize;
// Holds the value assigned to shared memory during a write command
unsigned char SharedMemory_writeValue;
// Buffer to hold the received response from a read request
unsigned char SharedMemory_receivedReadResponse[5];
// Buffer to hold the message that is sent in response to a read
unsigned char SharedMemory_sendReadResponse[5];
// Buffer to hold message received from I2C level
unsigned char SharedMemory_receiveBuffer[COMMAND_BUFFER_SIZE];
// Buffer to hold chat messages
unsigned char SharedMemory_chatBuffer[COMMAND_BUFFER_SIZE];
// Buffer to hold the command entered (also used for transmitting to I2C)
unsigned char SharedMemory_commandString[COMMAND_BUFFER_SIZE];
// Shared memory of a processor
unsigned char SharedMemory_shared[SHARED_MEMORY_BYTES];
// Clear the local processor's shared memory (set it to zero)
void SharedMemory_Zero()
{
unsigned char i;
// Initialize the shared memory to 0
for(i = 0; i < SHARED_MEMORY_BYTES; i++)
SharedMemory_shared[i] = 0;
}
// Display the contents of the local processor's shared memory
void SharedMemory_View()
{
unsigned char i;
// Initialize the shared memory to 0
for(i = 0; i < SHARED_MEMORY_BYTES; i++)
{
Serial_SendNewLine();
Serial_SendString("Processor <~",'~',80);
Serial_SendCharacter(ADDRESS_SELF);
Serial_SendString("> Memory <~",'~',80);
Serial_SendDecimal(i);
Serial_SendString("> = ~",'~',80);
Serial_SendDecimal(SharedMemory_shared[i]);
}
Serial_SendNewLine();
Serial_SendNewLine();
}
// Display the contents of the local memory location i
void SharedMemory_Read(unsigned char i)
{
Serial_SendNewLine();
Serial_SendString("Processor <~",'~',80);
Serial_SendCharacter(ADDRESS_SELF);
Serial_SendString("> Memory <~",'~',80);
Serial_SendDecimal(i);
Serial_SendString("> = ~",'~',80);
Serial_SendDecimal(SharedMemory_shared[i]);
Serial_SendNewLine();
Serial_SendNewLine();
}
// Write value to the local memory location i
void SharedMemory_Write(unsigned char i, unsigned char value)
{
SharedMemory_shared[i] = value;
}
// Display the last received message
void SharedMemory_DisplayReceive()
{
if(SharedMemory_receivedSize > 0)
{
Serial_SendNewLine();
Serial_SendString("To: ~",'~',80);
Serial_SendCharacter(SharedMemory_receiveBuffer[0]);
Serial_SendNewLine();
Serial_SendString("From: ~",'~',80);
Serial_SendCharacter(SharedMemory_receiveBuffer[1]);
Serial_SendNewLine();
Serial_SendString("Type: ~",'~',80);
switch(SharedMemory_receiveBuffer[2])
{
// READ
case 'r':
Serial_SendString("READ~",'~',80);
Serial_SendNewLine();
Serial_SendString("Variable: ~",'~',80);
Serial_SendDecimal(SharedMemory_receiveBuffer[3]);
Serial_SendNewLine();
break;
// RETURNED READ
case 'R':
Serial_SendString("RETURNED READ~",'~',80);
Serial_SendNewLine();
Serial_SendString("Variable: ~",'~',80);
Serial_SendDecimal(SharedMemory_receiveBuffer[3]);
Serial_SendNewLine();
Serial_SendString("Value: ~",'~',80);
Serial_SendDecimal(SharedMemory_receiveBuffer[4]);
Serial_SendNewLine();
break;
// WRITE
case 'w':
Serial_SendString("WRITE~",'~',80);
Serial_SendNewLine();
Serial_SendString("Variable: ~",'~',80);
Serial_SendDecimal(SharedMemory_receiveBuffer[3]);
Serial_SendNewLine();
Serial_SendString("Assigned: ~",'~',80);
Serial_SendDecimal(SharedMemory_receiveBuffer[4]);
Serial_SendNewLine();
break;
// CHAT
case 'c':
Serial_SendString("CHAT~",'~',80);
Serial_SendNewLine();
Serial_SendString("Message: ~",'~',80);
Serial_SendString(&SharedMemory_receiveBuffer[3],CARRIAGE_RETURN,SharedMemory_receivedSize-3);
Serial_SendNewLine();
break;
// ERROR
default:
Serial_SendString("ERROR - Unrecognized type!~",'~',80);
Serial_SendNewLine();
break;
}
Serial_SendNewLine();
}
else
{
Serial_SendNewLine();
Serial_SendString("No messages have been received.~",'~',80);
Serial_SendNewLine();
Serial_SendNewLine();
}
}
// Display an error message for an unrecognized command
void SharedMemory_CommandError()
{
Serial_SendNewLine();
Serial_SendString("Unrecognized command (type '?' for command syntax).~",'~',80);
Serial_SendNewLine();
Serial_SendNewLine();
}
// Initialize variables, serial interface, and I2C devices
// Display program name, authors, etc...
void SharedMemory_Init()
{
Serial_Init(BAUD_RATE_9600);
I2C_Init(ADDRESS_SELF,SharedMemory_receiveBuffer);
SharedMemory_respondingToRead = 0;
SharedMemory_attemptingRead = 0;
SharedMemory_receivedSize = 0;
SharedMemory_receivedChatMessage = 0;
SharedMemory_Zero();
Serial_SendNewLine();
Serial_SendNewLine();
Serial_SendString("***********************************************************~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** I2C Chat 1.30 ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** Final Project ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** CSE 466 Autumn 2001 ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** Michael Fernandes ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** Shirley Gaw ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** Type '?' for command syntax ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("***********************************************************~",'~',80);
Serial_SendNewLine();
Serial_SendNewLine();
}
// Display help (describes command syntax)
void SharedMemory_Help()
{
Serial_SendNewLine();
Serial_SendString("***********************************************************~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** COMMANDS ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** HELP: '?' ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** PING: 'P' ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** ZERO: 'Z' ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** VIEW: 'V' ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** CHAT:
'c' ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** READ: 'r' ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** WRITE: 'w' ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** Entering nothing displays the last message received ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** PARAMETERS ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** - address of processor ('a' to 'z') ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** - memory location ('0' to '9') ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** - message to send ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("*** - value to assign ('0' to '255') ***~",'~',80);
Serial_SendNewLine();
Serial_SendString("***********************************************************~",'~',80);
Serial_SendNewLine();
Serial_SendNewLine();
}
// Give the user a prompt to enter commands and parse the commands
void SharedMemory_Input()
{
unsigned char i;
unsigned int waitCount;
Serial_SendString("I2C Chat ~",'~',80);
Serial_SendCharacter(ADDRESS_SELF);
Serial_SendString(":\> ~",'~',80);
Serial_ReceiveString(SharedMemory_commandString,CARRIAGE_RETURN,COMMAND_BUFFER_SIZE);
while(SERIAL_getReceivingString())
{
// Handle the request to respond to a read
if(SharedMemory_respondingToRead)
{
// No longer responding to a read
SharedMemory_respondingToRead = 0;
I2C_Transmit(SharedMemory_sendReadResponse[0], SharedMemory_sendReadResponse, 5);
}
// Display the chat message
if(SharedMemory_receivedChatMessage)
{
Serial_SendNewLine();
Serial_SendNewLine();
Serial_SendString("Message from ~",'~',80);
Serial_SendCharacter(SharedMemory_chatBuffer[1]);
Serial_SendString(": ~",'~',80);
Serial_SendString(&SharedMemory_chatBuffer[3],CARRIAGE_RETURN,SharedMemory_receivedSize-3);
Serial_SendNewLine();
Serial_SendNewLine();
Serial_SendString("I2C Chat cont... ~",'~',80);
Serial_SendCharacter(ADDRESS_SELF);
Serial_SendString(":\> ~",'~',80);
SharedMemory_receivedChatMessage = 0;
}
}
Serial_SendNewLine();
if(SharedMemory_commandString[0] == CARRIAGE_RETURN)
{
SharedMemory_DisplayReceive();
}
else if(SharedMemory_commandString[0] == '?')
{
if(SharedMemory_commandString[1] != CARRIAGE_RETURN)
{
SharedMemory_CommandError();
return;
}
else
{
SharedMemory_Help();
return;
}
}
else if(SharedMemory_commandString[0] == 'Z')
{
if(SharedMemory_commandString[1] != CARRIAGE_RETURN)
{
SharedMemory_CommandError();
return;
}
else
{
SharedMemory_Zero();
return;
}
}
else if(SharedMemory_commandString[0] == 'V')
{
if(SharedMemory_commandString[1] != CARRIAGE_RETURN)
{
SharedMemory_CommandError();
return;
}
else
{
SharedMemory_View();
return;
}
}
else if(SharedMemory_commandString[0] == 'P')
{
if(SharedMemory_commandString[1] != CARRIAGE_RETURN)
{
SharedMemory_CommandError();
return;
}
SharedMemory_commandString[1] = ADDRESS_SELF;
SharedMemory_commandString[2] = 'r';
SharedMemory_commandString[3] = 0;
Serial_SendNewLine();
Serial_SendString("Searching for processors: a b c d e f g h i j k l m n o p q r s t u v w x y z~",'~',80);
Serial_SendNewLine();
Serial_SendString("Marked with 'X' if found: ~",'~',80);
// PING
for(i = 'a'; i <= 'z'; i++)
{
// Don't need to ping yourself
if(i == ADDRESS_SELF)
{
Serial_SendString("X ~",'~',80);
continue;
}
SharedMemory_commandString[0] = i;
// About to attempt a read
SharedMemory_attemptingRead = 1;
I2C_Transmit(SharedMemory_commandString[0], SharedMemory_commandString, 4);
// Attempt to read until waitCount exceeds MAX_WAIT
waitCount = 0;
while(SharedMemory_attemptingRead)
{
if(waitCount < MAX_WAIT)
{
waitCount++;
}
else
{
Serial_SendString(". ~",'~',80);
// No longer attempting a read
SharedMemory_attemptingRead = 0;
break;
}
}
if(waitCount < MAX_WAIT)
{
Serial_SendString("X ~",'~',80);
}
}
Serial_SendNewLine();
Serial_SendNewLine();
}
else if(SharedMemory_commandString[0] < 'a' || SharedMemory_commandString[0] > 'z')
{
Serial_SendNewLine();
Serial_SendString("Invalid address (must be from 'a' to 'z').~",'~',80);
Serial_SendNewLine();
Serial_SendNewLine();
}
else
{
if(SharedMemory_commandString[1] != ' ')
{
SharedMemory_CommandError();
return;
}
SharedMemory_commandString[1] = ADDRESS_SELF;
switch(SharedMemory_commandString[2])
{
// READ
case 'r':
if(SharedMemory_commandString[0] == ADDRESS_SELF)
{
if(SharedMemory_commandString[3] != ' ' ||
SharedMemory_commandString[4] > '9' ||
SharedMemory_commandString[4] < '0' ||
SharedMemory_commandString[5] != CARRIAGE_RETURN)
{
SharedMemory_CommandError();
return;
}
else
{
SharedMemory_Read(SharedMemory_commandString[4] - '0');
return;
}
}
else
{
if(SharedMemory_commandString[3] != ' ' ||
SharedMemory_commandString[4] > '9' ||
SharedMemory_commandString[4] < '0' ||
SharedMemory_commandString[5] != CARRIAGE_RETURN)
{
SharedMemory_CommandError();
return;
}
else
{
SharedMemory_commandString[3] = SharedMemory_commandString[4] - '0';
// About to attempt a read
SharedMemory_attemptingRead = 1;
I2C_Transmit(SharedMemory_commandString[0], SharedMemory_commandString, 4);
// Attempt to read until waitCount exceeds MAX_WAIT
waitCount = 0;
while(SharedMemory_attemptingRead)
{
if(waitCount < MAX_WAIT)
{
waitCount++;
}
else
{
// No longer attempting a read
SharedMemory_attemptingRead = 0;
Serial_SendNewLine();
Serial_SendString("Read timed out, please try again later.~",'~',80);
Serial_SendNewLine();
Serial_SendNewLine();
return;
}
}
Serial_SendNewLine();
Serial_SendString("Processor <~",'~',80);
Serial_SendCharacter(SharedMemory_receivedReadResponse[1]);
Serial_SendString("> Memory <~",'~',80);
Serial_SendDecimal(SharedMemory_receivedReadResponse[3]);
Serial_SendString("> = ~",'~',80);
Serial_SendDecimal(SharedMemory_receivedReadResponse[4]);
Serial_SendNewLine();
Serial_SendNewLine();
return;
}
}
break;
// WRITE
case 'w':
if(SharedMemory_commandString[0] == ADDRESS_SELF)
{
if(SharedMemory_commandString[3] != ' ' ||
SharedMemory_commandString[4] > '9' ||
SharedMemory_commandString[4] < '0')
{
SharedMemory_CommandError();
return;
}
else
{
if(SharedMemory_commandString[5] != ' ')
{
SharedMemory_CommandError();
return;
}
else
{
SharedMemory_writeValue = 0;
// very poor error checking here, but it will only assign a bad value
for(i = 6; SharedMemory_commandString[i] != CARRIAGE_RETURN; i++)
{
SharedMemory_writeValue *= 10;
SharedMemory_writeValue += SharedMemory_commandString[i] - '0';
}
SharedMemory_Write(SharedMemory_commandString[4] - '0',SharedMemory_writeValue);
return;
}
}
}
else
{
if(SharedMemory_commandString[3] != ' ' ||
SharedMemory_commandString[4] > '9' ||
SharedMemory_commandString[4] < '0')
{
SharedMemory_CommandError();
return;
}
else
{
if(SharedMemory_commandString[5] != ' ')
{
SharedMemory_CommandError();
return;
}
else
{
SharedMemory_writeValue = 0;
// very poor error checking here, but it will only assign a bad value
for(i = 6; SharedMemory_commandString[i] != CARRIAGE_RETURN; i++)
{
SharedMemory_writeValue *= 10;
SharedMemory_writeValue += SharedMemory_commandString[i] - '0';
}
SharedMemory_commandString[3] = SharedMemory_commandString[4] - '0';
SharedMemory_commandString[4] = SharedMemory_writeValue;
I2C_Transmit(SharedMemory_commandString[0], SharedMemory_commandString, 5);
return;
}
}
}
break;
// CHAT
case 'c':
if(SharedMemory_commandString[0] == ADDRESS_SELF)
{
// Do nothing for now, need to fix this up
Serial_SendNewLine();
Serial_SendString("Stop sending yourself messages!~",'~',80);
Serial_SendNewLine();
Serial_SendNewLine();
return;
}
else
{
if(SharedMemory_commandString[3] != ' ')
{
SharedMemory_CommandError();
return;
}
SharedMemory_transmitSize = 0;
while(SharedMemory_commandString[SharedMemory_transmitSize+4] != CARRIAGE_RETURN)
{
SharedMemory_commandString[SharedMemory_transmitSize+3] = SharedMemory_commandString[SharedMemory_transmitSize+4];
SharedMemory_transmitSize++;
}
if(SharedMemory_transmitSize > 0)
I2C_Transmit(SharedMemory_commandString[0], SharedMemory_commandString, SharedMemory_transmitSize+3);
else
SharedMemory_CommandError();
return;
}
break;
default:
SharedMemory_CommandError();
return;
}
}
}
// Interrupt handler called from I2C when a receive has completed
void SharedMemory_Receive(unsigned char* receiveBuffer, unsigned char size)
{
unsigned char i;
SharedMemory_receivedSize = size;
// Handle message
switch(SharedMemory_receiveBuffer[2])
{
// READ
case 'r':
// If already responding to a read, ignore all incoming read requests (will cause reqeuster to timeout)
if(!SharedMemory_respondingToRead)
{
// Prepare a message to respond to the read request
SharedMemory_sendReadResponse[0] = receiveBuffer[1];
SharedMemory_sendReadResponse[1] = receiveBuffer[0];
SharedMemory_sendReadResponse[2] = 'R';
SharedMemory_sendReadResponse[3] = receiveBuffer[3];
SharedMemory_sendReadResponse[4] = SharedMemory_shared[receiveBuffer[3]];
SharedMemory_respondingToRead = 1;
}
break;
// WRITE
case 'w':
SharedMemory_Write(receiveBuffer[3],receiveBuffer[4]);
break;
// CHAT
case 'c':
// If already receiving a chat message, ignore all incoming messages
if(!SharedMemory_receivedChatMessage)
{
for(i = 0; i < size; i++)
SharedMemory_chatBuffer[i] = receiveBuffer[i];
SharedMemory_receivedChatMessage = 1;
}
break;
// RETURNED READ
case 'R':
// Buffer the read response to dislay the results
SharedMemory_receivedReadResponse[0] = receiveBuffer[0];
SharedMemory_receivedReadResponse[1] = receiveBuffer[1];
SharedMemory_receivedReadResponse[2] = receiveBuffer[2];
SharedMemory_receivedReadResponse[3] = receiveBuffer[3];
SharedMemory_receivedReadResponse[4] = receiveBuffer[4];
// No longer attempting a read
SharedMemory_attemptingRead = 0;
break;
// ERROR
default:
break;
}
}