#ifndef _SHIFT_REGISTERS_SEDUCE #define _SHIFT_REGISTERS_SEDUCE #ifndef SR_DDR_OFFSET #define SR_DDR_OFFSET 1 #endif #ifndef SR_PORT_OFFSET #define SR_PORT_OFFSET 2 #endif typedef unsigned char bool; typedef unsigned char byte; /** * @brief Hold data port info. * * Structure used to hold PIN registers * along with a bit position. * * DDR and PORT registers will be automatically located * to save some RAM. offset of DDR can be set * using #define SR_DDR_OFFSET (default 1). For PORT use * #define SR_PORT_OFFSET (default 2). This number is then * added to the PIN address * * Can be used to dynamically save a position of I/O . * * @note Function @see data_position_create can be used as an shorthand for creating DataPosition. * * Example usage: * @code * data_position_create(&PINA, 1); // Pass position 1 of PINA * @endcode */ typedef struct DataPosition { volatile byte* pin; byte position; } DataPosition; typedef enum { SR_PISO, SR_SIPO } ShiftRegisterTypeHeader; typedef struct { const ShiftRegisterTypeHeader type; const DataPosition clockEnable; const DataPosition clockPulse; int waitTime; } ShiftRegister; typedef struct { const ShiftRegister shiftRegister; const DataPosition output; const DataPosition parallelLoad; } PisoShiftRegister; typedef struct { const ShiftRegister shiftRegister; const DataPosition input; const DataPosition outputEnable; const DataPosition pushOutput; } SipoShiftRegister; /** * @brief Create DataPosition struct. * * Pointers to PORT and DDR are automatically calculated. * Check out DataPosition documentation for more information. * * @param pin Pointer to PIN register (for example &PINA). * @param position Position within the register. * @return DataPosition * @note 0 is for LSB. 7 is for MSB. PORTA1 can be used. */ extern const DataPosition data_position_create(volatile byte* pin, byte position); /** * @brief Get PIN value of DataPosition. * * @param position * @return true When PIN (input) is HIGH. * @return false When PIN (input) is LOW. */ extern bool data_position_get_pin(const DataPosition position); /** * @brief Set PORT value of DataPosition. * * This function makes DataPosition PORT register value 1. * If the port is OUTPUT, it will output 5V. * If the port is INPUT, the pull up resistor will be activated. * * @param position */ extern void data_position_set_port(const DataPosition position); /** * @brief Reset PORT value of DataPosition. * * This function makes DataPosition PORT register value 0. * If the port is OUTPUT, it will output 0V. * If the port is INPUT, the pull up resistor will be deactivated. * * @param position */ extern void data_position_reset_port(const DataPosition position); /** * @brief Set DDR value of DataPosition * * This function makes DataPosition DDR register value 1 and thus making it OUTPUT. * * @param position */ extern void data_position_set_ddr(const DataPosition position); /** * @brief Reset DDR value of DataPosition. * * This function makes DataPosition DDR register value 0 and thus making it INPUT. * * @param position */ extern void data_position_reset_ddr(const DataPosition position); /******************************************************************************* * * * SHIFT REGISTER * * Part to define basic shift register functions used for both PISO and SIPO * * * *******************************************************************************/ /** * @brief Create shift register. * * This function creates generic shift register. * Functions beginning with avr_piso_shift_register may be used * with this type of ShiftRegister. * * @param type * @param clockEnable * @param clockPulse * @param waitTime * @return ShiftRegister * * @note You should always init the shift register after creating it. Use @see avr_piso_shift_register_init. */ extern const ShiftRegister avr_shift_register_create( ShiftRegisterTypeHeader type, const DataPosition clockEnable, const DataPosition clockPulse, int waitTime ); /** * @brief Send clock pulse to shift register. * * This function makes the clockPulse position HIGH for specified waitTime * Then makes it LOW again.` * * @param shiftRegister */ extern void avr_shift_register_clock_pulse(const ShiftRegister shiftRegister); /** * @brief Enable shift register clock. * * This function enables the DataPosition for clockEnable. * The clock must be enabled before using the sift register * Otherwise the shift register won't do anything. * * For SIPO registers if clockEnable is made low * the register is also cleared. * * @param shiftRegister * @note This function will be called in the init function. */ extern void avr_shift_register_enable_clock(const ShiftRegister shiftRegister); /** * @brief Disable shift register clock. * * This funciton disables the DataPosition for clockEnable. * @see avr_shift_register_enable_clock for more info * * @note some SIPO registers can be cleared using this function. * * @param shiftRegister */ extern void avr_shift_register_disable_clock(const ShiftRegister shiftRegister); /******************************************************************************* * * * PISO * * Part to define PISO shift register functions to allow shifting and getting * * input from the parallel-in/serial-out shift register * * * *******************************************************************************/ /** * @brief Create PISO shift register. * * This function creates PISO shift register. * Functions beginning with avr_piso_shift_register may be used * with this type of ShiftRegister. * * @param clockEnable Can be specified as CE in datasheet. * @param clockPulse Can be specified as CP in datasheet. * @param output Can be specified as Q7 in datasheet. Be careful not to use negative Q7. * @param parallelLoad Can be specified as PL. * @param waitTime Used to wait when pulsing the clock * @return PisoShiftRegister * * @note You should always init the shift register after creating it. Use @see avr_piso_shift_register_init. */ extern const PisoShiftRegister avr_piso_shift_register_create( const DataPosition clockEnable, const DataPosition clockPulse, const DataPosition output, const DataPosition parallelLoad, int waitTime ); /** * @brief Setup base values for PISO shift register. * * This function initializes the DataPositions so they are correctly set as * inputs or outputs. * * @see avr_shift_register_enable_clock is also called to enable the clock. * * @param shiftRegister */ extern void avr_piso_shift_register_init(const PisoShiftRegister shiftRegister); /** * @brief Asynchronously load the data * * This function is used on shift registers * that have the parallel load port. * PL port will be set LOW and then back * HIGH after waitTime has passed. * * @param shiftRegister */ extern void avr_piso_shift_register_parallel_load(const PisoShiftRegister shiftRegister); /** * @brief Shift next bit * * This function shifts next bit from the PISO shift register. * It just makes the clockPulse HIGH and then LOW. * * @param shiftRegister */ extern void avr_piso_shift_register_shift(const PisoShiftRegister shiftRegister); /** * @brief Read current bit * * This function gets the data from the output. * It will return 0 for LOW or 1 for HIGH * * @note You can read the whole byte using @see avr_piso_shift_register_read_byte * * @param shiftRegister * @return true * @return false */ extern bool avr_piso_shift_register_read_bit(const PisoShiftRegister shiftRegister); /** * @brief Read byte from the shift register * * This function gets byte from the output. * The first value read goes to the LSB. * * @note You can read one bit using @see avr_piso_shift_register_read_bit * * @param shiftRegister * @return byte */ extern byte avr_piso_shift_register_read_byte(const PisoShiftRegister shiftRegister); /******************************************************************************* * * * SIPO * * Part to define SIPO shift register functions to allow shifting and passing * * output to the seiarl-in/parallel-out shift register * * * *******************************************************************************/ /** * @brief Create SIPO shift register handle. * * This function creates SIPO shift register. * Functions beginning with avr_sipo_shift_register may be used * with this type of ShiftRegister. * * @param clockEnable Can be specified as SRCLR in datasheet. * @param clockPulse Can be specified as SRCLK in datasheet. * @param input Can be specified as SER in datasheet. * @param outputEnable Can be specified as OE in datasheet. * @param pushOutput Can be specified as RCLK in datasheet. * @param waitTime Used to wait when pulsing the clock * @return ShiftRegisterHandle * * @note You should always init the shift register after creating it. Use @see avr_sipo_shift_register_init. */ extern const SipoShiftRegister avr_sipo_shift_register_create( const DataPosition clockEnable, // SRCLR const DataPosition clockPulse, // SRCLK const DataPosition input, // SER const DataPosition outputEnable, // OE const DataPosition pushOutput, // RCLK int waitTime ); /** * @brief Setup base values for PISO shift register. * * This function initializes the DataPositions so they are correctly set as * inputs or outputs. * * @see avr_shift_register_enable_clock is also called to enable the clock. * * @param shiftRegister */ extern void avr_sipo_shift_register_init(const SipoShiftRegister shiftRegister); /** * @brief Shifts data by one position. * * This function shifts next bit from the PISO shift register. * It just makes the clockPulse HIGH and then LOW. * * @param shiftRegister */ extern void avr_sipo_shift_register_shift(const SipoShiftRegister shiftRegister); /** * @brief Write one bit to the shift register. * * This function writes one bit to the shift register. * Shift function is also called to save the data. * * @note You can read the whole byte using @see avr_sipo_shift_register_write_byte * * @param shiftRegister * @param data * @param position */ extern void avr_sipo_shift_register_write_bit(const SipoShiftRegister shiftRegister, byte data, int position); /** * @brief Write whole byte to the shift register. * * This function writes whole byte to the shift register. * The first written bit will be the LSB. * * @note You can write only one bit using @see avr_sipo_shift_register_write_bit * * @param shiftRegister * @param data */ extern void avr_sipo_shift_register_write_byte(const SipoShiftRegister shiftRegister, byte data); /** * @brief Enable output DataPosition * * This function enables the output so the shift register * outputs the data shifted in it. * * @param shiftRegister */ extern void avr_sipo_shift_register_enable_output(const SipoShiftRegister shiftRegister); /** * @brief Disable output DataPosition * * This function disables the output so the shift register * doesn't output anything. * * @param shiftRegister */ extern void avr_sipo_shift_register_disable_output(const SipoShiftRegister shiftRegister); /** * @brief Psuh data to output * * This function pushes the data from the shift register * to the storage register. That means the data you shift * in will be set only after you call this function. * * @param shiftRegister */ extern void avr_sipo_shift_register_push_data_to_output(const SipoShiftRegister shiftRegister); /** * @brief Disable and enable clock to reset the SR value * * This funciton disables the clock, then waits a bit * and enables the clock. Doing that the register will * be reset. * * @param shiftRegister */ extern void avr_sipo_shift_register_reset(const SipoShiftRegister shiftRegister); #endif