National CP3BT26 User Manual

Page of 278
191
www.national.com
CP3
BT26
    acb->ACBctl1    |=  ACBSTOP;                    /* Send STOP bit                                        */
                                                    /* Return success status....                            */
    return (ACB_NOERR);
}
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
; NAME: ACBStartX   Initiates an ACB bus transaction by sending the Start bit, followed by the Slave address
;                   and R/W flag.  Checks for any ACB errors throughout this sequence and returns status.
;
; PARAMETERS:   UBYTE   Slave   -   I2C address of Slave device
;               UBYTE   R_nW    -   Read/Write flag (0x01 or 0x00)
;               UWORD   Count   -   Desired number of bytes (read/write)
;
; CALLS:
;
; RETURNED: error/success
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
UWORD   ACBStartX (UBYTE Slave, UBYTE R_nW, UWORD Count)
{
    ACB_T   *acb;
    UWORD   Timeout;
                                                    /* Get address of ACB module                            */
    acb =   (ACB_T*)ACB_ADDRESS;
                                                    /* If Bus is Busy and we’re NOT the Master, return err  */
    if (acb->ACBcst & ACBBB && !(acb->ACBst & ACBMASTER))
        return (ACBERR_NOTMASTER);
                                                    /* If we’re good to go, send Start condition            */
    acb->ACBctl1    |=  ACBSTART;
                                                    /* Check if we’re the Bus Master with timeout           */
    Timeout =   100;
    while (!(acb->ACBst & ACBSDAST) && Timeout--)   /* Related to bus error problem                         */
    {
        if (acb->ACBst & ACBBER) {                  /* If collision occurs, clear error and return status   */
            acb->ACBst  |=  ACBBER;
            return (ACBERR_COLLISION);
        }
    }
    if (!Timeout)                                   /* If timeout, we must NOT be the Master...signal error */
        return (ACBERR_NOTMASTER);
                                                    /* Now, send the address and R/W flag...                */
    acb->ACBsda =   Slave | R_nW;                   /* Send address and R/W flag                            */
    Timeout =   1000;                               /* Failsafe for lockup                                  */
                                                    /* Wait for address to be sent and ACK’d                */
    while (!(acb->ACBst & ACBSDAST) && 
        !(acb->ACBst & ACBNEGACK)&& 
        --Timeout) {
        if (acb->ACBst & ACBBER) {                  /* If a bus error occurs while sending address, clear   */
            acb->ACBst  |=  ACBBER;                 /* the error flag and return error status               */
            return (ACBERR_COLLISION);
        }
    }
KBD_OUT |= BIT0; // OScope marker
    if (!Timeout)                                   /* If timeout, signal error                             */
        return (ACBERR_TIMEOUT);
                                                    /* Or if Slave does not reply, report busy/error        */
    else if (acb->ACBst & ACBNEGACK)
        return (ACBERR_NEGACK);
                                                    /* Otherwise return success                             */
    else {
        return (ACB_NOERR);
    }