Jump to content

18F + SID


Guest Klaas
 Share

Recommended Posts

I recently build a sid with an extra core + AIN for realtime controls over the parameters. Now i followed the new MIOS concept (which looks stunning). But what isn't exactly clear to me is that if it is possible to use one core with 18F to drive a sid module + an ain module for realtime controllers without the requirement of an extra core for the AIN module since I saw there is space in the PIC for two seperate applications.

Maybe it's a stupid question but I'm a newbie in elctronics and actually I was quite amazed to get the SID working in a couple of weeks. I'm now working on a 19" enclosure (not from schaeffer but a drill expierence for myself).

Thorsten I've followed your site since the first release of the midibox plus (which I of course build) and you're the man who drove me into electronics. Thanks for that  :D!!

Muchas Respect!!

Link to comment
Share on other sites

Hi Klaas,

major problem of the PIC16F architecture are the memory limitations, therefore it wasn't possible to offer such a high flexibility like with the PIC18F. In theory it could be possible to include an ADC driver for some pots to the PIC16F firmware of MIDIbox SID, but this would result into a lot (!!!) of effort for me - to find some free RAM, some free program memory in the 4 memory banks, and to build the hardware in order to test the extension. And the next guy wants to use rotary encoders, another guy wants a sequencer... not with me ;-) Since I don't use the MBSID in this configuration, this would be lost time for myself.

But with MIOS everthing will be changed. All routines which are necessary to handle with the MBHP modules (pots, faders, motorfaders, rotary encoders, buttons, LEDs, LED rings, LED digits, LCDs, BankStick) are already available and accessible by a simple software interface. Therefore it will be possible for the users to add their own extensions to the application source code in order to customize the box. I will provide some examples which can be copy & pasted into the code. My hope is, that with this concept other users will begin to distribute their customizations :)

Btw.: In theory also a graphical user interface could be programmed like known from Reaktor which allows to create the "functional connections" between the modules and drivers. But this will not be my job. In the meantime you've to work with your favourite texteditor ;-)

Best Regards, Thorsten.

P.S.: regarding performance: I noticed that possibly the whole MIDIbox LC (8 motorfaders, 96 buttons, 64 LEDs, 8 rotary encoders, 8 LED rings, graphical LCD) can be handled by one PIC18F core with a latency of ca. 1 ms!)

Link to comment
Share on other sites

Hello Thorsten,

My electronic knowledge isn't that good but I studied informatics so I know about programming (picassembly I never tried). If I could help you with programming some routines I'm more then willing to help.

Best regards

Klaas

Link to comment
Share on other sites

Hi Klaas,

any help (especially for the applications) is appreciated.

With the MIOS functions it will be easy to learn PIC assembly, since the difficult jobs are handled by the operating system itself, and you only have to control the data flow. Here a short example, how to realize an application for common software synthesizers like Reaktor, Reason, etc. --- for such programs, the controller has to send unique MIDI events for each pot:

;; this driver hook is called by MIOS when a pot has been moved
;; pot number in working register
MIOS_AIN_NotifyChange

        ;; save the pot number
        movwf   SAVED_POT_NUMBER

        ;; get 7-bit value of pot, result in working register
        call    MIOS_AIN_Pin7bitGet

        ;; save pot value
        movwf   SAVED_POT_VALUE

        ;; send a unique MIDI controller event on channel 0:
        ;; B0 <pot-number> <pot-value>
        movlw   0xb0
        call    MIOS_MIDI_TxBufferPut
        movf    SAVED_POT_NUMBER, W
        call    MIOS_MIDI_TxBufferPut
        movf    SAVED_POT_VALUE, W
        call    MIOS_MIDI_TxBufferPut

        ;; print the value on LCD at position 14 (first line)
        movlw   14
        call    MIOS_LCD_CursorSet
        movf    SAVED_POT_VALUE, W
        call    MIOS_LCD_PrintBCD3

        ;; thats all
        return
