⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radioclient.c

📁 simulink real-time workshop for dragon12 development board from
💻 C
📖 第 1 页 / 共 3 页
字号:
  CSN = 1;

#ifdef TO_DEBUG  
  SCI0_OutString("T~\r\n"); /* exit Transmit() */
#endif

  // Pulse CE to start transmission (must be > 10us)
  CE = 1;
}

/* 
  EnterReceive is a private procedure to configure the module for
  receive mode.
  Must be in a standby-mode to call this method.
*/
void RadioClient_EnterReceive() {

  /* a good idea to clear all interrupts and flush buffers first */
  SPI_OutChar(FLUSH_TX);
  SPI_OutChar(FLUSH_RX);
  SPI_OutChar2(W_STATUS, RX_DR_MASK | TX_DS_MASK | MAX_RT_MASK);

  /*
    bit  CONFIG Register
      7  0  Reserved
      6  1  MASK_RX_DR  : Don't reflect RX_DR on IRQ pin
      5  1  MASK_TX_DS  : Don't reflect TX_DS on IRQ pin
      4  1  MASK_MAX_RT : Don't reflect MAX_RT on IRQ pin
      3  1  EN_CRC      : Enable CRC
      2  1  CRCO        : 2 byte CRC
      1  1  PWR_UP      : Power Up
      0  1  PRIM_RX     : PRX
      
      Enter receive mode
  */
  SPI_OutChar2(W_CONFIG, 0x7f);
 
  CE = 1;
}

/* 
  OnReceive() is a private procedure which is called when the
  RX_DR flag is set in the STATUS register.
  Returns 1 if have received EOT, otherwise returns 0
*/
void RadioClient_OnReceive() {
unsigned char header, rID, tID, in, i, toEscape, haveReceivedEOT, trustData;

#ifdef TO_DEBUG
  SCI0_OutString("R\r\n"); /* enter onReceive() */
#endif															

  /* use in as a dummy */
  in = SPI0SR;
  in = SPI0DR;  // clear SPIF

  toEscape = haveReceivedEOT = 0;

  while(SPI0SR_SPTEF == 0) {}

  CSN = 0;
  
  /* send the read command */
  SPI0DR = R_RX_PAYLOAD;
  SPI_Pause();
  in = SPI_InChar(); // discard the status byte

  while(SPI0SR_SPTEF == 0) {}
  SPI0DR = NOP;      // output a dummy value to generate SCK
  SPI_Pause();

  /* read in header byte */
  header = SPI_InChar();

  while(SPI0SR_SPTEF == 0) {}
  SPI0DR = NOP;      // output a dummy value to generate SCK
  SPI_Pause();

  /* read in rID */
  rID = SPI_InChar();

  while(SPI0SR_SPTEF == 0) {}
  SPI0DR = NOP;      // output a dummy value to generate SCK
  SPI_Pause();

  /* read in tID */
  tID = SPI_InChar();

  if(tID == cc->inRB.in) {
    /* server's tID matches expected rID, i.e. the server's sending
       requested byte next, so can probably trust */
    trustData = 1;

  } else {

    /* the server is sending a byte out of order, probably cannot
       trust */
    trustData = 0;
    
#ifdef TO_DEBUG_ERROR_CONDITIONS
    SCI0_OutString("Invalid tID: ");
    SCI0_OutUDec(tID);
    SCI0_OutString(", expected ");
    SCI0_OutUDec(cc->inRB.in);
    SCI0_OutString("\r\n");
#endif
  }

  /* may be able to trust the data if the client has been reset
     recently */
  if(cc->reset & HEADER_RESET_MASK) {
    /* client has been reset recently */

    if(header & HEADER_ACK_RESET_MASK) {
      /* server has acknowledged client reset */
      cc->reset &= ~HEADER_RESET_MASK;
      
      /* what follows must be valid, since the server has ack'd
         reset */
      trustData = 1;

#ifdef TO_DEBUG
      SCI0_OutString("ACK'd reset\r\n");
#endif
    
    } else {

      /* server has not acknowledged reset, cannot trust data,
         even if had a "valid" tID */
      trustData = 0;

#ifdef TO_DEBUG_ERROR_CONDITIONS
      SCI0_OutString("Not ACK'd reset\r\n");
#endif
    }
  }
  
  /* if the server itself has been reset, we can trust the data */
  if(header & HEADER_RESET_MASK) {
    /* Server has been reset!
       This can be bad if there's still data in the buffer,
       may get data queued from another session => clean them */
    RadioClient_CleanOut();
    RadioClient_CleanIn();
  
    /* acknowledge to server that the reset has been a success */
    cc->reset |= HEADER_ACK_RESET_MASK;

    cc->failureCount = 0;

    /* what follows is a new byte (it's byte 0) */
    trustData = 1;
#ifdef TO_DEBUG
    SCI0_OutString("Server reset\r\n");
#endif
  } else {
    /* if server hasn't reset, clear ACK_RESET flag */
    cc->reset &= ~HEADER_ACK_RESET_MASK;
  }
  
#ifdef TO_DEBUG_ERROR_CONDITIONS
  if(!trustData) {
    SCI0_OutString("Discard data\r\n");
  }
#endif

  haveReceivedEOT = (header & HEADER_EOT_MASK) != 0;

  for(i=3; i<PAYLOAD_LEN; i++) {

    while(SPI0SR_SPTEF == 0) {}
    SPI0DR = NOP;      // output a dummy value to generate SCK
    SPI_Pause();

    in = SPI_InChar(); // read in potentially valid byte

    if(trustData && (haveReceivedEOT == 0)) {
      if(toEscape == 0) {    // last character in wasn't the ESCAPE char
        switch(in) {
        case RADIO_ESCAPE_CHAR:
          toEscape = 1;
          break;
          
        case RADIO_EOT_CHAR:
          /* have received EOT */
          haveReceivedEOT = 1;
          break;
          
        default:
          if(RB_PUSH(&cc->inRB, in)) {
#ifdef TO_DEBUG_ERROR_CONDITIONS
            SCI0_OutString("Dropped char: ");
            SCI0_OutUHex(in);
            SCI0_OutString("\r\n");
#endif
          }
          break;
        }
      } else {
        if(RB_PUSH(&cc->inRB, in)) {
#ifdef TO_DEBUG_ERROR_CONDITIONS
          SCI0_OutString("Dropped char: ");
          SCI0_OutUHex(in);
          SCI0_OutString("\r\n");
#endif
        }
        toEscape = 0;
      }
    }
  }
  
  CSN = 1;
  
#ifdef TO_DEBUG_ERROR_CONDITIONS
  if(cc->outRB.out != rID) {
    SCI0_OutString("Invalid rID: ");
    SCI0_OutUDec(rID);
    SCI0_OutString(", expected ");
    SCI0_OutUDec(cc->outRB.out);
    SCI0_OutString("\r\n");
  }
#endif

  RB_SET_OUT(&cc->outRB, rID);

    /* no more data in RX buffer */
#ifdef TO_DEBUG
  SCI0_OutString("R~"); /* exit onReceive() */
#endif
}

