Defines | Functions

hal/nrf24le1/hal_w2.c File Reference

Implementation of hal_w2. More...

#include <stdint.h>
#include <stdbool.h>
#include "nrf24le1.h"
#include "nordic_common.h"
#include "hal_w2.h"
#include "hal_delay.h"

Go to the source code of this file.

Defines

#define BROADCAST_ENABLE   7
#define CLOCK_STOP   6
#define X_STOP   5
#define X_START   4
#define CLOCK_FREQUENCY_1   3
#define CLOCK_FREQUENCY_0   2
#define MASTER_SELECT   1
#define WIRE_2_ENABLE   0

Functions

void hal_w2_soft_reset ()
void hal_w2_respond_to_gen_adr (_Bool resp_gen)
void hal_w2_alter_clock (_Bool alt_clk)
void hal_w2_irq_stop_cond_enable (_Bool stop_cond)
void hal_w2_irq_adr_match_enable (_Bool addr_match)
void hal_w2_set_slave_address (uint8_t address)
void hal_w2_set_clk_freq (hal_w2_clk_freq_t freq)
void hal_w2_set_op_mode (hal_w2_op_mode_t mode)
void hal_w2_enable (_Bool en)
void hal_w2_all_irq_enable (_Bool irq)
void hal_w2_configure_master (hal_w2_clk_freq_t mode)
uint8_t hal_w2_wait_data_ready (void)
_Bool hal_w2_init_transfer (uint8_t address, hal_w2_direction_t direction)
_Bool hal_w2_write (uint8_t address, const uint8_t *data_ptr, uint8_t data_len)
_Bool hal_w2_read (uint8_t address, uint8_t *data_ptr, uint8_t data_len)

Detailed Description

Implementation of hal_w2.

Definition in file hal_w2.c.


Define Documentation

#define BROADCAST_ENABLE   7

Definition at line 26 of file hal_w2.c.

#define CLOCK_STOP   6

Definition at line 27 of file hal_w2.c.

#define X_STOP   5

Definition at line 28 of file hal_w2.c.

#define X_START   4

Definition at line 29 of file hal_w2.c.

#define CLOCK_FREQUENCY_1   3

Definition at line 30 of file hal_w2.c.

#define CLOCK_FREQUENCY_0   2

Definition at line 31 of file hal_w2.c.

#define MASTER_SELECT   1

Definition at line 32 of file hal_w2.c.

#define WIRE_2_ENABLE   0

Definition at line 33 of file hal_w2.c.


Function Documentation

void hal_w2_soft_reset (  )

Definition at line 238 of file hal_w2.c.

{
#ifndef W2_SOFT_RESET_NOT_AVAILABLE
  uint8_t pulsecount, w2_freq;

  // Store the selected 2-wire frequency 
  w2_freq = W2CON0 & 0x0C;
  // Prepare the GPIO's to take over SDA & SCL
  HAL_W2_CLEAR_SDA_SCL;
  HAL_W2_OVERRIDE_SDA_SCL(1, 1);
  //P0DIR = 0xFF;
  
  // Reset 2-wire. SCL goes high.
  W2CON0 = 0x03;
  W2CON0 = 0x07;
  
  // Disable 2-wire.
  W2CON0 = 0x06;
  
  // SDA and SCL are now under software control, and both are high. 
  // Complete first SCL pulse.
  //P0DIR = 0xEF;
  HAL_W2_OVERRIDE_SDA_SCL(1, 0);
  
  // SCL low
  delay_us(5);
  //P0DIR = 0xCF;
  HAL_W2_OVERRIDE_SDA_SCL(0, 0);
  
  // SDA low
  // Create SCL pulses for 7 more data bits and ACK/NACK
  delay_us(5);
  for( pulsecount = 0; pulsecount < 8; pulsecount++ )
  {
    //P0DIR = 0xDF;
    HAL_W2_OVERRIDE_SDA_SCL(0, 1);
    delay_us(5);
    //P0DIR = 0xCF;
    HAL_W2_OVERRIDE_SDA_SCL(0, 0);
    delay_us(5);
  }
  
  // Generating stop condition by driving SCL high
  delay_us(5);
  //P0DIR = 0xDF;
  HAL_W2_OVERRIDE_SDA_SCL(0, 1);
  
  // Drive SDA high
  delay_us(5);
  //P0DIR = 0xFF;
  HAL_W2_OVERRIDE_SDA_SCL(1, 1);
  
  // Work-around done. Return control to 2-wire.
  W2CON0 = 0x07;
  
  // Reset 2-wire and return to master mode at the frequency selected before calling this function
  W2CON0 = 0x03;
  W2CON0 = 0x03 | w2_freq;
#endif
}
void hal_w2_set_clk_freq ( hal_w2_clk_freq_t  freq )

Function to set the clock frequency. Use this function select clock frequency of the 2-wire.

Parameters:
freqThe clock frequency of the 2-wire

Definition at line 94 of file hal_w2.c.

