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

simple bitbang SPI ram driver faults ODD addresses [SOLVED]

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



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

simple bitbang SPI ram driver faults ODD addresses [SOLVED]
PostPosted: Fri Dec 30, 2016 9:21 am     Reply with quote

compiler 5.064
I am certain i did something boneheaded here -but can't
for the life of me see it in this 128K byte SPI ram byte wide
bit bang driver for the 23LC1024 SPI SRAM

All the even addresses seem to work but the odd ones are wrong
by the absence of the low order bit -- ret data SHOULD look like

65,65,17,17, -!- 65,65,17,17,test33

but in reality the odd addresses on the right side of the -!- are wrong
it actually outputs

65,65,17,17, -!- 64,64,16,16,test33

datasheet at
http://www.mouser.com/ds/2/268/25142A-47786.pdf

Code:

//  23LC1024  24 bit address single byte SPI RAM bit bang
#include <18f46K22.h>
#fuses HSM,NOPLLEN,NOFCMEN,NOIESO,PUT,NOBROWNOUT
#Fuses CCP2C1,NOPBADEN,NOMCLR,NOSTVREN,NOLVP,
#Fuses NOPBADEN,NOMCLR,NOSTVREN,NOLVP,
#fuses NOXINST,NODEBUG,NOPROTECT,NOCPB,NOCPD,NOWRT,NOWRTC
#Fuses NOWRTB,NOWRTD,NOEBTR,NOEBTRB
#use delay( clock=16588888) // clock xtal
#use rs232(baud=57600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use fast_io(D)
#include <stdlib.h>
#include <stdio.h>

#define SRLS  pin_d0
#DEFINE SROUT pin_D1
#define SRDIN pin_d2
#define SCLK  pin_d3
#define mhz64 100
//  PIC portd  tris low bits:  out,in,out,out
// shift off hi order bit and clock out

void write8(unsigned int8 bt){
    unsigned int8 c;
    #bit b=bt.7
for (c=0;c<8; c++){
   if (b) output_high (SRDIN);
   else   output_low(SRDIN);
   delay_us(mhz64);    output_high(SCLK);    delay_us(MHZ64);   output_low(SCLK);
   bt  <<=1;    delay_us(MHZ64);
 }//end for
}

void writeadd ( unsigned int32 add ){

unsigned int8 c; // shifting hi order bit int 25th bit location
#bit a=add.24

 for (c=0;c<24;c++){  // address
   add<<=1;
   if (a) output_high (SRDIN);
   else   output_low(SRDIN);
   delay_us(mhz64); output_high(SCLK);    delay_us(mhz64);    output_low(SCLK);
   delay_us(mhz64);
 }}

// write byte to address
void W_SR( unsigned int32 addr, unsigned int8 d){
 output_low(SRLS);   write8(2); // command to write-a-byte
 writeadd(addr);
 write8(d);  output_high(SRLS);
}
//read byte from address
unsigned int8 R_SR(unsigned int32 addr){
  unsigned int8 i=0,c;
#bit r=i.0
 output_low(SRLS);  write8(3); // command to read abyte
 writeadd(addr);   // next read the byte
 for (c=0; c<8; c++){
   delay_us(mhz64);
   output_high(SCLK);
   delay_us(mhz64);
   if (input(SROUT)) r=1;
   else r=0;
   if(c<7) i  <<=1;  // don't shift last bit
   output_low(SCLK);
 }
 output_high(SRLS);  return(i);
}
// command to set to byte r/w mode
void SR_setmode(void){
  output_low(SRLS);    delay_us(mhz64);
  write8(1); // command
  write8(0); // to set byte mode
  delay_us(mhz64);  output_high(SRLS);
}
//

main(){

//******

  output_d(1);  set_tris_d(0b11110010);  output_low (sclk);  //next wake chip
  delay_ms(500);  output_low(SRLS);    delay_ms(10);     output_high(SRLS); delay_ms(10);     
  sr_setmode(); //byte mode set - then load values into different addresses
  W_SR(10,65);     W_SR(14,65);      W_SR(12,17);     W_SR(2156,17); 
  W_SR(11,65);     W_SR(37123,65);   W_SR(37133,17);  W_SR(13,17); 

  while(1) {

  printf("%u,", R_SR(10));  printf("%u,", R_SR(14)); printf("%u,", R_SR(12));     
  printf("%u,", R_SR(2156));

  printf ("-!-");

  printf("%u,", R_SR(11)); printf("%u,", R_SR(37123));
  printf("%u,", R_SR(37133));   printf("%u,", R_SR(13));   printf("test 33 \r");
  delay_ms(1000);
  } // end MAIN - WHILE
}   // end main


Last edited by asmboy on Fri Dec 30, 2016 2:42 pm; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Dec 30, 2016 11:48 am     Reply with quote

I notice in your R_SR() routine, you don't handle SCLK the same way
that you do in all other commands. You do it like this:
Quote:
for (c=0; c<8; c++){
delay_us(mhz64);
output_high(SCLK);
delay_us(mhz64);
if (input(SROUT)) r=1;
else r=0;
if(c<7) i <<=1; // don't shift last bit
output_low(SCLK);
}


To keep the same method, it should be done like this:
Quote:
for (c=0; c<8; c++){
delay_us(mhz64);
if (input(SROUT)) r=1;
else r=0;
if(c<7) i <<=1; // don't shift last bit

output_high(SCLK);
delay_us(mhz64);
output_low(SCLK);

}


The main question is why do this ? CCS has files such as 25640.c
which contain a template that could be modified for your eeprom.
Just remove the ext_eeprom_ready() code, and remove the for() loop
that sends the WREN byte, and it would probably work.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri Dec 30, 2016 2:41 pm     Reply with quote

