if we can just send 1 signal correctly over the mosi line!!! design and implementation details on...

30
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

Post on 18-Dec-2015

217 views

Category:

Documents


1 download

TRANSCRIPT

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

04/18/23 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? 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 to be developed• 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)MMMMMMM ???????????????

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

3 / 29

Review -- Master / Slave conceptSlave Select (Chip Select)We put a value into the Blackfin

SPI_TDBR register

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

When PF5 line goes high then Slave will send values to the LCD display.

If we get the first step correct – then everything else should happen automatically – provided we have set up the SPI interface correctly

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

4 / 29

Review -- Lab. 4 concept – Using an SPI interface to an LCD screen

SPI_TDBR Blackfin Processor SPI_RXBR

LCD SCREEN CJ7 / CJ8 SWITCHES (LOGIC LAB)

SLAVE INPUT INTERFACE SLAVE OUTPUT INTERFACE

MOSI MISO

SLAVE SELECTPF5 used (PF0 to PF7)

DATACONTROL

SPICLOCK

LOADSlave toLCD

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

5 / 29

Review -- Lab. 4 interfaceFrom Blackfin

SPI lines (MOSI, CLK, PF5)

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

6 / 29

ReviewQuestions still unanswered 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?

When do we activate the chip-select line, and how long for?

How do we know when LCD is ready for next character – do we poll a bit and wait till ready, or can it be done in the background? In Lab 4 – probably just “wait-long enough”

How do we stop multiple commands from being accidentally sent to LCD? -- too many cursor moves etc

We know answer to this one – activate the EN* line on the LCD

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

7 / 29

Review -- Lab. 4 -- Essentials of the Blackfin – LCD interface software

char HipHipArray[ ] = “Merry Christmas to all”;

SetUp_SPI_Interface(Baud_Rate); // Configure the SPI interface// Set up register_handler( ) and SIC_IMASK

LCD_Display (WHICH_LCD, “CONTROL”, “CLEAR_SCREEN”);

UseFixedTimeASM(Enough_Time_For _LCD_To_Work);

for (int count = 0; count < strlen(HipHipArray); count++) {

LCD_Display (WHICH_LCD, “DATA”, HipHipArray[count]); // Transmit the information we want from the array // one character at a time

UseFixedTimeASM(Enough_Time_For _LCD_To_Work);

}

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

8 / 29

Review -- LCD_Display (int, char*, char *);First attempt – may refactor later

#include <string.h>

LCD_Display (int lcd, char * type, char *operation) {

if (strcmp(type, “COMMAND”) == 0) { if (strcmp(operation, “CLEAR_SCREEN”) == 0) ClearScreen( );

if (strcmp(operation, “……..”) == 0) Do……..( );

}

if (strcmp(type, “DATA”) == 0) { if (strcmp(operation, “DISPLAY_TEMPERATURE”) == 0) DisplayTemperature( ); else WriteLetter(operation[0]); // First character

}}

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

9 / 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 0x4F0Then Blackfin must transmit 0x5F0 ( E High )0x4F0 ( E low )0x5F0 ( E high )

We don’t care at the momentTHIS IS NEW STUFFWe just want “something”valid on MOSI line

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

10 / 29

Start with something we know how to do – PF5 as Output signal Need to set PF5 as output But if we change Initialize_ProgrammableFlagsASM();

too much else MIGHT need changing

TEST(FIO_DIR, DEVELOPER_TEST) {TEST_LEVEL(10);

WatchDataClass<unsigned short int> 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);

}

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

11 / 29

Start with something we know how to do – PF5 changed to Output Solution – use Initialize_ProgrammableFlagsASM(); then change the direction

with new function void ChangePFtoOutput(int which_pins )

#define PF5 0x0020 // Check this is correctTEST(CHANGE_FIO_DIR, DEVELOPER_TEST) {

TEST_LEVEL(10);

Initialize_ProgrammableFlagsASM(); int oldFIO_DIR = *pFIO_DIR; // Use C++ to read FIO_DIR register

WatchDataClass<unsigned short int> FIO_DIR_access (1, (unsigned short *) pFIO_DIR);WATCH_MEMORY_RANGE(FIO_DIR_access, ChangePFtoOutput(PF5 ));

unsigned short int expected_result = oldFIO_DIR | PF5; Nothing else changedCHECK(FIO_DIR_access.getFinalValue(0) == expected_result);

}

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

12 / 29

#include <defsBF533.h>

#include <macros.h>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 ChangePFtoOutput(int which_pins )Make sure nothing else changes in FIO_DIR – so read, then OR, then write

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

13 / 29

Blackfin interface details

More slave side

Blackfin side

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

14 / 29

Concept

We write 16-bits (0xFF0A) into SPI_TDBR Hardware transfers this to SHIFT register

• SPI_TDBR now empty – new interrupt occurs 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

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

15 / 29

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

16 / 29

SPI_registers -- Hardware Chap. 10

SPI_BAUD – We want to be able to change this• 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)• 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 is ignored”

SOUNDS GOOD TO ME -- except what’s a CPHA?

NEED TO WATCH FOR THIS FURTHER THROUGH THE MANUAL

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

17 / 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• Need 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

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

18 / 29

Status register informationRO and W1C bits

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

19 / 29

????

????

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

20 / 29

SPI_CTL registerValues 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 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

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

21 / 29

SPI_CTL registerThings 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 EN* line will go low (zero) on the interface and the LCD might think it has received another command!

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

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

22 / 29

Figure 10-11

VALID slave load on signal transitionVALID DATA STORED

INVALID slave load on signal transitionINVALID DATA STORED

SLAVE DATA IS LOADED ON L-to-H CLOCK TRANSITION

Different thanSlave is SELECTED when PF5 = 0

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

23 / 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

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

24 / 29

SPI-Tests – InitializationSet_SPIregisters_ASM(ulong BAUD_SCALE)

#include <cdefsBF533.h>#define BAUD_SCALE 0x8000 // Make system slow so we can scope the data transfers

TEST(SET_SPI_Registers, ConfigureSPIregisters) {

WatchDataClass<unsigned short> 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( );

}

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

25 / 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. 3 to make the general purpose timer 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 }

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

26 / 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

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

27 / 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

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

28 / 29

Is this approach a better solutionStill 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

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

29 / 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 0x0400ClearScreen( ) { 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 work one to get Lab. 4 to work !!!!!!!!!!

04/18/23 SPI and LCD , Copyright M. Smith, ECE, University of Calgary, Canada

30 / 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