CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

9Bit SPI and inline asm

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Pyrofer



Joined: 13 Sep 2006
Posts: 16

View user's profile Send private message

9Bit SPI and inline asm
PostPosted: Wed Sep 13, 2006 7:14 am     Reply with quote

Hi, I want to use 9bit spi to a device, but the hardware only does 8bit.

So, I am manualy toggling the pins with code like this,
Code:

output_low(clockpin);
output_bit(datapin,address);
output_high(clockpin);

output_low(clockpin);
output_bit(datapin,data&&128);
output_high(clockpin);

output_low(clockpin);
output_bit(datapin,data&&64);
output_high(clockpin);

output_low(clockpin);
output_bit(datapin,data&&32);
output_high(clockpin);

 etc


I would like to do one manual toggle, then use hardware spi but when I enable hardware SPI it stops me changing the pins manualy and nothing works.

My only solution left to speed things up for output is to make this an inline ASM function but I dont know asm.
Can anybody help?
asmallri



Joined: 12 Aug 2004
Posts: 1635
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Sep 13, 2006 8:00 am     Reply with quote

OK - silly question but what SPI device are you using that expects 9 bits?
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
Pyrofer



Joined: 13 Sep 2006
Posts: 16

View user's profile Send private message

PostPosted: Wed Sep 13, 2006 8:00 am     Reply with quote

Nokia 6100 LCD.

No, i cant change the input mode to anything else.
asmallri



Joined: 12 Aug 2004
Posts: 1635
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Sep 13, 2006 8:18 am     Reply with quote

Here is a link to AVR code that you can port directly to CCS.

http://www.e-dsp.com/controlling-a-color-graphic-lcd-epson-s1d15g10-controller-with-an-atmel-avr-atmega32l/

It is pretty straight forward. Also be careful, unless you are using a very slow PIC you will almost certainly be too fast for the display.

I assume you don't have a PIC with a spare SPI port otherwise you would not be bitbashing the SPI stream.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!


Last edited by asmallri on Wed Sep 13, 2006 9:34 am; edited 1 time in total
Pyrofer



Joined: 13 Sep 2006
Posts: 16

View user's profile Send private message

PostPosted: Wed Sep 13, 2006 9:09 am     Reply with quote

I cant get the SPI port to work as I need 9 bits.

If you can tell me how to make the hardware SPI port output 9bit I will leap up and down screaming eureka!
I have the port spare, and am in fact using the pics for my manual bashing.

How to get 9bit out of hardware spi port?

Pic 18F2620
Ttelmah
Guest







PostPosted: Wed Sep 13, 2006 9:26 am     Reply with quote

You don't say what chip is involved, butyou can simply toggle out the extra bit.
The 'answer', is the 'SSPEN' bit. When the SSP is enabled (this bit set), it takes over control of the output on the SDO/SCK lines. However when this bit is cleared, you can control the lines.
Make #bit declaration and control this bit directly.
Remember to _leave_ the clock level, as you want it to be when you next change the line. So:
Code:

SSPEN=0;
output_low(clockpin);
output_bit(datapin,extrabit);
output_high(clockpin);
delay_us(1);
output_low(clockpin);
SSPEN=1;
//Now use the SPI command to send the next 8 bits.


Best Wishes
Pyrofer



Joined: 13 Sep 2006
Posts: 16

View user's profile Send private message

PostPosted: Wed Sep 13, 2006 9:51 am     Reply with quote

THANK YOU!!

Oh god that will save me so much trouble if it works. Ill compile it tonight and hopefully be jumping for joy as previously suggested.

The SPI mode is low to high, so the hardware SPI port leaves the pin HIGH
at the end of a write...
So i assume,
Code:

SSPEN=0;
output_low(clockpin);
output_bit(datapin,extrabit);
output_high(clockpin);
SSPEN=1;
SPI_WRITE(data);


is ok? As the pin is left High by my code and that is the state the hardware SPI expects it to be in, pulled low at the start of the spi send and left high at the end of the spi routine.

I will experiment tonight and let you know, but i hold out high hopes!
Pyrofer



Joined: 13 Sep 2006
Posts: 16

View user's profile Send private message

PostPosted: Wed Sep 13, 2006 5:28 pm     Reply with quote

Thank you. Dance done, all working. Hardware SPI now takes care of 8bits out of the 9.
Marcoose



Joined: 09 Dec 2006
Posts: 5
Location: Ontario, Canada

View user's profile Send private message Visit poster's website MSN Messenger

PostPosted: Fri Mar 09, 2007 2:21 pm     Reply with quote

Sorry this is an old post, but I just found it and it was exactly what I needed! (for the same Nokia issue) Thanks so much for the great tip... gotta love using hardware when it's available!
Rohit de Sa



Joined: 09 Nov 2007
Posts: 282
Location: India

View user's profile Send private message Visit poster's website

