static void setTxSignalEsc(escSerial_t *escSerial, uint8_t state)
{
    if (escSerial->mode == PROTOCOL_KISSALL)
    {
        for (volatile uint8_t i = 0; i < escSerial->outputCount; i++) {
            uint8_t state_temp = state;
            if (escOutputs[i].inverted) {
                state_temp ^= ENABLE;
            }

            if (state_temp) {
                IOHi(escOutputs[i].io);
            } else {
                IOLo(escOutputs[i].io);
            }
        }
    }
    else
    {
        if (escSerial->rxTimerHardware->output & TIMER_OUTPUT_INVERTED) {
            state ^= ENABLE;
        }

        if (state) {
            IOHi(escSerial->txIO);
        } else {
            IOLo(escSerial->txIO);
        }
    }
}
Beispiel #2
0
static void i2cUnstick(IO_t scl, IO_t sda)
{
    int i;
    int timeout = 100;

    IOHi(scl);
    IOHi(sda);

    IOConfigGPIO(scl, IOCFG_OUT_OD);
    IOConfigGPIO(sda, IOCFG_OUT_OD);

    for (i = 0; i < 8; i++) {
        // Wait for any clock stretching to finish
        while (!IORead(scl) && timeout) {
            delayMicroseconds(10);
            timeout--;
        }

        // Pull low
        IOLo(scl); // Set bus low
        delayMicroseconds(10);
        IOHi(scl); // Set bus high
        delayMicroseconds(10);
    }

    // Generate a start then stop condition
    IOLo(sda); // Set bus data low
    delayMicroseconds(10);
    IOLo(scl); // Set bus scl low
    delayMicroseconds(10);
    IOHi(scl); // Set bus scl high
    delayMicroseconds(10);
    IOHi(sda); // Set bus sda high
}
/*
 * Start a range reading
 * Called periodically by the scheduler
 * Measurement reading is done asynchronously, using interrupt
 */
