Presentation is loading. Please wait.

Presentation is loading. Please wait.

If we can just send 1 signal correctly over the MOSI line!!! Design and implementation details on the way to a valid SPI-LCD interface driver.

Similar presentations


Presentation on theme: "If we can just send 1 signal correctly over the MOSI line!!! Design and implementation details on the way to a valid SPI-LCD interface driver."— Presentation transcript:

1 If we can just send 1 signal correctly over the MOSI line!!! Design and implementation details on the way to a valid SPI-LCD interface driver

2 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 2 / 29 To be tackled today Review -- What is SPI? Review -- What is the SPI “master slave” relationship? How do we configure the SPI interface inside the Blackfin? How do we activate the chip-select line – PF5? Does activating the PF5 line as SPI output control mean we have to change all the SetupPF8to11ASM( ) and other routines? When do we activate the chip-select line, and how long for? What happens when there is not a new value in the SPI transmit buffer – what does the SPI interface do – it can’t do nothing – does it start transmitting zeros (which would turn out all the LEDs we just turned on One function left to be developed InitHardware_SPI( ), NO_DELAY, RUN_ONCE) perhaps contains InitializeSPI (unsigned short int SPI_baudrate); and void StartSPI_ASM(void);

3 Lab 3 Now looks like this InitScheduler( ) AddTask(InitHardware_SPI, NO_DELAY, RUN_ONCE) AddTask(SPI_Controller, SHORT_DELAY, RUN_OFTEN) AddTask(SPI_Message_Simple1, 1/10 SECOND, 1 /5 SECOND); (or faster) AddTask(SPI_Message_Simple2, 1/4 SECOND, 1 /5 SECOND); AddTask(WriteSPIInfo, SHORT_DELAY, RUN_OFTEN); StartScheduler( ) And we have NO idea of how to write WriteSPIInfo( ) or InitHardware_SPI( ) as these interface to the SPI hardware directly. Need to learn about the SPI interface