PostPosted: Mon Dec 24, 2007 11:36 pm     Reply with quote

Hey all,

I am attempting to interface an 18F2550 with a Nokia 6610 LCD, which has (apparently) a Phillips PCF8833 controller. I've come to that conclusion since the connector is orange and the LCD also has those large gold-plated connectors. Anyway, I wrote some code of my own; it seems to be running properly in the MPLAB simulator (though I have to manually set the SSPSTAT.0 bit for it to continue execution). However when I try to interface the LCD (physically) it just doesn't work. Would someone be so kind as to point out if I've made any coding mistakes. Thanks.

Regards.
Rohit
PS: I hope the documentation is adequate. I'm using v4.038 of the compiler.


Code:

// This is the prototype for a Nokia 6610
// 132*132 pixel colour LCD driver.
//
// Rohit de Sa
// 24Dec07
// ver1.0



#include <18F2550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN

#use delay(clock=48000000)


// defines for pins
#define hard_cs      pin_a1         //Chip select
#define hard_res   pin_a2         //Reset
#define hard_clk   pin_b1         //SPI clock
#define hard_sdo   pin_c7         //SPI data out
// defines for constants
#define sleepout   0x11         //from datasheet
#define invon      0x21
#define colmod      0x3a
#define setcon      0x25
#define dispon      0x29
#define ramwr      0x2c
#define paset      0x2b
#define caset      0x2a


#bit    SSPEN = 0xfc6.5
int1 command=0;
int1 data=1;
int i=0;


void write_command (int command)
{
   SSPEN=0;
   output_low(hard_clk);
   delay_us(2);
   output_low(hard_sdo);
   delay_us(2);
   output_high(hard_clk);
   delay_us(2);
   SSPEN=1;
   spi_write(command);
   delay_us(2);
}

void write_data (int data)
{
   SSPEN=0;
   output_low(hard_clk);
   delay_us(2);
   output_high(hard_sdo);
   delay_us(2);
   output_high(hard_clk);
   delay_us(2);
   SSPEN=1;
   spi_write(data);
   delay_us(2);
}

void main (void)
{
   output_high(hard_cs);         //initializing the LCD
   output_high(hard_clk);
   output_high(hard_sdo);
   output_low(hard_res);         //holding the LCD in reset
   
   output_high(pin_a0);         //pin connected to LCD backlight
      
   setup_spi(spi_master|spi_h_to_l|spi_clk_div_64);
   
   delay_ms(2);               //are these delays necessary?
   output_high(hard_res);         //bringing LCD out of reset
   delay_ms(2);
   output_low(hard_cs);         //enabling LCD
   delay_us(2);
   
   write_command(sleepout);
   write_command(invon);
   write_command(colmod);
   write_data(0x03);
   write_command(setcon);
   write_data(0x10);
   write_command(dispon);
   write_command(paset);
   write_data(0x00);
   write_data(131);
   write_command(caset);
   write_data(0x00);
   write_data(131);
   write_command(ramwr);      //shading part of the LCD white
   for (i=0;i<255;i++)
   {
      write_data(0xff);
      write_data(0xff);
      write_data(0xff);
   }
   delay_us(2);
   output_high(hard_cs);      //deselecting the LCD
   while (true)
   {
   }
}

Rohit de Sa



Joined: 09 Nov 2007
Posts: 282
Location: India

View user's profile Send private message Visit poster's website

PostPosted: Tue Dec 25, 2007 12:44 am     Reply with quote

I just checked the code again.

In the definition/declarations there are two statements
Code:

int1 command=0;
int1 data=1;


Those are residues from an older (now scrapped) version of the code. Though I have removed those lines, the LCD still doesnt work.

Rohit
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Dec 25, 2007 1:22 am     Reply with quote

Quote:
setup_spi(spi_master | spi_h_to_l | spi_clk_div_64);
However when I try to interface the LCD (physically) it just doesn't work.

You have selected SPI Mode 2. I can tell this from the code below:
Code:

#define SPI_MODE_0_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_0_1  (SPI_L_TO_H)
#define SPI_MODE_1_0  (SPI_H_TO_L)
#define SPI_MODE_1_1  (SPI_H_TO_L | SPI_XMIT_L_TO_H)
 


Look at the timing diagrams for the four SPI modes, down at the
bottom of the following web page:
http://elm-chan.org/docs/spi_e.html
It shows that in Mode 2, SCLK idles at a high level and it samples
data on the falling edge.

Download the data sheet for the LCD controller:
http://www.nxp.com/acrobat_download/datasheets/PCF8833_1.pdf
Look at the SPI timing diagrams on pages 71 to 73. They show that
SCLK must idle at a low level, and sample data on the rising edge.
(The rising edge is shown to occur in the middle of the data cell).
So SPI mode 2 is not correct. It's actually using mode 0.

Look at this SPI mode timing diagram, or the other one above:
http://www.totalphase.com/support/articles/article03/#modes
This shows the timing for mode 0.