void hcsr04_start_reading(void)
{
#if !defined(UNIT_TEST)
#ifdef RANGEFINDER_HCSR04_TRIG_INVERTED
    IOLo(triggerIO);
    delayMicroseconds(11);
    IOHi(triggerIO);
#else
    IOHi(triggerIO);
    delayMicroseconds(11);
    IOLo(triggerIO);
#endif
#endif
}
void serialUARTInit(IO_t tx, IO_t rx, portMode_t mode, portOptions_t options, uint8_t af, uint8_t index)
{
    if (options & SERIAL_BIDIR) {
        ioConfig_t ioCfg = IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, 
            (options & SERIAL_INVERTED) ? GPIO_OType_PP : GPIO_OType_OD, 
            (options & SERIAL_INVERTED) ? GPIO_PuPd_DOWN : GPIO_PuPd_UP
        );

        IOInit(tx, OWNER_SERIAL, RESOURCE_UART_TXRX, index);
        IOConfigGPIOAF(tx, ioCfg, af);

        if (!(options & SERIAL_INVERTED))
            IOLo(tx);   // OpenDrain output should be inactive
    } else {
        ioConfig_t ioCfg = IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, (options & SERIAL_INVERTED) ? GPIO_PuPd_DOWN : GPIO_PuPd_UP);
        if (mode & MODE_TX) {
            IOInit(tx, OWNER_SERIAL, RESOURCE_UART_TX, index);
            IOConfigGPIOAF(tx, ioCfg, af);
        }

        if (mode & MODE_RX) {
            IOInit(tx, OWNER_SERIAL, RESOURCE_UART_TX, index);
            IOConfigGPIOAF(rx, ioCfg, af);
        }
    }
}
Beispiel #5
0
void usbGenerateDisconnectPulse(void)
{
    /* Pull down PA12 to create USB disconnect pulse */
    IO_t usbPin = IOGetByTag(IO_TAG(PA12));
    IOConfigGPIO(usbPin, IOCFG_OUT_OD);

    IOLo(usbPin);

    delay(200);

    IOHi(usbPin);
}
Beispiel #6
0
static void setTxSignal(softSerial_t *softSerial, uint8_t state)
{
    if (softSerial->port.options & SERIAL_INVERTED) {
        state = !state;
    }

    if (state) {
        IOHi(softSerial->txIO);
    } else {
        IOLo(softSerial->txIO);
    }
}
Beispiel #7
0
static void i2cUnstick(IO_t scl, IO_t sda)
{
    int i;

    IOHi(scl);
    IOHi(sda);

    IOConfigGPIO(scl, IOCFG_OUT_OD);
    IOConfigGPIO(sda, IOCFG_OUT_OD);

    // Clock out, with SDA high:
    //   7 data bits
    //   1 READ bit
    //   1 cycle for the ACK
    for (i = 0; i < (LEN_ADDR + LEN_RW + LEN_ACK); i++) {
        // Wait for any clock stretching to finish
        int timeout = UNSTICK_CLK_STRETCH;
        while (!IORead(scl) && timeout) {
            delayMicroseconds(UNSTICK_CLK_US);
            timeout--;
        }

        // Pull low
        IOLo(scl); // Set bus low
        delayMicroseconds(UNSTICK_CLK_US/2);
        IOHi(scl); // Set bus high
        delayMicroseconds(UNSTICK_CLK_US/2);
    }

    // Generate a stop condition in case there was none
    IOLo(scl);
    delayMicroseconds(UNSTICK_CLK_US/2);
    IOLo(sda);
    delayMicroseconds(UNSTICK_CLK_US/2);

    IOHi(scl); // Set bus scl high
    delayMicroseconds(UNSTICK_CLK_US/2);
    IOHi(sda); // Set bus sda high
}
Beispiel #8
0
static pwmOutputPort_t *pwmOutConfig(const timerHardware_t *timerHardware, uint8_t mhz, uint16_t period, uint16_t value, bool enableOutput)
{
    pwmOutputPort_t *p = &pwmOutputPorts[allocatedOutputPortCount++];

    configTimeBase(timerHardware->tim, period, mhz);

    const IO_t io = IOGetByTag(timerHardware->tag);
    IOInit(io, OWNER_MOTOR, RESOURCE_OUTPUT, allocatedOutputPortCount);

    if (enableOutput) {
        // If PWM outputs are enabled - configure as AF_PP - map to timer
        // AF itself was configured by timerInit();
        IOConfigGPIO(io, IOCFG_AF_PP);
    }
    else {
        // If PWM outputs are disabled - configure as GPIO and drive low
        IOConfigGPIO(io, IOCFG_OUT_OD);
        IOLo(io);
    }

    pwmOCConfig(timerHardware->tim, timerHardware->channel, value, timerHardware->output & TIMER_OUTPUT_INVERTED);
    if (timerHardware->output & TIMER_OUTPUT_ENABLED) {
        TIM_CtrlPWMOutputs(timerHardware->tim, ENABLE);
    }
    TIM_Cmd(timerHardware->tim, ENABLE);

    switch (timerHardware->channel) {
    case TIM_Channel_1:
        p->ccr = &timerHardware->tim->CCR1;
        break;
    case TIM_Channel_2:
        p->ccr = &timerHardware->tim->CCR2;
        break;
    case TIM_Channel_3:
        p->ccr = &timerHardware->tim->CCR3;
        break;
    case TIM_Channel_4:
        p->ccr = &timerHardware->tim->CCR4;
        break;
    }
    p->period = period;
    p->tim = timerHardware->tim;

    *p->ccr = 0;

    return p;
}
Beispiel #9
0
void detectHardwareRevision(void)
{
    IO_t pin1 = IOGetByTag(IO_TAG(PB12));
    IOInit(pin1, OWNER_SYSTEM, RESOURCE_INPUT, 1);
    IOConfigGPIO(pin1, IOCFG_IPU);

    IO_t pin2 = IOGetByTag(IO_TAG(PB13));
    IOInit(pin2, OWNER_SYSTEM, RESOURCE_INPUT, 2);
    IOConfigGPIO(pin2, IOCFG_IPU);

    // Check hardware revision
    delayMicroseconds(10);  // allow configuration to settle

    /* 
        if both PB12 and 13 are tied to GND then it is Rev3A (mini)
        if only PB12 is tied to GND then it is a Rev3 (full size) 
    */
    if (!IORead(pin1)) {
        if (!IORead(pin2)) {
            hardwareRevision = BJF4_REV3A;
        }
        hardwareRevision = BJF4_REV3;
    }

    if (hardwareRevision == UNKNOWN) {
        hardwareRevision = BJF4_REV2;
        return;
    }
    
    /* 
        enable the UART1 inversion PC9
        
        TODO: once param groups are in place, inverter outputs
        can be moved to be simple IO outputs, and merely set them
        HI or LO in configuration.
    */
    IO_t uart1invert = IOGetByTag(IO_TAG(PC9));
    IOInit(uart1invert, OWNER_INVERTER, RESOURCE_OUTPUT, 2);
    IOConfigGPIO(uart1invert, IOCFG_AF_PP);
    IOLo(uart1invert);    
}
bool hcsr04Detect(rangefinderDev_t *dev, const sonarConfig_t * rangefinderHardwarePins)
{
    bool detected = false;

#ifdef STM32F10X
    // enable AFIO for EXTI support
    RCC_ClockCmd(RCC_APB2(AFIO), ENABLE);
#endif

#if defined(STM32F3) || defined(STM32F4)
    RCC_ClockCmd(RCC_APB2(SYSCFG), ENABLE); // XXX Do we need this?
#endif

    triggerIO = IOGetByTag(rangefinderHardwarePins->triggerTag);
    echoIO = IOGetByTag(rangefinderHardwarePins->echoTag);

    if (IOGetOwner(triggerIO) != OWNER_FREE) {
        return false;
    }

    if (IOGetOwner(echoIO) != OWNER_FREE) {
        return false;
    }

    // trigger pin
    IOInit(triggerIO, OWNER_SONAR_TRIGGER, 0);
    IOConfigGPIO(triggerIO, IOCFG_OUT_PP);
    IOLo(triggerIO);
    delay(100);

    // echo pin
    IOInit(echoIO, OWNER_SONAR_ECHO, 0);
    IOConfigGPIO(echoIO, IOCFG_IN_FLOATING);

    // HC-SR04 echo line should be low by default and should return a response pulse when triggered
    if (IORead(echoIO) == false) {
        for (int i = 0; i < 5 && !detected; i++) {
            timeMs_t requestTime = millis();
            hcsr04_start_reading();

            while ((millis() - requestTime) < HCSR04_MinimumFiringIntervalMs) {
                if (IORead(echoIO) == true) {
                    detected = true;
                    break;
                }
            }
        }
    }

    if (detected) {
        // Hardware detected - configure the driver
#ifdef USE_EXTI
        EXTIHandlerInit(&hcsr04_extiCallbackRec, hcsr04_extiHandler);
        EXTIConfig(echoIO, &hcsr04_extiCallbackRec, NVIC_PRIO_SONAR_EXTI, EXTI_Trigger_Rising_Falling); // TODO - priority!
        EXTIEnable(echoIO, true);
#endif

        dev->delayMs = 100;
        dev->maxRangeCm = HCSR04_MAX_RANGE_CM;
        dev->detectionConeDeciDegrees = HCSR04_DETECTION_CONE_DECIDEGREES;
        dev->detectionConeExtendedDeciDegrees = HCSR04_DETECTION_CONE_EXTENDED_DECIDEGREES;

        dev->init = &hcsr04_init;
        dev->update = &hcsr04_update;
        dev->read = &hcsr04_get_distance;

        return true;
    }
    else {
        // Not detected - free resources
        IORelease(triggerIO);
        IORelease(echoIO);
        return false;
    }
}