/*
  Setup timer.
*/
void RadioClient_RestartTick() {
  TICK_ENABLE = 1;
  TICK_REGISTER = TICK_PRESCALAR + TCNT;
  TICK_INTERRUPT = 1;
}



/* beginning of the interrupt service routine =================================  */
#pragma CODE_SEG __NEAR_SEG NON_BANKED /* Interrupt section for this module. Placement will be in NON_BANKED area. */

/**
 * Called regularly.
 */
__interrupt void RadioClient_OnTick(void) {
unsigned char status;

  /* first deal with the timer flags */
  TICK_ENABLE = 0;
  TICK_INTERRUPT = 1;

  /* re-enable all interrupts (to allow servicing of RxD interrupt) */
  asm cli                // re-enable interrupts to allow this one to be interrupted
  

  /* always increment the tick counter */
  tickCounter++;

#ifdef TO_DEBUG
  SCI0_OutChar('`'); /* tick */
#endif

  switch(moduleState) {
  
  case STATE_WAIT_FOR_EOT:

#ifdef TO_DEBUG
    SCI0_OutChar('@');
#endif

    /* read status (one byte long) */
    SPI_Read(R_STATUS, &status, 1);

    if(status & TX_DS_MASK) {
      
      /* successfully transmitted PAYLOAD_LEN bytes */
      
#ifdef TO_DEBUG
      SCI0_OutString("T'd\r\n"); /* successful transmit */
#endif

      /* clear interrupt */
      SPI_OutChar2(W_STATUS, TX_DS_MASK);

      /* Since EOT was transmitted, client is about to send,
         => enter RX */

      RadioClient_EnterReceive();

      setState(STATE_WAIT_FOR_RECEIVE);
      
    } else if(status & MAX_RT_MASK) {

      /* module has informed us there's been a timeout */

#ifdef TO_DEBUG_ERROR_CONDITIONS
      SCI0_OutString("F'd\r\n"); /* explicit timeout */
#endif

      /* clear interrupt */

      SPI_OutChar2(W_STATUS, MAX_RT_MASK);

      RB_SET_OUT(&cc->outRB, cc->lastTID);
      
      cc->failureCount++;

      RadioClient_EnterReceive();

      setState(STATE_WAIT_FOR_RECEIVE);

    } else if(tickCounter >= WAIT_FOR_ACK_TICK_COUNT) {

#ifdef TO_DEBUG_ERROR_CONDITIONS
      SCI0_OutString("Q'd\r\n"); /* implicit timeout */
#endif

      /* this is a very bizarre state to get into, treat it similarly
         to as though we had explicitly received a timeout */

      RB_SET_OUT(&cc->outRB, cc->lastTID);

      cc->failureCount++;

      RadioClient_EnterReceive();

      setState(STATE_WAIT_FOR_RECEIVE);
    }
    
    break;

  case STATE_WAIT_FOR_RECEIVE:


#ifdef TO_DEBUG
    SCI0_OutChar('r'); /* wait in receive */
#endif

    /* read status (one byte long) */
    SPI_Read(R_STATUS, &status, 1);

    if(status & RX_DR_MASK) {
#ifdef TO_DEBUG
      SCI0_OutString("R'd"); /* successful receive */
#endif

      /* to be pedantic, should ensure that the RX_P_NO matches
         the receive address pipe (1) */
      if((((status & RX_P_NO_MASK) >> 1) - 1) == cc->id) {
        RadioClient_OnReceive();
        setState(STATE_WAIT_FOR_SERVER);
      } else {
#ifdef TO_DEBUG_ERROR_CONDITIONS
        SCI0_OutString("Wrong pipe number!");
        SCI0_OutUHex((status & RX_P_NO_MASK) >> 1);
#endif
        RadioClient_EnterReceive();
        setState(STATE_WAIT_FOR_RECEIVE);

      }
    } else if(tickCounter >= TIME_OUT_TICK_COUNT) {

      /* client has timed out */
#ifdef TO_DEBUG_ERROR_CONDITIONS
      SCI0_OutString("Timeout");
#endif      

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -