• AVR Freaks

Interrupt latency problems with PIC24F USB Host

Author
AndersG
Senior Member
  • Total Posts : 179
  • Reward points : 0
  • Joined: 2008/08/05 04:51:24
  • Location: 0
  • Status: offline
2019/12/28 03:21:14 (permalink)
0

Interrupt latency problems with PIC24F USB Host

Hi!
 
Asking here in case anyone has any good ideas. I am emulating a legacy keyboard. The protocol is essentially 2-wire. One is clock, one is data. The host initiates polling by pulling the dataline low approx every 20ms. The keyboard replies by counting clockpulses and pulling the same dataline low after n pulses, where n is the scancode of the key. The clock is approx 100 us high, 28us low
 
I am using the hid keyboard sample from the 2017-03-06 MLA with a PIC24FJ64GB002, using the 24F_STARTER_KIT as a template.
 
What I essentially do is to feed the dataline to INT0 and also RB8, configured as open-drain. Clock is fed through an inverter into T1CK and RB5, for sense. INT0 puts the keycode into the PR1 register and waits for the compare interrupt. The compare interrupt takes down the data line until the clock goes high (or low in the code as clock is inverted)
 
This works very well, apart for when I hold a key down. Repeat works almost as expected, but there are occasional pauses where the host thinks I have released the key. If I look at the lines, I find that I am pulling the dataline low too late, by approx 100us every once in a while.
 
Any ideas what could cause this? If the timer initialisation was wrong, then I would lose a complete tick and get the wrong scancode.
 
Forum prevents me from posting the code, let me try again :( Edit: The last ISR,prevents me from posting. Trying an attchment
 
int flag = 1;
volatile unsigned int Capture;
volatile unsigned int Counter;
volatile unsigned char Key = 0;

typedef union {
    struct {
        unsigned status0 :1;
        unsigned status1 :1;
        unsigned status2 :1;
        unsigned status3 :1;
        unsigned status4 :1;
        unsigned status5 :1;
        unsigned shift :1;
        unsigned ctrl :1;
    };
    unsigned char status;
} KbdStatus_t;

KbdStatus_t KbdStatus;

int main(void)
{
    SYSTEM_Initialize(SYSTEM_STATE_USB_HOST);
    SYSTEM_Initialize(SYSTEM_STATE_USB_HOST_HID_KEYBOARD);
    //
    // Set 8MHz clock FRC. PLLDIV=2, gives 4MHz. Fed to PLL gives 96MHz
    // divided by 3 gives 32MHz cpu clock
    //
    CLKDIVbits.CPDIV = 0; // Divide by nothing = 32MHz
    CLKDIVbits.RCDIV = 0; // FRC Postscaler Select bits, divide by 0
                            // ie FRCDIV is 8MHz, same as FRC
                            // PLLDIV is set in config bits to 2 (system.c)
    //
    KbdStatus.status = 0;
    //
    // Set up Timer1 to count clock pulses
    //
    TRISAbits.TRISA4 = 1; // Pin is input
    T1CONbits.TCKPS = 0; // No prescale
    T1CONbits.TCS = 1; // External clock on pin 12
    T1CONbits.TON = 1; // Start timer
    IEC0bits.T1IE = 1; // Interrupt on compare
    _T1IP = 6; //Choose a priority
    //
    CNEN2bits.CN21IE = 1; // Interrupt on change on RB9
    CNPU2bits.CN21PUE = 1; // Weak pullup on RB9
    IEC1bits.CNIE = 0; // Disable interrupt on change
    //
    TRISBbits.TRISB8 = 0; // B8 is signal output
    PORTBbits.RB8 = 1;
    ODCBbits.ODB8 = 1; // Make it open drain.
    //
    // https://engineering.purdue.edu/ece477/Archive/2009/Spring/S09-Grp06/Code/PIC/pic24_code_examples/docs/int0__bounce_8c-source.html
    //
    TRISBbits.TRISB7 = 1; // Input for INT0
    _INT0IF = 0; //Clear the interrupt flag
    _INT0IP = 7; //Choose a priority
    _INT0EP = 1; //negative edge triggerred
    _INT0IE = 1; //enable INT0 interrupt
    TRISBbits.TRISB5 = 1; // Input for clock sense
    
    
    _U1RXIE = 0;
 _U1TXIE = 0;
    //unlock registers
    __builtin_write_OSCCONL(OSCCON & 0xBF);
    // Configure Output Functions (Table 9-2)
    // Assign U1TX To Pin RP2
    RPOR1bits.RP2R = 3;
    TRISBbits.TRISB2 = 0; // output
 /* Initialize UART1 */
 U1BRG = FCY / 2 / 16 / 57600 - 1;
 _UARTEN = 1;
 _UTXEN = 1;
    //Initialize the stack
    printf("\r\nStarting. CLKDIV is %X ", CLKDIV);
    USBHostInit(0);

    APP_HostHIDKeyboardInitialize();

    while(1)
    {
        USBHostTasks();
        USBHostHIDTasks();
        //Application specific tasks
        APP_HostHIDKeyboardTasks();
    }//end while
}//end main

 
// 
// Keyboard data went low? Signal to start counting. Zero counter and
// if we have a keystroke, set that code in the period register
//
void __attribute__((__interrupt__, auto_psv)) _INT0Interrupt( void )
{
    //if(PORTBbits.RB9 == 0)
    //{
        Counter = TMR1; // This is just used to read scancodes
                                        // from an existing keyboard
        TMR1 = 0;
        //
        if(KbdStatus.shift)
        {
            PR1 = 1;
        }
        else if(Key !=0) PR1 = Key;
        T1CONbits.TON = 1; // Start timer
    //}
    //IFS1bits.CNIF = 0;
    _INT0IF = 0; //clear the interrupt bit
}

 
post edited by AndersG - 2019/12/28 03:29:31
#1

0 Replies Related Threads

    Jump to:
    © 2020 APG vNext Commercial Version 4.5