lib/uwb_ccp/src/uwb_ccp.c
/**
 * @fn uwb_ccp_init(struct uwb_dev * inst, uint16_t nframes)
 * @brief Precise timing is achieved by adding a fixed period to the transmission time of the previous frame.
 * This approach solves the non-deterministic latencies caused by the OS. The OS, however, is used to schedule
 * the next transmission event, but the UWB tranceiver controls the actual next transmission time using the uwb_set_delay_start.
 * This function allocates all the required resources. In the case of a large scale deployment multiple instances
 * can be uses to track multiple clock domains.
 *
 * @param inst     Pointer to struct uwb_dev* dev
 * @param nframes  Nominally set to 2 frames for the simple use case. But depending on the interpolation
 * algorithm this should be set accordingly. For example, four frames are required or bicubic interpolation.
 *
 * @return struct uwb_ccp_instance *
 */
@fn uwb_ccp_init(struct uwb_dev * inst, uint16_t nframes)
@brief Precise timing is achieved by adding a fixed period to the transmission time of the previous frame.
This approach solves the non-deterministic latencies caused by the OS. The OS, however, is used to schedule
the next transmission event, but the UWB tranceiver controls the actual next transmission time using the uwb_set_delay_start.
This function allocates all the required resources. In the case of a large scale deployment multiple instances
can be uses to track multiple clock domains.

@param inst     Pointer to struct uwb_dev* dev
@param nframes  Nominally set to 2 frames for the simple use case. But depending on the interpolation
algorithm this should be set accordingly. For example, four frames are required or bicubic interpolation.


@fn uwb_ccp_init ( struct uwb_dev * inst uint16_t nframes ) @brief Precise timing is achieved by adding a fixed period to the transmission time of the previous frame . This approach solves the non - deterministic latencies caused by the OS . The OS however is used to schedule the next transmission event but the UWB tranceiver controls the actual next transmission time using the uwb_set_delay_start . This function allocates all the required resources . In the case of a large scale deployment multiple instances can be uses to track multiple clock domains . @param inst Pointer to struct uwb_dev * dev @param nframes Nominally set to 2 frames for the simple use case . But depending on the interpolation algorithm this should be set accordingly . For example four frames are required or bicubic interpolation .
struct uwb_ccp_instance *
uwb_ccp_init(struct uwb_dev* dev, uint16_t nframes)
{
    int i;
    assert(dev);
    assert(nframes > 1);
    struct uwb_ccp_instance *ccp = (struct uwb_ccp_instance*)uwb_mac_find_cb_inst_ptr(dev, UWBEXT_CCP);
    if (ccp == NULL) {
        ccp = (struct uwb_ccp_instance *) calloc(1, sizeof(struct uwb_ccp_instance) + nframes * sizeof(uwb_ccp_frame_t *));
        assert(ccp);
        ccp->status.selfmalloc = 1;
        ccp->nframes = nframes;
        uwb_ccp_frame_t ccp_default = {
            .fctrl = FCNTL_IEEE_BLINK_CCP_64,    
            .seq_num = 0xFF,
            .rpt_count = 0,
            .rpt_max = MYNEWT_VAL(UWB_CCP_MAX_CASCADE_RPTS)
        };
        for (i = 0; i < ccp->nframes; i++){
            ccp->frames[i] = (uwb_ccp_frame_t *) calloc(1, sizeof(uwb_ccp_frame_t));
            assert(ccp->frames[i]);
            memcpy(ccp->frames[i], &ccp_default, sizeof(uwb_ccp_frame_t));
            ccp->frames[i]->seq_num = 0;
        }
        ccp->dev_inst = dev;
        ccp->task_prio = dev->task_prio - 0x4;
    }else{
        assert(ccp->nframes == nframes);
    }
    ccp->period = MYNEWT_VAL(UWB_CCP_PERIOD);
    ccp->config = (struct uwb_ccp_config){
        .postprocess = false,
        .tx_holdoff_dly = MYNEWT_VAL(UWB_CCP_RPT_HOLDOFF_DLY),
    };
    dpl_error_t err = dpl_sem_init(&ccp->sem, 0x1);
    assert(err == DPL_OK);
#if MYNEWT_VAL(UWB_CCP_VERBOSE)
    uwb_ccp_set_postprocess(ccp, &ccp_postprocess);    
#endif
    ccp->cbs = (struct uwb_mac_interface){
        .id = UWBEXT_CCP,
        .inst_ptr = (void*)ccp,
        .tx_complete_cb = tx_complete_cb,
        .rx_complete_cb = rx_complete_cb,
        .rx_timeout_cb = rx_timeout_cb,
        .rx_error_cb = error_cb,
        .tx_error_cb = error_cb,
        .reset_cb = reset_cb
    };
    uwb_mac_append_interface(dev, &ccp->cbs);
    ccp_tasks_init(ccp);
    ccp->status.initialized = 1;
#if MYNEWT_VAL(UWB_CCP_STATS)
    int rc = stats_init(
                STATS_HDR(ccp->stat),
                STATS_SIZE_INIT_PARMS(ccp->stat, STATS_SIZE_32),
                STATS_NAME_INIT_PARMS(uwb_ccp_stat_section)
            );
    assert(rc == 0);
#if  MYNEWT_VAL(UWB_DEVICE_0) && !MYNEWT_VAL(UWB_DEVICE_1)
    rc = stats_register("ccp", STATS_HDR(ccp->stat));
#elif  MYNEWT_VAL(UWB_DEVICE_0) && MYNEWT_VAL(UWB_DEVICE_1)
    if (dev->idx == 0)
        rc |= stats_register("ccp0", STATS_HDR(ccp->stat));
    else
        rc |= stats_register("ccp1", STATS_HDR(ccp->stat));
#endif
    assert(rc == 0);
#endif
    return ccp;
}
struct uwb_ccp_instance * uwb_ccp_init ( struct uwb_dev * dev , uint16_t nframes ) { int i ; assert ( dev ) ; assert ( nframes > 1 ) ; struct uwb_ccp_instance * ccp = ( struct uwb_ccp_instance * ) uwb_mac_find_cb_inst_ptr ( dev , UWBEXT_CCP ) ; if ( ccp == NULL ) { ccp = ( struct uwb_ccp_instance * ) calloc ( 1 , sizeof ( struct uwb_ccp_instance ) + nframes * sizeof ( uwb_ccp_frame_t * ) ) ; assert ( ccp ) ; ccp -> status . selfmalloc = 1 ; ccp -> nframes = nframes ; uwb_ccp_frame_t ccp_default = { . fctrl = FCNTL_IEEE_BLINK_CCP_64 , . seq_num = 0xFF , . rpt_count = 0 , . rpt_max = MYNEWT_VAL ( UWB_CCP_MAX_CASCADE_RPTS ) } ; for ( i = 0 ; i < ccp -> nframes ; i ++ ) { ccp -> frames [ i ] = ( uwb_ccp_frame_t * ) calloc ( 1 , sizeof ( uwb_ccp_frame_t ) ) ; assert ( ccp -> frames [ i ] ) ; memcpy ( ccp -> frames [ i ] , & ccp_default , sizeof ( uwb_ccp_frame_t ) ) ; ccp -> frames [ i ] -> seq_num = 0 ; } ccp -> dev_inst = dev ; ccp -> task_prio = dev -> task_prio - 0x4 ; } else { assert ( ccp -> nframes == nframes ) ; } ccp -> period = MYNEWT_VAL ( UWB_CCP_PERIOD ) ; ccp -> config = ( struct uwb_ccp_config ) { . postprocess = false , . tx_holdoff_dly = MYNEWT_VAL ( UWB_CCP_RPT_HOLDOFF_DLY ) , } ; dpl_error_t err = dpl_sem_init ( & ccp -> sem , 0x1 ) ; assert ( err == DPL_OK ) ; #if MYNEWT_VAL ( UWB_CCP_VERBOSE ) uwb_ccp_set_postprocess ( ccp , & ccp_postprocess ) ; #endif ccp -> cbs = ( struct uwb_mac_interface ) { . id = UWBEXT_CCP , . inst_ptr = ( void * ) ccp , . tx_complete_cb = tx_complete_cb , . rx_complete_cb = rx_complete_cb , . rx_timeout_cb = rx_timeout_cb , . rx_error_cb = error_cb , . tx_error_cb = error_cb , . reset_cb = reset_cb } ; uwb_mac_append_interface ( dev , & ccp -> cbs ) ; ccp_tasks_init ( ccp ) ; ccp -> status . initialized = 1 ; #if MYNEWT_VAL ( UWB_CCP_STATS ) int rc = stats_init ( STATS_HDR ( ccp -> stat ) , STATS_SIZE_INIT_PARMS ( ccp -> stat , STATS_SIZE_32 ) , STATS_NAME_INIT_PARMS ( uwb_ccp_stat_section ) ) ; assert ( rc == 0 ) ; #if MYNEWT_VAL ( UWB_DEVICE_0 ) && ! MYNEWT_VAL ( UWB_DEVICE_1 ) rc = stats_register ( " " , STATS_HDR ( ccp -> stat ) ) ; #elif MYNEWT_VAL ( UWB_DEVICE_0 ) && MYNEWT_VAL ( UWB_DEVICE_1 ) if ( dev -> idx == 0 ) rc |= stats_register ( " " , STATS_HDR ( ccp -> stat ) ) ; else rc |= stats_register ( " " , STATS_HDR ( ccp -> stat ) ) ; #endif assert ( rc == 0 ) ; #endif return ccp ; }
@fn uwb_ccp_init(struct uwb_dev * inst, uint16_t nframes)
 @brief Precise timing is achieved by adding a fixed period to the transmission time of the previous frame.
@fn uwb_ccp_init ( struct uwb_dev * inst uint16_t nframes ) @brief Precise timing is achieved by adding a fixed period to the transmission time of the previous frame .
// frame control (FCNTL_IEEE_BLINK_64 to indicate a data frame using 64-bit addressing). /* TODO: fixme below */ // Using default process