Lab 3 and 4 - University of Calgarypeople.ucalgary.ca/.../17_Nov/17_11_ZZ_IdeasForLab4.pdfLab 3 and...
-
Upload
vuongkhanh -
Category
Documents
-
view
218 -
download
2
Transcript of Lab 3 and 4 - University of Calgarypeople.ucalgary.ca/.../17_Nov/17_11_ZZ_IdeasForLab4.pdfLab 3 and...
Lab 3 and 4B02 / 04 – Tuesday 31st October Reading week – Tuesday 7th November – I will be in Labs but no TAsB01 / 03 – Tuesday 14th NovemberB02/ 04 – Tuesday 21st NovemberB01 / 03 – Tuesday 28th NovemberB02 / 04 – Tuesday 5th November
Lab 4 Part 1 is a quick “Set up the LCD and a few wires, press a few buttons (in the exactly correct order) and leave the Lab”.It is demoed by your group outside the Lab period in under an hour. I will probably do this the 27th November 8:00 tutorial for B01 / B03 and after the class on Friday 1st December for B02 / B04.Can be done at other times, say after 4 pm during a Lab.
Lab 3 and Lab 4
• You now have enough knowledge to handle the remaining Labs• So I am going to allow you to work at your own speed
• Two Choices for getting full marks on the Labs. I will get you to confirm by letter in D2L drop box which is your team’s choice by 1stDecember. • Lab 0, 1, 2, 3, 4 OR since Lab 3 is mainly Lab 2 with a twist, and Lab 4 is different
• Lab 0, 1, 2 and 4, and understand Lab 3 ideas• Reports (mainly upload code and screen shots / video) for Lab 3 / 4 or just Lab 4 will be due before the end of term
• All demos need to be completed no later than last Lab period
Lab 4
Part 1 – Show you can MANUALLY send a message to LCD screen ‐‐ Quick 40%Part 2 – Set up a simple message system to use the SPI industry
standard to send a message to the LCD screen ‐‐ 40%
Part 3 – Either hook up Part 2 to Lab 3 (and send temperature messages to LCD screen)or Part 2 to Lab 2 (and send car direction messages to LCD) ‐‐ 20%
Making the SPI interface work to send messages• SPI_Message_OS_Thread( ) runs as a thread inside uTTCOSg and is totally responsible for sending SPI messages to the LCD screen
• Your threads from Lab 2 and 3 are not changed, unless they want to send a message to the LCD screen in this fashion
char myBuffer[200]volatile int count = 0;void ExampleMessageThread(void) { // My pattern – use markers
sprintf(myBuffer, “!%s %d!”, “Some Message”, count++);printf(“%s\n”, myBuffer); // Quick Check on use of sprintfunsigned int tokenSPI = PermissionToSendSPIMessage();if (tokenSPI != 0)
SendSPIMessage(tokenSPI, myBuffer);}
Second part of Lab 4Follow the logic – fix the syntax errors
• Set up a uTTCOS project –and add 4 message threads like this which Flash an LED but don’t send a message
• Once working – then change if 0 to if 1 to activate message passing• From home – don’t activate the LED
char myBuffer[200];volatile int count = 0;void ExampleMessageThread(void) {
sprint(myBuffer, “>%s %d<”, “Some message”, count++);FlashLED(?)
#if 0unsigned int tokenSPI = PermissionToSendSPIMessage();if (tokenSPI != 0)
SendSPIMessage(tokenSPI, myBuffer);#endif}
Set up the MOCK SPI Message OS stubs in the file SPI_Message_OS.cppstatic volatile unsigned int SPI_tokenSent = 0;static volatile bool SPI_interfaceInUse = true;static char SPI_MessageToSend[200];void SPI_Message_OS_Thread(void) {
/* TODO SPI_Message_OS_Thread */ }unsigned int PermissionToSendSPIMessage(void) {
printf(“No \n”); // TODO SPI_interfaceInUse = trueSPI_tokenSent = 0return SPI_ tokenSent;
}; // Look up .h for strcpy on the web
SendSPIMessage(unsigned tokenSPI, char * yourMessage) {if (tokenSPI == SPI_tokenSent) {
printf(“>%s<\n”, yourMessage); SPI_tokenSent = 0; strcpy(SPI_MessageToSend, yourMessage); }
else { printf(“Bad token – SPI request ignored\n”); }
Build and run the code
Message sending will always fail
Now change PermissionToSendSPIMessage( ) to use the rand( ) function to generate a random number
If the random number is divisible by 4 – send the random number as the token and don’t say now
There will be a 1 in 4 chance than any of the 4 messages will print
More realistic unsigned int PermissionToSendSPIMessage(void)Follow the logic – fix the syntax errors
unsigned int PermissionToSendSPIMessage(void) {unsigned int randomValue = rand( );// divide by 4 and keep remainderunsigned int remanider = randomValue & 0x3if remainder == 0 {
SPI_tokenSent = randomValue;SPI_interfaceInUse = true
printf(“Accepted\n”);}else {
printf(“No \n”); // TODO SPI_tokenSent = 0
}return SPI_ tokenSent;
};
SPI_Message_OS_Thread ‐‐ Planstatic volatile unsigned int SPI_tokenSent = 0;static volatile bool SPI_interfaceInUse = true;static volatile char SPI_MessageToSend[200];void SPI_Message_OS_Thread(void) {
State 0: Set up the SPI interface State 1 – Not sending a messageState 2 ‐‐ received a request to send a char message but already sending a
messageState 3 – Received a request to send a char message State 4 ‐‐ Change the char message into the SPI message format which includes
timing signals and char State 5 – Sending a SPI message but not yet finishedState 6 – Finished sending SPI message,
clean up interface so can safe fully go to State 1 and be ready for next message}
SPI_Message_OS_Thread – PlanWith some design refactoring static volatile unsigned int SPI_tokenSent = 0;static volatile bool SPI_interfaceInUse = true;static char SPI_MessageToSend[200]; void SPI_Message_OS_Thread(void) {
State 0: SetUpSPIInterface( ); SPISTATE = 1; SPI_interfaceInUse = ??Other stuff as needed
State 1 – Not sending a messageState 2 ‐‐ received a request to send a char message but already sending a messageState 3 – Received a request to send a char message State 4 ‐‐ Change the char message into the SPI message format which includes timing
signals and char State 5 – Sending a SPI message but not yet finishedState 6 – Finished sending SPI message,
clean up interface so can safe fully go to State 1 and be ready for next message}
SPI_Message_OS_Thread – PlanWith some design refactoring
static volatile unsigned int SPI_tokenSent = 0;static volatile bool SPI_interfaceInUse = true;static volatile char SPI_MessageToSend[200];static volatile short int SPI_MessageToSend_SPIFormat[600];void SPI_Message_OS_Thread(void) {
State 0: SetUpSPIInterface( ); SPISTATE = 1; SPI_interfaceInUse = ??Other stuff as needed
State 1 – Not sending a messageState 2 ‐‐ received a request to send a char message but already sending a messageState 3 – Received a request to send a char message State 4 ‐‐ ChangeToSPIMessageFormat(SPI_MessageToSend,
SPI_MessageToSend_SPIFormat);numberSPIshortIntsToSend = ???; numberSPIshortIntsSent = 0; SPISTATE = 5;
State 5 – Sending a SPI message but not yet finishedif (SPI_NOT_READY() ) return;else {numberSPIshortIntsToSend ‐‐; numberSPIshortIntsSent ++;
if (numberSPIshortIntsToSend == 0) SPISTATE = 6;State 6 – Finished sending SPI message,
clean up interface so can safe fully go to State 1 and be ready for next message}
SPI_Message_OS_Thread – PlanWith some design refactoring
static volatile unsigned int SPI_tokenSent = 0;static volatile bool SPI_interfaceInUse = true;static volatile char SPI_MessageToSend[200];static volatile short int SPI_MessageToSend_SPIFormat[600];void SPI_Message_OS_Thread(void) {
State 0: SetUpSPIInterface( ); SPISTATE = 1; SPI_interfaceInUse = ??Other stuff as needed
State 1 – Not sending a messageState 2 ‐‐ received a request to send a char message but already sending a messageState 3 – Received a request to send a char message State 4 ‐‐ // Change the char message into the SPI message format
ChangeToSPIMessageFormat(SPI_MessageToSend, SPI_MessageToSend_SPIFormat);
numberSPIshortIntsToSend = ???; numberSPIshortIntsSent = 0; SPISTATE = 5;State 5 – if (SPI_NOT_READY( )) return:
else {numberSPIshortIntsToSend ‐‐; numberSPIshortIntsSent ++;if (numberSPIshortIntsToSend == 0) SPISTATE = 6;
State 6 – SPI_interfaceInUse = false; numberSPIshortIntsToSend = 0; /* Other stuff */; SPISTATE = 0;clean up interface so can safe fully go to State 1 and be ready for next message
}
SPI_Message_OS_Thread – Planstatic volatile unsigned int SPI_tokenSent = 0;static volatile bool SPI_interfaceInUse = true;static volatile char SPI_MessageToSend[200];static volatile short int SPI_MessageToSend_SPIFormat[600];static volatile int messageRequest = 0;void SPI_Message_OS_Thread(void) {
State 0: SetUpSPIInterface( ); SPISTATE = 1; SPI_interfaceInUse = ??Other stuff as needed
State 1 – Not sending a messageState 2 ‐‐ received a request to send a char message but already sending a messageState 3 – Received a request to send a char messageState 4 ‐‐ // Change the char message into the SPI message format
ChangeToSPIMessageFormat(SPI_MessageToSend, SPI_MessageToSend_SPIFormat);
numberSPIshortIntsToSend = ???; numberSPIshortIntsSent = 0; SPISTATE = 5;MAKE A DECISION –
WHICH PART OF OS makes the decision to okay that another message is to be sent?}
New version of SendSPIMessage
void SendSPIMessage(unsigned tokenSPI, char yourMessage[]) {if (tokenSPI == SPI_tokenSent) {
printf(">%s<\n", yourMessage); // Remove later once working???
SPI_tokenSent = 0;strcpy(SPI_MessageToSend, yourMessage);SPI_newMessageRequest = true;
}else {
printf("Bad token – SPI request ignored\n");}
}
SPI_Message_OS_Thread – Planstatic volatile unsigned int SPI_tokenSent = 0;static volatile bool SPI_interfaceInUse = true;static volatile char SPI_MessageToSend[200];static volatile short int SPI_MessageToSend_SPIFormat[600];static volatile int messageRequest = 0;void SPI_Message_OS_Thread(void) {
State 0: SetUpSPIInterface( ); SPISTATE = 1; SPI_interfaceInUse = ??Other stuff as needed
State 1 – Not sending a messageif ( SPI_newMessageRequest == true) SPIState = 5; //FIX ME
// CAUGHT THIS ERROR ON WALK THROUGHState 2 ‐‐ already sending a message Should never get here State 3 – Received a request to send a char message Should never get here State 4 ‐‐ // Change the char message into the SPI message format
ChangeToSPIMessageFormat(SPI_MessageToSend, SPI_MessageToSend_SPIFormat);
numberSPIshortIntsToSend = ???; numberSPIshortIntsSent = 0; SPISTATE = 5;MAKE A DECISION –
WHICH PART OF OS makes the decision to okay that another message is to be sent?}
ChangeToSPIMessageFormat(SPI_MessageToSend, SPI_MessageToSend_SPIFormat);
• It turns out that there are two kinds of messages the LCD screen can process – SCREEN_CONTROL (cursor movement) and ASCII (print letter)
• SO we need a design change• SendSPIMessage(unsigned tokenSPI, char * yourMessage)• Becomes SendSPIMessage(unsigned tokenSPI, char * yourMessage,
bool isASCII)and we need to set a new global SPI variable static bool SPI_isASCII;
ChangeToSPIMessageFormat(SPI_MessageToSend, SPI_MessageToSend_SPIFormat);
• unsigned int numChars = SizeofMessageToSent(SPI_MessageToSend);SPIformatCount = 0;// Make room for 3 LCD timing signals (not SPI signals)for (int charCount = 0; charCount < numChars ) {SPIFormat[SPIformatCount] = SPI_Message[charCount ];SPIformatCount++SPIFormat[SPIformatCount] = SPI_Message[charCount ];SPIformatCount++SPIFormat[SPIformatCount] = SPI_Message[charCount ];SPIformatCount++
}
ChangeToSPIMessageFormat(SPI_MessageToSend, SPI_MessageToSend_SPIFormat);
• unsigned int numChars = SizeofMessageToSent(SPI_MessageToSend);SPIformatCount = 0;// Make room for 3 LCD timing signals (not SPI signals)// Need extra bits if screenCOntrol (or is it extra if data – need to look up)if (SPI_isASCII) asciiControlBit = XXXX Else asciiControlBit = YYYY
for (int charCount = 0; charCount < numChars ) {SPIFormat[SPIformatCount] = SPI_Message[charCount ] | asciiControlBit ;SPIformatCount++SPIFormat[SPIformatCount] = SPI_Message[charCount ] | asciiControlBit ;SPIformatCount++]SPIFormat[SPIformatCount] = SPI_Message[charCount ] | asciiControlBit ;SPIformatCount++
}
Now there is a special LCD accept commandline – This must go high, low, then high
for (int charCount = 0; charCount < numChars ) {controlLine = 0x8000; // Cjheck notes for actual valueSPIFormat[SPIformatCount] = SPI_Message[charCount ] | asciiControlBit
| controlLine ;SPIformatCount++
controlLine = 0x0000; // Cjheck notes for actual valueSPIFormat[SPIformatCount] = SPI_Message[charCount ] | asciiControlBit
| controlLine ;SPIformatCount++]
controlLine = 0x8000; // Cjheck notes for actual valueSPIFormat[SPIformatCount] = SPI_Message[charCount ] | asciiControlBit
| controlLine ;SPIformatCount++
}
Now we want to test the code – but without actually setting up the SPI and LCD interfacesStatic volatile bool isMockSPI = false;SetUpSPIInterface( ) {isMockSPI = true};SPI_NOT_Ready( ) { if (isMockSPI ) return false else return true;}DO WALK‐THROUGH OF CODEOops – Design error – rookie mistake in state 4– not sending anything
if (SPI_NOT_READY( )) return:else {numberSPIshortIntsToSend ‐‐;numberSPIshortIntsSent ++;
if (numberSPIshortIntsToSend == 0) SPISTATE = 6;
if (SPI_NOT_READY( )) return:else {numberSPIshortIntsToSend ‐‐;SPI_SendOneSPIFormat(SPIFormat[numberSPIshortIntsSent] numberSPIshortIntsSent ++;
if (numberSPIshortIntsToSend == 0) SPISTATE = 6;
SPI_SendOneSPIFormat(unsigned short int value)
If (isMockSPI ) {printf(“%4x “, value);if (numberSPIshortIntsToSend == 0)
printf(“\n”);
The design idea is complete – you and you partner need to work slowly through it – ON PAPER – checking the variable names, whether any static SPI variables are missing
The code should at least now compile
• When testing – use very short message “A1”, “A2”• The system mayrun very slowly – try with 1 thread first then 2• Have the message threads run about every 3 seconds to give time for the print statements to run, one with a delay
• To work this at home on the simulator – Run all the threads inside a super‐loop – no waits
• You need to give SPI_Message_OS_Thread( ) priority as it controls the speed of transmitting – I would suggest 10 times faster than all the other threads
My home loop looked like thisvolatile int loopTimes = 30;int main(int argc, char *argv[]){int count = 0;while (loopTimes) {printf("Loop %d\n“, loopTimes);SPI_Message_OS_Thread( );ExampleMessageThread();ExampleMessageThread2( );loopTimes‐‐;
}
return 0;}
I added in print statements inside my SPI_Message_OS_Thread case• Loop 30 S0• *Loop 29 S1 ‐‐ The star is my marker for “request rejected*• Accepted ‐‐ Request to transmit accept• >!AA 1!<• Loop 28 S1• *Loop 27 S4 ‐‐ The star is my marker for “request rejected*• Accepted ‐‐ BAD BAD BAD – DATA RACE‐‐ Request to transmit accept again –
My walk though of case 1 – spots A problem ‐‐ Do not move properly from state 1 to state 4Somebody is setting permission when they should not –
DO search for all parts of code setting permission – OOP rookie mistake 2 – should have seen that• >!AA 3!<• Loop 26 S5 a021 *Loop 25 S5 2021 Accepted• >!AA 5!<• Loop 24 S5 a021 *Loop 23 S5 a041 Accepted• >!AA 7!<• Loop 22 S5 2041 *Loop 21 S5 a041 *Loop 20 S5 a041 *Loop 19 S5 2041 *Loop 18 S5 a041 *Loop 17 S5
a020 *Loop 16 S5 2020 *Loop 15 S5 a020 *Loop 14 S5 a031 *Loop 13 S5 2031 *Loop 12 S5 a031 *Loop 11 S5 a021 *Loop 10 S5 2021 *Loop 9 S5 a021
• *Loop 8 S6 *Loop 7 S0 BIG MISTAKE HERE – We are jumping back to 0 – might still work • *Loop 6 S1
Looks better• Loop 30 S0• Accepted• >!AA 0!<• Loop 29 S1• *Loop 28 S4• *Loop 27 S5 a021 *Loop 26 S5 2021 *Loop 25 S5 a021 *Loop 24 S5 a041 *Loop 23 S5 2041 *Loop 22 S5
a041 *Loop 21 S5 a041 *Loop 20 S5 2041 *Loop 19 S5 a041 *Loop 18 S5 a020 *Loop 17 S5 2020 *Loop 16 S5 a020 *Loop 15 S5 a030 *Loop 14 S5 2030 *Loop 13 S5 a030 *Loop 12 S5 a021 *Loop 11 S5 2021 *Loop 10 S5 a021
• *Loop 9 S6 Accepted• >!AA 21!< // Says thread waited 21 times before being allowed to send message• Loop 8 S1• *Loop 7 S4• *Loop 6 S5 a021 *Loop 5 S5 2021 *Loop 4 S5 a021 *Loop 3 S5 a041 *Loop 2 S5 2041 *Loop 1 S5 a041 *
Prepare case statement for “debug” info some times#define DEBUG 0void SPI_Message_OS_Thread(void) {
switch (SPIstate) {case 0:
SetUpSPIInterface( );SPI_interfaceInUse = false;SPIstate = 1;if (DEBUG) printf("S0\n");
break;
• Loop 30 Accepted• >!AA 0!<• Loop 29 *Loop 28 • *Loop 27 a021 ‐‐ We can see LCD accept timing bit going – HIGH• *Loop 26 2021 ‐‐ LO• *Loop 25 a021 ‐‐ ACCEPT LCD command ON THIS HIGH• *Loop 24 a041 • *Loop 23 2041 • *Loop 22 a041 ‐‐ ACCEPT LCD command ON THIS HIGH• *Loop 21 a041 • *Loop 20 2041 • *Loop 19 a041 • *Loop 18 a020 *Loop 17 2020 *Loop 16 a020 *Loop 15 a030 *Loop 14 2030 *Loop 13 a030 *Loop 12 a021 *Loop 11 2021 *Loop 10 a021
• *Loop 9 Accepted• >!AA 21!<• Loop 8 *Loop 7 *Loop 6 a021 *Loop 5 2021 *Loop 4 a021 *Loop 3 a041 *Loop 2 2041 *Loop 1 a041 *
Do a little more cleaning upPSP ‐‐ One step at a time• Remove loop number messages – check still works• Clean up extra symbols in ExampleMessageThread( ) and ExampleMessageThread2( ) – check still works
• Add “main end of loop message” – check still works• Format output from SPI_SendOneSPIFormat
Final output – running 1 message threadswhile (loopTimes) {
if (DEBUG) printf("Loop %d ", loopTimes);SPI_Message_OS_Thread( );ExampleMessageThread();//ExampleMessageThread2( );loopTimes‐‐;
}printf("Done loop\n");
Problem – should print 2 chars not 4 not 5Modify to show character printed
Accepted AA 0**a041 *2041 *a041 *a041 *2041 *a041 *a020 *2020 *a020 * ?a030 *2030 *a030 ?*Accepted AA 15**a041 *2041 *a041 *a041 *2041 *a041 *a020 *2020 *a020 *a031 *2031 *a031 *a035 *2035 *a035 ??????*Accepted AA 33**a041 *2041 *a041 *a041 *2041 *a041 *a020 *2020 *a020 *a033 *2033 *a033 *a033 *2033 *a033 *Accepted AA 51**a041 *2041 *a041 *a041 *2041 *a041 *Done loop
Problem – should print 2 chars ‐‐ not 4 not 5Modify SPI_SendOneSPIFormatto show character printed• Accepted AA 0** >A< 65• a041 *2041 *a041 * >A< 65• a041 *2041 *a041 * > < 32• a020 *2020 *a020 * >0< 48• a030 *2030 *a030 We have sprintf(myBuffer, "%s %d", "AA", count++); for thread 1• *Accepted AA 15** >A< 65• a041 *2041 *a041 * >A< 65• a041 *2041 *a041 * > < 32• a020 *2020 *a020 * >1< 49• a031 *2031 *a031 * >5< 53• a035 *2035 *a035 • *Accepted AA 33** >A< 65• a041 *2041 *a041 * >A< 65• a041 *2041 *a041 * > < 32• a020 *2020 *a020 * >3< 51• a033 *2033 *a033 * >3< 51• a033 *2033 *a033 • *Accepted AA 51** >A< 65• a041 *2041 *a041 * >A< 65• a041 *2041 *a041 *Done loop
Accepted ABCD***** >A< 65a041 **2041 **a041 ** >B< 66a042 **2042 **a042 ** >C< 67a043 **2043 **a043 ** >D< 68a044 **2044 **a044 **Accepted ABCD***** >A< 65a041 **2041 **a041 ** >B< 66a042 **2042 **a042 ** >C< 67a043 **2043 **a043 ** >D< 68a044 **2044 **a044
Running with 2 threads – the second one does not runIs it a bug or does the first thread run with high priority
I then tried this testvolatile int loopTimes = 100;int main(int argc, char *argv[]){
int count = 0;while (loopTimes) {if (DEBUG) printf("Loop %d ", loopTimes);SPI_Message_OS_Thread( );if ( (loopTimes % 7) == 0) ExampleMessageThread();if ( (loopTimes % 5) == 0) ExampleMessageThread2( );loopTimes‐‐;
}printf("Done loop\n");return 0;}
Accepted 23456* >2< 50a032 2032 a032 * >3< 51a033 2033 a033 >4< 52a034 *2034 *a034 >5< 53a035 2035 a035 >6< 54a036 *2036 *a036 Accepted 23456 >2< 50a032 *2032 a032 * >3< 51a033 2033 a033 >4< 52a034 2034 **a034 >5< 53a035 2035 a035 >6< 54a036 *2036 a036 *Accepted 23456 >2< 50a032 2032 *a032 * >3< 51a033 2033 a033 >4< 52a034 2034 *a034 * >5< 53a035 2035 a035 >6< 54a036 *2036 a036 Accepted ABCD* >A< 65a041 2041 a041 >B< 66a042 2042 **a042 >C< 67a043 2043 a043 >D< 68a044 *2044 a044 *Accepted 23456 >2< 50a032 2032 *a032 * >3< 51a033 2033 a033 >4< 52a034 2034 *a034 * >5< 53a035 2035 a035 >6< 54a036 *2036 a036 Accepted ABCD* >A< 65a041 2041 a041 >B< 66a042 Done loop
I think the tests show interface is workingWatch out in class for the following hardware code Lab 4 Part 1 – will give us all the information about the special LCD commands needed to make thing work
SPI_SendOneSPIFormat(unsigned short int value) { ????? }SetUpSPIInterface( ) { ???? };SPI_NOT_Ready( ) { ?????}
These are all commands that control the actual SPI hardware2 are 4 lines long and the other is about 15