THKS PCM !! I
adapted the similar example from CCS and am up and running.

One thing the data sheet does not make clear -
in byte mode there are 131k addresses and it is easy to to adapt
to having a virtual 16 bit int storage array for 65k of those VARS
by simply changing out of BYTE mode - and taking a high level address
call and left shifting it one place.

My ultimate goal is to actually use the part to store variable length strings
from as few as 6 or 8 characters up to the range of about 23 or 24 bytes.

32 bit page mode looks GREAT for doing this in RLL fashion - null terminated.

when using page mode for these parts -
what is NOT obvious is what the address index range is -
is it linear 0=4095 by 'ones'
or is it 0,4096,8192,12288, etc --
can't find doc and unless somebody knows already - i'll have to enter experiment land to find out...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Dec 30, 2016 5:24 pm     Reply with quote

It says in diagrams 2-3 and 2-4, that the address is 24 bits and consists of
Page X and Word Y. The implications are:

1. If you want to start at the beginning of a page, then send the full
address, with the bottom 5 bits set to zero. So,

Page 0: Address 0x000000
Page 1: Address 0x000020
Page 2: Address 0x000040
Page 3: Address 0x000060
etc.

These addreses are 0x20 apart, because each page is 32 bytes long.

2. Because they say "Word Y", it implies that you could, if you wished,
start the page access at any byte address within the page.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Sat Dec 31, 2016 1:44 pm     Reply with quote

Thanks PCM for your careful reading-

SO for variable length strings of about 6 or 8 to 20 or 22 bytes or so
page boundary writes make good sense .

i already realized that storing an int8 can be done with a
virtual Array address
that spans a 131k integer range , 1:1

RAM_ADD=virtual_add

for int16 the virtual to real address conversion for 65k addresses is
RAM_ADD=virtual_add<<1

and for 4096 pages of null terminated variable length it becomes

RAM_ADD=virtual_add<<5

going to try this and report if i'm wrong ..
Ttelmah



Joined: 11 Mar 2010
Posts: 19549

View user's profile Send private message

PostPosted: Sat Dec 31, 2016 2:14 pm     Reply with quote

The nice thing here is that you can send the single address at the start of the page, and if you have switched the chip to page mode, just carry on writing bytes, and the chip auto increments to write to each successive byte. You should include a limit check so that if it gets to 31 bytes, it then writes a '\0' to terminate your string, and stops (otherwise stopping at the null in your source string). The funny thing is I'm storing string data in a file on an SD card using almost exactly the same layout at the moment. Smile
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Sat Dec 31, 2016 2:53 pm     Reply with quote

Exactly where i'm trying to go Ttelmah-

Basically enable the chip, write the command and address block
and then leave CS low- Then clock out and count bytes as the messages are built - then retrieve when data runs are complete for "export" -
So as data are generated from ADC words and a time signature generator- they are dumped into SP ram -
I just raise CS after the EOL char is sent -

Has to be all bit banged as i can't have access to the already committed SPI hardware in the PIC based instrument i'm upgrading. Plus
The part involved is so cheap it might as well be free compared to all the other costs of doing the upgrade....and adding this tiny PCB and some hay-wires.

Also considering using FRAM should non_V ram make sense to the customer -

As there seems to be pin compatibility there too.
I sincerely believe what i'm doing would be so much harder with any competing compiler too. I've looked at support forums on Microchip -hence feel grateful and lucky for the generous help i've found here. Very Happy Very Happy
Ttelmah



Joined: 11 Mar 2010
Posts: 19549

View user's profile Send private message

PostPosted: Sat Dec 31, 2016 3:22 pm     Reply with quote

You should be aware it doesn't have to be 'bit banged'.

#USE SPI, can generate software SPI just as easily as hardware based. You can use any pins you want, and it optimises the I/O over the bit banged approach. Even better spi_xfer allows you to specify how many bits to send, so to send a byte, you can use spi_xfer(STREAM_NAME, val, 8); while to send 16bits, just change the 8 to 16. It can also receive 8, 16 or 32bits at a time.
I must admit I always wonder why people are doing it manually now!...
Ttelmah



Joined: 11 Mar 2010
Posts: 19549

View user's profile Send private message

PostPosted: Sun Jan 01, 2017 4:32 am     Reply with quote

As a further comment, do consider the FRAM, or NVRAM. Both have the big advantage of being fast. Writes can be completed as fast as you can clock the data out.
Remember also that you should design your circuit to allow you to always 'complete' the write if something like a power fail happens or long term there may be problems....
temtronic



Joined: 01 Jul 2010
Posts: 9245
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Jan 01, 2017 8:17 am     Reply with quote

re:I must admit I always wonder why people are doing it manually now!...

Well it is hard to teach us 'old dogs' new tricks ! When you grow up manually toggling in boot loaders on PDP8s..need I say more ?
Anyone who started in assembler probably figures they can do code better than in these 'new,fangled' high level languages.....

Jay
Happy New Year
Ttelmah



Joined: 11 Mar 2010
Posts: 19549

View user's profile Send private message

PostPosted: Sun Jan 01, 2017 9:40 am     Reply with quote

Agreed. However I'm talking here about the large number of 'low mileage' posters who then write things like SPI code, and are wasting time doing it manually, and often getting something wrong....
Here 'asmboy' may well fit your 'assembler' model, but in fact he's already posted back to me directly, that he has now tried using the CCS functions and has this working.

I'm quite resistant to some 'new things', but a library that allows you to generate quite efficient code to clock in/out on whatever edge you want, however many bits are needed etc., is just too useful to ignore. Smile
It's actually one of the best bits of code that has been added to the compiler in recent times.

Happy New Year
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