Then use SPI_MODE_0_0 constant from the #define statements above,
and put it in the middle of the setup_spi() statement. Add those four
#define statements to your program.

Also, you have code that initializes the SCLK line to a high level.
That needs to be fixed. And also, you have code that manually
clocks out one bit of data. That code is not correct. It needs to be
made more like Ttelmah's code. Change the data, then issue the
clock pulse. Then set the clock line to the idle state (a low level).
Rohit de Sa



Joined: 09 Nov 2007
Posts: 282
Location: India

View user's profile Send private message Visit poster's website

PostPosted: Tue Dec 25, 2007 6:44 am     Reply with quote

Thanks PCM Programmer. I made adjustments as you mentioned. The command sequence is similar to Ttelmah's. But it still is not working. Its the same as before - only the LCD backlight turns on. Is there something I've missed?


Code:

#include <18F2550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN

#use delay(clock=48000000)


// defines for pins
#define hard_cs      pin_a1         //Chip select
#define hard_res   pin_a2         //Reset
#define hard_clk   pin_b1         //SPI clock
#define hard_sdo   pin_c7         //SPI data out

// defines for constants
#define sleepout   0x11         //from datasheet PCF8833
#define invon      0x21
#define colmod      0x3a
#define setcon      0x25
#define dispon      0x29
#define ramwr      0x2c
#define paset      0x2b
#define caset      0x2a

#bit    SSPEN = 0xfc6.5
int i=0;


void write_command (int command)
{
//   output_low(hard_cs);         //removed these because LCD gets deselected
//   delay_us(1);               //between data writes. Data gets corrupted
   SSPEN=0;                  //due to this.
   output_low(hard_sdo);         //Setting bit 8 = 0 for commands
   delay_us(1);
   output_high(hard_clk);
   delay_us(1);
   output_low(hard_clk);
   delay_us(1);
   SSPEN=1;
   spi_write(command);
   delay_us(1);
//   output_high(hard_cs);
}

void write_data (int data)
{
//   output_low(hard_cs);
//   delay_us(1);
   SSPEN=0;
   output_high(hard_sdo);         //Setting bit 8 = 1 for data
   delay_us(1);
   output_high(hard_clk);
   delay_us(1);
   output_low(hard_clk);
   delay_us(1);
   SSPEN=1;
   spi_write(data);
   delay_us(1);
//   output_high(hard_cs);
}

void main (void)
{
   output_high(hard_cs);         //initializing the LCD
   output_low(hard_clk);         //clock idle state in Mode0
   output_high(hard_sdo);
      
   output_low(hard_res);         //holding the LCD in reset
      
   setup_spi(spi_master|spi_l_to_h|spi_xmit_l_to_h|spi_clk_div_64);
   
   delay_ms(2);               //are these delays necessary?
   output_high(hard_res);         //bringing LCD out of reset
   delay_ms(2);
   
   output_high(pin_a0);         //pin connected to LCD backlight   
   output_low(hard_cs);         //enabling LCD

   write_command(sleepout);
   write_command(invon);
   write_command(colmod);
   write_data(0x03);
   write_command(setcon);
   write_data(0x20);
   write_command(dispon);
   write_command(paset);
   write_data(0x00);
   write_data(131);
   write_command(caset);
   write_data(0x00);
   write_data(131);
   
   write_command(ramwr);         //shading part of the LCD white
   for (i=0;i<255;i++)
   {
      write_data(0xff);
      write_data(0xff);
      write_data(0xff);
   }
   while (true)
   {
   }
}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Dec 25, 2007 8:12 am     Reply with quote

Code:
   delay_ms(2);               //are these delays necessary?
   output_high(hard_res);         //bringing LCD out of reset
   delay_ms(2);
Check figure 50 of the PCF8833 datasheet. The first delay can be reduced to a minimum of 1.5us but because of power supply startup and other synchronisation issues I would keep it at a save 1ms.
The second delay is too short, according to the same figure 50 it can take the controller 5ms to finish the reset sequence.

Digital pins A1 and A2 are multiplexed with the A/D-converter and comparator modules. When either of these analog modules is activated the digital ports will be disabled. Most compiler versions do disable the analog modules but this behaviour has been known to change in between releases. I therefore never assume the compiler will do something for me and always explicitly setup the hardware modules the way I want them:
Code:
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_comparator(NC_NC_NC_NC);
Rohit de Sa



Joined: 09 Nov 2007
Posts: 282
Location: India

View user's profile Send private message Visit poster's website

PostPosted: Wed Dec 26, 2007 5:39 am     Reply with quote

Hey all,

No go. I've tried, and nothing seems to ge the LCD to respond. Maybe its the LCD itself. It was an old one from a friend's phone. I'll try to procure another LCD and see if that works. Will post if I'm successful.

Thanks guys, once again.

Regards.
Rohit
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group