Bit Angle Modulation (BAM) in a PIC


Results 1 to 40 of 151

Threaded View

  1. #11
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default

    Hi Darrel,

    May I pass along my late congrats' on some brilliant work and share a couple ideas?

    Instead of using six instructions (6 cycles) per LED during each update interval you might consider updating one port at a time using an exclusive-or instruction (2 cycles) and data from an eight byte "toggle" array that's refreshed during that long 64T end-of-period interval. This reduces overhead from 288 cycles for 48 LEDs to just 12 cycles during each update interval. Using "toggle" data and an exclusive-or instruction lets us update MIBAM output bits without changing non-MIBAM bits on each port.

    Since the three '1T' intervals seem to be a major bottleneck we might consider combining the center |2T|1T|1T|1T|2T| intervals into a single '7T' interval and use small in-line isochronous delays to effect precise timing between updates. This would practically eliminate "overhead" effects on the center three '1T' intervals.

    Here's a pseudo C code driver example (sorry, I don't have PBP). I'm sure you realize that the "switch" function should be replaced with assembly language to reduce overhead and eliminate jitter and that the LEDs and "data benders" should probably be setup as macros as you did in your driver.

    An assembly language version I wrote supports 48 LEDs at decent refresh rates at almost any clock (4-MHz, 177 Hz, 1T = 22-usecs).

    Food for thought. Kind regards, Mike, K8LH

    Code:
    unsigned char interval = 0;     // ISR state machine var'
    
    unsigned char red = 44;
    unsigned char grn = 55;
    unsigned char blu = 66;
    
    volatile unsigned short ccpr1 @ 0xFBE;
    
    /*                                                                  *
     *  original intervals -> |64|32|16|8|4|2|1|1|1|2|4|8|16|32|64|     *
     *  modified intervals -> |64|32|16|8|4|----7----|4|8|16|32|64|     *
     *                                                                  */
    void interrupt()                // CCP1 "special event" interrupts
    { unsigned char Adat[8];        // porta "toggle" array
      unsigned char Bdat[8];        // portb "toggle" array
      pir1.CCP1IF = 0;              // clear CCP1 interrupt flag
      switch(interval++)            //
      { case 0:                     // 64T
          porta ^= Adat[7];         //
          portb ^= Bdat[7];         //
          ccpr1 = (64*tStep);       // ccpr1 = half 2^7 (64T)
          break;                    //
        case 1:                     // 32T
          porta ^= Adat[6];         //
          portb ^= Bdat[6];         //
          ccpr1 >>= 1;              // ccpr1 = half 2^6 (32T)
          break;                    //
        case 2:                     // 16T
          porta ^= Adat[5];         //
          portb ^= Bdat[5];         //
          ccpr1 >>= 1;              // ccpr1 = half 2^5 (16T)
          break;                    //
        case 3:                     // 8T
          porta ^= Adat[4];         //
          portb ^= Bdat[4];         //
          ccpr1 >>= 1;              // ccpr1 = half 2^4 (8T)
          break;                    //
        case 4:                     // 4T
          porta ^= Adat[3];         //
          portb ^= Bdat[3];         //
          ccpr1 >>= 1;              // ccpr1 = half 2^3 (4T)
          break;                    //
        case 5:                     // 7T (2T+1T+1T+1T+2T)
          porta ^= Adat[2];         //
          portb ^= Bdat[2];         //
          ccpr1 = (7*tStep);        // ccpr1 = 7*tStep  (7T)
          delayCy(2*tStep-8);       // 2T minus 8 cycles
          porta ^= Adat[1];         //
          portb ^= Bdat[1];         //
          delayCy(1*tStep-4);       // 1T minus 4 cycles
          porta ^= Adat[0];         //
          portb ^= Bdat[0];         //
          delayCy(1*tStep-4);       // 1T minus 4 cycles
          porta ^= Adat[0];         //
          portb ^= Bdat[0];         //
          delayCy(1*tStep-4);       // 1T minus 4 cycles
          porta ^= Adat[1];         //
          portb ^= Bdat[1];         //
          break;                    //
        case 6:                     // 4T
          porta ^= Adat[2];         //
          portb ^= Bdat[2];         //
          ccpr1 = (4*tStep);        // ccpr1 = half 2^3 (4T)
          break;                    //
        case 7:                     // 8T
          porta ^= Adat[3];         //
          portb ^= Bdat[3];         //
          ccpr1 <<= 1;              // ccpr1 = half 2^4 (8T)
          break;                    //
        case 8:                     // 16T
          porta ^= Adat[4];         //
          portb ^= Bdat[4];         //
          ccpr1 <<= 1;              // ccpr1 = half 2^5 (16T)
          break;                    //
        case 9:                     // 32T
          porta ^= Adat[5];         //
          portb ^= Bdat[5];         //
          ccpr1 <<= 1;              // ccpr1 = half 2^6 (32T)
          break;                    //
        case 10:                    // 64T (end-of-period)
          porta ^= Adat[6];         //
          portb ^= Bdat[6];         //
          ccpr1 <<= 1;              // ccpr1 = half 2^7 (64T)
          interval = 0;             // prep for new period
          Adat[0] = 0; Adat[1] = 0; // clear Adat[] array
          Adat[2] = 0; Adat[3] = 0; //
          Adat[4] = 0; Adat[5] = 0; //
          Adat[6] = 0; Adat[7] = 0; //
          Bdat[0] = 0; Bdat[1] = 0; // clear Bdat[] array
          Bdat[2] = 0; Bdat[3] = 0; //
          Bdat[4] = 0; Bdat[5] = 0; //
          Bdat[6] = 0; Bdat[7] = 0; //
    /*                                                                  *
     *  use one "data bender" for each LED (16 cycles each)             *
     *                                                                  */
          if(red.0) Bdat[0] |= 1;   // 2^0 data RB0 pin
          if(red.1) Bdat[1] |= 1;   // 2^1 data RB0 pin
          if(red.2) Bdat[2] |= 1;   // 2^2 data RB0 pin
          if(red.3) Bdat[3] |= 1;   // 2^3 data RB0 pin
          if(red.4) Bdat[4] |= 1;   // 2^4 data RB0 pin
          if(red.5) Bdat[5] |= 1;   // 2^5 data RB0 pin
          if(red.6) Bdat[6] |= 1;   // 2^6 data RB0 pin
          if(red.7) Bdat[7] |= 1;   // 2^7 data RB0 pin
    
          if(grn.0) Bdat[0] |= 2;   // 2^0 data RB1 pin
          if(grn.1) Bdat[1] |= 2;   // 2^1 data RB1 pin
          if(grn.2) Bdat[2] |= 2;   // 2^2 data RB1 pin
          if(grn.3) Bdat[3] |= 2;   // 2^3 data RB1 pin
          if(grn.4) Bdat[4] |= 2;   // 2^4 data RB1 pin
          if(grn.5) Bdat[5] |= 2;   // 2^5 data RB1 pin
          if(grn.6) Bdat[6] |= 2;   // 2^6 data RB1 pin
          if(grn.7) Bdat[7] |= 2;   // 2^7 data RB1 pin
    
          if(blu.0) Bdat[0] |= 4;   // 2^0 data RB2 pin
          if(blu.1) Bdat[1] |= 4;   // 2^1 data RB2 pin
          if(blu.2) Bdat[2] |= 4;   // 2^2 data RB2 pin
          if(blu.3) Bdat[3] |= 4;   // 2^3 data RB2 pin
          if(blu.4) Bdat[4] |= 4;   // 2^4 data RB2 pin
          if(blu.5) Bdat[5] |= 4;   // 2^5 data RB2 pin
          if(blu.6) Bdat[6] |= 4;   // 2^6 data RB2 pin
          if(blu.7) Bdat[7] |= 4;   // 2^7 data RB2 pin
    /*                                                                  *
     *  convert Bdat[] and Adat[] array "output" data to "toggle" data  *
     *                                                                  *
     *  red  0x2C 00101100 (on RB0)                                     *
     *  grn  0x37 00110111 (on RB1)                                     *
     *  blu  0x42 01000010 (on RB2)                                     *
     *                                                                  *
     *  Bdat 'output data'   Bdat 'toggle data'   Bdat 'toggle data'    *
     *   [0] 0x02 00000010    [0] 0x04 00000100    [0] 0x04 00000100    *
     *   [1] 0x06 00000110    [1] 0x05 00000101    [1] 0x05 00000101    *
     *   [2] 0x03 00000011    [2] 0x02 00000010    [2] 0x02 00000010    *
     *   [3] 0x01 00000001    [3] 0x03 00000011    [3] 0x03 00000011    *
     *   [4] 0x02 00000010    [4] 0x01 00000001    [4] 0x01 00000001    *
     *   [5] 0x03 00000011    [5] 0x07 00000111    [5] 0x07 00000111    *
     *   [6] 0x04 00000100    [6] 0x04 00000100    [6] 0x04 00000100    *
     *   [7] 0x00 00000000    [7] 0x00 00000000    [7] 0x01 00000001    *
     *                      portb 0x00 00000000  portb 0x01 00000001    *
     *                                                                  */
          asm {
          movf  _porta,W            // get current PORTA bits
          andlw 0                   // keep only MIBAM output bits
          xorwf _Adat+7,F           // create 2^7 toggle bits
          xorwf _Adat+7,W           // W simulates cumulative PORTA
          xorwf _Adat+6,F           // create 2^6 toggle bits
          xorwf _Adat+6,W           //
          xorwf _Adat+5,F           // create 2^5 toggle bits
          xorwf _Adat+5,W           //
          xorwf _Adat+4,F           // create 2^4 toggle bits
          xorwf _Adat+4,W           //
          xorwf _Adat+3,F           // create 2^3 toggle bits
          xorwf _Adat+3,W           //
          xorwf _Adat+2,F           // create 2^2 toggle bits
          xorwf _Adat+2,W           //
          xorwf _Adat+1,F           // create 2^1 toggle bits
          xorwf _Adat+1,W           //
          xorwf _Adat+0,F           // create 2^0 toggle bits
    
          movf  _portb,W            // get current PORTB bits
          andlw 7                   // keep only MIBAM output bits
          xorwf _Bdat+7,F           // create 2^7 toggle bits
          xorwf _Bdat+7,W           // W simulates cumulative PORTB
          xorwf _Bdat+6,F           // create 2^6 toggle bits
          xorwf _Bdat+6,W           //
          xorwf _Bdat+5,F           // create 2^5 toggle bits
          xorwf _Bdat+5,W           //
          xorwf _Bdat+4,F           // create 2^4 toggle bits
          xorwf _Bdat+4,W           //
          xorwf _Bdat+3,F           // create 2^3 toggle bits
          xorwf _Bdat+3,W           //
          xorwf _Bdat+2,F           // create 2^2 toggle bits
          xorwf _Bdat+2,W           //
          xorwf _Bdat+1,F           // create 2^1 toggle bits
          xorwf _Bdat+1,W           //
          xorwf _Bdat+0,F           // create 2^0 toggle bits
          }
          break;                    //
      }
    }
    Last edited by Mike, K8LH; - 26th July 2009 at 14:01.

Similar Threads

  1. decoding quadrature encoders
    By ice in forum mel PIC BASIC Pro
    Replies: 93
    Last Post: - 28th February 2017, 09:02
  2. Cordic trig assembly code for PIC18f
    By ScaleRobotics in forum mel PIC BASIC Pro
    Replies: 54
    Last Post: - 8th September 2015, 05:36
  3. AT/PS2 Keybord - PIC Interface?
    By Kamikaze47 in forum Code Examples
    Replies: 73
    Last Post: - 9th August 2009, 16:10
  4. MIBAM - (Mirror Imaged Bit Angle Modulation)
    By Darrel Taylor in forum Code Examples
    Replies: 2
    Last Post: - 15th February 2009, 16:02
  5. Bit Angle Modulation
    By BH_epuk in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 18th November 2008, 07:01

Members who have read this thread : 3

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts