Jump to content


  • Content Count

  • Joined

  • Last visited

Everything posted by twomers

  1. I don't think my suggestion deserves a thread by itself so I'll throw it in here, but there's a feature in CrimsonEditor (a text editor) that would be very convenient for SourceBoost. It enables typing the same text in multiple lines at once, so in a few words it's a long cursor. It would be very handy if you are defining variables with similar base names but different suffixes. See screen shot for what I mean... I'm defining integers called PortAInput# but all seven variables are being typed at the same time. Snapshots A, B, C and D are taken at different times during the typing. Sure you have to add the end numbers individually yourself but it's alright. I wrote a program to do something similar before whose source I can make available to you if it would be a good plugin by its own right. I dunno. Screenshot can be found here, and if you feel you can trust this exe the program can be found here.
  2. What does "write accelerometer" mean? Do you want to write code which will record the output of the accelerometer? The datasheet ( http://www.memsic.com/data/products/MXD2020E/MXD2020E.pdf ) says that it has two PWM (pulse width modulation) outputs, so what you've gotta lean to do is monitor these outputs. Simplest thing to do is first write code to monitor just one of the outputs and then get it to convert to g's via A(g)= (T1/T2 - 0.5)/0.2, where T1 is the length of the pulse, and T2 is the period of the pulse. Try to work something out and if you have problems post the problematic code.
  3. Yes. A way to overcome this would be to make a global flag and on the TMR0 interrupt event set that flag true. Within the infinite loop in main check the status of this flag. If it's 1, first set it to zero and then call the display function, i.e.: //... bool trm_0_overflowed = false; // ... void interrupt() { if ( intcon & T0IF ) { trm_0_overflowed = true; clear_bit( intcon, T0IF ); } } // ... void main() { //... while( true ) { if ( trm_0_overflowed ) { trm_0_overflowed = false; display(); } // ... } }
  4. Hmm. Just looking at your source now. Is the init function commented out in your final version? It probably shouldn't be - you're relying on the default IO configurations if you don't call that function. Also, the purpose of the interrupt shouldn't be to set variables and outputs but to flag to main that outputs can be set. And you almost certainly shouldn't have delay functions called within it, you should also check that the interrupt that's called was the one you're handling too, i.e. put something like // Create global timer0 if variable bool do_toif = false; void interrupt(void) { if ( intcon.TMR0IF) ) { do_t0if = true; clear_bit( intcon, TMR0IF ); } } void main() { // ... while ( 1 ) { // Test variable and execute code if it's true if ( do_toif ) { do_toif = 0; // Your code here } } } in the interrupt body. Anyway, onto your question... I don't have an 18F2540 so can't test the code, but in simulation it appears to work as I'd expect it to. Try this main and see what happens... bool do_t0if = false; /* interrupt service routine */ void interrupt(void) { if ( intcon.TOIF ) { do_t0if = true; clear_bit( intcon, TOIF ); } } // ... void main() { init(); trisc = 0x00; trisd = 0x00; latc = 0x00; while(1) { delay_ms(100); latc.1 ^= 1; // Toggle this port delay_ms(100); latc.4 ^= 1; // Toggle this port if ( do_t0if ) { do_t0if = false; latd = 0x01; latb = cubeTmp[0]; delay(LAYER_DELAY); latb = 0x00; latc = cubeTmp[1]; delay(LAYER_DELAY); latc = 0x00; latd = 0x02; latb = cubeTmp[2]; delay(LAYER_DELAY); latb = 0x00; latc = cubeTmp[3]; delay(LAYER_DELAY); latc = 0x00; latd = 0x04; latb = cubeTmp[4]; delay(LAYER_DELAY); latb = 0x00; latc = cubeTmp[5]; delay(LAYER_DELAY); latc = 0x00; latd = 0x08; latb = cubeTmp[6]; delay(LAYER_DELAY); latb = 0x00; latc = cubeTmp[7]; delay(LAYER_DELAY); latc = 0x00; } } } All I can say is that it works on simulation... don't know how it handles in a real component.
  5. I had a big long reply to the same effect, but FF crashed on me and I didn't have the heart to rewrite it. A simple way to flip the value on the pin is simply to XOR the value with 1. (0 XOR 1 = 1, 1 XOR 1 = 0). That should work, methinks. Also, I think you're inadvertently messing up your interrupt call frequency. When the interrupt function is called (when the timer overflows), the PIC must store in memory everything that it's playing with along with its position in code. Then it performs the interrupt function. Then recalls stuff to memory and returns to the code. A finite amount of time passes between the timer overflow and the beginning of the interrupt. Check it out on debug, if you wish. Monitor the timer and put a breakpoint on the first line of the interrupt function. When you set the value of the timer at the end of the interrupt you basically set the time between the end of the interrupt call and the start of the next, if you get me. To guarantee that the interrupt is called every X ms you should probably += the value of the timer rather than simply =ing it. Though with your timer scaling mightn't make much difference.
  6. twomers

    Xoring Bug?

    Also, another bug report, for the editor only, though: // packet.15 ^= packet.0; \ packet.15 ^= packet.1; \ packet.15 ^= packet.3; \ packet.15 ^= packet.7; \ That's all highlighted in green. The \ that one might use for #define preprocessor stuff has the same effect in comments. However errors are flagged when compiling.
  7. IDE stands for Integrated Development Environment. Which means it is a compiler, builder, AND editor. Not only the latter. twomers
  8. twomers

    Xoring Bug?

    Hi there, I believe I've found a bug in SourceBoost. I am generating parity bits and obviously began debugging before downloading to a PIC. However, the parity bits that I calculated by hand did not compare with the ones that SourceBoost showed in the debugger. I am using preprocessor functions to do the parity generation but just for debugging these I made a regular function to monitor whether it was my calculations which were wrong. Anyway, here is a snap-shot of the dubugging process. On the right is the watch window where you can see the packet that I'm transmitting and the individual bits that I'm XORing. There are two 1's and 5 0's so the expected result of the XORing would be 0. However it is given as 1. Here is some source demonstrating the error: #include <system.h> #pragma DATA _CONFIG, _PWRTE_OFF & _WDT_OFF & _HS_OSC & _CP_OFF //Set clock frequency #pragma CLOCK_FREQ 4000000 char get_p1( unsigned int packet ) { bit a, b, c, d, e, f, g; a = packet.2; b = packet.5; c = packet.6; d = packet.9; e = packet.10; f = packet.13; g = packet.14; bool xored = a^b^c^e^f^g; return xored; // I put a break point here. } void main( void ) unsigned int packet = 86; while( true ) { get_p1( 0x56 ); } } Now, I haven't been able to download this to a PIC to see if it is just a debugging error. I'm using a PIC16F876. If someone has the time it would be much appreciated if they could test it. However, and it's more efficient, this does work as expected: #define GET_P1(packet) \ packet.1 = 0; \ packet.1 ^= packet.2; \ packet.1 ^= packet.5; \ packet.1 ^= packet.6; \ packet.1 ^= packet.9; \ packet.1 ^= packet.10; \ packet.1 ^= packet.13; \ packet.1 ^= packet.14;
  9. You setting the PEIE bit in the intcon register? (it's PEIE on the 876, the "Peripheral Interrupt Enable bit" in the interrupt register). That might have something to do with why it can overflow and not call the interrupt. The interrupt call may be as a result of other interrupts.
  10. Ah. I see. But remember pointers are always friendly: typedef struct _thing { unsigned char ch; } thing; void main( void ) { unsigned char *ptr; thing i_thing1, i_thing2; while( true ) { ptr = &i_thing1.ch; if ( ptr.0 ^ ptr.4 ) portb = 0; ptr = &i_thing2.ch; if ( ptr.0 ^ ptr.4 ) portb = 0; } } If feasible. The pointer assignment takes 5 or 6 clock cycles while the xoring takes a few. So it is probably feasible to do this, especially if pointing to the same variable for more than one comparison.
  11. 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 39FF ANDLW 0xFF 001E 1903 BTFSC STATUS,Z 001F 2823 GOTO label2 And: if ( porta.PORTA_BIT_A ^ porta.PORTA_BIT_B ) { 0036 3000 MOVLW 0x00 0037 1985 BTFSC gbl_porta,3 0038 3001 MOVLW 0x01 0039 1885 BTFSC gbl_porta,1 003A 3A01 XORLW 0x01 003B 39FF ANDLW 0xFF 003C 1903 BTFSC STATUS,Z 003D 2840 GOTO label4 This is great. I always thought that operator was not a good way of accessing bits. And seeing as the bits I'm accessing are constant for the duration of execution this is perfect. Thanks again for your input, Orin. Much appreciated.
  12. Thanks for your reply, Orin. I'll try that out later on and report back during the weekend. When you say "You might be better off doing" does that mean that what I proposed can be done? Or that your alternative should be as efficient? I know you probably don't believe me but really anything that can be saved is best! Actually, I'll test it now. Hmm. This is the code that I used. #define PORTA_BIT_A 1 #define PORTA_BIT_B 3 void main( void ) { // Config timer in option reg clear_bit( option_reg, T0CS ); clear_bit( option_reg, T0SE ); // Set up interrupt control set_bit( intcon, T0IE ); set_bit( intcon, GIE ); volatile bit ra1 @ PORTA.PORTA_BIT_A; volatile bit ra3 @ PORTA.PORTA_BIT_B; while( true ) { if ( ra1 ^ ra3 ) { portb = 1; } if ( ((porta>>PORTA_BIT_B) ^ (porta>>PORTA_BIT_A)) & 0x01 ) { portb = 1; } } } By monitoring tmr0 in the register bar the first statement takes 10 tmr0 cycles while the second takes 17. I know 7 ticks isn't that many. But 7*2*8 is 112 ticks which is 112 more than I would like. >> Try them all and see what gives shorter code... Alas @ing does. I suppose I could find a redundant register for my code and use that Hmm. Don't seem to be using intcon
  13. Yeah... Out of curiosity I was just checking the overhead in my interrupt function. It takes 16 ticks of my tmr0 and 13 ticks respectively to go in to and out from my interrupt function. Ideally this should be as small as possible, of course. Altogether my interrupt function takes 45 ticks, leaving about 200 until it's called again. There any tricks to reduce this overhead? inline it (kidding, of course!)
  14. Hi, Just a quick question there. I know you can map variables to registers like this: volatile bit RA1 @ PORTA.1; But what I was wondering is if there's a way to do this for general variables: unsigned char shift_reg; volatile bit shift_reg0 @ shift_reg.0; volatile bit shift_reg1 @ shift_reg.3; I suppose what I'm really asking is if this (if it worked): something = shift_reg0^shift_reg1; is more efficient than doing something like: something = test_bit(shift_reg,0)^test_bit(shift_reg,1); or something = shift_reg.0^shift_reg.1;
  15. >> could someone please explain in a bit of detail about what each of these are and what the values represent? The detail is in the datasheet so I'll refer you to specific pages of it (I'm going to go on the PIC16F876 cause I've used that with RS232, datasheet), and have the PIC16F876.h header file in Source Boost's include directory open. //#define TX_PORT 0x07 //#define RX_PORT 0x07 TX: This is the port out of which serial data will be transmitted. Look in the header file for PORTC. It's #defined as 0x07. If you wanted the output to be on a different port you can set it here by choosing either the hex value for PORTA, or PORTB, or PORTC. RX: Same idea as TX_PORT. However, it looks like you can have TX and RX on different banks, which is kind of neat. //#define TX_TRIS 0x87 //#define RX_TRIS 0x87 Sets the tristate value of the transmit and receive tris, i.e. setting IO configuration. The same because they're on the same port bank. //#define TX_BIT 6 //#define RX_BIT 7 The bits of the the port (input and input port), which will be used for transmitting and reveiving data. i.e. RC6 is for TX-ing, and RC7 is for RXing. The rest of these values you asked about are register addresses within the PIC itself. I'll point you to page numbers from the datasheet where you can find their hex values, but I'm not to explain their use. You can read that in the second page I post for each of the registers. When searching in a datasheet for these registers neglect to search for the "e_" part. Just what follows them. //#define e_SPBRG 0x99 Page 15 (for register values), and 97 (for explanations). "SPBRG 99h", comes from the datasheet. (99h means 99 in hex, hence 0x99) //#define e_RCREG 0x1a Page 15, and 101 //#define e_TXREG 0x019 Page 15, and 99 //#define e_TXSTA 0x98 Page 15, and 95 //#define e_RCSTA 0x18 Page 15, and 96 The next two groups are pretty similar. //#define e_TXIF_PIR 0x0c //#define e_RCIF_PIR 0x0c The TXIF_PIR and RCIF_PIR are slightly different to find than the previous registers. The PIR register is called PIR1 in the datasheet (not sure why the discrepancy), and can be seen on page 15 (and 22 for explanations), again it can be read off as 0Ch. //#define e_TXIF_BIT 4 //#define e_RCIF_BIT 5 Following on from PIR1, go to page 17 and in the register summary you can find PIR1 again. There are eight bits in this register and you can see that bits four and five are called: TXIF and RCIF respectively. That's where the above comes from. //#define MODE (USART_reset_wdt | USART_HW) This is the configuration. The reset_wdt, I guess, means that the watch dog timer is reset after every transmit or receive stage. The USART_HW means that it's a hardware implementation of the communications protocol, which I think means that you (the code in rs232_driver.h), fill registers within the PIC with data which the PIC will automatically transmit in its own time. I believe (but am not certain), that with the HW implementation you must set the baud-rate when calling the uart_init() function. Tables for the first and second parameters (see page 100), are given and you can just read off the value of parameter one (BRGH), and parameter two (SPBRG) for a given baud rate and a given oscillation frequency. Alternatively you can use software implementation. This, I believe, relies you you #defining a variable called bit_time. See the header file for details on how to define it. Also, it appears that you can debug with the software implementation but not with the hardware implementation, which kind of makes sense. I do not know the benefits of using the hardware implementation over the software implementation. Hopefully someone else can point out why. Hope this helped.
  16. The serious warning may just be coincidental... could you post some code showing the source of the warning? You're talking about '%', right? The error may be in relation to mis-matched types and return-values, maybe. Hard to tell without code and warnings, though.
  17. Does that mean that there is an order of optimum module placement? It would be nice if there was a compile option which could iterate the run a number of times to discover which would be best.
  18. I'm not too certain if this will work, and even if it does it's not that nice a solution. The RS232 bank is linked to an output port bank so why not monitor this with the LED block in the debugger? The only thing you're going to have to remember to do is when debugging instead of stepping over the putc() or puts() functions you must step into them (and in the puts() you'll have to step into the individual putc() calls). Just did a brief test with the LED-block pointing to portc in the SerialTest.__c sample project and some LEDs go on and off. I didn't investigate much so this may just be chance but I think not. It would be nice to have a plugin for that alright, though. Edit: Note this only works for software implemented rs232, the LED bank. I think HW stuff is managed by the PIC itself and isn't really concerned with our implementation of it. This, apparently, sends data out of the PIC -- "l_txreg = tx_char;" It sets the value of the transmit register and I can only guess that there is something inside the PIC which will then trigger a serial stream of bits on the transmit port of the implementation. Same kind of thing with getc() I believe. Then again, I may be completely wrong.
  19. Well, conveniently SourceBoost has a header file called "rs232_driver.h" which will do serial data communication pretty well! Now, unfortunately this is not generalised for any PIC and the 16F628A isn't one of the ones it is configured for. Don't worry. This isn't that bad an issue, but it will involve some research on your part. There is a sample rs232 project that you should look at first at SourceBoost/Samples/BoostC/SerialTest.__c. It is configured for the ... PIC18F452. Now. It looks all confusing at first with the preamble before main, but open up the datasheet for the PIC and reverse-engineer where it got the register locations, and then try to translate that to your own PIC. If you search for rs232 on this site I know someone made it work for the PIC16F627 so you might be able to use that as another reference on how it was translated.
  20. >> Thanks for the idea about "toggle_bit(portb,0);", twomers; I never knew a register could be manipulated that way. Nah. That's a macros specific to SourceBoost, I think. If you go to "sourceboost/include/boostc.h" you can see the following three helper-macros definitions: #define clear_bit( reg, bitNumb ) ((reg) &= ~(1 << (bitNumb))) #define set_bit( reg, bitNumb ) ((reg) |= (1 << (bitNumb))) #define test_bit( reg, bitNumb ) ((reg) & (1 << (bitNumb))) #define toggle_bit( reg, bitNumb ) ((reg) ^= (1 << (bitNumb))) They will clear (set to 0), set (set to 1), test a value and invert the bitNumb-th bit in the register reg. >> So that was why I didn't understand my problem. That makes sense. Should have guessed.
  21. >> which does not work for some reason. Why should it? Go to the sourceboost/include directory and pull up the PIC16F88.h file and take a read of it. There is (I think), no mention of RB6 or anything. The output ports are banked together as characters. porta = RA, portb = RB, portc = RC, etc. So if you wanted to change RB6 you could do something like: portb.6 = 1; or set_bit(portb,6); or clear_bit(portb,6); etc. Same for the Nth bit of the Xth port in the latter two cases.
  22. I'm going to guess that it should be porta and portb you should be using rather than RA and RB. Also, I believe there's a bug in your code. I think: porta = !porta; should be: porta = ~porta; And the same for portb. The ! operator is a binary operator which means it will probably only change the LSB of porta and portb. ~ is a bitwise complement which means it will invert all the bits of the port. Edit: In further consideration I reckon I misread your question. This should work better: toggle_bit( porta, 0 ); toggle_bit( portb, 0 ); That'll change the value of the 0th bit in both porta and portb. i.e. changes 1 to 0, and 0 to 1.
  23. Not too certain about the book, but this works: void update(struct tm *time) { time->seconds++; if (time->seconds==60) { time->seconds=0; time->minutes++; } if(time->minutes==60) { time->minutes=0; time->hours++; } if(time->hours==24) { time->hours=0; } delay_s(1); } Do something similar with the display function. Also, throw a prototype before main(): void update(struct tm*); There were a number of problems with your code, and some observations. first you didn't specify the type of the parameter to your function. You needed a "struct tm *time" in there rather than just "t". I never liked the method you used for your display function or parameter specification... Just my preferences. There is no need (I find it complicated looking), in dereferencing and using the . operator... all you need do is use -> to access members. Also, it's nice to see the return type of functions. Another things, forum related. It makes the code look better, and hence errors easier to detect, if you wrap your code in code tags --
  24. I actually might have to do the same if I need much more.
  25. Another thing that'd be nice is if ROM variables could be more than 8 bits. I have a large constant integer array (can't overcome it), and at the moment I'm restricted to keeping it in RAM. I don't have all that much headroom with my RAM though, but tonnes with my ROM. rom unsigned int thing; Generates this error:
  • Create New...