Jump to content

wackazong

Programmer
  • Posts

    298
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by wackazong

  1. OK, then that was it. However, I did it in C now, does not really slow down anything..... Still learning... :) At least now i get a smooth interpolation between 0 and 32 steps (which is 33 steps in total). Best, ALEXander.. ///////////////////////////////////////////////////////////////////////////// // Interpolate ///////////////////////////////////////////////////////////////////////////// unsigned char KNOEPFLI_Interpolate32(unsigned char step, unsigned char value1, unsigned char value2) { unsigned char swap, diff; //send out value2 if step is the max value if( step == 32 ) { return value2; }; //send out value1 if step i 0 if( step == 0 ) { return value1; }; //invert the interpolation if value1 > value2 if( value1 > value2 ) { //swap the values swap = value2; value2 = value1; value1 = swap; //--step because we are counting from 0 to 32, not to 31 --step; //invert the step counter step = ~step; //clear the upper three bits step &= 0x1f; }; //get the difference diff = value2 - value1; //divide it through the total number of steps (>>5) and multiply it with step (gives an integer) then get the high byte, //shift the step counter three to the left to make it 8bit, store it in PRODL PRODL = step << 3; //store diff in PRODH PRODH = diff; //do the multiplication in assembler __asm movf _PRODL, W mulwf _PRODH, 0 __endasm; //add the lower value return value1 + PRODH; }
  2. Ups, doesn't the line accessram udata tell the linker to put these variables into the accessram? I will check the .map file.
  3. Hi, I have a strange bug using an ASM function in a C applikation: When I call the ASM function, random values get written into the variable RAM. I would be very glad if somebody could have a look a the header and main file, I cannot find the problem... The header file /* */ #ifndef _KNOEPFLI_ASM_H #define _KNOEPFLI_ASM_H ///////////////////////////////////////////////////////////////////////////// // Prototypes ///////////////////////////////////////////////////////////////////////////// extern unsigned char KNOEPFLI_Interpolate(unsigned char step, unsigned char val1, unsigned char val2) __wparam; #endif /* _KNOEPFLI_ASM_H */ The main file radix dec #include <mios.h> #include <mios_vectors.inc> #include <macros.h> ; ========================================================================== ; Define constants ; ========================================================================== ; ========================================================================== ; Import/Export Labels ; ========================================================================== ; export labels global _KNOEPFLI_Interpolate ; (for C, ) ; ========================================================================== ; Declare variables ; ========================================================================== accessram udata pca9635_StepCounter res 1 pca9635_Temp res 1 ; ========================================================================== ; Start code section and include driver code ; ========================================================================== KNOEPFLI_ASM CODE ; ========================================================================== ;; -------------------------------------------------------------------------- ;; FUNCTION: KNOEPFLI_Interpolate ;; C_DECLARATION: void KNOEPFLI_Interpolate(unsigned char step, unsigned char val1, unsigned char val2) ;; DESCRIPTION: Testing the interpolation algorithm: interpolate between value 1 and value 2 in ;; 16 steps and return the corresponding step value. ;; ;; C IN: step number in step (through WREG, using __wparam) ;; value 1 in val1 ;; value 2 in val2 ;; ;; C OUT: interpolated value as unsigned char (through WREG __wparam) ;; ;; USES: MIOS_PARAMETER3 ;; -------------------------------------------------------------------------- _KNOEPFLI_Interpolate KNOEPFLI_Interpolate ;save step value in variable movwf pca9635_StepCounter movff FSR0L, FSR2L ; get other arguments from stack movff PREINC2, MIOS_PARAMETER1 movff PREINC2, MIOS_PARAMETER2 ;find out if we have to swap the values ;move MIOS_PARAMETER1 into W movf MIOS_PARAMETER2, W ;compare, skip the swap if MIOS_PARAMETER2 > MIOS_PARAMETER1 cpfsgt MIOS_PARAMETER1 rgoto pca9635_interpolate_NoSwap ;we just swap the values and invert the step counter ;using a temporary variable movff MIOS_PARAMETER1, pca9635_Temp movff MIOS_PARAMETER2, MIOS_PARAMETER1 movff pca9635_Temp, MIOS_PARAMETER2 ;invert the step counter and delete the upper nibble (for four bit counter) comf pca9635_StepCounter, F movlw 0x0f andwf pca9635_StepCounter, F pca9635_interpolate_NoSwap ;now find the difference between MIDI_PARAMETER1 and MIDI_PARAMETER2 ;load MIDI_PARAMETER1 into W movf MIOS_PARAMETER1, W ;subtract W from MIOS_PARAMETER2, store result in W subwf MIOS_PARAMETER2, W ;add 1 for rounding errors addlw 1 ;now divide this value by the number of steps ;because the next operation is a floating point 16bit calculaton, we leave it ;as it is and take away the decimals later ;to get the result in the upper byte PRODH, shift the step ;counter four to the left (for 4-bit counter) rlncf pca9635_StepCounter, F rlncf pca9635_StepCounter, F rlncf pca9635_StepCounter, F rlncf pca9635_StepCounter, F ;therefore, multiply the difference with the number of steps mulwf pca9635_StepCounter ;now we just need to get the high byte movf PRODH, W ;add the MIOS_PARAMETER1 (the low value) addwf MIOS_PARAMETER1, W return ; ========================================================================== END When I run the function, another array in my program gets values written into it, and I don't know why. Any tips for how to debug something like this? The array that gets written into is passed as the first parameter value (not the array, but one part of it, of course, like array ). Thanks, ALEXander.
  4. Hi, take a look at: http://www.midibox.org/forum/index.php/topic,11805.0.html
  5. Hi! Another thing that occured to me today: Is it possible/recommended to pass arrays as function parameters? I defined a struct like: typedef union { struct { unsigned char RED; unsigned char GREEN; unsigned char BLUE; }; struct { unsigned char COLOR[3]; }; } led_color_t; This way, if I pass this variable to a function, lets say void SetColor(led_color_t color); I can go through the three colors in a loop (color[0], color[1], color[2]), and do not have to adress them each on their own in the code. Is that a bright thing to do? If I try, I get a compiler warning: structure '_color' passed as function argument changed to pointer It seems that a pointer is passed instead of the variable, and it seems that this could be inefficient code. But actually I have no idea. Does anybody know whether this is recommended? I till stick to passing three unsigned chars red, green, blue until I know whether passing the array is a good idea. Thanks, ALEXander.
  6. Don't get me wrong, I looked at the matrix as well, I do not want to use it for my design. The question really is: Is 256 possible, or is it not due to some hardware limitation? Thanks! ALEXander.
  7. and if i do not want to two cores? Some tips? Pretty please?
  8. Hi! I was just wondering whether it is at all possible to get 256 DINs in MIOS, provided that: 1) I adjust the corresponding routines in mios_din.inc, mios_srio.inc etc. 2) I adjust the memory allocated in mios_defines.inc What I would like to know is whether there is any technical/hardware problem that would make it impossible to address 256 DINs, the timing of the interrupt routine for example. Would be happy for any help, ALEXander.
  9. Wow, I just discovered that the syx_dump is brandnew. Thanks TK for that, that is really just in time :) @Anakin, I successfully implemented the sysex transfer in my project. If you need it I did some encoding to send 8bit values over sysex (which can only use 7bit). You find it at http://www.midibox.org/forum/index.php/topic,10598.15.html. You can also ask me if you need the algorithm explained. Best, ALEXander.
  10. Here we go. Its largely based on the syx_dump example, but does some descrambling. The function you are interested in is SYSEX_Cmd_GetDataBytes. Comments on the efficiency and style of coding as always very welcome, I have very little experience in C and assembler. // $Id: sysex.c 441 2008-08-13 21:27:08Z tk $ /* * SysEx Parser Demo * see README.txt for details * * ========================================================================== * * Copyright (C) 2008 Thorsten Klose (tk@midibox.org) * Licensed for personal non-commercial use only. * All other rights reserved. * * ========================================================================== */ //wackazong: Differences to original //I use a format that has only one command byte (with the MSB = 0) and then //8bit data coded into 7bit values //The length of the message depends on the command byte ///////////////////////////////////////////////////////////////////////////// // Include files ///////////////////////////////////////////////////////////////////////////// #include <cmios.h> #include <sysex.h> #include <knoepfli.h> ///////////////////////////////////////////////////////////////////////////// // Internal Prototypes ///////////////////////////////////////////////////////////////////////////// void SYSEX_SendAck(unsigned char ack_code, unsigned char ack_arg); void SYSEX_CmdFinished(void); void SYSEX_SendFooter(unsigned char force); void SYSEX_Cmd(unsigned char cmd_state, unsigned char midi_in); void SYSEX_Cmd_GetDataBytes(unsigned char cmd_state, unsigned char midi_in); void SYSEX_Cmd_Ping(unsigned char cmd_state, unsigned char midi_in); ///////////////////////////////////////////////////////////////////////////// // Global Variables ///////////////////////////////////////////////////////////////////////////// sysex_state_t sysex_state; unsigned char sysex_cmd; unsigned char sysex_data_size; //size of the sysex data part in bytes unsigned char sysex_checksum; unsigned char sysex_received_checksum; unsigned int sysex_receive_ctr; //counts the number of sysex bytes received unsigned int sysex_data_receive_ctr; //counts the number of data bytes received (8bit) unsigned char sysex_bit_pointer; //for unscrambling, tells how many bits of the received 7 already belong to the next bit unsigned char sysex_buffer[8]; //8byte buffer containing the sysex message converted to 8bit format ///////////////////////////////////////////////////////////////////////////// // Static definitions ///////////////////////////////////////////////////////////////////////////// // should be changed for your own application // Headers used by MIDIbox applications are documented here: // http://svnmios.midibox.org/filedetails.php?repname=svn.mios&path=%2Ftrunk%2Fdoc%2FSYSEX_HEADERS // if you decide to use "F0 00 00 7E" prefix, please ensure that your // own ID (here: 0x7f) will be entered into this document. // Otherwise please use a different header const unsigned char sysex_header[] = { 0xf0, 0x00, 0x00, 0x7e, 0x7f }; ///////////////////////////////////////////////////////////////////////////// // This function initializes the SysEx handler ///////////////////////////////////////////////////////////////////////////// void SYSEX_Init(void) { sysex_state.ALL = 0; } ///////////////////////////////////////////////////////////////////////////// // This function parses an incoming sysex stream for SysEx messages ///////////////////////////////////////////////////////////////////////////// void SYSEX_Parser(unsigned char midi_in) { // ignore realtime messages (see MIDI spec - realtime messages can // always be injected into events/streams, and don't change the running status) if( midi_in >= 0xf8 ) return; // branch depending on state if( !sysex_state.MY_SYSEX ) { if( midi_in != sysex_header[sysex_state.CTR] ) { // incoming byte doesn't match SYSEX_CmdFinished(); } else { if( ++sysex_state.CTR == sizeof(sysex_header) ) { // complete header received, waiting for data sysex_state.MY_SYSEX = 1; // disable merger forwarding until end of sysex message MIOS_MPROC_MergerDisable(); } } } else { // check for end of SysEx message or invalid status byte if( midi_in >= 0x80 ) { if( midi_in == 0xf7 && sysex_state.CMD ) { SYSEX_Cmd(SYSEX_CMD_STATE_END, midi_in); } SYSEX_CmdFinished(); } else { // check if command byte has been received if( !sysex_state.CMD ) { sysex_state.CMD = 1; sysex_cmd = midi_in; SYSEX_Cmd(SYSEX_CMD_STATE_BEGIN, midi_in); } else SYSEX_Cmd(SYSEX_CMD_STATE_CONT, midi_in); } } } ///////////////////////////////////////////////////////////////////////////// // This function sends a SysEx acknowledge to notify the user about the received command // expects acknowledge code (e.g. 0x0f for good, 0x0e for error) and additional argument ///////////////////////////////////////////////////////////////////////////// void SYSEX_SendAck(unsigned char ack_code, unsigned char ack_arg) { int i; unsigned char checksum; unsigned char c; // send header for(i=0; i<sizeof(sysex_header); ++i) MIOS_MIDI_TxBufferPut(sysex_header[i]); // send ack code and argument MIOS_MIDI_TxBufferPut(ack_code); MIOS_MIDI_TxBufferPut(ack_arg); // send footer MIOS_MIDI_TxBufferPut(0xf7); } ///////////////////////////////////////////////////////////////////////////// // This function is called at the end of a sysex command or on // an invalid message ///////////////////////////////////////////////////////////////////////////// void SYSEX_CmdFinished(void) { // clear all status variables sysex_state.ALL = 0; sysex_cmd = 0; // enable MIDI forwarding again MIOS_MPROC_MergerEnable(); } ///////////////////////////////////////////////////////////////////////////// // This function sends the SysEx footer if merger enabled // if force == 1, send the footer regardless of merger state ///////////////////////////////////////////////////////////////////////////// void SYSEX_SendFooter(unsigned char force) { if( force || (MIOS_MIDI_MergerGet() & 0x01) ) MIOS_MIDI_TxBufferPut(0xf7); } ///////////////////////////////////////////////////////////////////////////// // This function handles the sysex commands ///////////////////////////////////////////////////////////////////////////// void SYSEX_Cmd(unsigned char cmd_state, unsigned char midi_in) { // enter the commands here switch( sysex_cmd ) { case 0x01: //set color of one LED sysex_data_size = 10; SYSEX_Cmd_GetDataBytes(cmd_state,midi_in); break; case 0x02: // break; case 0x0f: SYSEX_Cmd_Ping(cmd_state, midi_in); break; default: // unknown command SYSEX_SendFooter(0); SYSEX_SendAck(SYSEX_DISACK, SYSEX_DISACK_INVALID_COMMAND); SYSEX_CmdFinished(); } } ///////////////////////////////////////////////////////////////////////////// // Receive the data bytes of the command ///////////////////////////////////////////////////////////////////////////// void SYSEX_Cmd_GetDataBytes(unsigned char cmd_state, unsigned char midi_in) { int i; unsigned char tmp; switch( cmd_state ) { case SYSEX_CMD_STATE_BEGIN: sysex_checksum = 0; // clear checksum sysex_receive_ctr = 0; // clear byte counter sysex_data_receive_ctr = 0; sysex_received_checksum = 0; sysex_bit_pointer = 0; break; case SYSEX_CMD_STATE_CONT: if( sysex_receive_ctr < sysex_data_size ) { // add to checksum sysex_checksum += midi_in; //do some unscrambling //shift the midi_in one to the left, then the LSB is 0 and has no meaning midi_in <<= 1; //move the right bits over to the last buffer char for (i = 0; i < sysex_bit_pointer; ++i) { //set the bit to be changed to 0 //sysex_buffer[sysex_data_receive_ctr-1] & ~(0x01 << i); //it is zero anyway //isolate the bit to be set into tmp. Its always the MSB! tmp = midi_in & 0x80; //shift the bit to be set from midi_in to the right place tmp >>= (7-sysex_bit_pointer+i+1); //set the new bit value sysex_buffer[sysex_data_receive_ctr-1] |= tmp; //shift midi_in to the left, now the next bit we are interested in is again the MSB midi_in <<= 1; }; //store the received byte in the buffer sysex_buffer[sysex_data_receive_ctr] = midi_in; //increase the pointer if(sysex_bit_pointer==7) { sysex_bit_pointer = 0; } else { ++sysex_bit_pointer; ++sysex_data_receive_ctr; } #if SYSEX_CHECKSUM_PROTECTION } else if( sysex_receive_ctr == sysex_data_size ) { // store received checksum sysex_received_checksum = midi_in; #endif } else { // wait for F7 } // increment counter ++sysex_receive_ctr; break; default: // SYSEX_CMD_STATE_END SYSEX_SendFooter(0); #if SYSEX_CHECKSUM_PROTECTION //increase the sysex_data_size by the checksum byte ++sysex_data_size #endif //prepare here for new packet in the same sysex session. if( sysex_receive_ctr < sysex_data_size) { // not enough bytes received SYSEX_SendAck(SYSEX_DISACK, SYSEX_DISACK_LESS_BYTES_THAN_EXP); } else if( sysex_receive_ctr > sysex_data_size) { // too many bytes received SYSEX_SendAck(SYSEX_DISACK, SYSEX_DISACK_MORE_BYTES_THAN_EXP); #if SYSEX_CHECKSUM_PROTECTION } else if( sysex_received_checksum != ((sysex_checksum ^ 0xff) & 0x7f) ) { // notify that wrong checksum has been received SYSEX_SendAck(SYSEX_DISACK, SYSEX_DISACK_WRONG_CHECKSUM); #endif } else { // call the command as a function returning 0 or 1 depending on success // put your function where the 0 is if( 0 ) { // write failed (bankstick not available) SYSEX_SendAck(SYSEX_DISACK, SYSEX_DISACK_BS_NOT_AVAILABLE); } else { // notify that bytes have been received SYSEX_SendAck(SYSEX_ACK, 0x00); } } break; } } ///////////////////////////////////////////////////////////////////////////// // Command 0F: Ping (just send back acknowledge) ///////////////////////////////////////////////////////////////////////////// void SYSEX_Cmd_Ping(unsigned char cmd_state, unsigned char midi_in) { switch( cmd_state ) { case SYSEX_CMD_STATE_BEGIN: // nothing to do break; case SYSEX_CMD_STATE_CONT: // nothing to do break; default: // SYSEX_CMD_STATE_END SYSEX_SendFooter(0); // send acknowledge SYSEX_SendAck(SYSEX_ACK, 0x00); break; } }
  11. Yeah, I am using these right now, but I love to scramble :) I am almost finished with a descramble code in C, will post it here later.
  12. Hey Audiocommander, have you developed your C routines any further? I want to send some data to my core via sysex, and would love to not have to write my own scramble/descramble routine. Best, ALEXander.
  13. Hi, I think I mixed things up here: If you divide a difference by 16, you actually get 17 steps, including the step zero. So everything is correct, only the last step happens when the StepCounter reaches 16, not 15 (which is binary 1111 and is the highest value in 4 bits). If I want step 0 to be the minimum value and step 15 to be the maximum value, I will have to divide the difference by 15, not by 16 (which would be much more difficult, because then it is not a shift operation). So the solution seems like using one additional bit for the step counter, just for the value of 16. Or does anybody have a better idea? Thanks for the tips about the banked acces and the carry flag, I think I am starting to understand how the PIC works now. Best, ALEXander. PS: Illustration: Minvalue is 100, Maxvalue is 150, 16 is the number of steps 1) Divide 50 by 16 2) Add n times (50/16) to the min value, starting with n = 0 n=0 min value n=1 min value + step n=2 min value + 2*step ... n=15 min value + 15*step (which is not yet the max value!) n=16 max value!
  14. Hi, sorry, still having problems. This is my code, very similar to the code in MB64_POT_ScaleValue. ;; -------------------------------------------------------------------------- ;; FUNCTION: pca9635_Interpolate ;; C_DECLARATION: void ASM_Interpolate(unsigned char step, unsigned char val1, unsigned char val2) ;; DESCRIPTION: Testing the interpolation algorithm: interpolate between value 1 and value 2 in ;; 16 steps and return the corresponding step value. ;; ;; IN: 4bit step in WREG ;; 8bit value 1 in MIOS_PARAMETER1 ;; 8bit value 2 in MIOS_PARAMETER2 ;; ;; C IN: step number in step ;; value 1 in val1 ;; value 2 in val2 ;; ;; OUT: interpolated value in WREG ;; ;; C OUT: interpolated value as unsigned char ;; ;; USES: MIOS_PARAMETER3 ;; -------------------------------------------------------------------------- ;_pca9635_interpolate ; (for C) pca9635_interpolate #if _pca9635_def==1 ; note this is using the define from the fix in the asm file! incf _mod_skel_var, F, BANKED #endif ;save step value in variable movwf pca9635_StepCounter ;find out if we have to swap the values ;move MIOS_PARAMETER1 into W movf MIOS_PARAMETER2, W ;compare, skip the swap if MIOS_PARAMETER2 > MIOS_PARAMETER1 cpfsgt MIOS_PARAMETER1 rgoto pca9635_interpolate_NoSwap ;we just swap the values and invert the step counter ;using a temporary variable movff MIOS_PARAMETER1, pca9635_Temp movff MIOS_PARAMETER2, MIOS_PARAMETER1 movff pca9635_Temp, MIOS_PARAMETER2 ;invert the step counter and delete the upper nibble (for four bit counter) comf pca9635_StepCounter, F movlw 0x0f andwf pca9635_StepCounter, F pca9635_interpolate_NoSwap ;now find the difference between MIDI_PARAMETER1 and MIDI_PARAMETER2 ;load MIDI_PARAMETER1 into W movf MIOS_PARAMETER1, W ;subtract W from MIOS_PARAMETER2, store result in W subwf MIOS_PARAMETER2, W ;add 1 for rounding errors addlw 1 ;now divide this value by the number of steps ;because the next operation is a floating point 16bit calculaton, we leave it ;as it is and take away the decimals later ;to get the result in the upper byte PRODH, shift the step ;counter four to the left (for 4-bit counter) rlncf pca9635_StepCounter, F rlncf pca9635_StepCounter, F rlncf pca9635_StepCounter, F rlncf pca9635_StepCounter, F ;therefore, multiply the difference with the number of steps mulwf pca9635_StepCounter ;now we just need to get the high byte movf PRODH, W ;add the MIOS_PARAMETER1 (the low value) addwf MIOS_PARAMETER1, W ;test send the result call MIOS_MIDI_TxBufferPut return Essentially, I get the difference of the two values, and multiply them with a 4-bit step counter which is shifted 4 bits to the left. The result then is in PRODH. But the closer I come to the high value, the more inaccurate it gets: If the max value is 150, the min value is 100 and the step number is 15 (from 0-15 steps), then I get 147 and not 150. What did I do wrong? Thanks, ALEXander.
  15. OK, thanks. Am I going right with the assumption that in the code, W is 0, F is 1 and BANKED is 1, used as constants to increase readability? Best, ALEXander.
  16. Ah, see, that was occuring to me now, too. Thanks! I will check that out.
  17. I need some low level routines for blinking the LEDs, thats why I turned to assembler. @audiocommander: Thats what I did actually, I have a sdcc skeleton which relies on a mod_skel module for the low level routines driving the PCA9635 LED driver. I thought this would be the best way to implement it in a way that maybe also other people can use the PCA9635 driver. The whole thing compiles and works, but only if I take the mentioned line out of the code. I was just wondering about the double definition of the _<function> label, but now by what TK said its clear: 1) if the function passes only WREG, or no parameter, the label is in the mod_skel.inc. Logically it would make more sense to me to also put that in the wrapper, but by putting it in the .inc you can save one rgoto 2) if not, the label (and the wrapper code) is in the mod_skel.asm Thanks and best, ALEXander.
  18. WREG contains the first parameter value of the C function call, and it is returned correctly. I have a bytewise monitor installed, so it can't be the interpretation of the MIDI signal. I will try to send the value of WREG via assembler to see whats going on. BTW: I was just testing the whole functionality of mod-skel, its not really relevant for my program, and I know its not the best programming style, but you never know, it might come in handy.
  19. Yes you can. I have another program where I do exactly that. I will have a look at the headers again, maybe something ist missing there.
  20. Hello, using the sdcc sceleton and the mod_skel I made my own MIOS application (still pretty empty). I can now call an assembler function with multiple variables, and call a C function from assembler, but the C function called from assembler does not return to the assember code. Isn't "return" the correct statement to use? ///////////////////////////////////////////////////////////////////////////// // This function is called by pca9635 ///////////////////////////////////////////////////////////////////////////// void mod_skel_extfunc(unsigned char val1) __wparam { // Just a dummy empty function --mod_skel_var; MIOS_MIDI_TxBufferPut(val1); return; } The asm function looks as follows. The first call sends a MIDI Byte, then nothing more comes, not even the second call directly after the first. pca9635_interpolate #if _pca9635_def==1 ; note this is using the define from the fix in the asm file! incf _mod_skel_var, F, BANKED #endif call _mod_skel_extfunc call _mod_skel_extfunc movf MIOS_PARAMETER1, W call _mod_skel_extfunc movf MIOS_PARAMETER2, W call _mod_skel_extfunc return ALEXander.
  21. Since the _mod_skel_function is already defined in the wrapper, shouldn't the following line be taken out of the mod_skel.inc? ;; -------------------------------------------------------------------------- ;; FUNCTION: mod_skel ;; DESCRIPTION: mod_skel. does something stupid. Put your code in here instead. ;; ;; IN: - ;; OUT: - ;; USES: - mod_skel_var ;; -------------------------------------------------------------------------- THE NEXT LINE GENERATES A COMPILER ERROR _mod_skel_function ; (for C) mod_skel_function #if _pca9635_def==1 ; note this is using the define from the fix in the asm file! incf _mod_skel_var, F, BANKED #endif call _mod_skel_extfunc return
  22. Sorry, I do not completely get it. If b < a then for me, the algorithm does not work. example (d is decimal, b is binary): a is d3 b00000011 b is d15 b00001111 put the next value in prodh, differentiate two cases: 1) b-a+1 is d13 b00001101 2) a-b+1 is d245 b11110101 Now multiply i with prodh. Lets say i is an 8 bit value of 100 1) b00001101 * b01100100 = prodl contains b00010100 and prodh contains b00000101 this results in a final value of d8 (d5 of prodh plus the min d3 makes d8). is this correct? d100/d255 gives something like 0.39, mutiply this with 12 and you get 4.7, seems fair enough. 2) b11110101 * b01100100 = prodl contains b10110100 and prodh contains b01011111. This is wrong. What am I not getting (maybe I should go to bed?) What I want to do is this assembler function: I have to 8-bit values a and b, and need to linearly interpolate between these in 4, 5 or 6 bit steps (ie 16, 32 or 64 steps), the step number is given in i (which has 4, 5 or 6 bit) for example: a is 100 b is 187 example for 5-bit i if i is 0, then the result should be 100 if i is 63, then the result should be 187 if i is 23, then the result should be 131 And I cannot reproduce the above example. When I use an i with less bits, do I have to shift it left as well? and do I have to fill up the lower digits with 1 or 0? Any help is very much appreciated, thanks. ALEXander.
  23. OK, but three wires is better than 6, right? I have two other wires for I2C already, and I need to connect a lot of modules, therefore I think to reduce EMI and all that it would be good to keep wires to a minimum. How hard would it be to modify the DIN module to accept 256 inputs? Or is it not feasible due to some technical reason (interference, cable length, speed, ...)?
  24. Let me reply to myself: 4kB is too much for the data memory, it is only roughly 3kB. And the EEProm is only 1kB (I was just fixed on the 96kB program memory)... So I have the choice between Bankstick or access to the Flash Memory. Which one ist faster? I should have plenty of free flash available in the PIC18F4685, or shouldn't I? If yes, which address could I use to store my 4kB? Many thanks, ALEXander.
×
×
  • Create New...