/** * @brief Enables a channel de-activation edge notification. * @pre The PWM unit must have been activated using @p pwmStart(). * @pre The channel must have been activated using @p pwmEnableChannel(). * @note If the notification is already enabled then the call has no effect. * * @param[in] pwmp pointer to a @p PWMDriver object * @param[in] channel PWM channel identifier (0...channels-1) * * @api */ void pwmEnableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel) { osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels)); osalSysLock(); osalDbgAssert(pwmp->state == PWM_READY, "not ready"); osalDbgAssert((pwmp->enabled & (1 << channel)) != 0, "channel not enabled"); osalDbgAssert(pwmp->config->channels[channel].callback != NULL, "undefined channel callback"); pwmEnableChannelNotificationI(pwmp, channel); osalSysUnlock(); }
/** * @brief Read some bites from slave device. * * @param[in] owp pointer to the @p onewireDriver object * @param[out] rxbuf pointer to the buffer for read data * @param[in] rxbytes amount of data to be received */ void onewireRead(onewireDriver *owp, uint8_t *rxbuf, size_t rxbytes) { PWMDriver *pwmd; PWMConfig *pwmcfg; size_t mch, sch; osalDbgCheck((NULL != owp) && (NULL != rxbuf)); osalDbgCheck((rxbytes > 0) && (rxbytes <= ONEWIRE_MAX_TRANSACTION_LEN)); osalDbgAssert(owp->reg.state == ONEWIRE_READY, "Invalid state"); /* Buffer zeroing. This is important because of driver collects bits using |= operation.*/ memset(rxbuf, 0, rxbytes); pwmd = owp->config->pwmd; pwmcfg = owp->config->pwmcfg; mch = owp->config->master_channel; sch = owp->config->sample_channel; owp->reg.bit = 0; owp->reg.final_timeslot = false; owp->buf = rxbuf; owp->reg.bytes = rxbytes; pwmcfg->period = ONEWIRE_ZERO_WIDTH + ONEWIRE_RECOVERY_WIDTH; pwmcfg->callback = NULL; pwmcfg->channels[mch].callback = NULL; pwmcfg->channels[mch].mode = owp->config->pwmmode; pwmcfg->channels[sch].callback = pwm_read_bit_cb; pwmcfg->channels[sch].mode = PWM_OUTPUT_ACTIVE_LOW; ow_bus_active(owp); osalSysLock(); pwmEnableChannelI(pwmd, mch, ONEWIRE_ONE_WIDTH); pwmEnableChannelI(pwmd, sch, ONEWIRE_SAMPLE_WIDTH); pwmEnableChannelNotificationI(pwmd, sch); osalThreadSuspendS(&owp->thread); osalSysUnlock(); ow_bus_idle(owp); }
/** * @brief Generate reset pulse on bus. * * @param[in] owp pointer to the @p onewireDriver object * * @return Bool flag denoting device presence. * @retval true There is at least one device on bus. */ bool onewireReset(onewireDriver *owp) { PWMDriver *pwmd; PWMConfig *pwmcfg; size_t mch, sch; osalDbgCheck(NULL != owp); osalDbgAssert(owp->reg.state == ONEWIRE_READY, "Invalid state"); /* short circuit on bus or any other device transmit data */ if (PAL_LOW == ow_read_bit(owp)) return false; pwmd = owp->config->pwmd; pwmcfg = owp->config->pwmcfg; mch = owp->config->master_channel; sch = owp->config->sample_channel; pwmcfg->period = ONEWIRE_RESET_LOW_WIDTH + ONEWIRE_RESET_SAMPLE_WIDTH; pwmcfg->callback = NULL; pwmcfg->channels[mch].callback = NULL; pwmcfg->channels[mch].mode = owp->config->pwmmode; pwmcfg->channels[sch].callback = pwm_reset_cb; pwmcfg->channels[sch].mode = PWM_OUTPUT_ACTIVE_LOW; ow_bus_active(owp); osalSysLock(); pwmEnableChannelI(pwmd, mch, ONEWIRE_RESET_LOW_WIDTH); pwmEnableChannelI(pwmd, sch, ONEWIRE_RESET_SAMPLE_WIDTH); pwmEnableChannelNotificationI(pwmd, sch); osalThreadSuspendS(&owp->thread); osalSysUnlock(); ow_bus_idle(owp); /* wait until slave release bus to discriminate short circuit condition */ osalThreadSleepMicroseconds(500); return (PAL_HIGH == ow_read_bit(owp)) && (true == owp->reg.slave_present); }
/** * @brief Performs tree search on bus. * @note This function does internal 1-wire reset calls every search * iteration. * * @param[in] owp pointer to a @p OWDriver object * @param[out] result pointer to buffer for discovered ROMs * @param[in] max_rom_cnt buffer size in ROMs count for overflow prevention * * @return Count of discovered ROMs. May be more than max_rom_cnt. * @retval 0 no ROMs found or communication error occurred. */ size_t onewireSearchRom(onewireDriver *owp, uint8_t *result, size_t max_rom_cnt) { PWMDriver *pwmd; PWMConfig *pwmcfg; uint8_t cmd; size_t mch, sch; osalDbgCheck(NULL != owp); osalDbgAssert(ONEWIRE_READY == owp->reg.state, "Invalid state"); osalDbgCheck((max_rom_cnt <= 256) && (max_rom_cnt > 0)); pwmd = owp->config->pwmd; pwmcfg = owp->config->pwmcfg; cmd = ONEWIRE_CMD_SEARCH_ROM; mch = owp->config->master_channel; sch = owp->config->sample_channel; search_clean_start(&owp->search_rom); do { /* every search must be started from reset pulse */ if (false == onewireReset(owp)) return 0; /* initialize buffer to store result */ if (owp->search_rom.reg.devices_found >= max_rom_cnt) owp->search_rom.retbuf = result + 8*(max_rom_cnt-1); else owp->search_rom.retbuf = result + 8*owp->search_rom.reg.devices_found; memset(owp->search_rom.retbuf, 0, 8); /* clean iteration state */ search_clean_iteration(&owp->search_rom); /**/ onewireWrite(&OWD1, &cmd, 1, 0); /* Reconfiguration always needed because of previous call onewireWrite.*/ pwmcfg->period = ONEWIRE_ZERO_WIDTH + ONEWIRE_RECOVERY_WIDTH; pwmcfg->callback = NULL; pwmcfg->channels[mch].callback = NULL; pwmcfg->channels[mch].mode = owp->config->pwmmode; pwmcfg->channels[sch].callback = pwm_search_rom_cb; pwmcfg->channels[sch].mode = PWM_OUTPUT_ACTIVE_LOW; ow_bus_active(owp); osalSysLock(); pwmEnableChannelI(pwmd, mch, ONEWIRE_ONE_WIDTH); pwmEnableChannelI(pwmd, sch, ONEWIRE_SAMPLE_WIDTH); pwmEnableChannelNotificationI(pwmd, sch); osalThreadSuspendS(&owp->thread); osalSysUnlock(); ow_bus_idle(owp); if (ONEWIRE_SEARCH_ROM_ERROR != owp->search_rom.reg.result) { /* check CRC and return 0 (0 == error) if mismatch */ if (owp->search_rom.retbuf[7] != onewireCRC(owp->search_rom.retbuf, 7)) return 0; /* store cached result for usage in next iteration */ memcpy(owp->search_rom.prev_path, owp->search_rom.retbuf, 8); } } while (ONEWIRE_SEARCH_ROM_SUCCESS == owp->search_rom.reg.result); /**/ if (ONEWIRE_SEARCH_ROM_ERROR == owp->search_rom.reg.result) return 0; else return owp->search_rom.reg.devices_found; }