7 Replies Latest reply on Mar 4, 2016 3:04 PM by op_2169936

    IR_TX inverted output

      Hi,

      I'm testing various hardware functions of the BCM2073x devices, and am currently on the IR_TX output.

      This post has really helped me:

      Examples using irtxdriver and syncedpulse?

       

      #include "myirtx.h"

      #include "irtxdriver.h"

      #include "gpiodriver.h"

      #include "aclk.h"

       

      #define BUFFER_SIZE 16    

      UINT16 send_buffer[BUFFER_SIZE];

       

      #define HIGH(value) (value | HW_MIA_IR_CMD_IR_RAW_BIT_MASK)

      #define LOW(value) (value & ~(HW_MIA_IR_CMD_IR_RAW_BIT_MASK)

      // 1<<15==0x8000 == HW_MIA_IR_CMD_IR_RAW_BIT_MASK when this bit is set, it should be 1, if not, zero (unless control inverts it.)

      // max value: 0x7FFF=32768 microseconds, or 32 milliseconds

       

      IR_TX_CLOCK_SETTING irtxClockSet;

       

      void myirtx_init()

      {

        /// IR TX initialization routine.

        irtx_IrTx();

        //(1) Configure the IrTx Port and Pin to be used

        irtx_setIrTxPortPin(GPIO_PIN_P4/16, GPIO_PIN_P4%16);

        ble_trace1("P4: %x", gpio_getPinConfig(GPIO_PIN_P4/16, GPIO_PIN_P4%16)); //=> 0x0010 == GPIO_KS_OUTPUT_ENABLE

       

       

        irtxClockSet.invertOutput=1; //Invert HIGH and LOW if true

        irtxClockSet.modulateFreq=38000; //Modulation frequency 38KHz

        irtxClockSet.clockSrcFreq=ACLK_FREQ_24_MHZ; //I assume it works as ACLK, so use defines from aclk.h

        irtxClockSet.clockSrc=ACLK1;

      }

       

      void myirtx_tx_something()

      {

      //Prepare an array to send

        send_buffer[0]=HIGH(208);  //Stay high for 208us

        send_buffer[1]=LOW(834);   //Stay low for 834us

        send_buffer[2]=HIGH(417);   //Stay high for 417us

        send_buffer[3]=LOW(417);   //etc...

        send_buffer[4]=HIGH(208);

        send_buffer[5]=LOW(625);

        send_buffer[6]=HIGH(625);

        send_buffer[7]=LOW(625);

        send_buffer[8]=HIGH(208);

        send_buffer[9]=LOW(208);

        send_buffer[10]=HIGH(208);

        send_buffer[11]=LOW(208);

        send_buffer[12]=HIGH(208);

        send_buffer[13]=LOW(208);

        send_buffer[14]=HIGH(417);

        send_buffer[15]=LOW(625);

       

       

        irtx_sendData(send_buffer, 16, irtxClockSet);

       

        //while (! irtx_isAvailable()); //Hardware IR Bloc is turned off during deep sleep

        //We must wait until the transmission is done before going to sleep

      }

       

      This seems to work very well (I call myirtx_init at the end of the app_create() funciton, and myirtx_tx_something in the button interrupt routine)

      I'm also able to invert the output by setting irtxClockSet.invertOutput=1; or 0 respectively. However, the inversion only inverts the transmission, but not the idle state, so it's not very helpful at all. Idle seems to be low at all times.

      I've tried a few things, such as adding a GPIO_PULL_UP, but this has no effect.

      I've also tried manually using gpio_configure to output high, right after irtx_setIrTxPortPin, and only changing that just before irtx_sendData. This might work in a pinch, but does not pull up the line after transmission is done, and because the tx_done interrupt does not seem to be available to us, I can't manually use gpioconfigure or setoutput to pull it up again immediately after transmission.

       

      Could someone from Broadcom tell us if this is expected behaviour (that the idle state is unaffected by "invertOutput")? If not, could you give us a solution to fix this?

       

      I could imagine the only real purpose for the invertOutput would be to connect the TX IR diode differently, ie between VDD and IR_TX_PIN rather than between IR_TX_PIN and GND... but then the idle state would need to be inverted too, right?

       

      I'm also very interested in IR_RX functionality, any more info on this would be great!

        • 1. Re: IR_TX inverted output
          MichaelF_56

          I've asked JacobT_81 to look into this with the developers and confirm that the SDK supports what you are trying to accomplish.

           

          Unfortunately, we do not have any sample applications for the IR function, so it can be challenging.

          • 2. Re: IR_TX inverted output
            JacobT_81

            Any call to gpio_configure() or gpio_setOutput() will do nothing but possibly take control of the GPIO from the IR hw block. By calling irtx_setIrTxPortPin() you are yielding control of the pin to the IR hw. The output must now be configured from within that hw.

             

            I believe the idle-low behavior to be the intended functionality of the IR hw whether or not the bits are inverted. However, I will look deeper into the source code to come to a final conclusion within a few days.

             

            Jacob

            • 3. Re: IR_TX inverted output

              Thanks already, JacobT_81

              I've been snooping around the sdk a little more too and have the following idea:

                   irtx_setIrTxPortPin(GPIO_PIN_P4/16, GPIO_PIN_P4%16);

                   ble_trace1("P4: %x", gpio_getPinConfig(GPIO_PIN_P4/16, GPIO_PIN_P4%16)); //=> 0x0010 == GPIO_KS_OUTPUT_ENABLE

              I checked the GPIO configuration after calling setIrTxPortPin. The result is 0x0010 which is the same as KS_OUTPUT_ENABLE.

              P4 is part of a possible Keyscan setup, so I was wondering if it might be possible to enable a keyscan pullup, as found in hidddriversconf.h from line 64 onward? Here's an exerpt - I have not yet done any testing with this:

                  ///  - 16 =>    Enable active pull up on the columns after each column scan to alleviate

                  ///             slow RC times on keyboard designs.

                  ///  - 17 =>    Enable active pull up on the rows in between scans to

                  ///             alleviate slow RC times on keyboard designs and avoid

                  ///             false key detection

              • 4. Re: IR_TX inverted output
                JacobT_81

                Unfortunately, the IR hardware doesn't allow us to toggle the idle state.

                 

                The only way I was able to produce the behavior you want is with the code below:

                 

                void myirtx_tx_something(void) {

                 

                       send_buffer[0]=HIGH(208);  //Stay high for 208us

                          .............

                       send_buffer[15]=LOW(625);

                 

                       irtx_setIrTxPortPin(GPIO_PIN_P4/16, GPIO_PIN_P4%16);

                 

                       irtx_sendData(send_buffer, 16, irtxClockSet);

                 

                       while (!irtx_isAvailable());

                 

                       gpio_configurePin(GPIO_PIN_P4/16, GPIO_PIN_P4%16,           GPIO_OUTPUT_ENABLE | GPIO_INPUT_DISABLE,           GPIO_PIN_OUTPUT_HIGH);

                }

                 

                I'm sure you had come up with this one on your own. And, of course, it's not optimal because it leaves you in a loop polling for the tx done bit.

                 

                As you mentioned, the only interrupt is internal. I'll work to see if I can bring it to the application level. If I'm unsuccessful, it will need to be created as a patch and released with the next SDK.

                 

                Jacob

                • 5. Re: IR_TX inverted output

                  Thanks for the answer, even if it's not what I was hoping to hear.

                   

                  Yes, I had thought of this, but of course blocking the CPU with such a while-loop ist a no-go in my thinking.

                  My idea was to caluclate the time for the total tranmission (by adding up all the values in the sendbuffer), then add a HIGH(0x7FFF) (maximum time of about 32ms) at the end of every transmission. This would provide a "window" in which, using the fine_timer (or a BT_timer) interrupt, we could check if we should be done with the transmission by now (if we're in that 32ms window) and if yes, change the gpio configuration to output high.

                  Does IR_TX use timer2 internally?

                  or does it use timer1?  can I use hw_timer at the same time as IR_TX?

                  or is timer1 the bluetooth timer?

                  • 6. Re: IR_TX inverted output
                    JacobT_81

                    Since the IR hw is running on ACLK, using the fine timer is precarious. It's still causing me problems per the last thread about ACLK.

                     

                    The idea to hold the line high with a long tx is viable if we can bring out another clock line, other than the fine timer.

                     

                    I recommend trying to run on the bt clock:

                         do a #include bt_clock_based_timer.h

                         also, you'll need to include the respective archive (.a) file into your application makefile.

                     

                    The .h has some notes for registering a timer callback.

                     

                    Find the files here in the SDK:

                         WICED-Smart-SDK/Wiced-Smart/tier2/brcm/libraries/inc/bt_clock_based_timer.h

                     

                         WICED-Smart-SDK/Wiced-Smart/tier2/brcm/libraries/lib/20737/bt_clock_based_periodic_timer.a

                     

                    In regard to your last questions, I'm not sure what you're referring to when you say timer1 and timer2?

                     

                    Jacob

                    • 7. Re: IR_TX inverted output

                      Thanks for the info on bt_clock_based_timer.h I'll have a closer look at that.

                       

                      OK, so the fine timer is messing with ACLK generally, not just the direct output on the pins? That might explain a few other issues I've run into with PWM and fine_timer!

                       

                      bt_clock_based_timer does seem to be be the right choice then, and since it's a very very simple task (only incrementing a counter and if counter is greater than the length of transmission change the gpioconfiguration), there shouldn't be anything to worry about, regarding "adversely affecting Bluetooth Performance".

                       

                       

                      what I meant with timer1 and timer2 are the underlying hardware timers.

                      in hw_timer.h  this is written at the top (line 27):

                      /****************************************************************************

                      * Use an accurate HW timer - timer2 as a 1-shot timer

                      and the assumption that if there's a timer2, there must be a timer1 as well, led me to find the registers for these timers in Wiced-Smart/bsp/inc/20732mapa1.h, lines 100 and following.

                       

                      I thought I had read something about hw_timer and ir_tx being mutually exclusive (would make sense if both are using timer2), but can't find where I read that anymore.