um-cseg/chez-betty

View on GitHub
bill_acceptor/software/apps/pa7-to-hid/main.c

Summary

Maintainability
Test Coverage

#include <stdio.h>
#include <stdlib.h>

#include "bsp.h"
#include "ioc.h"
#include "gptimer.h"
#include "bsp_led.h"
#include "string.h"
#include "usb_hid.h"
#include "usb_firmware_library_headers.h"


//*****************************************************************************
//
// Local functions
//
//*****************************************************************************
void selKeyRemoteWakeupIsr(void) {
    usbsuspDoRemoteWakeup();
    IntDisable(INT_GPIOA);
}


void dirKeyRemoteWakeupIsr(void) {
    usbsuspDoRemoteWakeup();
    IntDisable(INT_GPIOC);
}


//*****************************************************************************
//
// Implementations of function that are required by usb framework.
//
//*****************************************************************************
void usbsuspHookEnteringSuspend(bool remoteWakeupAllowed) {
    if (remoteWakeupAllowed) {
        GPIOPowIntClear(BSP_KEY_SEL_BASE, BSP_KEY_SELECT);
        GPIOPowIntEnable(BSP_KEY_SEL_BASE, BSP_KEY_SELECT);
        IntPendClear(INT_GPIOA);
        IntEnable(INT_GPIOA);

        GPIOPowIntClear(BSP_KEY_DIR_BASE, BSP_KEY_DIR_ALL);
        GPIOPowIntEnable(BSP_KEY_DIR_BASE, BSP_KEY_DIR_ALL);
        IntPendClear(INT_GPIOC);
        IntEnable(INT_GPIOC);
    }
}


void usbsuspHookExitingSuspend(void) {
    IntDisable(INT_GPIOA);
    GPIOPowIntDisable(BSP_KEY_SEL_BASE, BSP_KEY_SELECT);

    IntDisable(INT_GPIOC);
    GPIOPowIntDisable(BSP_KEY_DIR_BASE, BSP_KEY_DIR_ALL);
}

volatile uint8_t send = 0;
volatile uint8_t count = 0;
//uint32_t last_interrupt_time = 0;

void gpio_toggle (uint32_t base, uint8_t ui8Leds) {
    uint32_t ui32Toggle = GPIOPinRead(base, ui8Leds);
    ui32Toggle = (~ui32Toggle) & ui8Leds;
    GPIOPinWrite(base, ui8Leds, ui32Toggle);
}






void GPIOBIntHandler(void) {
    static uint32_t rising_edge_time = 0;

    uint32_t ui32GPIOIntStatus;

    bspLedToggle(BSP_LED_1);

    // Get the masked interrupt status.
    ui32GPIOIntStatus = GPIOPinIntStatus(GPIO_B_BASE, true);

    // Acknowledge the GPIO  - Pin n interrupt by clearing the interrupt flag.
    GPIOPinIntClear(GPIO_B_BASE, ui32GPIOIntStatus);

    // Was this a rising edge or falling edge. True==rising
    bool direction = (GPIOPinRead(GPIO_B_BASE, GPIO_PIN_6) != 0);




    if (direction == true) {
        // Got rising edge of pulse.

        // Start timeout timer and wait for falling edge
        TimerDisable(GPTIMER0_BASE, GPTIMER_A);
        // Timeout in 100 ms
        TimerLoadSet(GPTIMER0_BASE, GPTIMER_A, SysCtrlClockGet() / 10);
        TimerEnable(GPTIMER0_BASE, GPTIMER_A);

        // Save this time
        rising_edge_time = TimerValueGet(GPTIMER0_BASE, GPTIMER_A);


    } else {
        // Got falling edge
        // Ensure this was about when we expect
        uint32_t falling_edge_time = TimerValueGet(GPTIMER0_BASE, GPTIMER_A);
        uint32_t diff = rising_edge_time - falling_edge_time;
        if (diff > (SysCtrlClockGet() / 66) && diff < (SysCtrlClockGet() / 20)) {
            // This looks like a valid pulse, count it!

            count += 1;

            // On the first edge send a notice so the listener knows its getting
            // data.
            if (count == 1) {
                send = 2;
            }
        }



    }





    // // Check to make sure this is valid, and to debounce (not strictly sure
    // // this is necessary...).
    // bool valid_pulse = true;

    // // Wait 15 ms and make sure line is still high
    // int start = TimerValueGet(GPTIMER0_BASE, GPTIMER_A);
    // while (start - TimerValueGet(GPTIMER0_BASE, GPTIMER_A) < (SysCtrlClockGet() / 66)) {
    //     if (GPIOPinRead(GPIO_B_BASE, GPIO_PIN_6) == 0) {
    //         valid_pulse = false;
    //         break;
    //     }
    // }

    // if (valid_pulse) {

    //     if (count != 0) {
    //         // We have gotten multiple pulses in a row. Make sure they are not
    //         // too close.
    //         valid_pulse = false;

    //         // See if this is a valid edge
    //         uint32_t curr_time = TimerValueGet(GPTIMER0_BASE, GPTIMER_A);
    //         // Must be at least 30 ms from last edge
    //         if ((last_interrupt_time - curr_time) > (SysCtrlClockGet() / 33)) {
    //             valid_pulse = true;
    //         }
    //     }

    //     // Increment our dollar count and set a timeout timer
    //     if (valid_pulse) {

    //         count += 1;

    //         // Start a timeout timer
    //         TimerDisable(GPTIMER0_BASE, GPTIMER_A);
    //         // Timeout in 100 ms
    //         TimerLoadSet(GPTIMER0_BASE, GPTIMER_A, SysCtrlClockGet() / 10);
    //         TimerEnable(GPTIMER0_BASE, GPTIMER_A);

    //         // Save the time we got this edge so we can detect if the next one
    //         // is too close.
    //         last_interrupt_time = TimerValueGet(GPTIMER0_BASE, GPTIMER_A);

    //         gpio_toggle(GPIO_B_BASE, GPIO_PIN_5);

    //         // On the first edge send a notice so the listener knows its getting
    //         // data.
    //         if (count == 1) {
    //             send = 2;
    //         }
    //     }

    // }

}


void Timer0AIntHandler(void) {
    // Clear the timer interrupt flag.
    TimerIntClear(GPTIMER0_BASE, GPTIMER_TIMA_TIMEOUT);

    // Set a flag to indicate that the timeout interrupt occurred
    // and that we should report the dollar amount.
   send = 1;
}




void send_char (char c, bool shift) {
    KEYBOARD_IN_REPORT keybReport;
    memset(&keybReport, 0x00, sizeof(KEYBOARD_IN_REPORT));

    if (shift) {
       keybReport.modifiers    = 2;
       keybReport.pKeyCodes[1] = 0xE1;
    }

    if (c >= 97 && c <= 122) {
        keybReport.pKeyCodes[0] = c - 93;
    } else if (c >= 49 && c <= 57) {
        keybReport.pKeyCodes[0] = c - 19;
    } else if (c == '0') {
        keybReport.pKeyCodes[0] = 39;
    } else if (c == '\n') {
        keybReport.pKeyCodes[0] = 0x28;
    } else {
        keybReport.pKeyCodes[0] = 0x38; // "?"
        keybReport.modifiers    = 2;
        keybReport.pKeyCodes[1] = 0xE1;
    }
    hidUpdateKeyboardInReport(&keybReport);

    while (!hidSendKeyboardInReport()) {
        usbHidProcessEvents();
    }

    // Clear button press
    memset(&keybReport, 0x00, sizeof(KEYBOARD_IN_REPORT));
    hidUpdateKeyboardInReport(&keybReport);

    while (!hidSendKeyboardInReport()) {
        usbHidProcessEvents();
    }
}


void dollars_to_characters (int dollars) {
    char buf[10];
    int offset = 0;

    if (dollars < 100) {
        offset++;
        buf[0] = '0';
    }
    if (dollars < 10) {
        offset++;
        buf[1] = '0';
    }

    itoa(dollars, buf+offset, 10);

    int i;
    for (i=0; i<3; i++) {
        send_char(buf[i], false);
    }

}






