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); } } }
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); } } }
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); }
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); } }
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 }
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; }
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; } }