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

📄 z1slaveio.c

📁 nrf24z1 代码
💻 C
字号:
/*= z1slaveio.c ================================================================
 *
 * Copyright (C) 2005 Nordic Semiconductor
 *
 * This file is distributed in the hope that it will be useful, but WITHOUT
 * WARRANTY OF ANY KIND.
 *
 * Author(s): Borge Strand
 *
 * Description:
 *
 *    Primitive access to internal registers in nRF24Z1. 
 *    This file is independant of MCU, DAC and ADC.
 *
 * Compiler: Tested with WinAVR, avr-gcc (GCC) 3.4.3
 *
 * Revision: 2.0 
 *
 *==============================================================================
 */


#include "z1slaveio.h"


// Read a single byte from nRF24Z1's slave interface using 2-wire 
char z1_singleread(char adr) {
    return mcu_2w_read(Z12WDEVADR, adr);
}


// Write a single byte to nRF24Z1's slave interface using 2-wire
void z1_singlewrite(char adr, char data) {
    mcu_2w_write(Z12WDEVADR, adr, data);
}


// Wait until a flag indicates that registers are ready. Time out if it takes too long!
char z1_flagready(char flag) {
    char inbyte;
    int counter = MAXPOLLITER;
    extern char error;
    
    error = OKAY;                                   // Nothing wrong found yet!
    
    while (counter-- > 0) {                         // Only run permitted number of times
        inbyte = z1_singleread(flag);               // Read the flag through slave interface
        if (inbyte==FLAGREADY)                      // Flag is ready, 
            return OKAY;                            // all is well
        else if (inbyte==Z1TIMEOUT)                 // nRF24Z1 was unable to finish transfer but may receive new data
            return OKAY;                            // Here if nRF24Z1 wasn't able to complete a transfer
        else 
            mcu_wait_ms(POLLDURATION);              // Wait before polling the flag again
    }
    
    return TIMEOUT;                                 // Function timed out!
}


// Write 0x01 to a flag in order to initiate a transfer etc.
void z1_setflag(char flag) {
    z1_singlewrite (flag, 0x01);
}


// Check four times in a row if nRF24Z1 has a link, this is a simple binary test!
char z1_haslink(void) {
    char counter = 4;
    
    while (counter-- != 0) {
        if (z1_singleread(LNKSTA)!=LINKPRESENT)     // Flag is not ready, 
            return 0;                               // Return signal of no link present
        else                                        // Flag is ready, but we should wait and check again
            mcu_wait_ms(5);
    }

    return 1;                                       // All link search attempts were successfull
}


// Wait for a link to be established, return z1_haslink(). Poll for a link LINKFINDCOUONTER times, 
// each time waiting for LINKFINDPERIOD ms. 
char z1_haslink_wait(void) {
    char temp = LINKFINDCOUNTER;

    while (temp != 0) {                             // Have we looked for a link for long enough?
        #ifdef DEBUG
            mcu_putchar('0');                       // Monitor linkup
        #endif
        if (z1_haslink()) {                         // Did we find a link?
            return 1;                               // If we did, quit happily
        }
        else {                                      // If not, wait some more and look again
            temp--;
            mcu_wait_ms(LINKFINDPERIOD);    // Give it chance to link up
        }
    }

    return 0;
}


// Make ATX initiate a relink 
void z1_force_relink(void) {
    z1_singlewrite(LNKMOD, 0x10);                   // Write a "1" to LNKMOD[4] to force relink
}


// Turn ARX muting on and off
char z1_arx_mute(char muting) {
    char temp = z1_flagready(RXCSTATE);             // Check if ATX is ready to transfer new data to ARX
    
    if (temp == OKAY) {                             // If it is, start processing mute data
        if (muting == MUTEON)                       // Turning muting on, i.e. ARX goes quiet
            z1_singlewrite(I2SCNF_OUT, z1_singleread(I2SCNF_OUT) | 0x40);   // Set bit 6 of I2SCNF_OUT
        else if (muting == MUTEOFF)                 // Turning muting off, i.e. ARX plays music
            z1_singlewrite(I2SCNF_OUT, z1_singleread(I2SCNF_OUT) & ~0x40); // clear bit 6 of I2SCNF_OUT
        z1_setflag(RXCSTATE);                       // Transfer new contents to ARX
    }
    return temp;
}


#ifdef Z1ALTERADDRESS
// The private address is used once the RX and TX link up. The RX is listening
// on this address if it comes back after having been out of range.
// This function assumes that the caller has tested flags before calling it. It will not
// perform any relinking, only set up the address and frequency hopping registers.
void z1_setprivateadr(void) {
    z1_singlewrite(ADDR_0, mcu_randombyte());       // Data for ADDR_0 through ADDR_4
    z1_singlewrite(ADDR_1, mcu_randombyte());       // Data for ADDR_0 through ADDR_4
    z1_singlewrite(ADDR_2, mcu_randombyte());       // Data for ADDR_0 through ADDR_4
    z1_singlewrite(ADDR_3, mcu_randombyte());       // Data for ADDR_0 through ADDR_4
    z1_singlewrite(ADDR_4, mcu_randombyte());       // Data for ADDR_0 through ADDR_4
}


