# Orin

EstablishedMember

55

0 Neutral

• Rank
Regular
1. ## Assembly Moving Average Algorithm Pic18f4550

I have done some test with a spreadsheet. Round off error is indeed a problem. Scaling the values up by a couple of powers of 2 may solve this problem. Most of the math is 16 bit and I would like it to work well for 10 bit a to d. More info when I look into it some more. The division is by 8 not 7 so the shift is fine, but for the loss of bits off the right hand end. I almost suggested this method in my original reply. It's a filter of the form: Filtered value = (New value * p) + ((1-p)*Filtered Value) where 0 < p < 1. The suggested filter has p = 1/8. It sca
2. ## Assembly Moving Average Algorithm Pic18f4550

I wouldn't recompute the total each time. I'd do the following: /* Zero nTotMagX and xMagArray at program initialization */ nTotMagX -= aMagXArray[nPos]; /* remove oldest value from sum */ aMagXArray[nPos] = SensorMagX; /* save new value */ nTotMagX += SensorMagX; /* add new value to sum */ nPos = (nPos + 1) & 7; nMagXAveragedValue = nTotMagX / 8; This does assume you have enough RAM for the extra global variables, nTotMagX (and nTotMagY). If you wanted to use a pointer instead of nPos to step through the array: /* Program initialization */ int *pOldestM
3. ## Typedef For Volatile

MS VC6 lets me do: typedef volatile unsigned char vuchar; vuchar c = 1; without complaint, so I don't see why not. Orin.
4. ## "for" Loop Infinite

If you want an infinite loop, you should use for ( ; ; ) { }. while ( 1 ) { } will generate warnings with some compilers. FWIW, the sematics of the for loop are as follows: for ( expression1; expression2; expression3 ) statement means: #ifdef SOME_VERSIONS_OF_C_PLUSPLUS { #endif expression1; while ( expression2 ) { statement; expression3; } #ifdef SOME_VERSIONS_OF_C_PLUSPLUS } #endif If expression2 is empty, it's taken to be true. The surrounding braces are due to the scope of variables declared in "expression1" (it's not just an expression in C++). For exa
5. ## Interrupts ! They Are Driving Me Nuts !

There is nothing wrong with doing all your work in an interrupt routine and have your main routine simply sleep waiting for an interrupt if there is no 'background' processing to do. For this particular code: sleep() should be in an infinite loop. You shouldn't touch GIE in the interrupt routine as it's reset by the interrupt logic and set by the return from the interrupt routine. Orin. On further thought, there is a major problem with the original code: sleep() will disable the clock to the timer, so the timer interrupt will never occur while asleep. So, you should
6. ## Interrupts ! They Are Driving Me Nuts !

There is nothing wrong with doing all your work in an interrupt routine and have your main routine simply sleep waiting for an interrupt if there is no 'background' processing to do. For this particular code: sleep() should be in an infinite loop. You shouldn't touch GIE in the interrupt routine as it's reset by the interrupt logic and set by the return from the interrupt routine. Orin.
7. ## Bug With If Statement Comparing To Two Added Constants

You are quite right. We just started looking at this problem and it happens exactly as you described. We'll check if it can get fixed. Even though sum was promoted by compiler the resulting code should work. Can you please point where you think wrong code was generated. Regards, Pavel Hi Pavel This is the bad code , result will always end up set to NO_FRUIT // TWO #defined constants if(result >= (APPLES + PEARS)) 0004 0E13 MOVLW 0x13 0006 84D8 BSF STATUS,Z 0008 6001 CPFSLT gbl_result 000A B4D8 BTFSC STATUS,Z 000C D001 BRA label1 000E D002 BRA label2 00

9. ## Interfacing To Power Lines

I agree. What the ap note fails to mention is that for the method to work, the power line neutral would need connecting to the PIC's ground line. Expect that someone somewhere will get the hot and neutral lines crossed - the circuit ground is now at 120V or worse...
10. ## Structure Members Passed Incorrectly By Reference

Works fine if you remove the inline from "inline void GetValueInline(char& c) { setTo12©; }" so the problem is passing a reference to a structure to an inline function. Note that neither the address of a or the address of b are passed in any case. Call by reference is implemented by copying the variable to the function parameter, then copying the function parameter back to the variable when the function returns. Indeed, in the 'inline' case, it is msg.a that is copied/restored rather than msg.b. Orin.
11. ## Uneven Bit Durations

Try the following: char shadowA; shadowA = porta; shadowA.0 = 0; if ( packet.0 ) shadowA.0 = 1; porta = shadowA; Or even: asm { movf _porta, W // repeat per bit andlw 0xFE btfsc _packet, 0 iorlw 0x01 movwf _porta // } BTW, all bets are off if the variable 'packet' isn't in the same bank as porta as the compiler will insert bank switching code. Yes, the assembly code is a slow read - modify - write of porta. Remember bsf and bcf on porta are implemented in the PIC hardware as read-modify-write so there's no real difference. Orin.
12. ## Uneven Bit Durations

I couldn't agree more. In addition, to do what was suggested would penalise those who require the fastest overall execution speed. Not to mention for a non volatile destination, there's nothing wrong with the compiler implementing the assignment as: dest = 0; if ( src.0 ) dest = 1; // and so on You could spend hours tinkering with the C to get the compiler to produce the code you want and the timings you want only to have the next version of the compiler do something slightly differently and break your code. So, if you want precise timings, you absolutely have to use asse
13. ## Xoring Bug?

It would appear that a^b^c^e^f^g is compiling to something like ( a^b ) |c|e|f|g. Orin.
14. ## Mapping To Bit Number

Heh. I was just about to post solution! For me this now operates at 12 cycles (while the @ing is now 9 for some reason), so it reduces it by a deascent amount! Assuming the B value is greater than the A value is fine. That's not a restriction or anything. In fact this: if ( porta.PORTA_BIT_A ^ porta.PORTA_BIT_B ) { portb = 1; } Performs as well as the @ operator... I must have mis-read my code when I analysed it before: if ( ra1 ^ ra3 ) { 0018 3000 MOVLW 0x00 0019 1985 BTFSC main_1_ra3,3 001A 3001 MOVLW 0x01 001B 1885 BTFSC main_1_ra1,1 001C 3A01 XORLW 0x01 001D 3
15. ## Mapping To Bit Number

Actually, I wasn't commenting on whether your proposal worked or not, just adding another alternative. Try: if ( ((porta>>(PORTA_BIT_B-PORTA_BIT_A)) ^ porta) & (0x01<<PORTA_BIT_A) ) { portb = 1; } It shifts porta such that the bits of interest overlap, xors them together and tests the overlapping bit. It does assume that PORTA_BIT_B > PORTA_BIT_A... It only does two shifts rather than 4, a saving of 4 ticks for the shifts alone. It might avoid a second temporary variable and load/store for additional savings. This method will only work for bits that ar
×