Jump to content


  • Content Count

  • Joined

  • Last visited

Everything posted by davidb

  1. Pavel, See my post "eeprom.pic18.lib broken in V6.96" in Bug Reports. As you say, 16 bit eeprom addresses for PIC18 parts are supported in V6.96 with the eeprom library. The caveat here is that it will only work for those PIC18 parts that have more than 256 bytes of eeprom. This is because the hi byte of the eeprom address, eeadrh, does not exist in PIC18 parts that only have 256 bytes . If the current eeprom library is used for these then it will not link. Regards davidb
  2. Hi, A previous project using an 18F4520 compiled & linked OK with V6.96RC but no longer links with release version 6.96. The project uses eeprom.pic18.lib. Tried compiling with eeprom.c & eeprom.h but this fails due to the assumption in the latest versions that ALL PIC18 devices have >256 bytes of eeprom and therefore require a 16-bit address. The conditionals in eeprom.c & eeprom.h assume that ALL 18F parts have eeadrh defined and need a 16 bit address. This is not the case. Work around is to compile the project with modified versions of eeprom.c & eeprom.h instead of using eeprom.pic18.lib. Regards davidb
  3. Ian, I was only suggesting the possibility of trying the Duff principle of embedding a do-while within a switch for simply clearing your arrays, not necessarily the form shown in the example for copying using pointers. However, as you point out, it is academic anyway since SourceBoost won't compile it. I just had to try a simple example but the compiler expects a right parenthesis at the end of a case statement so a do-while cannot be spread across the switch. Nothing ventured nothing gained! Cheers davidb
  4. Ian, If you are experimenting with loop unrolling try using Tom Duffs 'Duffs Device' or its variants. Speed v ROM tradeoff. Cheers davidb
  5. Ian, OK, another clue - try making your count variable an unsigned short. Regards davidb
  6. Ian, Not enough time to look at it a properly but maybe a clue for you - If you restrict your buffer size to < 256 i.e. 255 then it seems to compile as you wanted. If the second buffer size is 256 then the second part seems to be optimised out as you say. Interestingly if you make the first buffer size 256 it then compiles both! Regards davidb
  7. This issue has been fixed in BoostC V6.96, certain debug information was missing from the coff (debug file) generated by BoostC linker. Regards Dave V6.96 RC seems to have fixed this issue in MPLAB and arrays in structures expand correctly (and automatically) but it still doesn't seem to work at all in the SB Debugger. e.g. entering test.array shows 0x0 'NUL' but test.array[0] just gives an error. davidb
  8. I am using: SourceBoost V6.95 MPLAB V8.30 Win XP PRO SP3 I have no problems seeing the members of a structure, its when one or more of those members is an array. Take the following simple example: struct { unsigned char array[10]; unsigned char byte_a; unsigned char byte_b; }test; When viewed using the watch window in MPLAB or SB dubugger the structure 'test' expands correctly to show the members byte_a and byte_b but array[] just appears as a normal char and does not expand any further so only the first element of this can be seen and modified. The generated code appears to work correctly and so only causes problems when debugging. MPLAB help shows the correct expansion with their own compilers. I am pretty sure this is an SB issue but haven't had time to prove it beyond all doubt. davidb
  9. Just discovered this problem myself and it is almost a year old with no answer. Can only see the first element of a char array within a structure in MPLAB watch window. Can't make any sense using the SourceBoost debugger either. Any solution apart from not using arrays in structures? Regards davidb
  10. Hi Pavel, Shortly after asking this question in January I moved it to Bug Reports and then as often happens I solved it myself - see reply on 17th Jan. You are right of course it does need administrator priviliges but what confused me was that goodies.exe ran without producing any error message e.g. cannot write, file read only or something along those lines. Thanks davidb
  11. Hi, IMHO, although not necessarily incorrect, your coding style is poor and makes finding errors more difficult. The cryptic compiler messages do give clues as to what the errors are and where they might be found: 1. If you change your style and indent your code you will immediately find several missing right paranthesis. 2. There should be // before the last 'test button pressed' comment. 3. count3 is mistyped as coun3t. Other than this I have no idea if your code does what you require. Correcting these errors should at least make your code compile so you can proceed. Good luck! Regards davidb
  12. Ok, I get that. But what is this memory location? Is there a way to get its address and use it? Thanks alot. I knew the simplest way, but I want to have button specific code in my button .c and .h files. So the second solution is use-able! I hoped there was a better solution than splitting the defines in port, and number. Just by using 1 define (e.g. #define button portc.5). I quess I'm making things to difficult for myself here. Baga How about: bit button_5 @0x007.5; davidb
  13. What do you want to know, speed or position ?? One of the key things here is you need to detect on which input the rising or falling edge occurs, to do this you need to keep the last states For position you would need the following (this is pseudo code to demonstrate the logic not real code):. A_rising_edge = (A_prev == 0 and A == 1); A_falling_edge = (A_prev == 1 and A == 0); B_rising_edge = (B_prev == 0 and B == 1); B_falling_edge = (B_prev == 1 and B == 0); A_prev = A; B_prev = B; if( A_rising_edge and B == 1 )then pos = pos + 1; if( B_rising_edge and A == 0 )then pos = pos + 1; if( A_rising_edge and B == 0 )then pos = pos - 1; if( B_rising_edge and A == 1 )then pos = pos - 1; I hope that helps. I have never actually done this, but I just worked through the logic Regards Dave If you are using the typical contact type encoder for user input then you will almost certainly need to apply debouncing to the inputs before saving the current state and comparing to the last state. Just look at the output of one of these on a scope and you will see that without debouncing you don't stand a chance of detecting anything sensible! davidb Regarding debouncing try Googling 'vertical counters' These can be used to efficiently debounce multiple inputs such as switches, push-buttons and encoders e.g. Define an array to create 2 bit (4 cycle) vertical counters - up to 8 inputs in this case i.e. unsigned char sw_data[4]; (INPUT, V_COUNT_A, V_COUNT_B, RESULT) Read your switch or encoder inputs by calling the following function every few mS. For manual input calling every 5mS - 10mS should still allow fast movement to be detected. Read the debounced result from sw_data[RESULT] void debounce_switch(void) { unsigned char delta; sw_data[INPUT]) = PORTB; // Read your noisy inputs sw_data[V_COUNT_A] ^= sw_data[V_COUNT_B]; // Increment the vertical counter sw_data[V_COUNT_B] = ~sw_data[V_COUNT_B]; // Increment the vertical counter sw_data[V_COUNT_B] &= delta = (sw_data[RESULT] ^ sw_data[INPUT]); // Reset the counter if no change has occurred sw_data[V_COUNT_A] &= delta; // Difference sw_data[RESULT] ^= (0xff ^ (sw_data[V_COUNT_B] | (sw_data[V_COUNT_A] | (0xff ^ delta)))); // Obtain debounced result } The above function is only shown as an example and believed to work but can almost certainly be optimised. Challenge for some one here! The code can be minimised by using assembler where the W reg can hold the delta results. Hope this helps! davidb
  14. What do you want to know, speed or position ?? One of the key things here is you need to detect on which input the rising or falling edge occurs, to do this you need to keep the last states For position you would need the following (this is pseudo code to demonstrate the logic not real code):. A_rising_edge = (A_prev == 0 and A == 1); A_falling_edge = (A_prev == 1 and A == 0); B_rising_edge = (B_prev == 0 and B == 1); B_falling_edge = (B_prev == 1 and B == 0); A_prev = A; B_prev = B; if( A_rising_edge and B == 1 )then pos = pos + 1; if( B_rising_edge and A == 0 )then pos = pos + 1; if( A_rising_edge and B == 0 )then pos = pos - 1; if( B_rising_edge and A == 1 )then pos = pos - 1; I hope that helps. I have never actually done this, but I just worked through the logic Regards Dave If you are using the typical contact type encoder for user input then you will almost certainly need to apply debouncing to the inputs before saving the current state and comparing to the last state. Just look at the output of one of these on a scope and you will see that without debouncing you don't stand a chance of detecting anything sensible! davidb
  15. Hi, To try and be consistent I have used the set_bit, clear_bit, toggle_bit and test_bit macros fairly extensively in most of my BoostC projects and apart from early versions which didn't work correctly above 8 bits I have had no problems. While checking the code generated for something else I noticed that the code was bloated when using test_bit compared to the normal if(a.n) form when being used on 16 bit fields. As an example the following shows the generated code for different ways of bit testing with 8 and 16 bit fields, although most would not be used in practice. I have commented the tests which generate more code than I would have expected. Using SourceBoostC V6.91 unsigned char a; unsigned short b; while( 1 ) 003A label1 009A 283A GOTO label1 { // Testing for TRUE on 8-bit bitfield // ================================== if(a.2) {nop();} 003A 1D23 BTFSS main_1_a,2 003B 283D GOTO label2 003C 0000 NOP 003D label2 if(a.2 != 0) {nop();} 003D 1D23 BTFSS main_1_a,2 003E 2840 GOTO label3 003F 0000 NOP 0040 label3 if(a.2 == 1) {nop();} 0040 1D23 BTFSS main_1_a,2 0041 2843 GOTO label4 0042 0000 NOP 0043 label4 if(test_bit(a,2)) {nop();} 0043 1D23 BTFSS main_1_a,2 0044 2846 GOTO label5 0045 0000 NOP 0046 label5 if(test_bit(a,2) != 0) {nop();} 0046 1D23 BTFSS main_1_a,2 0047 2849 GOTO label6 0048 0000 NOP 0049 label6 if(test_bit(a,2) == 1) {nop();} // Generates Bloated Code 0049 3004 MOVLW 0x04 004A 0523 ANDWF main_1_a, W 004B 00A6 MOVWF CompTempVar552 004C 0326 DECF CompTempVar552, W 004D 1D03 BTFSS STATUS,Z 004E 2850 GOTO label7 004F 0000 NOP 0050 label7 // Testing for FALSE on 8-bit bitfield // =================================== if(!a.2) {nop();} 0050 1923 BTFSC main_1_a,2 0051 2853 GOTO label8 0052 0000 NOP 0053 label8 if(a.2 == 0) {nop();} 0053 1923 BTFSC main_1_a,2 0054 2856 GOTO label9 0055 0000 NOP 0056 label9 if(!test_bit(a,2)) {nop();} 0056 1923 BTFSC main_1_a,2 0057 2859 GOTO label10 0058 0000 NOP 0059 label10 if(test_bit(a,2) == 0) {nop();} 0059 1923 BTFSC main_1_a,2 005A 285C GOTO label11 005B 0000 NOP 005C label11 // Testing for TRUE on 16-bit bitfield // =================================== if(b.2) {nop();} 005C 1D24 BTFSS main_1_b,2 005D 285F GOTO label12 005E 0000 NOP 005F label12 if(b.2 == 1) {nop();} 005F 1D24 BTFSS main_1_b,2 0060 2862 GOTO label13 0061 0000 NOP 0062 label13 if(b.2 != 0) {nop();} 0062 1D24 BTFSS main_1_b,2 0063 2865 GOTO label14 0064 0000 NOP 0065 label14 if(test_bit(b,2)) {nop();} 0065 1D24 BTFSS main_1_b,2 0066 2868 GOTO label15 0067 0000 NOP 0068 label15 if(test_bit(b,2) != 0) {nop();} // Generates Bloated Code 0068 3004 MOVLW 0x04 0069 0524 ANDWF main_1_b, W 006A 00A7 MOVWF CompTempVar554 006B 01A8 CLRF CompTempVar555 006C 08A7 MOVF CompTempVar554, F 006D 1D03 BTFSS STATUS,Z 006E 2872 GOTO label16 006F 08A8 MOVF CompTempVar555, F 0070 1903 BTFSC STATUS,Z 0071 2873 GOTO label17 0072 label16 0072 0000 NOP 0073 label17 if(test_bit(b,2) == 1) {nop();} // Generates Bloated Code 0073 3004 MOVLW 0x04 0074 0524 ANDWF main_1_b, W 0075 00A9 MOVWF CompTempVar556 0076 01AA CLRF CompTempVar557 0077 3001 MOVLW 0x01 0078 0629 XORWF CompTempVar556, W 0079 1903 BTFSC STATUS,Z 007A 082A MOVF CompTempVar557, W 007B 1D03 BTFSS STATUS,Z 007C 287E GOTO label18 007D 0000 NOP 007E label18 // Testing for FALSE on 16-bit bitfield // ==================================== if(!b.2) {nop();} 007E 1924 BTFSC main_1_b,2 007F 2881 GOTO label19 0080 0000 NOP 0081 label19 if(b.2 == 0) {nop();} 0081 1924 BTFSC main_1_b,2 0082 2884 GOTO label20 0083 0000 NOP 0084 label20 if(!test_bit(b,2)) {nop();} // Generates Bloated Code 0084 3004 MOVLW 0x04 0085 0524 ANDWF main_1_b, W 0086 00AB MOVWF CompTempVar560 0087 01AC CLRF CompTempVar561 0088 08AB MOVF CompTempVar560, F 0089 1D03 BTFSS STATUS,Z 008A 288F GOTO label21 008B 08AC MOVF CompTempVar561, F 008C 1D03 BTFSS STATUS,Z 008D 288F GOTO label21 008E 0000 NOP 008F label21 if(test_bit(b,2) == 0) {nop();} // Generates Bloated Code 008F 3004 MOVLW 0x04 0090 0524 ANDWF main_1_b, W 0091 00AD MOVWF CompTempVar562 0092 01AE CLRF CompTempVar563 0093 08AD MOVF CompTempVar562, F 0094 1D03 BTFSS STATUS,Z 0095 283A GOTO label1 0096 08AE MOVF CompTempVar563, F 0097 1D03 BTFSS STATUS,Z 0098 283A GOTO label1 0099 0000 NOP } } In an ideal world I would expect the test_bit macros to generate the same code as any test using the if(a.n) form. Dave, Pavel, anyone else want to comment? Many thanks davidb
  16. Did you run goodies second time after it was registered? When goodies is run to register no files get unpacked. You need to run goodies after registration to get everything unpacked. Regards, Pavel Pavel, Yes, I ran goodies.exe several times without success and then remembered that with Vista you either have to be specifically logged in with administrator privilages or use 'run as administrator' for many programs to work. Problem solved. Many thanks Davidb
  17. Goodies were designed to work under Vista. I just tried them on a Vista computer and they did register and unpacked without any problems. Remember you need to register them using either preg or command line argument 'registre' and after a successful registration run goodies again. They will unpack on this second run. Regards, Pavel Pavel, Thanks thats all I wanted to know. I did register goodies correctly and the program apparently runs successfully it's just that the source files aren't copied. I now need to delve into Vista to find out why it is not copying! Thanks again. Regards Davidb
  18. Hi, I have already posted this on the Novo forum but I believe that it might be better here as a bug. For my own convenience I am simply trying to move my Pro licensed, BoostC installation, V6.91, currently running on an XP Pro desktop, to an HP laptop running Vista. I know that Windows Vista is not on the recommended platform list for BoostC but it does seem to run perfectly well, although I haven't tried plug-ins as I don't normally use them. The problem I do have is in extracting the source files for Novo and other library functions. I have my key for goodies.exe and it registers successfully. When I run goodies.exe it gives an appropriate 'files successfully copied' message but the source files do not appear in either the Novo or libc directories as they do on the on the XP Pro machine. I am not sure if there are any other files that should also be extracted by goodies.exe. Is this a SourceBoost incompatibility with Vista, a hardware issue or just me being stupid? Anyone got goodies.exe working correctly on Vista? Any ideas? Many thanks davidb
  19. Hi, This is not specifically a Novo issue and I don't know if this is a problem with SourceBoost, Vista or me! I have a Pro license for BoostC and have been using it for quite a while and I also tried Novo briefly some time ago. I recently decided to try Novo more intensively and this has worked fine on my desktop PC running XPpro. For convenience I decided to move the whole SourceBoost package to my laptop running Vista. I installed a freshly downloaded copy of V6.91 and all seem to be fine at first, registration worked OK and goodies.exe stated that programs had been copied using my orginal Pro license usernames and keys. I tried compiling a few programs and everything seemed to be working correctly. Before deleting SourceBoost from the desktop PC I checked to see what files I needed to copy over e.g. C projects and custom Novo libraries that I had created. I then noticed that the novo source files was missing from the Novo directory on the laptop. Further investigation showed that the source files in libc were also missing. It seems that although goodies.exe says it has copied the files it doesn't actually do it! I have tried re-installing from my original CD and various other combinations but no matter what I do goodies.exe does not work although it says that everything has been successfully copied. I could obviously copy the current source files from the desktop PC but when there is a new version of SourceBoost these are likely to change so I would have to re-install SourceBoost on the desktop again. I have now uninstalled everything from the laptop but would still like to do the transfer eventually. Perhaps I need to clean out the registry as well. Before wasting any more time on this has anybody who has a Pro license and is running Vista managed to copy the Novo and libc source files using goodies.exe or is this a known problem? Many thanks davidb
  20. Dave, I knew it was something simple! I completely forgot about the need to extract the Novo source from 'goodies'. The files I have been trying to compile were from many versions ago. Works fine now. I must remember to run 'goodies' after every update. Thanks Dave Regards davidb
  21. I have a small test project running under Novo on a 16F887 using one of the supplied libraries and am very impressed with the operation and relative simplicity of coding. I want to add more tasks and generally increase the complexity of the project to see the limitations but I am having problems creating a new library. I assume I am doing something wrong with the compiler since a previously compiled obj file links OK and builds a library. I have tried various combinations of tasks and events as well as PIC16 or PIC18 targets and always get the same response. Here is the result using one of the supplied projects using SourceBoost V6.91RC3: "C:\Program Files\SourceBoost\boostc.pic16.exe" -W2 novolib_pic16t3e5ts1.c BoostC Optimizing C Compiler Version 6.91 (for PIC16 architecture) http://www.sourceboost.com Copyright© 2004-2008 Pavel Baranov Copyright© 2004-2008 David Hobday Licensed to Farn50598 under Single user Pro License for 1 node(s) Limitations: PIC12,PIC16 max code size:Unlimited, max RAM banks:Unlimited novolib_pic16t3e5ts1.c failure novo.c(529): error: failure Failed to locate output file 'novolib_pic16t3e5ts1.obj' Done Failed Always fails to compile and indicates an error at line 529 in novo.c whatever processor target, tasks or events are chosen. Fails with SourceBoost V6.90 as well. Am I missing something obvious? Any ideas? Many thanks davidb
  22. How little code were you expecting to generate? If you clear bit1 first and then only set it if gpio,4 is set but this will work but will also produce a zero glitch if gpio,4 is already set. If this doesn't matter in your code then you can save one instruction! Cheers davidb
  23. Try the following: bit bit1; test_bit(gpio, 4) ? bit1 = 1 : bit1 = 0; Less bloated now? Regards Davidb
  24. Hi all, I do exactly the same as Reynard. Since starting with embedded 16F PICs many moons ago (using assembler) I found the safest way was to always use port shadow registers. Using them means direct writes to a port must not be done if unexpected operation is to be avoided. All writes and port output status reads should be carried out via the shadow register. Many of my projects require multiple port pin changes that need to be synchronised with an event of some sort, either a timer, input edge or interrupt etc., so the shadow registers are typically changed in a number of places but are only copied to the port when the required event occurs. This is in addition to any instantaneous, single pin, updates that may also be required. Ians PickPack library is a neat way of implementing port shadow registers as the user doesn't have to worry about the shadow register itself. Unfortunately, it is not very code efficient if you need to change more than two pins at a time. More importantly, for me at least, it does not allow delayed or synchronised writes to the actual port. The way round this is to either do what I do and simply use shadow registers directly in the code or use the PickPack library and create some additional macros to do the job. I think the later is preferable, certainly for newbies, since it reduces the chance of errors. Just remember to use upper case for the port name! Typically a port may need initialising to a value. Rather than using a series of the clear_port(PORT,x) or set_port(PORT,x) instructions from the library simply do the whole lot in one go using the following macros: // Set a port to a value via the shadow register. e.g. set_port(PORTB, 0b00111100) #define set_port(port, value) \ port_shadow[port - PORTA] = value; port_array[port - PORTA] = port_shadow[port - PORTA]; // Clear a port via the shadow register. e.g. clear_port(PORTB) #define clear_port(port) \ port_shadow[port - PORTA] = 0; port_array[port - PORTA] = port_shadow[port - PORTA]; Rather than change the whole port in one go it is often required to change the state of a number of pins so we could use the following macro: // Change multiple port pins via the shadow register using a literal and port pin mask to select the pins to be changed // e.g. change_port_pins(PORTD, 0b00010011, 0b00011111) // Note that this is very useful but not so user friendly since the individual pins are not named #define change_port_pins(port, literal, mask) \ port_shadow[port - PORTA] ^= ((mask & 0xff) & (port_shadow[port - PORTA] ^ (literal & 0xff))); \ port_array[port - PORTA] = port_shadow[port - PORTA]; The rest of the macros allow a shadow register to be changed without writing the value directly to the port. The shadow register is copied to the port when required using another macro (below). First individual pins: // Set port shadow register pin. e.g. set_shadow_pin(PORTB,6); #define set_shadow_pin(port, pin) \ set_bit(port_shadow[port - PORTA], pin); // Clear port shadow register pin. e.g. clear_shadow_pin(PORTB,5); #define clear_shadow_pin(port, pin) \ clear_bit(port_shadow[port - PORTA], pin); // Toggle port shadow register pin. e.g. toggle_shadow_pin(PORTB,4); #define toggle_shadow_pin(port, pin) \ toggle_bit(port_shadow[port - PORTA], pin); Now for multiple pins: // Set port shadow register to a literal. e.g. set_shadow_port(PORTB, 0b00111100); #define set_shadow_port(port, value) \ port_shadow[port - PORTA] = value; // Clear port shadow register. e.g. clear_shadow_port(PORTB); #define clear_shadow_port(port) \ port_shadow[port - PORTA] = 0; // Change multiple pins in a port shadow register using a literal and a port pin mask to select bits to change // e.g. change_shadow_pins(PORTC, 0b00001100, 0b00001111) #define change_shadow_pins(port, literal, mask) \ port_shadow[port - PORTA] ^= ((mask & 0xff) & (port_shadow[port - PORTA] ^ (literal & 0xff))); The following macro simply copies the shadow register to the port output register as and when required: // Update port from shadow register. e.g. update_port(PORTC); #define update_port(port) \ port_array[port - PORTA] = port_shadow[port - PORTA]; The last macro is used to read a port pin value from the shadow register: // Test a port shadow register pin. e.g. test_shadow_pin(PORTB,3); #define test_shadow_pin(port, pin) \ ((port_shadow[port - PORTA] & (1 << pin)) != 0) Please note that I have not fully tested these macros and there may be errors, they are just offered as ideas at the moment. The advantage is that they work in a consistent way with Ians PickPack library. The disadvantage is that they now expose the user to the shadow register. Can they be improved or are there better ways? Perhaps they can be given more imaginative names? Perhaps Ian will consider adding them or similar macros to his library? Thoughts anyone? davidb
  25. Ian, Firstly, good work with your PICPAK and inspired use of the pre-processor. However, I would like to point out a bug in your pic_utils.h V1.2. Providing that PLATFORM_CLOCK has been defined then CLOCK_FREQ will always be set to 8000000 (last in the list). If you try to set PLATFORM_CLOCK to anything else then you get an error. This is because you have used #ifdef PLATFORM_CLOCK XXXXXXXXX for checking the clock speeds to set #pragma CLOCK_FREQ when I think you meant to use #if PLATFORM_CLOCK == XXXXXXXXX instead! When you do an update how about including 16MHz, 10MHz and 4MHz clocks and my current favorite target the 16F88X series. I have designed a few projects using them and wouldn't go back to the PIC16F87XA series. They have more and improved features, a better implementation of analogue port control, interrupt on change, etc. Code is easily ported and as a bonus they are less than half the price! Here's one that is currently working, at 9600 at least: #if PLATFORM_CLOCK == 16000000 #define SPBRG_9600 103 #define SPBRG_19200 51 #define SPBRG_57600 16 #define SPBRG_115200 8 #endif Regards davidb
  • Create New...