
/** Configuration: HDLC FCS Calculation Method
 *
 *  Set FCS_METHOD to one of:
 *   - FCS_USE_TABLE is the fastest method, but uses a 512-byte
 *     feedback table that may be too large for some small
 *     systems.
 *   - FCS_USE_SHIFT uses a byte-wise shift and XOR calculation
 *     method, but some shift counts (e.g., 5-bit and 12-bit
 *     shifts) may not be optimally coded in some architectures.
 *   - FCS_USE_SHORT_SHIFT uses the same byte-wise shift and XOR
 *     calculation method as FCS_USE_SHIFT, but has been
 *     optimized for most 8-bitters, especially those with a
 *     nibble swap instruction.
 */
#define FCS_USE_TABLE           1
#define FCS_USE_SHIFT           2
#define FCS_USE_SHORT_SHIFT     3
#define FCS_METHOD              FCS_USE_SHORT_SHIFT

/*  FCS_UPD() implements the FCS calculation selected by FCS_METHOD.
 */
#if   FCS_METHOD == FCS_USE_TABLE
#define FCS_UPD(u16, b) 
    ((u16).w = ((u16).w >> 8) ^ feedback[((u16).w ^ (b)) & 0xFF])
#elif FCS_METHOD == FCS_USE_SHIFT
#define FCS_UPD(u16, b)                                  
do {                                                     
    (u16).w ^= (b);                                      
    (u16).w  = (U8)((u16).w >> 8) | (U16)((u16).w << 8); 
    (u16).w ^= (U16)(((u16).w & 0xFF00) << 4);           
    (u16).w ^= (u16).w >> 12;                            
    (u16).w ^= (U16)(((u16).w & 0xFF00) >> 5);           
} while (0)
#elif FCS_METHOD == FCS_USE_SHORT_SHIFT
#define FCS_UPD(u16, b)                                        
do {                                                           
    U8  u8;                                                    
    U16_LSB(u16) ^= (b);                                       
    u8            = U16_MSB(u16);                              
    U16_MSB(u16)  = U16_LSB(u16);                              
    U16_LSB(u16)  = u8;                                        
    U16_MSB(u16) ^= (U8)(U16_MSB(u16) << 4);                   
    U16_LSB(u16) ^= U16_MSB(u16) >> 4;                         
    u8            = U16_MSB(u16) ^ ((U16_MSB(u16) >> 4) >> 1); 
    U16_LSB(u16) ^= (U8)(U16_MSB(u16) << 3);                   
    U16_MSB(u16)  = u8;                                        
} while (0)
#else
#   error Unsupported FCS_METHOD.
#endif
