lib/uwb_ccp/src/uwb_ccp.c
/**
 * @fn tx_complete_cb(struct uwb_dev * inst, struct uwb_mac_interface * cbs)
 * @brief Precise timing is achieved by adding a fixed period to the transmission time of the previous frame. This static
 * function is called on successful transmission of a CCP packet, and this advances the frame index point. Circular addressing is used
 * for the frame addressing. The next dpl_event is scheduled to occur in (MYNEWT_VAL(UWB_CCP_PERIOD) - MYNEWT_VAL(UWB_CCP_OS_LATENCY)) usec
 * from now. This provided a context switch guard zone. The assumption is that the underlying OS will have sufficient time start
 * the call uwb_set_delay_start within ccp_blink.
 *
 * @param inst   Pointer to struct uwb_dev.
 * @param cbs    Pointer to struct uwb_mac_interface.
 *
 * @return bool
 */
@fn tx_complete_cb(struct uwb_dev * inst, struct uwb_mac_interface * cbs)
@brief Precise timing is achieved by adding a fixed period to the transmission time of the previous frame. This static
function is called on successful transmission of a CCP packet, and this advances the frame index point. Circular addressing is used
for the frame addressing.

@param inst   Pointer to struct uwb_dev.
@param cbs    Pointer to struct uwb_mac_interface.

@return bool
@fn tx_complete_cb ( struct uwb_dev * inst struct uwb_mac_interface * cbs ) @brief Precise timing is achieved by adding a fixed period to the transmission time of the previous frame . This static function is called on successful transmission of a CCP packet and this advances the frame index point . Circular addressing is used for the frame addressing . @param inst Pointer to struct uwb_dev . @param cbs Pointer to struct uwb_mac_interface . @return bool
static bool
tx_complete_cb(struct uwb_dev * inst, struct uwb_mac_interface * cbs)
{
    int rc;
    struct uwb_ccp_instance * ccp = (struct uwb_ccp_instance *)cbs->inst_ptr;
    if(dpl_sem_get_count(&ccp->sem) == 1)
        return false;
    CCP_STATS_INC(tx_complete);
    if (ccp->config.role != CCP_ROLE_MASTER)
        return false;
    uwb_ccp_frame_t * frame = ccp->frames[(++ccp->idx)%ccp->nframes];
    uint32_t delta_0 = 0xffffffffU&(uwb_read_systime_lo32(inst) - frame->transmission_timestamp.lo);
    ccp->os_epoch = dpl_cputime_get32();
    uint32_t delta_1 = 0xffffffffU&(uwb_read_systime_lo32(inst) - frame->transmission_timestamp.lo);
    uint32_t delta = (delta_0>>1) + (delta_1>>1);
    ccp->os_epoch -= dpl_cputime_usecs_to_ticks(uwb_dwt_usecs_to_usecs(delta>>16));
    CCP_STATS_SET(irq_latency, uwb_dwt_usecs_to_usecs(delta>>16));
    ccp->local_epoch = frame->transmission_timestamp.lo;
    ccp->master_epoch = frame->transmission_timestamp;
    ccp->period = (frame->transmission_interval >> 16);
    adjust_for_epoch_to_rm(ccp, frame->epoch_to_rm_us);
    if (ccp->status.timer_enabled){
        rc = dpl_cputime_timer_start(&ccp->timer, ccp->os_epoch
            - dpl_cputime_usecs_to_ticks(MYNEWT_VAL(OS_LATENCY))
            + dpl_cputime_usecs_to_ticks(uwb_dwt_usecs_to_usecs(ccp->period))
        );
        if (rc == 0) ccp->status.timer_restarted = 1;
    }
    ccp->status.valid |= ccp->idx > 1;
    struct uwb_mac_interface * lcbs = NULL;
    if(!(SLIST_EMPTY(&inst->interface_cbs))) {
        SLIST_FOREACH(lcbs, &inst->interface_cbs, next) {
            if (lcbs != NULL && lcbs->superframe_cb) {
                if(lcbs->superframe_cb((struct uwb_dev*)inst, lcbs)) continue;
            }
        }
    }
    if (ccp->config.postprocess && ccp->status.valid)
        dpl_eventq_put(dpl_eventq_dflt_get(), &ccp->postprocess_event);
    if(dpl_sem_get_count(&ccp->sem) == 0){
        dpl_error_t err = dpl_sem_release(&ccp->sem);
        assert(err == DPL_OK);
    }
    return false;
}
static bool tx_complete_cb ( struct uwb_dev * inst , struct uwb_mac_interface * cbs ) { int rc ; struct uwb_ccp_instance * ccp = ( struct uwb_ccp_instance * ) cbs -> inst_ptr ; if ( dpl_sem_get_count ( & ccp -> sem ) == 1 ) return false ; CCP_STATS_INC ( tx_complete ) ; if ( ccp -> config . role != CCP_ROLE_MASTER ) return false ; uwb_ccp_frame_t * frame = ccp -> frames [ ( ++ ccp -> idx ) % ccp -> nframes ] ; uint32_t delta_0 = 0xffffffffU & ( uwb_read_systime_lo32 ( inst ) - frame -> transmission_timestamp . lo ) ; ccp -> os_epoch = dpl_cputime_get32 ( ) ; uint32_t delta_1 = 0xffffffffU & ( uwb_read_systime_lo32 ( inst ) - frame -> transmission_timestamp . lo ) ; uint32_t delta = ( delta_0 >> 1 ) + ( delta_1 >> 1 ) ; ccp -> os_epoch -= dpl_cputime_usecs_to_ticks ( uwb_dwt_usecs_to_usecs ( delta >> 16 ) ) ; CCP_STATS_SET ( irq_latency , uwb_dwt_usecs_to_usecs ( delta >> 16 ) ) ; ccp -> local_epoch = frame -> transmission_timestamp . lo ; ccp -> master_epoch = frame -> transmission_timestamp ; ccp -> period = ( frame -> transmission_interval >> 16 ) ; adjust_for_epoch_to_rm ( ccp , frame -> epoch_to_rm_us ) ; if ( ccp -> status . timer_enabled ) { rc = dpl_cputime_timer_start ( & ccp -> timer , ccp -> os_epoch - dpl_cputime_usecs_to_ticks ( MYNEWT_VAL ( OS_LATENCY ) ) + dpl_cputime_usecs_to_ticks ( uwb_dwt_usecs_to_usecs ( ccp -> period ) ) ) ; if ( rc == 0 ) ccp -> status . timer_restarted = 1 ; } ccp -> status . valid |= ccp -> idx > 1 ; struct uwb_mac_interface * lcbs = NULL ; if ( ! ( SLIST_EMPTY ( & inst -> interface_cbs ) ) ) { SLIST_FOREACH ( lcbs , & inst -> interface_cbs , next ) { if ( lcbs != NULL && lcbs -> superframe_cb ) { if ( lcbs -> superframe_cb ( ( struct uwb_dev * ) inst , lcbs ) ) continue ; } } } if ( ccp -> config . postprocess && ccp -> status . valid ) dpl_eventq_put ( dpl_eventq_dflt_get ( ) , & ccp -> postprocess_event ) ; if ( dpl_sem_get_count ( & ccp -> sem ) == 0 ) { dpl_error_t err = dpl_sem_release ( & ccp -> sem ) ; assert ( err == DPL_OK ) ; } return false ; }
@fn tx_complete_cb(struct uwb_dev * inst, struct uwb_mac_interface * cbs)
 @brief Precise timing is achieved by adding a fixed period to the transmission time of the previous frame.
@fn tx_complete_cb ( struct uwb_dev * inst struct uwb_mac_interface * cbs ) @brief Precise timing is achieved by adding a fixed period to the transmission time of the previous frame .
/* Read os_time and correct for interrupt latency */ /* Adjust for delay between epoch and rmarker */ /* Call all available superframe callbacks */