//
// Application entry point
//
int main (void) {

    //
    // Initialize board and system clock
    //
    bspInit(SYS_CTRL_32MHZ);

    //
    // Enable the USB interface
    //
    usbHidInit();

    // Initialize GPIO pins for LEDs
    GPIOPinTypeGPIOOutput(BSP_LED_BASE, BSP_LED_2 | BSP_LED_3 | BSP_LED_1);
    GPIOPinTypeGPIOOutput(GPIO_B_BASE, GPIO_PIN_5);

    bspLedSet(BSP_LED_2);
    bspLedSet(BSP_LED_3);
    bspLedSet(BSP_LED_1);



    //
    // Configure interrupt with wakeup for all buttons
    //
    // IntRegister(INT_GPIOB, buttonPress);
    // GPIOPowIntTypeSet(GPIO_B_BASE, GPIO_PIN_6, GPIO_POW_RISING_EDGE);
    // IntRegister(INT_GPIOC, dirKeyRemoteWakeupIsr);
    // GPIOPowIntTypeSet(BSP_KEY_DIR_BASE, BSP_KEY_DIR_ALL, GPIO_POW_RISING_EDGE);

    GPIOPinTypeGPIOInput(GPIO_B_BASE, GPIO_PIN_6);
    IOCPadConfigSet(GPIO_B_BASE, GPIO_PIN_6, IOC_OVERRIDE_DIS);
    GPIOIntTypeSet(GPIO_B_BASE, GPIO_PIN_6, GPIO_BOTH_EDGES);
    GPIOPinIntEnable(GPIO_B_BASE, GPIO_PIN_6);

    IntMasterEnable();
    IntEnable(INT_GPIOB);




    // setup timer
    SysCtrlPeripheralEnable(SYS_CTRL_PERIPH_GPT0);
    TimerConfigure(GPTIMER0_BASE, GPTIMER_CFG_ONE_SHOT);
    TimerIntEnable(GPTIMER0_BASE, GPTIMER_TIMA_TIMEOUT);
    IntEnable(INT_TIMER0A);






    bspLedClear(BSP_LED_2);

    // Main loop
    while (1) {

        // Process USB events
        usbHidProcessEvents();

        if (send == 1) {
            send = 0;

            uint8_t local_count = count;
            count = 0;

            if (local_count != 0) {

                bspLedToggle(BSP_LED_3);

                send_char('b', true);
                send_char('i', true);
                send_char('l', true);
                send_char('l', true);

                dollars_to_characters(local_count);

            }

            // // if (local_count > 0 && local_count < 3) {
            // if (local_count == 1) {
            //     send_char('0', false);
            //     send_char('0', false);
            //     send_char('1', false);
            // // } else if (local_count >= 3 && local_count < 7) {
            // } else if (local_count == 5) {
            //     send_char('0', false);
            //     send_char('0', false);
            //     send_char('5', false);
            // // } else if (local_count >= 8 && local_count < 12) {
            // } else if (local_count == 10) {
            //     send_char('0', false);
            //     send_char('1', false);
            //     send_char('0', false);
            // // } else if (local_count >= 17 && local_count < 22) {
            // } else if (local_count == 20) {
            //     send_char('0', false);
            //     send_char('2', false);
            //     send_char('0', false);
            // // } else if (local_count >= 45 && local_count < 55) {
            // } else if (local_count == 50) {
            //     send_char('0', false);
            //     send_char('5', false);
            //     send_char('0', false);
            // // } else if (local_count >= 90 && local_count < 110) {
            // } else if (local_count == 100) {
            //     send_char('1', false);
            //     send_char('0', false);
            //     send_char('0', false);
            // } else {
            //     send_char('e', true);
            //     send_char('r', true);
            //     send_char('r', true);
            // }

            // // send_char('\n', false);




        } else if (send == 2) {
            send = 0;

            send_char('b', true);
            send_char('i', true);
            send_char('l', true);
            send_char('l', true);
            send_char('b', true);
            send_char('e', true);
            send_char('g', true);

            // send_char('\n', false);
        }

    }

}


//
// Callback function for HID application
//
void usbHidAppPoll(void) {

    //
    // Output keyboard LED status on LEDs 2-4
    //
    // if (hidData.keyboardOutReport.ledStatus & 0x01)
    // {
    //     bspLedSet(BSP_LED_2);
    // }
    // else
    // {
    //     bspLedClear(BSP_LED_2);
    // }
    // if (hidData.keyboardOutReport.ledStatus & 0x02)
    // {
    //     bspLedSet(BSP_LED_3);
    // }
    // else
    // {
    //     bspLedClear(BSP_LED_3);
    // }
    // if (hidData.keyboardOutReport.ledStatus & 0x04)
    // {
    //     bspLedSet(BSP_LED_4);
    // }
    // else
    // {
    //     bspLedClear(BSP_LED_4);
    // }
}