4 DONE -- SPI_Message_Simple1( ) Racing LEDS 0 to 7 on Logic Lab. void Task_SPI_Simple1(void) { static short int MyMessage[ ] = {0, 1, 3, 7, 15, 31, 63, 127}; // no lights, one light, two lights, three lights etc -- your choice // Ask SPI controller if anybody else using SPI interface if (SPI_MessageCanBeSent_G == 0) return; // Somebody else using SPI // This step only works with a “co-operative scheduler” where only 1 task can access memory SPI_MessageCanBeSent_G = 0; // Stop anybody else sending a message SPI_MessageSize_G = 8; for (int count = 0; count < SPI_MessageSize_G; count++) SPI_Message[count] = MyMessage[count]; // Copy message into shared buffer // Tell SPI controller that there is a message to send pleaseSendSPIMessage = 1; } 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 4 / 26

5 DONE -- void Task_SPI_controller(void) volatile short int next_SPIinfo = 0; volatile short int nextValueReady = 0; // If 1, waiting for SPI to transmit void Task_SPI_Controller(void) { static counter = 0; // Count how many parts of message sent // No messages to send or last message already sent if (pleaseSendSPIMessage == 0) return; if (SPI_MessageSize_G == counter) { pleaseSendSPIMessage = 0; SPI_MessageCanBeSent_G = 1; counter = 0; return); if (nextValueReady != 0) return // SPI interface not ready – still transmitting last value next_SPIinfo = SPI_Message_G[counter++]; nextValueReady = 1; } 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 5 / 26

6 DONE?? We know that any value written into SPI transmit data buffer register gets transmitted immediately extern volatile short int next_SPIinfo; extern volatile short int nextValueReady; void WriteSPIInfo (void) { if (nextValueReady == 0) return; Nothing to send *pSPI_TDBR = next_SPIinfo; WaitAwhileForSPIToTransmit( ) // how long is this ? // Is there a hardware flag we can read? nextValueReady = 0;// Tell SPI controller to send again? } 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 6 / 26

7 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 7 / 29 Review -- Master / Slave concept Slave Select (Chip Select) We put a value into the Blackfin SPI_TDBR register – hardware does the rest Blackfin sends out active low chip select signal PF5 Blackfin sends out the “value- bits” on the MOSI signal. Slave accepts signal as SS1 is connected to PF5 Then PF5 goes high – no more information for SLAVE If we get the first step correct – then everything else should happen automatically – provided we have set up the SPI interface correctly

8 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 8 / 29 Review -- Lab. 3 interface SPI bus from Blackfin SPI bus to parallel interface chip from Blackfin To logic lab LED lights

9 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 9 / 29 Review -- Lab. 3 concept – Using an SPI interface to logic lab LED SPI_TDBR Blackfin Processor SPI_RXBR CJ7 / CJ8 output to LED SWITCHES (LOGIC LAB) SLAVE INPUT INTERFACE SLAVE OUTPUT INTERFACE MOSIMISO SLAVE SELECT PF5 used (PF0 to PF7) DATA CONTROL SPI CLOCK LOAD Slave to LCD

10 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 10 / 29 Review of the SPI questions we still don’t know the answers to How do we configure the SPI interface inside the Blackfin? How do we activate the chip-select line – PF5? Does activating the PF5 line as SPI output control mean we have to change all the InitializePFLinesASM( ) and other routines and Tests?

11 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 11 / 29 Blackfin transmits 16 bits with THIS format over the MOSI line DB7, DB6, ………DB1, DB0 RS 1 – LCD data 0 – LCD instruction R/W 1 – Read from LCD 0 – Write to LCD E – Enable / Strobe 1  0 – When this line goes from high to the low, then the command is send to (latched into) LCD To make LCD respond to command 0x4F0 Then Blackfin must transmit 0x5F0 ( E High ) 0x4F0 ( E low ) 0x5F0 ( E high ) We don’t care at the moment THIS IS NEW STUFF We just want “something” valid on MOSI line

12 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 12 / 29 Start with something we know how to do – PF5 as Output signal Need to set PF5 as output to make SPI work But if we change Initialize_ProgrammableFlagsASM(); from Lab. 1 too much else MIGHT need changing TEST(FIO_DIR, DEVELOPER_TEST) { TEST_LEVEL(10); WatchDataClass FIO_DIR_access (1, (unsigned short *) pFIO_DIR); WATCH_MEMORY_RANGE(FIO_DIR_access, Initialize_ProgrammableFlagsASM()); unsigned short int expected_result = 0x0000; CHECK(FIO_DIR_access.getFinalValue(0) == expected_result); }

13 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 13 / 29 Start with something we know how to do – PF5 GPIO changed to Output Solution – use Initialize_ProgrammableFlagsASM(); then change the direction with new function void ChangePFtoOutput(int which_pins ) #include #define PF5 0x0020 // Check this is correct TEST(CHANGE_FIO_DIR_DEVELOPER_TEST) { TEST_LEVEL(10); Initialize_ProgrammableFlagsASM(); int oldFIO_DIR = *pFIO_DIR; // Use C++ to read FIO_DIR register WatchDataClass FIO_DIR_access (1, (unsigned short *) pFIO_DIR); WATCH_MEMORY_RANGE(FIO_DIR_access, ChangePFtoOutputASM(PF5 )); unsigned short int expected_result = oldFIO_DIR | PF5; Nothing else changed CHECK(FIO_DIR_access.getFinalValue(0) == expected_result); }

14 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 14 / 29 #include P1.L = lo (FIO_DIR); P1.H = hi (FIO_DIR); old_value_R1 = W[P1] (Z); // Get old value -- unsigned new_value_R2 = old_value_R1 | which_pins_R0 // INPAR1 in R0 W[P1] = new_value_R2; ssync; // Force Blackfin to do the write (store) NOW not later void ChangePFtoOutputASM(int which_pins ) Make sure nothing else changes in FIO_DIR – so read, then OR, then write Review for Quiz 3 and Final exam

15 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 15 / 29 Blackfin interface details More slave side Blackfin side

16 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 16 / 29 Concept We write 16-bits (0xFF0A) into SPI_TDBR Hardware transfers this to SHIFT register SPI_TDBR now empty For next 16 ticks of SPI clock Hardware sends out 1 bit from shift register over MOSI line to SLAVE each clock tick – speeds up to 25 MHz per bit (way faster than LEDs flashing speed) Hardware receives 1 bit over MISO line from the SLAVE and puts into shift register each clock tick – speeds up to 25 MHz per bit Hardware transfers shift register value (from slave) into SPI_RDBR (receive DBR) SPI_RDBR is now FULL This transmission over a serial line (16-bits 1 at a time) is much slower than other internal Blackfin operation Must be careful not to overwrite last transmission with new transmission by “tryin to hard” – writing values too quickly 0x F F 0 A

17 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 17 / 29

18 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 18 / 29 SPI_registers -- Hardware Chap. 10 SPI_BAUD – We want to be able to change this – slow it down to ??? Maximum serial clock rate is ¼ of the system clock rate SCK freq = Peripheral clock frequency / 2 * SPI_BAUD -- Many Mbits SPI_FLG (Not SPI_FLAG) – do we need ChangePFtoOutputASM FLS5 bit – activates PF5 as slave select line FLG5 bit – could be used by us to control value of PF5 line when FLG5 bit is low, PF5 output is low, when FLG5 bit is high, PF5 output is high, However we would rather have the SPI hardware change PF5 output line at the correct time for us. Page 10-12 of the manual says “if CPHA = 0, the SPI hardware sets the output value and the FLG5 bit (that developer sets) is ignored” SOUNDS GOOD TO ME -- except what’s a CPHA? NEED TO WATCH FOR THIS FURTHER THROUGH THE MANUAL

19 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 19 / 29 SPI-registers -- more SPI_STAT – SPI Status register Has some read only bits Has some “write 1 to clear” sticky bits which are set when error condition occurs Remember to to write 1 to clear these bits during SPI Setup SPI_TDBR – transmit data buffer register Value written to this register is transmitted over SPI interface Writing to this register clears the SPI transmit interrupt signal One of the questions about writing the SPI_ISR function is answered by this information When we write to the SPI_TDBR register, the interrupt signal is cleared automatically. We don’t have to clear a bit as we did inside the core timer and general purpose timer registers However we not writing an SPI_ISR – what a shame – all that information going to waste

20 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 20 / 29 Status register information RO and W1C bits

21 DONE?? We know that any value written into SPI transmit data buffer register gets transmitted immediately extern volatile short int next_SPIinfo; extern volatile short int nextValueReady; void WriteSPIInfo (void) { if (nextValueReady == 0) return; Nothing to send *pSPI_TDBR = next_SPIinfo; WaitAwhileForSPIToTransmit( ) // how long is this ? // Is there a hardware flag we can read? DOES SPIF FLAG fix this unanswered question while (SPIF bit in *pSPI_STAT == 0) wait New question – who clears the SPIF bit for the next time? Us or the hardware? nextValueReady = 0;// Tell SPI controller to send again? } 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 21 / 26

22 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 22 / 29 ???? ????

23 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 23 / 29 SPI_CTL register Values needed during setup TIMOD – transfer initiation mode 01 – Start transfer with write to SPI_TDBR. Interrupt when SPI_TDBR is empty. Timing issues possible here – get an interrupt after SPI_TDBR is empty the first time PSSE – Slave Select Enable 0 – Disable – setting this as 1 makes this Blackfin a slave device. There might be circumstances where you want one Blackfin as master, and another as a slave – but this is not one of them. SIZE = 1 (16 bits) LSBF – Last significant bit first 0 as we want MSBF first as that is the way the LCD interface has been designed MSTR – master 1 as we want Blackfin to be master, not slave SPE – SPI Enable 1 – but we might not want to do this during set-up, set SPI up – then enable SPI later WOM – Write open drain master 0 – Normal – because this was the way the interface was designed EMISO – Enable MISO to allow slave to talk to master 0 – Not in this part of the lab GM – Get more data 0 – when SPI_RDBR (receive buffer) is full – discard new incoming data – don’t really care at the moment

24 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 24 / 29 SPI_CTL register Things we still don’t understand SZ – send zeros (or last word again) when SPI_TDBR is empty causes what to happen? Sending zeros sounds bad as that means the LEDs on the logic lab will out (most of the time) CPOL – clock polarity Means what – and do we care? CPHA – Clock Phase When CPHA = 1, slave select controlled by user software When CPHA = 0, slave select controlled by SPI hardware MURPHY’S RULE – any bit whose function is not obvious will be the key of whether you get the interface to work or not 

25 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 25 / 29 Figure 10-11 VALID slave load on signal transition VALID DATA STORED INVALID slave load on signal transition INVALID DATA STORED SLAVE DATA IS LOADED ON L-to-H CLOCK TRANSITION Different than Slave is SELECTED when PF5 = 0

26 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 26 / 29 We are now at the stage where we can do some experimenting with the hardware We know that the following pins are “key” to the operation of the SPI interface. MOSI – this will show the data being transmitted from the SPI interface PF5 – chip select line When this is pulled low, then the slave will accept any data being transmitted, otherwise data is ignored When this goes – low to high – then the serial data transmitted to the slave is “latched” (converted into a parallel signal that is then sent to LCD as a data or a command request. Place scope probes on these lines

27 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 27 / 29 SPI-Tests – Initialization Set_SPIregisters_ASM(ulong BAUD_SCALE) #include #define BAUD_SCALE 0x8000 // Make system slow so we can scope the data transfers TEST(SET_SPI_Registers, ConfigureSPIregisters) { WatchDataClass spi_reg(4, pSPI_BAUD, pSPI_CTL, pSPI_FLG, pSPI_STAT); WATCH_MEMORY_RANGE(spi_reg, InitializeSPI_ASM (BAUD_SCALE)); // Warning – many of the SPI_STAT bits are W1C – write 1 to clear – DON”T write 0’s USHORTS_EQUAL(spi_reg.getFinalValue(0), BAUD_SCALE); USHORTS_EQUAL((spi_reg.getStartValue(1) | 0x01 | /* SPE | */ MSTR | CPOL | /* CPHA | */ SIZE), spi_reg.getFinalValue(1)); USHORTS_EQUAL((spi_reg.getStartValue(2) | FLS5), spi_reg.getFinalValue(2)); USHORTS_EQUAL(spi_reg.getStartValue(3), 1); // Reset value is 1 CHECK(spi_reg.getReadsWrites() == 6); // Depends on how you code InitializeSPI_ASM( ); }

28 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 28 / 29 Can we write this sort of test to make things work on the SPI interface? Don’t even worry about LCD working! EX_INTERRUPT_HANDLER(spi_ISR); TEST(WriteSPIValue, ConfigureSPIregisters) { InitSPI_ASM(0x8000); register_handler(?????, SPI_ISR); Set_SIC_IMASK_ASM(0x2000); // Set the SIC_IMASK as we needed to do // in Lab. 2 to make the GPIO interrupts work StartSPI( ); WriteSPI(0x0A); // Connect SPI interface to LED’s on logic station WriteSPI(0xFF05);// Values should be there WriteSPI(0x0F0F); // Look at values on MOSI line with scope // SOMETHING should be there EVEN IF WRONG // Need to look at both MOSI and PF5 }

29 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 29 / 29 Concept We write 16-bits (0xFF0A) into SPI_TDBR Hardware transfers this to SHIFT register SPI_TDBR now empty For next 16 ticks of SPI clock Hardware sends out 1 bit from shift register over MOSI line to SLAVE each clock tick – speeds up to 25 MHz per bit Hardware receives 1 bit over MISO line from the SLAVE and puts into shift register each clock tick – speeds up to 25 MHz per bit Hardware transfers shift register value (from slave) into SPI_RDBR (receive DBR) SPI_RDBR is now FULL This transmission over a serial line (16-bits 1 at a time) is much slower than other internal Blackfin operation Must be handled via interrupt control 0x F F 0 A

30 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 30 / 29 volatile bool transmit_empty; // SPI interface ready for next value volatile unsigned short transmit_value; // Value to transmit over SPI EX_INTERRUPT_HANDLER(SPI_ISR) { SPI_TDBR  transmit_value; transmit_empty = true; Clear the interrupt signal so don’t re-enter ISR } void WriteSPI(unsigned short int value ) { while (transmit_empty = = false) /* wait for a signal from the ISR to say ready for next */ ; transmit_empty = false; transmit_value  value; // Store the value as a message for ISR } Would this sort of code work to transmit values over the MOSI line !!!!!! WE KNOW WE DON’T NEED THIS LINE

31 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 31 / 29 Is this approach a better solution Still a work in progress !!!!!! ClearScreenASM( ) { while (transmit_empty = = false) /* wait for signal from ISR */ ; transmit_empty = false; transmit_value  0x0001; // Store the clear screen command } WriteLetterASM(char letter) { while (transmit_empty = = false) /* wait for signal from ISR */ ; transmit_empty = false; transmit_value  0x200 | letter; Call CursorMoveASM; // Move cursor to place next letter or not??????? } Change to C++ programs as no longer talking directly to the hardware ClearScreen( ) { WriteSPIASM(0x0001); } WriteLetter(char letter) { WriteSPIASM(0x0200 | letter); Call CursorMoveASM} CursorMove ( ) {WriteSPIASM( 0x????); } etc

32 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 32 / 29 No – We need to toggle that E- flag as well to make LCD work #define EN_LINE_HIGH 0x0100 #define EN_LINE_LOW 0x0000 #define ISDATA 0x0400 ClearScreen( ) { WriteSPIASM(EN_LINE_HIGH | 0x0001); WriteSPIASM(EN_LINE_LOW | 0x0001); WriteSPIASM(EN_LINE_HIGH | 0x0001); } WriteLetter(char letter) { WriteSPIASM(EN_LINE_HIGH | ISDATA | letter); WriteSPIASM(EN_LINE_HIGH | ISDATA | letter); WriteSPIASM(EN_LINE_LOW | ISDATA | letter); CursorMove( ); ?????? // Do we need to do this? } // Just ONE routine to make one to get Lab. 4 to work !!!!!!!!!!

33 8/20/2015 SPI and LCD, Copyright M. Smith, ECE, University of Calgary, Canada 33 / 29 Tackled today Review -- What is SPI? Review -- What is the SPI “master slave” relationship? Review -- How do you send commands from the Blackfin to a LCD device? Review -- What commands are necessary to control the LCD device -- HD44780? Just 4 functions Done thing like the first 3 in Lab. 1, 2 and 3 – only hassle need to read the manual void InitializeSPI_ASM(unsigned short int SPI_baudrate); void StartSPI_ASM(void); void Set_SIC_IMASK_ASM(unsigned long int SIC_IMASK_value); void WriteSPIASM(unsigned short int value) MIGHT NOT BE SO BAD AFTER ALL


Download ppt "If we can just send 1 signal correctly over the MOSI line!!! Design and implementation details on the way to a valid SPI-LCD interface driver."

Similar presentations


Ads by Google