summaryrefslogtreecommitdiff
path: root/hal/phy
diff options
context:
space:
mode:
authorburet2007-07-17 13:59:13 +0000
committerburet2007-07-17 13:59:13 +0000
commit523cf6952b845075c2b5efcb70222d22520c4918 (patch)
tree5c40c7b9669076b3be346575b5b1a3835dc990d2 /hal/phy
parentcbb620e9e4101abefb7c2bce938ecd574c4469f3 (diff)
HAL Phy Maximus:
- handle separately PRS0 and PRS1 phy messages + tests - update rx/tx mode - update medium state git-svn-id: svn+ssh://pessac/svn/cesar/trunk@488 017c9cb6-072f-447c-8318-d5b54f68fe89
Diffstat (limited to 'hal/phy')
-rw-r--r--hal/phy/maximus/inc/maximus_phy_access.h25
-rw-r--r--hal/phy/maximus/inc/maximus_phy_ctx.h20
-rw-r--r--hal/phy/maximus/src/maximus_phy_access.c368
-rw-r--r--hal/phy/maximus/src/maximus_phy_ctrl.c122
-rw-r--r--hal/phy/maximus/test/src/test_phy_access.c200
-rw-r--r--hal/phy/maximus/test/src/test_phy_ctrl.c11
6 files changed, 596 insertions, 150 deletions
diff --git a/hal/phy/maximus/inc/maximus_phy_access.h b/hal/phy/maximus/inc/maximus_phy_access.h
index 4125fe1bad..4505b1f59d 100644
--- a/hal/phy/maximus/inc/maximus_phy_access.h
+++ b/hal/phy/maximus/inc/maximus_phy_access.h
@@ -29,6 +29,26 @@ struct maximus_phy_access_backoff_t
typedef struct maximus_phy_access_backoff_t maximus_phy_access_backoff_t;
/**
+ * Maximus access slot count callback called when the corresponding netclock message is received.
+ * \param data pointer to phy_t structure.
+ */
+void maximus_phy_access_slot_count_cb (void *data);
+
+/**
+ * Maximus access PRS0 callback called when the corresponding netclock message is received,
+ * i.e. at the end of the PRS0.
+ * \param data pointer to phy_t structure.
+ */
+void maximus_phy_access_prs0_cb (void *data);
+
+/**
+ * Maximus access PRS1 callback called when the corresponding netclock message is received,
+ * i.e. at the end of the PRS1.
+ * \param data pointer to phy_t structure.
+ */
+void maximus_phy_access_prs1_cb (void *data);
+
+/**
* Maximus access timer program callback called when the corresponding netclock message is received.
*/
void maximus_phy_access_timer_cb (void *data);
@@ -41,9 +61,4 @@ struct maximus_phy_access_timer_t
};
typedef struct maximus_phy_access_timer_t maximus_phy_access_timer_t;
-/**
- * Maximus slot count callback called when the corresponding netclock message is received.
- */
-void maximus_phy_slot_count_cb (void *data);
-
#endif /* hal_phy_maximus_inc_maximus_phy_access_h */
diff --git a/hal/phy/maximus/inc/maximus_phy_ctx.h b/hal/phy/maximus/inc/maximus_phy_ctx.h
index 8f293f6c82..25639e169a 100644
--- a/hal/phy/maximus/inc/maximus_phy_ctx.h
+++ b/hal/phy/maximus/inc/maximus_phy_ctx.h
@@ -24,12 +24,11 @@
enum medium_state_t
{
- MAXIMUS_PHY_MEDIUM_NONE = 0x00,
- MAXIMUS_PHY_MEDIUM_PRE_DETECTED = 0x01,
- MAXIMUS_PHY_MEDIUM_BUSY_RX = 0x01,
- MAXIMUS_PHY_MEDIUM_PRP = 0x03,
- MAXIMUS_PHY_MEDIUM_BUSY_TX = 0x02,
- MAXIMUS_PHY_MEDIUM_IDLE = 0x04
+ MAXIMUS_PHY_MEDIUM_IDLE = 0x00,
+ MAXIMUS_PHY_MEDIUM_BUSY = 0x01,
+ MAXIMUS_PHY_MEDIUM_PRS0 = 0x02,
+ MAXIMUS_PHY_MEDIUM_PRS1 = 0x03,
+ MAXIMUS_PHY_MEDIUM_CW = 0x04
};
typedef enum medium_state_t medium_state_t;
@@ -38,9 +37,13 @@ struct maximus_phy_access_t
{
/** Channel access priority. Priority to assert in next PRP. Can be changed at anytime (by 'phy_access_backoff_update'). */
u8 cap_mpdu;
+ /** Current CAP asserted in previous PRP. */
+ u8 cap_sent;
+ /** Medium CAP decoded in previous PRP. */
+ u8 cap_medium;
/** Number of slots measured since end of PRP and before PRE detection. */
uint slot_count;
- /** Possible values are: NONE, BUSY_RX, BUSY_TX, PRP, IDLE. */
+ /** Possible values are: IDLE, BUSY, PRS0, PRS1, CW. */
medium_state_t medium_state;
/** PRP result. */
bool prp_result;
@@ -48,6 +51,7 @@ struct maximus_phy_access_t
netclock_id_t netclock_id;
/** Callback contexts to insert into callback queue. */
netclock_callback_t *access_backoff_netclock_cb;
+ netclock_callback_t *access_slot_count_netclock_cb;
netclock_callback_t *access_timer_netclock_cb;
};
typedef struct maximus_phy_access_t maximus_phy_access_t;
@@ -79,6 +83,8 @@ struct maximus_phy_ctrl_t
phy_fc_mode_t fc_mode;
/** Used to enable or disable PRE detection. */
bool pre_detection;
+ /** Used to set RX mode (true) or TX mode (false).*/
+ bool rx_tx_mode;
/** Callback contexts to insert into callback queue. */
netclock_callback_t *tx_frame_netclock_cb;
netclock_callback_t *rx_activate_netclock_cb;
diff --git a/hal/phy/maximus/src/maximus_phy_access.c b/hal/phy/maximus/src/maximus_phy_access.c
index 0a4a8e74e7..90037faa89 100644
--- a/hal/phy/maximus/src/maximus_phy_access.c
+++ b/hal/phy/maximus/src/maximus_phy_access.c
@@ -30,11 +30,8 @@ extern uint32_t maximus_pending_isrs;
*/
void maximus_phy_access_backoff_cb (void *data)
{
- /* At the corresponding event reception, this function is called with the given cap as argument.
- * For simulation, all stations send a PHY SCI message with PRS0 and PRS1,
- * i.e. this callback has to send a phy message containing PRS0 and PRS1 symbols (i.e. cap on 1 octet).
- * Maximus simulator will answer with a PHY message giving the PRP result (won/lost). */
-
+ /* At the corresponding event reception, this function is called with the given cap as argument. */
+
if (NULL == data)
{
errno = EINVAL;
@@ -49,77 +46,307 @@ void maximus_phy_access_backoff_cb (void *data)
}
else
{
- // for phy message
- unsigned char buffer[SCI_MSG_MAX_SIZE];
- sci_msg_t msg;
-
// for netclock message
netclock_id_t id;
uint32_t tick_high, tick_low;
tick_t schedule_tick;
+
+ // update medium state
+ access_backoff_data->ctx->access.medium_state = MAXIMUS_PHY_MEDIUM_PRS0;
+
+ // set tx mode
+ access_backoff_data->ctx->control.rx_tx_mode = false;
- // init for phy message
- memset(buffer, '\0', SCI_MSG_MAX_SIZE);
+ // update cap mpdu
+ access_backoff_data->ctx->access.cap_mpdu = access_backoff_data->cap;
+
+ // update cap sent
+ access_backoff_data->ctx->access.cap_sent = access_backoff_data->ctx->access.cap_mpdu;
+
+ // reset cap medium
+ access_backoff_data->ctx->access.cap_medium = 0;
+
+ // reset prp result
+ access_backoff_data->ctx->access.prp_result = false;
+
+ // reset slot counter
+ access_backoff_data->ctx->access.slot_count = 0;
+
+ /* Send a netclock message to Maximus simulator scheduled in a slot time,
+ * to increment slot counter. */
+
+ tick_high = my_station.current_tick_tck >> 32;
+ tick_low = (my_station.current_tick_tck & 0x00000000ffffffff) + 896; // schedule_tick = slot_time / maximus_tick = 35.84us / 40ns = 896 ticks
+ schedule_tick = (((unsigned long long)(tick_high)) << 32) | (unsigned long long)(tick_low);
+
+ netclock_schedule(my_station.netclock,
+ access_backoff_data->ctx->access.access_slot_count_netclock_cb,
+ NETWORK_CLOCK_TYPE_STATION,
+ schedule_tick,
+ &maximus_phy_access_slot_count_cb,
+ (void*)access_backoff_data->ctx,
+ &id);
+
+ /* Send a netclock message to Maximus simulator scheduled in a slot time,
+ * to send PRS1 (depending on PRS0). */
+
+ netclock_schedule(my_station.netclock,
+ access_backoff_data->ctx->access.access_backoff_netclock_cb,
+ NETWORK_CLOCK_TYPE_STATION,
+ schedule_tick,
+ &maximus_phy_access_prs0_cb,
+ (void*)access_backoff_data->ctx,
+ &id);
+
+ /* According to the CAP value, PHY emits or reads PRS0 and PRS1:
+ * - if CAP = 3, PHY emits PRS0 (= 1) and PRS1 (= 1);
+ * - if CAP = 2, PHY emits PRS0 (= 1) and reads PRS1;
+ * - if CAP = 1, PHY reads PRS0:
+ * - if PRS0 = 0, PHY emits PRS1 (= 1);
+ * - if PRS0 = 1, PHY reads PRS1;
+ * - if CAP = 0, PHY reads PRS0 and PRS1. */
+
+ if (2 <= access_backoff_data->ctx->access.cap_mpdu)
+ {
+ /* PHY emits PRS0. */
+
+ // for phy sci message
+ unsigned char buffer[SCI_MSG_MAX_SIZE];
+ sci_msg_t msg;
+
+ // init for phy sci message
+ memset(buffer, '\0', SCI_MSG_MAX_SIZE);
+
+ if (0 == sci_msg_init(&msg, buffer, SCI_MSG_MAX_SIZE))
+ {
+ // for phy message
+ uint32_t nek[4];
+ uint32_t pb_measurement[PHY_PB_MAX_NB];
+ uint32_t pb_header[PHY_PB_MAX_NB];
+ uint8_t prs0 = 1;
+
+ // init for phy message
+ memset(nek, '\0', 4*sizeof(uint32_t));
+ memset(pb_measurement, '\0', PHY_PB_MAX_NB*sizeof(uint32_t));
+ memset(pb_header, '\0', PHY_PB_MAX_NB*sizeof(uint32_t));
+
+ /* Send phy message containing PRS0. */
+
+ // fill sci data
+ if (sizeof(uint8_t) == sci_msg_push(&msg, sizeof(uint8_t)))
+ {
+ memcpy(msg.data_begin, &prs0, sizeof(u8));
+ }
+
+ // fill phy header
+ maximus_phy_fill_hdr(access_backoff_data->ctx,
+ &msg,
+ PHY_TYPE_PRS,
+ PHY_MPDU_FORMAT_NONE,
+ 0, // pb_nb
+ (uint8_t)access_backoff_data->ctx->tm_dma.tonemap_index,
+ PHY_FLAG_CRC_OK,
+ nek,
+ pb_measurement,
+ pb_header);
+
+ // fill sci header
+ sci_fill_hdr(my_station.sci, &msg, SCI_MSG_TYPE_PHY, 0 /* flags */);
+
+ // send message
+ sci_send(my_station.sci, &msg);
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * Maximus access slot count callback called when the corresponding netclock message is received.
+ * \param data pointer to phy_t structure.
+ */
+void
+maximus_phy_access_slot_count_cb (void *data)
+{
+ if (NULL == data)
+ {
+ errno = EINVAL;
+ }
+ else
+ {
+ // for netclock message
+ netclock_id_t id;
+ uint32_t tick_high, tick_low;
+ tick_t schedule_tick;
+
+ // increment slot count
+ phy_t *ctx = (phy_t*)data;
+ ctx->access.slot_count++;
+
+ if ((MAXIMUS_PHY_MEDIUM_PRS0 == ctx->access.medium_state)
+ || (MAXIMUS_PHY_MEDIUM_PRS1 == ctx->access.medium_state)
+ || (MAXIMUS_PHY_MEDIUM_CW == ctx->access.medium_state))
+ {
+ /* During PRP, send a netclock message to Maximus simulator scheduled in a slot time,
+ * to increment slot counter. */
+
+ tick_high = my_station.current_tick_tck >> 32;
+ tick_low = (my_station.current_tick_tck & 0x00000000ffffffff) + 896; // schedule_tick = slot_time / maximus_tick = 35.84us / 40ns = 896 ticks
+ schedule_tick = (((unsigned long long)(tick_high)) << 32) | (unsigned long long)(tick_low);
+ netclock_schedule(my_station.netclock,
+ ctx->access.access_backoff_netclock_cb,
+ NETWORK_CLOCK_TYPE_STATION,
+ schedule_tick,
+ &maximus_phy_access_slot_count_cb,
+ (void*)ctx,
+ &id);
+ }
+ }
+}
+
+
+/**
+ * Maximus access PRS0 callback called when the corresponding netclock message is received,
+ * i.e. at the end of the PRS0.
+ * \param data pointer to phy_t structure.
+ */
+void
+maximus_phy_access_prs0_cb (void *data)
+{
+ if (NULL == data)
+ {
+ errno = EINVAL;
+ }
+ else
+ {
+ phy_t *ctx = (phy_t*)data;
+
+ // for netclock message
+ netclock_id_t id;
+ uint32_t tick_high, tick_low;
+ tick_t schedule_tick;
+
+ // update medium state
+ ctx->access.medium_state = MAXIMUS_PHY_MEDIUM_PRS1;
+
+ /* Send a netclock message to Maximus simulator scheduled in a slot time,
+ * to compute prp result. */
+
+ tick_high = my_station.current_tick_tck >> 32;
+ tick_low = (my_station.current_tick_tck & 0x00000000ffffffff) + 896; // schedule_tick = slot_time / maximus_tick = 35.84us / 40ns = 896 ticks
+ schedule_tick = (((unsigned long long)(tick_high)) << 32) | (unsigned long long)(tick_low);
+
+ netclock_schedule(my_station.netclock,
+ ctx->access.access_backoff_netclock_cb,
+ NETWORK_CLOCK_TYPE_STATION,
+ schedule_tick,
+ &maximus_phy_access_prs1_cb,
+ (void*)ctx,
+ &id);
+
+ /* According to the CAP value, PHY emits or reads PRS0 and PRS1:
+ * - if CAP = 3, PHY emits PRS0 (= 1) and PRS1 (= 1);
+ * - if CAP = 2, PHY emits PRS0 (= 1) and reads PRS1;
+ * - if CAP = 1, PHY reads PRS0:
+ * - if PRS0 = 0, PHY emits PRS1 (= 1);
+ * - if PRS0 = 1, PHY reads PRS1;
+ * - if CAP = 0, PHY reads PRS0 and PRS1. */
+
+ if ((3 == ctx->access.cap_mpdu)
+ || ((1 == ctx->access.cap_mpdu)
+ && (1 >= ctx->access.cap_medium)))
+ {
+ /* PHY emits PRS1. */
+
+ // for phy sci message
+ unsigned char buffer[SCI_MSG_MAX_SIZE];
+ sci_msg_t msg;
+
+ // init for phy sci message
+ memset(buffer, '\0', SCI_MSG_MAX_SIZE);
+
if (0 == sci_msg_init(&msg, buffer, SCI_MSG_MAX_SIZE))
{
// for phy message
uint32_t nek[4];
uint32_t pb_measurement[PHY_PB_MAX_NB];
uint32_t pb_header[PHY_PB_MAX_NB];
+ u8 prs1 = 1;
// init for phy message
memset(nek, '\0', 4*sizeof(uint32_t));
memset(pb_measurement, '\0', PHY_PB_MAX_NB*sizeof(uint32_t));
memset(pb_header, '\0', PHY_PB_MAX_NB*sizeof(uint32_t));
- /* Send phy message. */
-
+ /* Send phy message containing PRS1. */
+
// fill sci data
if (sizeof(uint8_t) == sci_msg_push(&msg, sizeof(uint8_t)))
{
- memcpy(msg.data_begin, &access_backoff_data->ctx->access.cap_mpdu, sizeof(u8));
+ memcpy(msg.data_begin, &prs1, sizeof(u8));
}
-
+
// fill phy header
- maximus_phy_fill_hdr(access_backoff_data->ctx,
+ maximus_phy_fill_hdr(ctx,
&msg,
PHY_TYPE_PRS,
PHY_MPDU_FORMAT_NONE,
0, // pb_nb
- (uint8_t)access_backoff_data->ctx->tm_dma.tonemap_index,
+ (uint8_t)ctx->tm_dma.tonemap_index,
PHY_FLAG_CRC_OK,
nek,
pb_measurement,
pb_header);
-
+
// fill sci header
sci_fill_hdr(my_station.sci, &msg, SCI_MSG_TYPE_PHY, 0 /* flags */);
-
+
// send message
sci_send(my_station.sci, &msg);
-
- // update medium state
- access_backoff_data->ctx->access.medium_state = MAXIMUS_PHY_MEDIUM_PRP;
-
- // reset slot counter
- access_backoff_data->ctx->access.slot_count = 0;
-
- /* Send a netclock message to Maximus simulator scheduled in a slot time,
- * to increment slot counter. */
-
- tick_high = my_station.current_tick_tck >> 32;
- tick_low = 896; // schedule_tick = slot_time / maximus_tick = 35.84us / 40ns = 896 ticks
- schedule_tick = (((unsigned long long)(tick_high)) << 32) | (unsigned long long)(tick_low);
-
- netclock_schedule(my_station.netclock,
- access_backoff_data->ctx->access.access_backoff_netclock_cb,
- NETWORK_CLOCK_TYPE_STATION,
- schedule_tick,
- &maximus_phy_slot_count_cb,
- (void*)access_backoff_data->ctx,
- &id);
}
+ }
+ }
+}
+
+
+/**
+ * Maximus access PRS1 callback called when the corresponding netclock message is received,
+ * i.e. at the end of the PRS1.
+ * \param data pointer to phy_t structure.
+ */
+void
+maximus_phy_access_prs1_cb (void *data)
+{
+ if (NULL == data)
+ {
+ errno = EINVAL;
+ }
+ else
+ {
+ phy_t *ctx = (phy_t*)data;
+
+ // update medium state
+ ctx->access.medium_state = MAXIMUS_PHY_MEDIUM_CW;
+
+ /* If cap_sent = cap_medium (cap_sent can be different of cap_mpdu if the CAP was updated during the PRS0),
+ * and cap_mpdu ≥ cap_medium, PRP is won. */
+
+ // compute prp result
+ if ((ctx->access.cap_sent == ctx->access.cap_medium)
+ && ((uint)ctx->access.cap_mpdu >= (uint)ctx->access.cap_medium))
+ {
+ ctx->access.prp_result = true;
+ }
+
+ /* If PRP is lost (i.e. the detected CAP is greater than the programmed one), PHY stops Tx. */
+
+ if (!ctx->access.prp_result
+ && ctx->control.stop_tx_on_prp_lost)
+ {
+ // set rx mode
+ ctx->control.rx_tx_mode = true;
}
}
}
@@ -148,8 +375,8 @@ void maximus_phy_access_timer_cb (void *data)
}
else
{
- if ((MAXIMUS_PHY_MEDIUM_PRE_DETECTED != access_timer_data->ctx->access.medium_state)
- && (MAXIMUS_PHY_MEDIUM_BUSY_RX != access_timer_data->ctx->access.medium_state))
+ if ((MAXIMUS_PHY_MEDIUM_BUSY != access_timer_data->ctx->access.medium_state)
+ || !access_timer_data->ctx->control.rx_tx_mode)
{
if((*access_timer_data->ctx->control.access_cb)(access_timer_data->ctx->control.user_data))
{
@@ -163,48 +390,6 @@ void maximus_phy_access_timer_cb (void *data)
/**
- * Maximus slot count callback called when the corresponding netclock message is received.
- */
-void
-maximus_phy_slot_count_cb (void *data)
-{
- if (NULL == data)
- {
- errno = EINVAL;
- }
- else
- {
- // for netclock message
- netclock_id_t id;
- uint32_t tick_high, tick_low;
- tick_t schedule_tick;
-
- // increment slot count
- phy_t *ctx = (phy_t*)data;
- ctx->access.slot_count++;
-
- if (MAXIMUS_PHY_MEDIUM_PRP == ctx->access.medium_state)
- {
- /* During PRP, send a netclock message to Maximus simulator scheduled in a slot time,
- * to increment slot counter. */
-
- tick_high = my_station.current_tick_tck >> 32;
- tick_low = 896; // schedule_tick = slot_time / maximus_tick = 35.84us / 40ns = 896 ticks
- schedule_tick = (((unsigned long long)(tick_high)) << 32) | (unsigned long long)(tick_low);
-
- netclock_schedule(my_station.netclock,
- ctx->access.access_backoff_netclock_cb,
- NETWORK_CLOCK_TYPE_STATION,
- schedule_tick,
- &maximus_phy_slot_count_cb,
- (void*)ctx,
- &id);
- }
- }
-}
-
-
-/**
* Start the backoff procedure.
* \param ctx phy context
* \param date PRP start date
@@ -274,12 +459,25 @@ phy_access_backoff_update (phy_t *ctx, uint cap)
}
else
{
- if (MAXIMUS_PHY_MEDIUM_PRP != ctx->access.medium_state)
+ if ((MAXIMUS_PHY_MEDIUM_PRS0 != ctx->access.medium_state)
+ && (MAXIMUS_PHY_MEDIUM_PRS1 != ctx->access.medium_state)
+ && (MAXIMUS_PHY_MEDIUM_CW != ctx->access.medium_state))
{
/* Set the given cap value into PHY context (cap_mpdu). */
ctx->access.cap_mpdu = (u8)cap;
}
+ else if (MAXIMUS_PHY_MEDIUM_PRS0 == ctx->access.medium_state)
+ {
+ if ((u8)cap > ctx->access.cap_mpdu)
+ {
+ ctx->access.cap_mpdu |= 0x01; // set PRS1 to 1
+ }
+ else if ((u8)cap < ctx->access.cap_mpdu)
+ {
+ ctx->access.cap_mpdu &= 0x02; // set PRS1 to 0
+ }
+ }
}
}
diff --git a/hal/phy/maximus/src/maximus_phy_ctrl.c b/hal/phy/maximus/src/maximus_phy_ctrl.c
index a3a9c4d4b5..306f1f3693 100644
--- a/hal/phy/maximus/src/maximus_phy_ctrl.c
+++ b/hal/phy/maximus/src/maximus_phy_ctrl.c
@@ -78,8 +78,10 @@ maximus_phy_tx_fc_cb (void *data)
netclock_id_t id;
uint32_t tick_high, tick_low;
tick_t schedule_tick;
-
- if (tx_fc_data->want_conf && (MAXIMUS_PHY_MEDIUM_BUSY_RX != tx_fc_data->ctx->access.medium_state))
+
+ if (tx_fc_data->want_conf
+ && ((MAXIMUS_PHY_MEDIUM_BUSY != tx_fc_data->ctx->access.medium_state)
+ || !tx_fc_data->ctx->control.rx_tx_mode))
{
if ((*tx_fc_data->ctx->control.access_conf_cb)(tx_fc_data->ctx->control.user_data))
{
@@ -89,6 +91,15 @@ maximus_phy_tx_fc_cb (void *data)
}
+ // update medium state
+ tx_fc_data->ctx->access.medium_state = MAXIMUS_PHY_MEDIUM_BUSY;
+
+ // set tx mode
+ tx_fc_data->ctx->control.rx_tx_mode = false;
+
+ // deactivate preamble detection
+ tx_fc_data->ctx->control.pre_detection = false;
+
/* Then, this callback has to send a phy message containing fc_av
* (and fc_10 in Hybrid Mode). */
@@ -146,9 +157,6 @@ maximus_phy_tx_fc_cb (void *data)
// send the message
sci_send(my_station.sci, &msg);
-
- // update medium state
- tx_fc_data->ctx->access.medium_state = MAXIMUS_PHY_MEDIUM_BUSY_TX;
}
/* At last, to simulate the transmission time, this callback has to send a netclock message
@@ -212,7 +220,8 @@ maximus_phy_tx_frame_cb (void *data)
}
else
{
- if (MAXIMUS_PHY_MEDIUM_BUSY_TX == tx_frame_data->ctx->access.medium_state)
+ if ((MAXIMUS_PHY_MEDIUM_BUSY == tx_frame_data->ctx->access.medium_state)
+ && !tx_frame_data->ctx->control.rx_tx_mode)
{
// for phy message
unsigned char buffer[SCI_MSG_MAX_SIZE];
@@ -472,8 +481,7 @@ maximus_phy_recv (sci_msg_t *msg, void *phy)
&& (!encrypted // - and message is not encrypted
|| (encrypted // or message is encrypted with a correct nek
&& (0 == memcmp(msg->hdr.phy->nek, ctx->pb_dma.nek, 4*sizeof(uint32_t)))))
- && (msg->hdr.phy->tonemap_index == ctx->tm_dma.tonemap_index) // - and received tonemap index is correct
- && (MAXIMUS_PHY_MEDIUM_BUSY_TX != ctx->access.medium_state)) // - and phy is not transmitting
+ && (msg->hdr.phy->tonemap_index == ctx->tm_dma.tonemap_index)) // - and received tonemap index is correct
{
// depending on the phy header type, different actions have to be done
ret = (*(function_array[msg->hdr.phy->type]))(ctx, msg);
@@ -505,6 +513,8 @@ maximus_phy_recv_fc_hybrid_mode (phy_t *ctx, sci_msg_t *msg)
/* If a PRE is detected before Tx starts, CW is lost.
* PHY stops Tx without raising an IT. */
+ int ret = -1;
+
if((NULL == ctx)
|| (NULL == msg)
|| (NULL == msg->sci_hdr)
@@ -514,16 +524,26 @@ maximus_phy_recv_fc_hybrid_mode (phy_t *ctx, sci_msg_t *msg)
}
else
{
- if (ctx->control.pre_detection)
+ if ((ctx->control.pre_detection)
+ &&((MAXIMUS_PHY_MEDIUM_BUSY != ctx->access.medium_state)
+ || ctx->control.rx_tx_mode))
{
memcpy(&ctx->control.fc_10, msg->data_begin, 4);
sci_msg_pop(msg, 4);
memcpy(ctx->control.fc_av, msg->data_begin, 16);
sci_msg_pop(msg, 16);
-
- // set medium state to idle
- ctx->access.medium_state = MAXIMUS_PHY_MEDIUM_PRE_DETECTED;
+ ctx->access.prp_result = false;
+
+ // update medium state
+ ctx->access.medium_state = MAXIMUS_PHY_MEDIUM_BUSY;
+
+ // set rx mode
+ ctx->control.rx_tx_mode = true;
+
+ // deactivate preamble detection
+ ctx->control.pre_detection = false;
+
// PHY raises an IT_RX_FC by calling 'phy_rx_fc_cb'
if ((*ctx->control.rx_fc_cb)(ctx->control.user_data, msg->sci_hdr->netclock_low, ctx->control.fc_av))
{
@@ -531,9 +551,10 @@ maximus_phy_recv_fc_hybrid_mode (phy_t *ctx, sci_msg_t *msg)
(*ctx->control.deferred_cb)(ctx->control.user_data);
}
}
+ ret = 0;
}
- return 0;
+ return ret;
}
int
@@ -542,6 +563,8 @@ maximus_phy_recv_fc_av_only_mode (phy_t *ctx, sci_msg_t *msg)
/* If a PRE is detected before Tx starts, CW is lost.
* PHY stops Tx without raising an IT. */
+ int ret = -1;
+
if((NULL == ctx)
|| (NULL == msg)
|| (NULL == msg->sci_hdr)
@@ -551,14 +574,24 @@ maximus_phy_recv_fc_av_only_mode (phy_t *ctx, sci_msg_t *msg)
}
else
{
- if (ctx->control.pre_detection)
+ if ((ctx->control.pre_detection)
+ &&((MAXIMUS_PHY_MEDIUM_BUSY != ctx->access.medium_state)
+ || ctx->control.rx_tx_mode))
{
memcpy(ctx->control.fc_av, msg->data_begin, 16);
sci_msg_pop(msg, 16);
-
- // set medium state to idle
- ctx->access.medium_state = MAXIMUS_PHY_MEDIUM_PRE_DETECTED;
-
+
+ ctx->access.prp_result = false;
+
+ // update medium state
+ ctx->access.medium_state = MAXIMUS_PHY_MEDIUM_BUSY;
+
+ // set rx mode
+ ctx->control.rx_tx_mode = true;
+
+ // deactivate preamble detection
+ ctx->control.pre_detection = false;
+
// PHY raises an IT_RX_FC by calling 'phy_rx_fc_cb'
if ((*ctx->control.rx_fc_cb)(ctx->control.user_data, msg->sci_hdr->netclock_low, ctx->control.fc_av))
{
@@ -566,9 +599,10 @@ maximus_phy_recv_fc_av_only_mode (phy_t *ctx, sci_msg_t *msg)
(*ctx->control.deferred_cb)(ctx->control.user_data);
}
}
+ ret = 0;
}
- return 0;
+ return ret;
}
int
@@ -582,22 +616,38 @@ maximus_phy_recv_prs (phy_t *ctx, sci_msg_t *msg)
}
else
{
- uint8_t prp_result = 0;
-
- memcpy(&prp_result, msg->data_begin, sizeof(uint8_t));
- ctx->access.prp_result = (0 == prp_result) ? false : true;
- sci_msg_pop(msg, sizeof(uint8_t));
-
- /* If PRP is lost (i.e. the detected CAP is greater than the programmed one), PHY stops Tx. */
-
- if (!ctx->access.prp_result
- && ctx->control.stop_tx_on_prp_lost)
+ if ((MAXIMUS_PHY_MEDIUM_PRS0 == ctx->access.medium_state)
+ || (MAXIMUS_PHY_MEDIUM_PRS1 == ctx->access.medium_state))
{
- // set medium state to idle
- ctx->access.medium_state = MAXIMUS_PHY_MEDIUM_IDLE;
+ uint8_t prs = 0;
+ memcpy(&prs, msg->data_begin, sizeof(uint8_t));
+ sci_msg_pop(msg, sizeof(uint8_t));
+
+ if (1 < prs)
+ {
+ errno = EPROTO;
+ }
+ else
+ {
+ if (MAXIMUS_PHY_MEDIUM_PRS0 == ctx->access.medium_state)
+ {
+ if (1 == prs)
+ {
+ // update cap medium
+ ctx->access.cap_medium = 2;
+ }
+ }
+ else // ctx->access.medium_state = MAXIMUS_PHY_MEDIUM_PRS1
+ {
+ // update cap medium
+ if (1 == prs)
+ {
+ ctx->access.cap_medium = 3;
+ }
+ }
+ ret = 0;
+ }
}
-
- ret = 0;
}
return ret;
@@ -747,7 +797,9 @@ phy_init (void *user_data, phy_rx_fc_cb_t rx_fc_cb, phy_access_cb_t access_cb,
* Set the deferred_cb value of PHY context. */
static phy_t ctx;
+
static netclock_callback_t access_backoff_netclock_cb;
+ static netclock_callback_t access_slot_count_netclock_cb;
static netclock_callback_t access_timer_netclock_cb;
static netclock_callback_t tx_frame_netclock_cb;
static netclock_callback_t rx_activate_netclock_cb;
@@ -771,6 +823,7 @@ phy_init (void *user_data, phy_rx_fc_cb_t rx_fc_cb, phy_access_cb_t access_cb,
ctx.control.pbdma_cb = pbdma_cb;
ctx.control.deferred_cb = deferred_cb;
ctx.access.access_backoff_netclock_cb = &access_backoff_netclock_cb;
+ ctx.access.access_slot_count_netclock_cb = &access_slot_count_netclock_cb;
ctx.access.access_timer_netclock_cb = &access_timer_netclock_cb;
ctx.control.tx_frame_netclock_cb = &tx_frame_netclock_cb;
ctx.control.rx_activate_netclock_cb = &rx_activate_netclock_cb;
@@ -1059,6 +1112,9 @@ phy_rx_prepare (phy_t *ctx, uint tonemap_index, phy_pb_size_t pb_size)
{
ctx->tm_dma.tonemap_index = tonemap_index;
ctx->pb_dma.pb_size = pb_size;
+
+ // set rx mode
+ ctx->control.rx_tx_mode = true;
}
}
diff --git a/hal/phy/maximus/test/src/test_phy_access.c b/hal/phy/maximus/test/src/test_phy_access.c
index 70c2861d9c..dff059ca47 100644
--- a/hal/phy/maximus/test/src/test_phy_access.c
+++ b/hal/phy/maximus/test/src/test_phy_access.c
@@ -35,16 +35,20 @@ phy_t *ctx;
void phy_access_backoff_start_test_case(test_t t)
{
u32 date = 10;
- uint cap = 1;
+ uint cap = 3;
tick_t msg_tick_tck;
printf("backoff start\n");
test_case_begin(t, "backoff start");
- phy_access_backoff_start (ctx, date, cap);
+ test_begin(t, "backoff start")
+ {
+ phy_access_backoff_start (ctx, date, cap);
+ test_fail_unless (EINVAL != errno);
+ } test_end;
// check that the correct netclock message has been sent to Maximus
- test_begin(t, "first netclock message")
+ test_begin(t, "netclock message for maximus access cb")
{
unsigned char data[256];
netclock_msg_hdr_t *netclock_hdr;
@@ -71,6 +75,13 @@ void phy_access_backoff_start_test_case(test_t t)
// close pipe
close(fd_in);
+ // get new network tick
+ msg_tick_tck = (((unsigned long long)(ntohl(netclock_hdr->tick_high))) << 32)
+ | (unsigned long long)(ntohl(netclock_hdr->tick_low));
+
+ // update current tick value
+ my_station.current_tick_tck = msg_tick_tck;
+
/* Remove netclock callback. */
// init callback to find
@@ -85,12 +96,12 @@ void phy_access_backoff_start_test_case(test_t t)
set_remove(&my_station.netclock->callback_set, found_node);
} test_end;
- // test the first callback
+ // test the maximus access callback
test_begin(t, "maximus access cb")
{
maximus_phy_access_backoff_t access_backoff_data;
void *data = NULL;
-
+
access_backoff_data.isr = maximus_pending_isrs;
access_backoff_data.ctx = ctx;
access_backoff_data.cap = cap;
@@ -100,13 +111,98 @@ void phy_access_backoff_start_test_case(test_t t)
&& (maximus_pending_isrs & (1 << PHY_HAL_INTERRUPT_PHY)));
} test_end;
+ // check that the correct netclock message has been sent to Maximus
+ test_begin(t, "netclock message for maximus access slot count cb")
+ {
+ unsigned char data[256];
+ netclock_msg_hdr_t *netclock_hdr;
+ int fd_in = -1;
+
+ netclock_callback_t reference, *found_callback;
+ set_node_t *found_node;
+
+ // open pipe
+ fd_in = open(my_station.pipe_out_name, O_RDONLY);
+
+ // read sci and netclock headers
+ memset(data, '\0', 256);
+ test_fail_unless ((-1 != fd_in)
+ && (sizeof(sci_msg_hdr_t) == read(fd_in, data, sizeof(sci_msg_hdr_t)))
+ && (sizeof(netclock_msg_hdr_t) == read(fd_in, data+sizeof(sci_msg_hdr_t), sizeof(netclock_msg_hdr_t))));
+
+ // set netclock header pointer
+ netclock_hdr = (netclock_msg_hdr_t *)(data+sizeof(sci_msg_hdr_t));
+
+ // check netclock tick value
+ test_fail_unless ((my_station.current_tick_tck & 0x00000000ffffffff)+896 == ntohl(netclock_hdr->tick_low)); // slot_time = 896 ticks
+
+ // close pipe
+ close(fd_in);
+
+ /* Remove netclock callback. */
+
+ // init callback to find
+ reference.id = ntohs(netclock_hdr->id);
+ set_node_init(&reference.node);
+
+ // find it
+ test_fail_unless((found_node = set_find(&my_station.netclock->callback_set, &reference.node)) != NULL);
+
+ // remove it from callback set
+ found_callback = (netclock_callback_t *)PARENT_OF(netclock_callback_t, node, found_node);
+ set_remove(&my_station.netclock->callback_set, found_node);
+ } test_end;
+
+ // check that the correct netclock message has been sent to Maximus
+ test_begin(t, "netclock message for maximus_phy_access_prs0_cb")
+ {
+ unsigned char data[256];
+ netclock_msg_hdr_t *netclock_hdr;
+ int fd_in = -1;
+
+ netclock_callback_t reference, *found_callback;
+ set_node_t *found_node;
+
+ // open pipe
+ fd_in = open(my_station.pipe_out_name, O_RDONLY);
+
+ // read sci and netclock headers
+ memset(data, '\0', 256);
+ test_fail_unless ((-1 != fd_in)
+ && (sizeof(sci_msg_hdr_t) == read(fd_in, data, sizeof(sci_msg_hdr_t)))
+ && (sizeof(netclock_msg_hdr_t) == read(fd_in, data+sizeof(sci_msg_hdr_t), sizeof(netclock_msg_hdr_t))));
+
+ // set netclock header pointer
+ netclock_hdr = (netclock_msg_hdr_t *)(data+sizeof(sci_msg_hdr_t));
+
+ // check netclock tick value
+ test_fail_unless ((my_station.current_tick_tck & 0x00000000ffffffff)+896 == ntohl(netclock_hdr->tick_low)); // slot_time = 896 ticks
+
+ // close pipe
+ close(fd_in);
+
+ /* Remove netclock callback. */
+
+ // init callback to find
+ reference.id = ntohs(netclock_hdr->id);
+ set_node_init(&reference.node);
+
+ // find it
+ test_fail_unless((found_node = set_find(&my_station.netclock->callback_set, &reference.node)) != NULL);
+
+ // remove it from callback set
+ found_callback = (netclock_callback_t *)PARENT_OF(netclock_callback_t, node, found_node);
+ set_remove(&my_station.netclock->callback_set, found_node);
+ } test_end;
+
// check that the correct phy message has been sent to Maximus
- test_begin(t, "phy message")
+ test_begin(t, "phy message for PRS0")
{
unsigned char data[SCI_MSG_MAX_SIZE];
sci_msg_hdr_t *sci_hdr;
phy_msg_hdr_t *phy_hdr;
int fd_in = -1;
+ uint8_t prs0 = 1;
// open pipe
fd_in = open(my_station.pipe_out_name, O_RDONLY);
@@ -122,12 +218,12 @@ void phy_access_backoff_start_test_case(test_t t)
// check phy header
test_fail_unless (PHY_TYPE_PRS == phy_hdr->type);
-
+
// read the remaining part of message
test_fail_unless (sizeof(uint8_t) == read(fd_in, data+sizeof(sci_msg_hdr_t)+sizeof(phy_msg_hdr_t), sizeof(uint8_t)));
// check phy data
- test_fail_unless (0 == memcmp(&ctx->access.cap_mpdu, data+sizeof(sci_msg_hdr_t)+sizeof(phy_msg_hdr_t), sizeof(u8)));
+ test_fail_unless (0 == memcmp(&prs0, data+sizeof(sci_msg_hdr_t)+sizeof(phy_msg_hdr_t), sizeof(u8)));
// get new network tick
msg_tick_tck = (((unsigned long long)(ntohl(sci_hdr->netclock_high))) << 32)
@@ -140,8 +236,16 @@ void phy_access_backoff_start_test_case(test_t t)
close(fd_in);
} test_end;
+ // test the maximus access slot count callback
+ test_begin(t, "maximus access slot count cb")
+ {
+ maximus_phy_access_slot_count_cb ((void*)ctx);
+ test_fail_unless ((EINVAL != errno)
+ && (1 == ctx->access.slot_count));
+ } test_end;
+
// check that the correct netclock message has been sent to Maximus
- test_begin(t, "second netclock message")
+ test_begin(t, "netclock message for maximus access slot count cb")
{
unsigned char data[256];
netclock_msg_hdr_t *netclock_hdr;
@@ -182,21 +286,24 @@ void phy_access_backoff_start_test_case(test_t t)
set_remove(&my_station.netclock->callback_set, found_node);
} test_end;
- // test the second callback
- test_begin(t, "maximus slot count cb")
+ // test the maximus access PRS0 callback
+ test_begin(t, "maximus access PRS0 cb")
{
- maximus_phy_slot_count_cb ((void*)ctx);
+ maximus_phy_access_prs0_cb ((void*)ctx);
test_fail_unless ((EINVAL != errno)
- && (1 == ctx->access.slot_count));
+ && (MAXIMUS_PHY_MEDIUM_PRS1 == ctx->access.medium_state));
} test_end;
- // check that the correct netclock message has been sent to Maximus
- test_begin(t, "third netclock message")
+ // check that the correct netclock message has been sent to Maximus
+ test_begin(t, "netclock message for maximus_phy_access_prs1_cb")
{
unsigned char data[256];
netclock_msg_hdr_t *netclock_hdr;
int fd_in = -1;
+ netclock_callback_t reference, *found_callback;
+ set_node_t *found_node;
+
// open pipe
fd_in = open(my_station.pipe_out_name, O_RDONLY);
@@ -214,6 +321,69 @@ void phy_access_backoff_start_test_case(test_t t)
// close pipe
close(fd_in);
+
+ /* Remove netclock callback. */
+
+ // init callback to find
+ reference.id = ntohs(netclock_hdr->id);
+ set_node_init(&reference.node);
+
+ // find it
+ test_fail_unless((found_node = set_find(&my_station.netclock->callback_set, &reference.node)) != NULL);
+
+ // remove it from callback set
+ found_callback = (netclock_callback_t *)PARENT_OF(netclock_callback_t, node, found_node);
+ set_remove(&my_station.netclock->callback_set, found_node);
+ } test_end;
+
+ // check that the correct phy message has been sent to Maximus
+ test_begin(t, "phy message for PRS1")
+ {
+ unsigned char data[SCI_MSG_MAX_SIZE];
+ sci_msg_hdr_t *sci_hdr;
+ phy_msg_hdr_t *phy_hdr;
+ int fd_in = -1;
+ uint8_t prs1 = 1;
+
+ // open pipe
+ fd_in = open(my_station.pipe_out_name, O_RDONLY);
+
+ // read sci and phy headers
+ memset(data, '\0', SCI_MSG_MAX_SIZE);
+ test_fail_unless ((-1 != fd_in)
+ && ((int)(sizeof(sci_msg_hdr_t)+sizeof(phy_msg_hdr_t)) == read(fd_in, data, sizeof(sci_msg_hdr_t)+sizeof(phy_msg_hdr_t))));
+
+ // set sci and phy headers pointers
+ sci_hdr = (sci_msg_hdr_t *)(data);
+ phy_hdr = (phy_msg_hdr_t *)(data+sizeof(sci_msg_hdr_t));
+
+ // check phy header
+ test_fail_unless (PHY_TYPE_PRS == phy_hdr->type);
+
+ // read the remaining part of message
+ test_fail_unless (sizeof(uint8_t) == read(fd_in, data+sizeof(sci_msg_hdr_t)+sizeof(phy_msg_hdr_t), sizeof(uint8_t)));
+
+ // check phy data
+ test_fail_unless (0 == memcmp(&prs1, data+sizeof(sci_msg_hdr_t)+sizeof(phy_msg_hdr_t), sizeof(u8)));
+
+ // get new network tick
+ msg_tick_tck = (((unsigned long long)(ntohl(sci_hdr->netclock_high))) << 32)
+ | (unsigned long long)(ntohl(sci_hdr->netclock_low));
+
+ // update current tick value
+ my_station.current_tick_tck = msg_tick_tck;
+
+ // close pipe
+ close(fd_in);
+ } test_end;
+
+ // test the maximus access PRS1 callback
+ test_begin(t, "maximus access PRS1 cb")
+ {
+ maximus_phy_access_prs1_cb ((void*)ctx);
+ test_fail_unless ((EINVAL != errno)
+ && (MAXIMUS_PHY_MEDIUM_CW == ctx->access.medium_state)
+ && !ctx->access.prp_result);
} test_end;
return;
diff --git a/hal/phy/maximus/test/src/test_phy_ctrl.c b/hal/phy/maximus/test/src/test_phy_ctrl.c
index b3a6d2ecc0..36b925a24f 100644
--- a/hal/phy/maximus/test/src/test_phy_ctrl.c
+++ b/hal/phy/maximus/test/src/test_phy_ctrl.c
@@ -172,7 +172,7 @@ void maximus_phy_recv_test_case(test_t t)
// sci data
u32 fc_10 = 1234567890; // for PHY_TYPE_FC_HYBRID_MODE
u32 fc_av[4]; // for PHY_TYPE_FC_HYBRID_MODE and PHY_TYPE_FC_AV_ONLY_MODE
- u32 prp_result = 1; // for PHY_TYPE_PRS
+ u32 prs = 1; // for PHY_TYPE_PRS
// for PHY_TYPE_MPDU_PAYLOAD
u8 pb_data[PHY_PB_NB][PHY_PB_MAX_SIZE];
phy_pb_t phy_pb[PHY_PB_NB];
@@ -233,13 +233,14 @@ void maximus_phy_recv_test_case(test_t t)
&& (ENOSPC != errno));
memcpy(msg.data_begin, &fc_10, 4);
}
- // PRP result (1 octet, but must be aligned on 4 octets)
+ // PRS (1 octet, but must be aligned on 4 octets)
if (PHY_TYPE_PRS == phy_hdr.type)
{
+ ctx->access.medium_state = MAXIMUS_PHY_MEDIUM_PRS0;
test_fail_unless ((4 == sci_msg_push(&msg, 4))
&& (EINVAL != errno)
&& (ENOSPC != errno));
- memcpy(msg.data_begin, &prp_result, 4);
+ memcpy(msg.data_begin, &prs, 4);
}
// PBs
if (PHY_TYPE_MPDU_PAYLOAD == phy_hdr.type)
@@ -348,10 +349,10 @@ void maximus_phy_recv_test_case(test_t t)
{
test_fail_unless (fc_10 == ctx->control.fc_10);
}
- // test PRP result
+ // test PRS
if (PHY_TYPE_PRS == phy_hdr.type)
{
- test_fail_unless (prp_result == (ctx->access.prp_result) ? 1 : 0);
+ test_fail_unless (2 == ctx->access.cap_medium);
}
// test PBs
if (PHY_TYPE_MPDU_PAYLOAD == phy_hdr.type)