// The initial address is the one stored in an external EEPROM or MCU on the RX side. 
// The RX will listen on this address after an RX power cycle.
// This function assumes that the caller has tested flags before calling it. It will not
// perform any relinking, only set up the address and frequency hopping registers.
void z1_setinitialadr(void) {
    z1_singlewrite(ADDR_0, 0x98);                   // Data for ADDR_0
    z1_singlewrite(ADDR_1, 0x38);                   // Data for ADDR_1
    z1_singlewrite(ADDR_2, 0xA2);                   // Data for ADDR_2
    z1_singlewrite(ADDR_3, 0x34);                   // Data for ADDR_3
    z1_singlewrite(ADDR_4, 0x85);                   // Data for ADDR_4  
}
#endif // Z1ALTERADDRESS


#ifdef USELED

// Turn a LED on the ARX on or off. The LED is located on DO1. It is active high. 
// This feature only works with slave interface disabled in ARX.
void z1_arxled(char mode) {
    char temp = z1_singleread(RXPIO);

    if (z1_flagready(RXCSTATE) == OKAY) {           // Okay to update ARX registers?
        if (mode == LEDON)
            temp |= 0x22;                           // Set DO1="1" with high drive high enable
        else if (mode == LEDOFF)
            temp &= 0xDD;                           // Set DO1="0" without high drive high enable
        z1_singlewrite(RXPIO, temp);                // Update RXPIO
        z1_setflag(RXCSTATE);                       // Transfer contents to ARX
    }
    else {
        #ifdef DEBUG
            mcu_putchar('#');                       // Indicate failure
        #endif
    }
}


// Rotate LED sequence and return LED code according to the MSB that is about to be rotated through left shift
char z1_rotate_led(void) { 
    extern unsigned int ledsequence;                // FIX: hard code to 16-bit value

    if (ledsequence & 0x8000) {                     // Check if the MSB of ledsequence is set
        ledsequence <<= 1;                          // If it is, perform left-shift and
        ledsequence |= 0x0001;                      // insert a "1" at the LSB end to make it circular
        return LEDON;                               // Indicate that LED is to be turned on
    }
    else {                                          // If MSB of ledsequence is cleared,
        ledsequence <<= 1;                          // Perform left-shift which will insert a zero at the LSB end to make it circular
        return LEDOFF;                              // Indicate that LED is to be turned off
    } 
}
#endif // USELED


#ifdef Z1INTERRUPT

// Report which interrupt is received. Interrupts are handled according to a priority list
char z1_intstatus(void) {
    char temp = z1_singleread(INTSTA);
    
    if ((temp & INT_LBROKEN) != 0x00)
        return INT_LBROKEN;
    else if ((temp & INT_LQUAL) != 0x00)
        return INT_LQUAL;
    else if ((temp & INT_RTRANS) != 0x00)
        return INT_RTRANS;
    else if ((temp & INT_RINPUT) != 0x00)
        return INT_RINPUT;
    else if ((temp & INT_LERROR) != 0x00)
        return INT_LERROR;
    else if ((temp & INT_WAKE) != 0x00)
        return INT_WAKE;
    else
        return INT_VOID;
}

// Enable one or more interrupt sources in nRF24Z1, call it like this:
// z1_intinit(INT_LBROKEN | INT_LQUAL | INT_RINPUT); with the desired interrupt 
// definitions OR'ed into one parameter byte. Interrupt output from ATX to MCU 
// is active low in all of the program. It may be set active high by OR'ing interrupts by 0x80
void z1_intinit(char interrupts) {
    z1_singlewrite(INTCF, interrupts);              // Enable whatever interrupt was selected. This might trigger IRQ immediately
    mcu_wait_ms(2);                                 // Wait for possible interrupt to occur
   
    if ((interrupts & INT_LQUAL) == 0x00)           // If there is no interrupt due to poor link quality, 
        z1_singlewrite(LNKWTH, 0x00);               // Don't give the corresponding flag a chance to occur
    
    if ((interrupts & INT_LERROR) == 0x00)          // If there is no interrupt due to link errors,
        z1_singlewrite(LNKETH, 0xFF);               // Don't give the corresponding flag a chance to occur
}


void z1_intdeactivate(void) {
    z1_singlewrite(INTCF, 0x00);                    // Disable all nRF24Z1 interrupt sources
}
#endif // Z1INTERRUPT

⌨️ 快捷键说明

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