{                                             
  W2CON0 = (W2CON0 & 0xF3) | (((uint8_t)freq) << CLOCK_FREQUENCY_0);       
}                                             // Update "clockFrequency" bits
void hal_w2_set_op_mode ( hal_w2_op_mode_t  mode )

Function to set the operation mode of the 2-wire. Use this function select master or slave mode.

Parameters:
modeThe operation mode of the 2-wire

Definition at line 99 of file hal_w2.c.

{
  if(mode == HAL_W2_MASTER)                   // Check for master mode
  {                                                                  
    W2CON0 = W2CON0 | (1 << MASTER_SELECT);   // Set "masterSelect" bit
  }
  else
  {
    W2CON0 = W2CON0 & ~(1 << MASTER_SELECT);  // Clear "masterSelect" bit
  }
}
void hal_w2_enable ( _Bool  en )

Function to enable the 2-wire. Use this function enable the 2-wire, must be done before any other programming of the 2-wire.

Parameters:
enTrue to enable, false to disable

Definition at line 111 of file hal_w2.c.

{ 
  if(en)
  {
    W2CON0 = W2CON0 | (1 << WIRE_2_ENABLE);   // Set "wire2Enable" bit
  }
  else
  {
    W2CON0 = W2CON0 & ~(1 << WIRE_2_ENABLE);  // Clear "wire2Enable" bit
  }
}
void hal_w2_all_irq_enable ( _Bool  irq )

Function to enable all interrupts. Use this function enable all interrupts.

Parameters:
irqTrue to enable, false to disable all interrupts in the 2-wire

< The value of bit 5

< The value of bit 5

Definition at line 123 of file hal_w2.c.

{ /* In this function the standard "read-modify-write" is not used because
     bit 4:0 (the status bits) in W2CON1 are cleared when read. These bits
     are read only so they can not be modified. */
  if(irq)
  {
    W2CON1 = ~(BIT_5);                        // Clear "maskIrq" bit
  }
  else
  {
    W2CON1 = BIT_5;                           // Set "maskIrq" bit
  }
}
void hal_w2_configure_master ( hal_w2_clk_freq_t  mode )

Definition at line 137 of file hal_w2.c.

{
  hal_w2_enable(true);
  hal_w2_set_clk_freq(mode);
  hal_w2_set_op_mode(HAL_W2_MASTER);

  INTEXP |= 0x04;                         // Enable 2 wire interrupts
  W2CON1 = 0x00;
  hal_w2_all_irq_enable(true);             // Enable interrupts in the 2-wire  
  SPIF = 0;
}
uint8_t hal_w2_wait_data_ready ( void   )

Definition at line 149 of file hal_w2.c.

{
  uint32_t timeout_counter = 0x0FF;
  uint8_t w2_status;
  bool data_ready;
  bool nack_received;

  do
  {
    w2_status = W2CON1;
    data_ready = (w2_status & W2CON1_FLAG_DATA_READY);
    nack_received = (w2_status & W2CON1_FLAG_NACK);
    delay_us(10);
  } while (!data_ready);


  return w2_status;
}
_Bool hal_w2_init_transfer ( uint8_t  address,
hal_w2_direction_t  direction 
)

Definition at line 168 of file hal_w2.c.

{
  uint8_t w2_status;

  HAL_W2_ISSUE_START_COND;
  HAL_W2_WRITE((address << 1) | (uint8_t)direction);

  w2_status = hal_w2_wait_data_ready();

  if (w2_status & W2CON1_FLAG_NACK)
  {
    return false; // NACK received from slave or timeout
  }
  else
  {
    return true; // ACK received from slave
  }
}
_Bool hal_w2_write ( uint8_t  address,
const uint8_t *  data_ptr,
uint8_t  data_len 
)

Definition at line 187 of file hal_w2.c.

{
  bool ack_received;
  ack_received = hal_w2_init_transfer(address, HAL_W2_DIR_WRITE);

  while (data_len-- > 0 && ack_received == true)
  {
    uint8_t w2_status;
    HAL_W2_WRITE(*data_ptr++);
    w2_status = hal_w2_wait_data_ready();
    if (w2_status & W2CON1_FLAG_NACK)
    {
      ack_received = false;
    }
  }

  HAL_W2_ISSUE_STOP_COND;

  return ack_received;
}
_Bool hal_w2_read ( uint8_t  address,
uint8_t *  data_ptr,
uint8_t  data_len 
)

Definition at line 208 of file hal_w2.c.

{
  uint8_t w2_status;
  bool ack_received;
  
  ack_received = hal_w2_init_transfer(address, HAL_W2_DIR_READ);

  if (ack_received == false) 
  {
    // This situation (NACK received on bus while trying to read from a slave) leads to a deadlock in the 2-wire interface. 
    hal_w2_soft_reset(); // Workaround for the deadlock
  }


  while (data_len-- && ack_received)
  {
    if (data_len == 0)
    {
      HAL_W2_ISSUE_STOP_COND;
    }

    w2_status = hal_w2_wait_data_ready();

    *data_ptr++ = HAL_W2_READ();
    ack_received = !(w2_status & W2CON1_FLAG_NACK);
  }

  return ack_received;  
}