obcsim/msp_obc_link.c
struct msp_response msp_send_header_frame(msp_link_t *lnk)
{
	struct msp_response r;
	int code;
	struct msp_obc_frame frame;
	unsigned long len;

	if (lnk == NULL || lnk->buffer == NULL)
		return msp_response_error(MSP_OBC_ERR_NULL_POINTER);

	if (lnk->next_action != MSP_LINK_ACTION_TX_HEADER) {
		lnk->corrupt_frame_count += 1;
		return msp_response_error(MSP_OBC_ERR_INVALID_ACTION);
	}

	/* Determine which type of header to send */
	switch (lnk->state) {
	case MSP_LINK_STATE_SEND_TX_HEADER:
		frame.type = MSP_OBC_FRAME_HEADER;
		frame.id = lnk->transaction_id;
		frame.opcode = lnk->opcode;
		frame.dl = lnk->total_length;
		break;
	case MSP_LINK_STATE_REQ_TX_HEADER:
		/* Send request header (DL0, FID0) */
		frame.type = MSP_OBC_FRAME_HEADER;
		frame.id = 0;
		frame.opcode = lnk->opcode;
		frame.dl = 0;
		break;
	case MSP_LINK_STATE_REQ_RX_DATA:
		frame.type = MSP_OBC_FRAME_HEADER;
		if (msp_next_data_length(lnk) == 0) {
			frame.id = lnk->transaction_id;
			frame.opcode = MSP_OP_T_ACK;
			frame.dl = 0;
			msp_debug_int("formatting T_ACK with id ", frame.id);
		} else {
			frame.id = lnk->frame_id;
			frame.opcode = MSP_OP_F_ACK;
			frame.dl = 0;
			msp_debug_int("formatting F_ACK with id ", frame.id);
		}
		break;
	default:
		msp_debug("Invalid state at 1st switch statement in msp_send_header_frame");
		return msp_response_error(MSP_OBC_ERR_INVALID_STATE);
	}
	
	code = msp_obc_encode_frame(lnk, lnk->buffer, &len, frame);
	if (code) {
		lnk->corrupt_frame_count += 1;
		return msp_response_error(code);
	}

	code = msp_i2c_write(lnk->slave_address, lnk->buffer, len);
	if (code) {
		lnk->corrupt_frame_count += 1;
		return msp_response_error(MSP_OBC_ERR_I2C_ERROR);
	}

	/* Now check what the next action should be */
	if (frame.opcode == MSP_OP_T_ACK) {
		msp_seqflags_set(&lnk->flags, lnk->opcode, lnk->transaction_id);
		r = msp_response_successful(lnk);
		msp_set_as_ready(lnk);
		return r;
	}

	switch (lnk->state) {
	case MSP_LINK_STATE_SEND_TX_HEADER:
		/* Should read an ACK next */
		lnk->next_action = MSP_LINK_ACTION_RX_HEADER;
		break;
	case MSP_LINK_STATE_REQ_TX_HEADER:
		/* Should read the response header next */
		lnk->state = MSP_LINK_STATE_REQ_RX_RESPONSE;
		lnk->next_action = MSP_LINK_ACTION_RX_HEADER;
		break;
	case MSP_LINK_STATE_REQ_RX_DATA:
		/* Should read a data frame next */
		lnk->next_action = MSP_LINK_ACTION_RX_DATA;
		break;
	default:
		msp_debug("Invalid state at 2nd switch statement in msp_send_header_frame");
		lnk->corrupt_frame_count += 1;
		return msp_response_error(MSP_OBC_ERR_INVALID_STATE);
	}

	return msp_response_ok();
}
/*
 * Blocking (send over I2C)
 *
 * Sends a header frame to the experiment. The exact type of header frame that
 * is sent is determined by the state that the link is in.
 *
 * This function will also update the state of the link.
 *
 * If the link is in an incorrect state or if any of the inputs are invalid
 * then no I2C transmission will be made and an error will be returned.
 */
Blocking (send over I2C)

Sends a header frame to the experiment. The exact type of header frame that
is sent is determined by the state that the link is in.

This function will also update the state of the link.

If the link is in an incorrect state or if any of the inputs are invalid
then no I2C transmission will be made and an error will be returned.
Blocking ( send over I2C ) Sends a header frame to the experiment . The exact type of header frame that is sent is determined by the state that the link is in . This function will also update the state of the link . If the link is in an incorrect state or if any of the inputs are invalid then no I2C transmission will be made and an error will be returned .
struct msp_response msp_send_header_frame(msp_link_t *lnk)
{
	struct msp_response r;
	int code;
	struct msp_obc_frame frame;
	unsigned long len;
	if (lnk == NULL || lnk->buffer == NULL)
		return msp_response_error(MSP_OBC_ERR_NULL_POINTER);
	if (lnk->next_action != MSP_LINK_ACTION_TX_HEADER) {
		lnk->corrupt_frame_count += 1;
		return msp_response_error(MSP_OBC_ERR_INVALID_ACTION);
	}
	switch (lnk->state) {
	case MSP_LINK_STATE_SEND_TX_HEADER:
		frame.type = MSP_OBC_FRAME_HEADER;
		frame.id = lnk->transaction_id;
		frame.opcode = lnk->opcode;
		frame.dl = lnk->total_length;
		break;
	case MSP_LINK_STATE_REQ_TX_HEADER:
		frame.type = MSP_OBC_FRAME_HEADER;
		frame.id = 0;
		frame.opcode = lnk->opcode;
		frame.dl = 0;
		break;
	case MSP_LINK_STATE_REQ_RX_DATA:
		frame.type = MSP_OBC_FRAME_HEADER;
		if (msp_next_data_length(lnk) == 0) {
			frame.id = lnk->transaction_id;
			frame.opcode = MSP_OP_T_ACK;
			frame.dl = 0;
			msp_debug_int("formatting T_ACK with id ", frame.id);
		} else {
			frame.id = lnk->frame_id;
			frame.opcode = MSP_OP_F_ACK;
			frame.dl = 0;
			msp_debug_int("formatting F_ACK with id ", frame.id);
		}
		break;
	default:
		msp_debug("Invalid state at 1st switch statement in msp_send_header_frame");
		return msp_response_error(MSP_OBC_ERR_INVALID_STATE);
	}
	code = msp_obc_encode_frame(lnk, lnk->buffer, &len, frame);
	if (code) {
		lnk->corrupt_frame_count += 1;
		return msp_response_error(code);
	}
	code = msp_i2c_write(lnk->slave_address, lnk->buffer, len);
	if (code) {
		lnk->corrupt_frame_count += 1;
		return msp_response_error(MSP_OBC_ERR_I2C_ERROR);
	}
	if (frame.opcode == MSP_OP_T_ACK) {
		msp_seqflags_set(&lnk->flags, lnk->opcode, lnk->transaction_id);
		r = msp_response_successful(lnk);
		msp_set_as_ready(lnk);
		return r;
	}
	switch (lnk->state) {
	case MSP_LINK_STATE_SEND_TX_HEADER:
		lnk->next_action = MSP_LINK_ACTION_RX_HEADER;
		break;
	case MSP_LINK_STATE_REQ_TX_HEADER:
		lnk->state = MSP_LINK_STATE_REQ_RX_RESPONSE;
		lnk->next_action = MSP_LINK_ACTION_RX_HEADER;
		break;
	case MSP_LINK_STATE_REQ_RX_DATA:
		lnk->next_action = MSP_LINK_ACTION_RX_DATA;
		break;
	default:
		msp_debug("Invalid state at 2nd switch statement in msp_send_header_frame");
		lnk->corrupt_frame_count += 1;
		return msp_response_error(MSP_OBC_ERR_INVALID_STATE);
	}
	return msp_response_ok();
}
struct msp_response msp_send_header_frame ( msp_link_t * lnk ) { struct msp_response r ; int code ; struct msp_obc_frame frame ; unsigned long len ; if ( lnk == NULL || lnk -> buffer == NULL ) return msp_response_error ( MSP_OBC_ERR_NULL_POINTER ) ; if ( lnk -> next_action != MSP_LINK_ACTION_TX_HEADER ) { lnk -> corrupt_frame_count += 1 ; return msp_response_error ( MSP_OBC_ERR_INVALID_ACTION ) ; } switch ( lnk -> state ) { case MSP_LINK_STATE_SEND_TX_HEADER : frame . type = MSP_OBC_FRAME_HEADER ; frame . id = lnk -> transaction_id ; frame . opcode = lnk -> opcode ; frame . dl = lnk -> total_length ; break ; case MSP_LINK_STATE_REQ_TX_HEADER : frame . type = MSP_OBC_FRAME_HEADER ; frame . id = 0 ; frame . opcode = lnk -> opcode ; frame . dl = 0 ; break ; case MSP_LINK_STATE_REQ_RX_DATA : frame . type = MSP_OBC_FRAME_HEADER ; if ( msp_next_data_length ( lnk ) == 0 ) { frame . id = lnk -> transaction_id ; frame . opcode = MSP_OP_T_ACK ; frame . dl = 0 ; msp_debug_int ( " " , frame . id ) ; } else { frame . id = lnk -> frame_id ; frame . opcode = MSP_OP_F_ACK ; frame . dl = 0 ; msp_debug_int ( " " , frame . id ) ; } break ; default : msp_debug ( " " ) ; return msp_response_error ( MSP_OBC_ERR_INVALID_STATE ) ; } code = msp_obc_encode_frame ( lnk , lnk -> buffer , & len , frame ) ; if ( code ) { lnk -> corrupt_frame_count += 1 ; return msp_response_error ( code ) ; } code = msp_i2c_write ( lnk -> slave_address , lnk -> buffer , len ) ; if ( code ) { lnk -> corrupt_frame_count += 1 ; return msp_response_error ( MSP_OBC_ERR_I2C_ERROR ) ; } if ( frame . opcode == MSP_OP_T_ACK ) { msp_seqflags_set ( & lnk -> flags , lnk -> opcode , lnk -> transaction_id ) ; r = msp_response_successful ( lnk ) ; msp_set_as_ready ( lnk ) ; return r ; } switch ( lnk -> state ) { case MSP_LINK_STATE_SEND_TX_HEADER : lnk -> next_action = MSP_LINK_ACTION_RX_HEADER ; break ; case MSP_LINK_STATE_REQ_TX_HEADER : lnk -> state = MSP_LINK_STATE_REQ_RX_RESPONSE ; lnk -> next_action = MSP_LINK_ACTION_RX_HEADER ; break ; case MSP_LINK_STATE_REQ_RX_DATA : lnk -> next_action = MSP_LINK_ACTION_RX_DATA ; break ; default : msp_debug ( " " ) ; lnk -> corrupt_frame_count += 1 ; return msp_response_error ( MSP_OBC_ERR_INVALID_STATE ) ; } return msp_response_ok ( ) ; }
Blocking (send over I2C)
Blocking ( send over I2C )
/* Determine which type of header to send */ /* Send request header (DL0, FID0) */ /* Now check what the next action should be */ /* Should read an ACK next */ /* Should read the response header next */ /* Should read a data frame next */