And now the same example for MIDIbox SID/18F if you would like to control the cutoff parameter with pot #0
MIOS_AIN_NotifyChange
        ;; normaly we would use the table jump method here (64 gotos
        ;; in a table) - but this is just a simple demonstration
        
        ;; save the pot number
        movwf   SAVED_POT_NUMBER

        ;; if pot number is not 0 (first pot), branch to another routine
        movlw   0
        IFNEQ   SAVED_POT_NUMBER, ACCESS, rgoto NotPot00

        ;; get 7-bit value of pot, result in working register
        call    MIOS_AIN_Pin7bitGet

        ;; save value in MIOS_PARAMETER1
        movwf   MIOS_PARAMETER1

        ;; forward the value to SID CC#46
        movlw   46
        call    SID_CCSet       ; (value in MIOS_PARAMETER1)

        ;; thats all
        return

NotPot00
        ;; do something else
        ;; ...
        return

Such code snippets can be uploaded within one second to the MIDIbox...

And by using tables (arrays), the configuration can be clearly arranged.

I hope that the upcoming examples and applications will provide enough inspirations :)

Best Regards, Thorsten.

Link to comment
Share on other sites

Hello Thorsten,

I seem to get the point in the structure of the language.

It's just a matter of calling procedures you written, move values into locations to forward them into other procedures.

The only thing I don't get in the example

In the sid application the potnumber data is forwarded into the saved_pot_number allocation. Then the IFNEQ is used to compare the saved_pot_number allocation with 0. If it's not 0 you are able to start a new loop.  Suppose I connect two pots and pot0 controls cuttoff and pot1 will controll frequency. The code would porbably look like this then:

MIOS_AIN_NotifyChange

  ;; normaly we would use the table jump method here (64 gotos

  ;; in a table) - but this is just a simple demonstration

   

  ;; save the pot number

  movwf   SAVED_POT_NUMBER

  ;; if pot number is not 0 (first pot), branch to another routine

  movlw   0

  IFNEQ   SAVED_POT_NUMBER, ACCESS, rgoto NotPot00

  ;; get 7-bit value of pot, result in working register

  call    MIOS_AIN_Pin7bitGet

  ;; save value in MIOS_PARAMETER1

  movwf   MIOS_PARAMETER1

  ;; forward the value to SID CC#46

  movlw   46

  call    SID_CCSet  ; (value in MIOS_PARAMETER1)

  ;; thats all

  return

NotPot00

movlw   1

IFNEQ   SAVED_POT_NUMBER, ACCESS, rgoto NotPot01

  ;; get 7-bit value of pot, result in working register

  call    MIOS_AIN_Pin7bitGet

  ;; save value in MIOS_PARAMETER1

  movwf   MIOS_PARAMETER1

  ;; forward the value to SID CC#47

  movlw   47

  call    SID_CCSet  ; (value in MIOS_PARAMETER1)  

     return

NotPot01

;; more to come

But I can't see a IFNEQ function in the first example for the unique CC. Suppose I connect again 2 pots with that application the controller will output the same value for every pot connected because the controller  can not be directed to a specific potnumber.

Is this correct and if you use it with more pots you should use the IFNEQ function?

How many premade routines are there coming to be available; I can imagine there is a notifychange for the DIN  as well and several routines which output to the LCD, LEDS, MF and bankstick to call in various applications.

I'm I on the right track?

Regards

Klaas

 

Link to comment
Share on other sites

Hi Klaas,

thats not exactly the point, but you will regognize the difference when you start to play with the code. The first example doesn't need a branch with the IFNEQ macro (If-Not-Equal), since simply the pot number and the pot value will be sent out. Pot #0 will send: B0 00 <value>, Pot #1: B0 01 <value>, Pot #2: B0 02 <value>, ...

Your modification for the second example will work. And you see that this method will lead to a lot of code (and therefore to a high danger that anything will not work due to a copy&paste error or similar). But fortunately there are two more advanced solutions: array and jumptables.

