+ Reply to Thread
Results 1 to 16 of 16
  1. #1
    Join Date
    Jul 2003
    Posts
    2,358

    Default Making Program Code Space your playground...

    Whilst this has also been posted to the piclist here it is for reference - and also that several hours after posting it's still somewhere 'lost in space'.

    >
    > Can you provide a quick example of writing data to
    > code space and reading it back?
    >

    This is relatively simple... and there's many ways of doing this... so I'll keep it short with just one method...

    The PBP command to read data from codespace is READCODE address,data.

    For example 16F pics that support READCODE like the 16F876, and the 16F877 (amongst others) allow you to save and extract 14-bits of data per memory location. For those that haven't got enough fingers and toes to do the math, that gives you a range of 0-16383. Let's call this PCWord (for Program Code Word rather than a real word which is 16 bits). Naturally you define 'data' as a word if you want to grab all 14-bits, and if you define it as a byte you just get the lower 8 bits. The 'address' is also a WORD (a real 16-bit variety) and is any spot in valid codespace.

    WRITING to codespace should be restricted, it's not as resilient as EEPROM and theoretically wears out quicker, but for use as sporadic storage or for giant Lookup tables, it saves on an external EEPROM if you're tight for cash or PCB Real-Estate. READING from codespace is unlimited, doesn't wear out your PIC, doesn't use any calories and can be used without restriction - so go do it.

    WRITECODE is the opposite to READCODE and allows you to write to those memory locations. But it's kinda wasteful having to use WRITECode to create a 1000 word table before having to use it. Whilst WRITECODE and READCODE are the equivalents of READ and WRITE on a bigger scale, what's missing is the equivalent of the DATA statement which allows you to preset those memory locations.

    For this we have to jump into some lines of Assembler which I'll teach you here...

    Let's say we wish to create a 1000 word table in Program space. First choose a memory location well away from your code. So an PIC16F876/877 has 8K (8192) words of Program Codespace. If we put our data table out of the way starting at address 7190, it means we can create a program that uses up to 7190 words. Any bigger and it risks overwriting our data table.

    Our Data table is created thus (note caps for CODE and DB)... and shove it at the end of your code... PLEASE NOTE that I am using PBP's Assembler mnemonics here, there are some variances for MPASM but the theory is the same.
    Code:
        Asm
        CODE 7190
        DB 254
        DB 1
        DB "Hey, Beautiful"
        DB 254
        DB 192
        DB "What's Cookin?"
        DB 0
        Endasm
    (Note: Here on this forum, the display above will corrupted and left-justified. The CODE and DB statements must be indented and must NOT start at column 1 in your code. The left-hand edge is reserved in Assembler for Labels ONLY.)

    This is the equivalent of sequentially storing...
    Code:
       $FE,$01,"Hey, Beautiful",$FE,$C0,"What's Cookin?",0
    Let's now read that data in and display it on our LCD... here's a couple of ways rolled into one demo program...
    Code:
        PCAddress var WORD
        PCData var BYTE
    
    DoitAgain:
        PCAddress=7190
        '
        ' Read & Display till we get a stop character
        '
    ReadCodeLoop:
        READCODE PCAddress,PCData
        If PCData>0 then
            LCDOut PCData
            PCAddress=PCAddress+1
            Goto ReadCodeLoop
            endif
        Pause 2000
        '
        ' Read a set number of locations
        ' (two in this case - to Clear the LCD)
        '
        For PCAddress=7190 to 7191
            READCODE PCAddress,PCData
            LCDOut PCData
            Next PCAddress
        Pause 1000
        Goto DoitAgain
        End
    (Download the accompanying pcode.txt file for a pretty example).

    There are a number of things you have to remember. So here's the rules of the game - don't disregard them or they'll come back and bite you...

    1. Don't spill your data out of available memory... you'll get stacks of compiler error messages anyway. Remember, be nice, leave some space for your program. Every PCWord you steal from Program Memory is one word less you've got available in programming.

    2. Remember how many data elements you've preset. If you've preset 1000 PCWords, don't access 1001 because it probably won't contain things relevant to your data table.

    3. When using WRITECODE, if you access the WRONG memory locations, you run the risk of corrupting your program code. Stick rigidly to the addresses for your data. Remember the golden rule of programming... "if you put it into memory, remember where you put it".

    The downside... OK there's no free lunch (unless you're buying it for me). No gain without pain, and this little niggle is significant...

    4. Whilst you can WRITECODE with 14 bits, and READCODE with 14 bits, you can't preset 14-bits with the assembler DB statement. You can ONLY preset 8 bits, and the upper 6 bits (remember 14-bits for our PCWord) will always be preset to %110100. Hey, I didn't write the assemblers - so don't lay this one on me. Consider the DB statement as standing for 'Data Byte'. BYTE being the appropriate thing to notice. So each 8-bit BYTE you store, gets saved as a 14-bit PCWord... example...

    You want to save a value of ONE...

    DB 1

    That memory location will actually contain in 14-bits...

    11010000000001

    You can however within your PBP Program do this...
    Code:
        MyWord var Word
        MyWord=1
        WRITECODE address,MyWord
    and that address will have in 14-bits...

    00000000000001

    (when reading or writing with WRITECODE and READCODE into/from a 16-bit word, the upper two bits should always be considered zero)...

    You might think that instead of using the DB statement, I'll go and use DW (Data Word rather than Data Byte)... but look what happens...
    Code:
        CODE 7190
        DW 1
    You would think you would get 00000000000001 stored into location 7190... but hey, they've thought of that and you actually get the lower 8-bits stored into location 7190, and the upper eight bits (yes of a whole 16-bit word) gets stored in location 7191. The upper six bits of both memory locations stubbornly still get preset to %110100. Like I said, don't lay this on me.

    Finally... if there is such a thing as 'finally'...

    5. Playing with the CODE directive (as in example CODE 7190), kinda screws the compiler reporting the true value of the words used in your program. If you need to know the actual size of your compiled program (useful to determine how much Program Code space it's used), just remove the Asm...Endasm section and compile. Drop it back in for your final program. Some folks will argue that the Asm...Endasm section should be lower down in your code and just jump over it. Sure you could do that. Personally I like to keep the data blocks that I'm tampering with well away from my Program Code.

    The appended file is a ready-to-run demonstrator. Go create and have fun.

    So I lied about keeping it short...

    Melanie
    Attached Files Attached Files
    Last edited by ScaleRobotics; - 30th October 2010 at 18:01. Reason: added a few code tags

  • #2
    Join Date
    Apr 2003
    Location
    Cambridge - UK
    Posts
    903

    Default Another way to write/read to code space

    To all, from Greg Yent, San Diego, CA


    Another way to write/read to code space that I've used for Font
    tables is to use an @ ORG XXXXh then Pokecode (v2.42) to write, and
    Peekcode or Readcode to read. Pokecode/Peekcode works great with table
    because you don't need the address for each byte. But Pokecode can only
    be used at program time. You can edit individual bytes during operation
    with Writecode. Loading an Image file into the graphic LCD, as an
    example:

    Code:
    To Write:
    
    DISABLE
    'Introduction Image File
    @	org 12C0h
    Pokecode    $00,$00,$00,$80,$C0,$E0,$E0,$F0, etc for 80 bytes
    Pokecode    $07,$3F,$7F,$FF,$F0,$E0,$C0,$C0, etc for 80 bytes
    Pokecode    $80,$F8,$FE,$FF,$1F,$07,$03,$01, etc for 80 bytes
    Pokecode    $00,$00,$00,$00,$01,$01,$01,$03, etc for 80 bytes
    Etc......
    
    To Read:
    StrAddr = $12C0
    for j = 0 to 3
    	CharAddr = StrAddr + (80*j)	'80 for the example given
    	for k = 0 to 79
    		PeekCode CharAddr+k, x		
    		Shiftout SDA, SCL, 1, [ x ]
    
    	next k
    next j
    Greg Yent
    San Diego, CA

  • #3
    Join Date
    May 2004
    Posts
    30

    Default Code Space problem !

    Hi Melanie

    Is this your code space solution ?
    I can't understand the final part !
    Please explain me !


    Thank you very much

    Don Mario
    Attached Files Attached Files

  • #4
    Join Date
    Oct 2005
    Posts
    35

    Question Playing at the Playground

    Hello,

    This project uses ports A-B and C to drive a display containing 21 LED's.
    To generate the patterns I started with arrays but quickly ran out of space. The following is a partial sample of an array pattern setup. Using binary helps to visualize what the pattern will look like.

    ARRAYDATA5:

    ARRAY5C[0]=%00000111:ARRAY5B[0]= %00000111:ARRAY5A[0]=%000001
    ARRAY5C[1]=%00001110:ARRAY5B[1]= %00001110:ARRAY5A[1]=%000011
    ARRAY5C[2]=%00011100:ARRAY5B[2]= %00011100:ARRAY5A[2]=%000111
    ARRAY5C[3]=%00111000:ARRAY5B[3]= %00111000:ARRAY5A[3]=%001110
    .
    .
    .
    .
    RETURN

    I looked at the code space playground thread and got some good results, but not perfect. I disabled the LCD code and instead have the data output to portb with led monitors. I put in a 2 second delay between each read.
    Decimal DB values give the expected display results however using binary values produces some extra bits within the expected pattern. I tried 14 bits and 8 bits and using the % symbol which the compiler dosen't like.


    test pattern does not work properly
    Asm
    CODE 7190
    DB 00000000000001
    DB 00000000000010
    DB 00000000000100
    DB 00000000001000
    DB 00000000010000
    DB 00000000100000
    DB 0
    endasm

    ........................................

    this code works
    Asm
    CODE 7190
    DB 1
    DB 2
    DB 4
    DB 8
    DB 16
    DB 0
    endasm

    Is there something wrong with entering binary values this way? I must be able to develop patterns in binary. It is just too hard to visualize decimal values.
    Maybe I could use the arrays just to develop the patterns then have some utility program convert binary to decimal and generate "DB (decimal}" code somehow. This would make things easier. Any ideas?


    Thanks

    "Weaseling out of things is important to learn. It's what separates us from the animals... Except the weasel."
    Last edited by Homerclese; - 8th October 2005 at 01:32.

  • #5
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898

    Default

    if i can suggest one thing, use the internal EEPROM of your PIC if he have one. Really easy to do with DATA to load your value, later use READ to read your aray from the internal EEPROM.

    Can you start another thread and post your whole code? That way we will be able to point you some idea.
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  • #6
    Join Date
    Oct 2005
    Posts
    35

    Lightbulb

    Hi,

    Yes I was using EEPROM for array storage but the 16f877 has only 256 bytes available. I will need about 4k just for pattern storage. That is why I'm looking at using the code program space. The problem seems to be my use of binary data input. Here's the code i'm using for testing.


    ' PCode.bas
    ' Quick Demo Program
    ' showing how you can play with
    ' Program Code Space

    Define debug_pacing 1000 'serial setup
    Define debug_reg porta
    Define debug_bit 0
    Define debug_baud 2400
    Define debug_mode 1
    TRISB= %00000000
    TRISa= %00000 '
    '

    ' RAM Assignments & Variables
    ' ---------------------------
    PCAddress var WORD ' Used to determine ADDRESS of Data
    ' within Program Code space
    PCData var BYTE ' Data Variable - in this example a BYTE
    ' but could be a WORD as each memory
    ' address is capable of storing 14-bits
    PCWord var WORD
    '
    ' Start Program
    ' =============
    Pause 2000
    DoitAgain:
    PCAddress=7190 ' Pointer to start of Data area
    '
    ' Read & Display till we get a stop character
    ' -------------------------------------------
    ReadCodeLoop:
    READCODE PCAddress,PCData ' Sequentially read bytes
    If PCData>0 then ' Until a Stop character is found

    debug "ADD=", dec pcaddress 'lcd display
    debug 254,192
    debug "DAT=", dec pcdata

    PCAddress=PCAddress+1 ' Remembering to increment our address
    portB=pcdata 'output data to portB LEDs

    Pause 300
    Goto ReadCodeLoop
    endif
    Pause 50

    Goto DoitAgain

    End


    Asm
    CODE 7190



    DB 00000001
    DB 00000010
    DB 00000100
    DB 00001000
    DB 00010000
    DB 00100000
    DB 01000000
    DB 10000000
    DB 0

    Endasm




    ........................
    RESULTS

    debug LCD readout values
    00000001 = 1 OK
    00000010 = 10 NG
    00000100 = 100 NG
    00001000 = 232 NG
    00010000 = 16 OK
    00100000 = 160 NG
    01000000 = 64 OK
    10000000 = 128 OK
    Last edited by Homerclese; - 9th October 2005 at 01:23.

  • #7
    El_AMPo's Avatar
    El_AMPo Guest

    Default Using program space for tables on smaller PICs

    The first method shown work only on 16F87X flash memory PICs as far as i know.

    The second method posted that used PEEKCODE and POKECODE works great in smaller pics.

    ...for the ones that didn'd get it in the first example

    --[To Write]--
    Just include after the END tag of the program:

    POKECODE @[start address],[byte0],[byte1],[byte2]....(up to 79)

    (note: start address must be bigger than your program size, and the command only works when programming the pic)

    --[To Read]--

    (use something like...)

    OUT var byte
    y var word

    For y = [start address] to [start address + nºbytes]
    PEEKCODE y, OUT
    Next y


    hope it helps...
    Last edited by El_AMPo; - 17th January 2006 at 06:50.

  • #8
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french region)
    Posts
    755

    Default Determine free memory space

    How do I determine the free memory space?

    PBP manual: The listing file may be examined to determine program addresses.

    I've appended a test list file (original .LST file, renamed .TXT for uploading) generated by MCS.

    How must I read & understand this file?

    PIC16F690's Memory Map looks like this:
    <img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=2728&stc=1&d=121534385 0">
    Attached Images Attached Images  
    Attached Files Attached Files
    Roger

  • #9
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,541

    Lightbulb

    Hi, Roger

    MPLAB, Program window ... does it sound something to You ???

    ... Lol

    With MCS, have a look to the SMALL characters at the bottom left part of your screen ...

    ...

    Alain
    Last edited by Acetronics2; - 6th July 2008 at 13:02.
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  • #10
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french region)
    Posts
    755

    Default

    Bonjour Alain,

    Sorry, I'm still an amateur and I don't use MPLAB...

    Are you meaning I just have to add the amount of words in MCS to the memory starting adress?

    It can't be that simple?!
    Roger

  • #11
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,541

    Wink

    Hi, Roger

    Not so simple ...

    say it is a 16F628 with 2k memory ( 2048 words )

    2048 minus the "little number" is the first memory adress you can use for placing tables ... ( remember the default DEC radix for PbP !!! )

    to be sure ... you can let some "blank lines" ... before the Table. Or begin your table on a "round" adress ... 2FF, or 1200 i.e. ( Remember A good programmer NEVER adds mods to his programs !!! ... LoL ...)


    Alain
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  • #12
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,541

    Default K.I.S.S Method ...

    Bonsoir Roger,

    Have a look to those nice Subroutines ...

    as you see they are placed at the end of the Basic File ...

    Code:
    END ' This is the Program END
    
    
    '*****************************************************************************
    '*****************************************************************************
    'Tables de linéarisation
    '*****************************************************************************
    '*****************************************************************************
    
    
    '*****************************************************************************
    Linearisation2:'Linearisation complète Courbe A(15A)> Linéaire B(1B)
    '*****************************************************************************
    
    LOOKUP Lecture, [  0,  0,  0,  0,  0,  0,  4, 16, 16, 16,   18, 21, 25, 25, 26, 26, 26, 27, 27, 27,   28, 28, 28, 29, 29, 30, 30, 30, 31, 31,   31, 32, 32, 32, 33, 33, 33, 34, 34, 34,   35, 35, 35, 36, 36, 37, 37, 37, 38, 38,_
    				  38, 39, 39, 39, 40, 40, 40, 41, 41, 41,   42, 42, 42, 43, 43, 43, 44, 44, 45, 45,   45, 46, 46, 46, 47, 47, 47, 48, 48, 48,   49, 49, 49, 50, 50, 50, 51, 51, 52, 52,   52, 53, 53, 53, 54, 54, 54, 55, 55, 55,_
    				  56, 56, 56, 57, 57, 57, 58, 58, 59, 59,   59, 60, 60, 60, 61, 61, 61, 62, 62, 62,   63, 63, 63, 64, 64, 64, 65, 65, 65, 66,   66, 67, 67, 67, 68, 68, 68, 69, 69, 69,   70, 70, 70, 71, 71, 71, 72, 72, 72, 73,_
    				  73, 74, 74, 74, 75, 75, 75, 76, 76, 76,   77, 77, 78, 78, 79, 80, 80, 81, 82, 83,   83, 84, 85, 85, 86, 87, 87, 88, 89, 89,   90, 91, 92, 92, 93, 94, 94, 95, 96, 96,   97, 98, 99, 99,100,101,101,102,104,106,_
    				 108,110,112,114,116,118,120,122,124,126,  128,130,132,134,136,138,140,142,144,146,  148,150,152,155,157,159,161,163,165,167,  169,171,173,175,177,179,181,183,185,187,  189,191,193,195,197,199,201,205,208,214,_
    				 220,230,240,250,255,255], Result
    				 
    RETURN
    
    END
    
    '*****************************************************************************
    Linearisation1:'Linéarisation exp simple à 26 points
    '*****************************************************************************
    
    LOOKUP Lecture, [  1,  1,  1,  1,  1,  2,  2,  2,  2,  3,    3,  3,  3,  4,  4,  4,  5,  5,  5,  6,    6,  7,  8,  9, 10, 11, 12, 12], Result
    				  								  
    RETURN
    
    END
    
    '*****************************************************************************
    '****************************************************
    PbP will AUTOMATICALLY place them in the free memory space ... with some blanks lines before !!!

    just use a "Gosub Linearisation2 " in your program and PbP will do all the Work !!!

    Yes ..., you can cry ...

    Alain
    Last edited by Acetronics2; - 6th July 2008 at 16:48.
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  • #13
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french region)
    Posts
    755

    Thumbs up Okay!!!

    As often, I don't see simple things at the first glance.

    I should have thought about the PicKit2 prog and its Program Memory viewer...
    <img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=2729&stc=1&d=121536137 1">
    Thank you, Microchip.
    Attached Images Attached Images  
    Roger

  • #14
    skimask's Avatar
    skimask Guest

    Default

    Quote Originally Posted by flotulopex View Post
    As often, I don't see simple things at the first glance.
    I should have thought about the PicKit2 prog and its Program Memory viewer...
    Something else to keep in the back of your head...
    If/When you switch over to 18F series PICs and start using MPASM, if you set MCS up to generate a .LST file, in the last few lines of the .LST file, it'll tell you exactly how many bytes/words of program space you've used.

  • #15
    Join Date
    Aug 2006
    Location
    SWITZERLAND (french region)
    Posts
    755

    Default really no way to program 14bits with POKECODE?

    ...
    You can however within your PBP Program do this...
    MyWord var Word
    MyWord=1
    WRITECODE address,MyWord
    and that address will have in 14-bits...
    00000000000001
    This is working fine with WRITECODE.

    Is it really impossible using POKECODE? Isn't there any workaround?
    Roger

  • #16
    skimask's Avatar
    skimask Guest

    Default

    As far as I can tell, according to the manual...
    POKECODE puts 'data' into program memory in the middle of your program, during 'program time', when your programmer is actually programming the chip.
    WRITECODE allows you to change the 'data' in the program memory space while your program is executing (after the PIC has been programmed, etc).

    Disregard...I see what you're saying...Statement above almost completely irrelevant!
    Last edited by skimask; - 19th July 2008 at 08:29.

  • Similar Threads

    1. Presetting Configuration Fuses (PIC Defines) into your Program
      By Melanie in forum FAQ - Frequently Asked Questions
      Replies: 82
      Last Post: - 15th December 2013, 09:54
    2. Minimizing code space
      By Tobias in forum mel PIC BASIC Pro
      Replies: 2
      Last Post: - 30th May 2009, 07:25
    3. Replies: 1
      Last Post: - 23rd May 2009, 09:22
    4. Need more code space
      By ghutchison in forum General
      Replies: 1
      Last Post: - 12th February 2005, 20:54
    5. oscillator code and placement within program
      By bartman in forum mel PIC BASIC
      Replies: 14
      Last Post: - 14th December 2004, 02:39

    Members who have read this thread : 3

    You do not have permission to view the list of names.

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts