Jump to content


  • Content Count

  • Joined

  • Last visited

Community Reputation

0 Neutral

About twomers

  • Rank
  • Birthday 04/15/1986

Profile Information

  • Gender
  • Location
  • Interests
    Learning new things. <br />Doing things that interest me.
  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.
  • Create New...