Jump to content

My first table...


Alkex
 Share

Recommended Posts

Hi there!

I am making a little Sid control surface handling 50 knobs and forwarding the corresponding CCs to the midibox SID.

I plan to implement 12 LOAD and SAVE buttons that can store and recall the 50 knobs positions to 12 seperate presets.

I therefore need to adress these values to 12 areas of the pic's "hard drive", so I don't loose them on poweroff.

I kinda understood I need tables for this but aren't very confident with my programming yet and don't know where to start...

I would really appreciate it if anyone could point me to a beginner's guide to reading/writing tables or just give me a kick start as I am really willing to learn!

ultimately, I would write to a 13th table using a " hardware random generator"  thus enabling a beloved RANDOM button  :D

Thanks in advance!!

Alex

Link to comment
Share on other sites

Alex,

I've been interested in that as well. I understand the concept and the table part of the lists are pretty self explanatory, but I don't know enough assembler to be able to work it into the places I would want it in Thorsten's code.

I started with a book by Square 1 electronics called "Easy Microcontrol'n". It goes very briefly into a simple lookup table for assigning different 8 bit binary values to the anodes of a common cathode 7-segment digit display. My sister just got me the "Programming and Customizing PIC uC's" book by Myke Predko, so maybe there's better info in that. If I find anything good, I'll bring a link back to this thread.

Here's most of the "baby" table from the book. Sorry if it's stuff you already know, but maybe someone else can use it. It's also directly loading the outputs with the eight ones and zeros for each table item, so it's a heck of a lot simpler than trying to link the items to individual "snapshot" type functions or MIDI messages.

-----Basic header junk snipped, including an equate for the program counter's address in this particular chip (0x02), and the assignment of all outputs to portb (the 7-segment display).

-----the code (they're trying to send a number "2" to the display) --

char        movlw    0x02

              call        segmnt

              movwf   portb

;

segmnt    addwf    pc, f

               retlw     0x3f

               retlw     0x06

               retlw     0x5b

               retlw     0x4f

               retlw     0x66

               end     ; I skipped the remainder of the table

------------------------------------- and here it is with comments and formatting that would flip MPASM like a Mario Bros. turtle  ;D ---->

char  movlw  0x02   

; That's actually the "2nd" item in the table list (table item could be anything, and has no connection to the "2" you're trying to display). Don't know why they gave this area a label, or why they foolishly chose an example number which looks just like the program counter's address either. The number lands in the work register.

call segmnt     

; The routine which uses the work register's contents as the offset from the start of the table list (starting at zero), and loads the work register with the binary data (in hex here) which you wish to display. The program counter holds the current location in the code, so once you jump into the table, whatever offset you have in the work reg. will take you to that number of lines beyond the start of the table, jumping over any previous items. The table items in this example are all retlw instructions, so right after they load the work reg., they'll leave the segmnt routine and jump back to where you were when you called it, but with new work reg. contents (you won't hit any subsequent table items).

movwf  portb   

; After returning from the segment routine with a new hex number in the work reg., it dumps the contents into the lights at portb.

segment  addwf  pc,f   

; The "segmnt" routine adds the work reg. offset (0x02 here) to the start of the program counter, which will begin at the table below.

             

retlw   0x3f   ; Start of the table. This is the first (no offset) item. Sends back a hex 3f to light up a "0". (0011 1111)

retlw   0x06  ; If given an offest of one, it would come back with 0x06 to display a "1"

retlw   0x5b  ; Offset of two (the example offset). Displays 0101 1011 (a number 2)

retlw   0x4f  ; Gives you a number four, blah, blah, blah (5 more table items for the numbers 5-9)

-- If there are any errors in those descriptions, feel free to correct them.

Hope that helps somebody, and please put any good info links here for us.

                              -George   

 

Link to comment
Share on other sites

One is glad to be of service. ;)

Perhaps someone can come in and elaborate on the MIDIBox application of it for us. I guess you'll be needing to keep the table list somewhere that's read/write and then jump to it or store stuff in it as necessary.

I'll probably have to get on the table thing later. I've got enough other MIOS stuff to keep me confused for a while. :-[

-Take Care

Link to comment
Share on other sites

George: your code won't work correctly on the PIC18F, since it doesn't take the high-byte of the instruction counter into account. See the JUMPTABLE_2BYTES_UNSECURE macro in macros.inc how jumptable can be realized securely

With PIC18F devices table accesses can be realized much easier, since it provides a "table read" command, which reads directly from flash memory. The result will be put into the TABLAT register.

Here a simple examle which reads a table entry, each entry consists of two bytes:


;; index of entry in W register
mullw 2 ; multiply by two
movlw (MyTable & 0xff) ; create 16-bit table pointer
addwf PRODL, W ; add low-byte of multiplication result
movwf TBLPTRL ; store in low-byte of table pointer
movlw ((MyTable>>8) & 0xff) ; high-byte of table
addwfc PRODH, W ; add high-byte of multiplication result (with cary from last addition)
movwf TBLPTRH ; store in high-byte of table pointer

tblrd*+ ; read first entry and increment table pointer
movff TABLAT, PRODL ; store byte in PRODL
tblrd*+ ; read second entry and increment table pointer
movff TABLAT, PRODH ; store byte in PRODH

return


MyTable
dw 0x1234 ; first entry
dw 0x5678 ; second entry
dw 0x9abc ; third entry
[/code] However, I strongly recomment the use of C for such experiments, the code is much smaller!
[code]
const unsigned int MyTable[] = {
  0x1234, 0x5678, 0x9abc
  };
A table entry can be accessed with:
MyTable[x]

(where x is the table index)

Alex, you wrote that you want to implement a random generator. The SID Random toy is written in C, it's more difficult to merge assembly with C code, then just to write the whole application in C - you make it much more complicated than it really is!

Best Regards, Thorsten.

Link to comment
Share on other sites

Hi Thorsten!

Thanks for your support, I know I should go C but I've just got the hang of the basics of asm so It's not easy to make the change...

Anyway, your little example is really helping me out now, only two questions remain:

-to store midi CCs using this example, I presume I want to "cut" the 16bit value with into 3 midi bytes using MIOS_HLP_Dec2BCD

Right?

-You say MyTable is read/writen to and from flash, does this mean I don't need any specific FLASH commands to expect to find the same values after reboot?

Enlightenment on those two questions ought to sort me out for good  ! I promise I'll make the leap to C on my next project (FM synth) ;)

As for the random generator I mentionned, I was just planning on using a couple of noisy AIN pins (maybe with charging/discharging caps of differant values on them and a 555)  and filling up a table with  consecutive MIOS_AIN_Pin7bitGet commands so It was nothing exciting like your SID RANDOM TOY (which I MUST build some time!)

Best regards, and thanks again for your help!

Link to comment
Share on other sites

-to store midi CCs using this example, I presume I want to "cut" the 16bit value with into 3 midi bytes using MIOS_HLP_Dec2BCD

Right?

No, you can store it directly in binary format. It heavily depends on the application which format is the best. For example, if you want to save 128 CC values of a single channel, then you don't need to save the first and the second byte, only the third (the value) in a table of 128 8-bit entries.

If you want to save the CC number as well as the number, a table of 16-bit entries is enough, but searching for a specific CC is more time consuming.

-You say MyTable is read/writen to and from flash, does this mean I don't need any specific FLASH commands to expect to find the same values after reboot?

It's better (and easier) to store such data into the internal EEPROM or into an external BankStick. The EEPROM provides 256 bytes, the external BankStick up to 8*64k

Reading from EEPROM is easy, example for a 128 byte CC table:

  cc_value = MIOS_EEPROM_Read(cc_number)

Writing to EEPROM:

  MIOS_EEPROM_Write(cc_number, cc_value)

Sending a pot value which is stored in EEPROM:

  MIOS_MIDI_TxBufferPut(0xb0); // CC channel #1

  MIOS_MIDI_TxBufferPut(cc_number); // the CC number

  MIOS_MIDI_TxBufferPut(MIOS_EEPROM_Read(cc_number));

The handling for a BankStick is very similar, just replace EEPROM by BANKSTICK

Best Regards, Thorsten.

Link to comment
Share on other sites

Hi Thorsten,

Looks like stored cc Values in a table of  8-bit entries is the way to go for my project!

I'll use a bankstick, should be more than enough to store 12* 50 values!!!

Can't wait to get the synth finished, and start playing with it.

I'll send you photos as soon as It's finished!

Best regards and thanks again for your precious help!

Alex

Link to comment
Share on other sites

Thorsten, I've been meaning to thank you for the corrections.

That first book is quite brief (only for the 16F84) and the name admits that he uses many old techniques which have been changed or replaced, but that MPASM can still use them. He didn't however, mention what they might do in other situations or on newer processors.

In that newer Predko book I got (old, but newer), he also mentions some warning about the tables normally needing to be in the first 256 instructions of the PIC's program memory and PCLATH needing to be unchanged since reset, or you'll risk jumping to an invalid address. I don't completely understand that, but he warns of it and lists a workaround below. And TK, thanks for the tip about the newer instructions, they do look more friendly, but I'm a bit vague on some of it. I've been trying not to look too far into the larger PIC's capabilities and instruction sets until I was more confident with the smaller ones.

Here's his safe code-

movwf Temp   ; saves the value that he brought into the table in a Temp variable (I guess he's already jumped in)

movlw HIGH TableEntries   ;Get the current 256 instruction block

movwf PCLATH     ; Store it so the next jump is correct

movwf Temp,w              ;compute the offset

addlw LOW TableEntries    ; within the 256 instruction block

btfsc STATUS,C

incf PCLATH, f     ; If in next, increment PCLATH

movwf PCL        ; write the correct address to the program counter

I'm lost on these last couple instructions, but I'm just getting into it. Thorsten, please let us know again if that info doesn't apply to the current chips.    --- and Thanks!

-George

PS- Alex, you're further along than I had figured. Maybe I should be asking you the questions. ;)

PSPS- I've gone through the "ASM vs. C" dilemma as well. I knew there were people in here working in C, but I figured assembler was more the native, older format for PICs, and I'd learn some good stuff either way. I've attempted to skim through C on a couple occasions, but having nothing more to build than the crappy "hello world" and database apps, I didn't hang with it long enough to be able to do anything worthwhile. Having music tools and programs to build or edit with PIC code has managed to keep my learning rate about 10x what it was in the C books. I may even get back on C to see how MB source editing feels in that. I haven't forgotten *all* of the C stuff yet, but it's slipping away fast.  :-[ 

Link to comment
Share on other sites

Hi Jidis,

I know what you mean about C slipping away!

I find it applies to loads of software I use, so much to remember, one month away from the thing and its forgotten!

like skiing up and down the learning curve!

Anyway, back to the tables buisness,

For storing my data, I forgot about tables all together and just use a bankstick with variable as adress pointer

That way I have the equivalent of a hard drive with a random access reading head!

Best

Alex

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...