An array can be accessed by the "table read" instruction on this way (I don't write the complete code here, because can be found in the examples later):

(Note: the functions with capitalized letters are predefined macros which simplifies the programming - they contain some additional instructions)

   ;; get 7-bit value of pot, result in working register  
   call    MIOS_AIN_Pin7bitGet   
 
   ;; save value in MIOS_PARAMETER1  
   movwf   MIOS_PARAMETER1  

   ;; preload table pointer with first entry of MyCCTable
   TABLE_ADDR    MyCCTable

   ;; get pot number
   movf    SAVED_POT_NUMBER, W

   ;; add pot number in WREG to table pointer
   TABLE_ADD_W

   ;; read table entry
   tblrd*

   ;; get table entry, it has been stored in TABLAT
   movf    TABLAT, W

   ;; this is our CC number. now set the CC parameter
   call    SID_CCSet  ; (value in MIOS_PARAMETER1)   
an example for the table:
MyCCTable
        ;; define CC values for Pot #0 - #16
        db      44, 46, 48, 52, 56, 60, 61, 62, 01, 02, 03, 04, 05, 06, 07, 08
This reduces the code a lot and different banks can be defined on this way. Another advantage: for users who don't like programming, a GUI could be provided which allows to edit such tables. The second method are jumptables. It's like a "case" function in C. Here an example for the buttons:
;; this routine will be called when a DIN pin has been toggled.
;; DIN pin number in WREG and MIOS_PARAMETER1, 
;; DIN pin value (0 or 1) in MIOS_PARAMETER2
USER_DIN_NotifyToggle
   ;; branch depending on pin number (which is in WREG)
   JUMPTABLE_2BYTES 4  ;; 2-byte instructions, 4 entries
   rgoto    DIN0_MIDIChannelDown
   rgoto    DIN1_MIDIChannelUp
   rgoto    DIN2_DeviceNumberDown
   rgoto    DIN3_DeviceNumberUp

DIN0_MIDIChannelDown
   ;; only continue if button has been pressed (value = 0)
   movlw   0
   IFNEQ  MIOS_PARAMETER2, ACCESS, return

   call    SID_MIDIChannelGet
   addlw   -1
   call    SID_MIDIChannelSet
   return
DIN1_MIDIChannelUp
   ;; only continue if button has been pressed (value = 0)
   movlw   0
   IFNEQ  MIOS_PARAMETER2, ACCESS, return

   call    SID_MIDIChannelGet
   addlw   1
   call    SID_MIDIChannelSet
   return
;; ...

Best Regards, Thorsten.

Link to comment
Share on other sites

  • 2 months later...

I have a few question about the examples in this post.

First of all id like to say that im new to pic programming so my problem might be pretty simple.

I was trying to add the code from TK´s  2nd exampel from this post to the sid_ain.inc. But when i compile it shows the following error messages:

Error[113] *long path*\SID_AIN.INC 41 : Symbol not previously defined (SAVED_POT_NUMBER)

Error[113]  *long path*\MACROS.H 54 : Symbol not previously defined (SAVED_POT_NUMBER)

Error[113]  *long path*\SID_AIN.INC 55 : Symbol not previously defined (SID_CCSet)

Does the symbol need to be defined in the sid_ain.inc file and if so,how do you do that? Or is the problem in other files? Or could it be my mplab that needs change in the configuration?

Another question: I was wondering if you know a place where i can find a listing of the keywords of this programming language. fx that IFNEQ mean if-not-equal and so on. some of them im able guess but not all.

Thanks for any help! :) Right now im unemployed  after finishing my education as a computer-programmer. I think learning to program these things is a great way to spend my spare time.

js

Link to comment
Share on other sites

Hi js,

in the meantime I've changed the name of the functions, so good that you mention it, it's time for an update. :)

SAVED_POT_NUMBER, etc are registers which are used like variables in a high-level programming language. These variables have to be located to free SRAM im app_defines.h so that the addresses are globally available.

When you open the app_defines.h file of the SID application you will already see some allocated SRAM cells. Addresses from 0x30 to 0x7f will also be free in the future and can be used for your own extensions.

PIC instructions: a nice overview can be found in the PIC18F452 datasheet. The macros (capitalized letters) are "my own creations" and defined in macros.h - I use the macros to improve the readability.

To the examples: the routine which allows to set a CC value has been realized on another way, now you have to use it like below:

;; in sid_ain.inc:

USER_AIN_NotifyChange
        ;; get 7-bit value of pot #0
        movlw   0x00
        call    MIOS_AIN_Pin7bitGet
 
        ;; forward value to the CC handler
        ;; it expects: CC parameter number in WREG
        ;; CC parameter value in MIOS_PARAMETER1, so:
 
        movwf   MIOS_PARAMETER1 ; save 7-bit value in MIOS_PARAMETER1
        movlw   0x10  ; control CC #10h == Transpose V1/V2/V3
        call    SID_CCIN_Set ; call function
 
        return   ; and exit AIN handler 
You also have to enable the AIN handler in sid_init.inc like below (replace the existing code lines by):
        ;; initialize the AIN driver
        movlw   0x01                    ; use 1 pot
        call    MIOS_AIN_NumberSet
        call    MIOS_AIN_UnMuxed        ; don't service multiplexer interface

Hope this helps for your next experiments - have fun! :)

Best Regards, Thorsten.

Link to comment
Share on other sites

Thanks alot for the crash course in pic programming! :) It really makes it esier to understand to get some known words on things. For now i´ve tried to make the changes and build the hex, and that works without any probs. Im going to build a ain module today then im able to experiment a bit more. I´ll let you know how it goes.

:D

js

Link to comment
Share on other sites

Hi Thorsten, i´ve build a 1xain and tried you code but i couldn´t get it to work. Then I tried to call MIOS_AIN_Muxed instead of MIOS_AIN_UnMuxed, and then everything worked fine.

Is it right that you need to use:

MIOS_AIN_UnMuxed: -when you don´t have a ain module (and connect post direct to the pic.)

&

MIOS_AIN_Muxed: -when you use a ain module.

anyways now i´ve got controle.. :)

js

Link to comment
Share on other sites

Now i´ve got the thing working with 8 pots (connected thru a ain x1 module)  programmed to control the arp, portamento etc. But I have one problem: If i turn one pot the sid recives the position from the other post. Fx if the arpeggiator pot is positioned in the middle and i switch to a program with no arpegio and tur the portamento pot the arpeggiator get turned on.

Is there a way to avoid this problem? Would it be better to skip the ain module and connect the pots directly to the pic?

Thanx alot for the help so far! :)

js

Link to comment
Share on other sites

Hi js,

did you really exchange the "call MIOS_AIN_UnMuxed" in sid_init.inc by "call MIOS_AIN_Muxed". Because the effect you are describing here is exactly that what would happen with an un-multiplexed device ;-)

Maybe you should also check the multiplexers with the ain64_din128_dout128_v1_1 application first

Best Regards, Thorsten.

Link to comment
Share on other sites

Thanks for your responce,

I am sure at I did call the MIOS_Ain_Muxed function, just to make sure I tried to call the UnMuxed one and everything was much worse than it was before.

I tried the ain64_din128_dout128_v1_1 test app. When I do, the core sends out loads of CC messages.

I guess that that´s because the program opens 64 ain´s and i´ve only connected one ain module.

I´ve connected pic-pin 3, 4 & 5 to ground. Is it   possible that my trouble is because I havn´t connected pic-pin 7, 8, 9 & 10 to ground. Does that make a difference when I´ve only opend the first 8 pot in sid_init.inc:

;; initialize the AIN driver 
movlw   0x08     ; use 8 pot 
call    MIOS_AIN_NumberSet 
call    MIOS_AIN_Muxed   ;  service multiplexer interface 

is there a similar way to open only 8 pots in the test app instead of all 64? That way i´d might get a better idea of what´s happening.

Thanks again for your help!:)

js

************

EDIT: I just tested ain64_din128_dout128_v1_1 with cubase. It pretty clear that the random CC messages are sent on all between cc32 & cc63 that probaly stop once i connect pic-pin 7, 8 ,9 & 10 to ground. Then I can only hope that that helps the trouble with the sid :-/

************

Edit II (im sorry that this is becomming a long post...)

Now I grounded pic-pin 7,8,9 & 10 and now ain64_din128_dout128_v1_1 only send messages when i turn a pot :) But the problem with the sid is the same :-/

js

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...