4094.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * 74HCT4094 shift register driver
  3. *
  4. * Copyright (C) 2009-2016 Michael Buesch <m@bues.ch>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * version 2 as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include "4094.h"
  16. #include "util.h"
  17. #include <avr/io.h>
  18. #define _sr4094_clear(pin) \
  19. SR4094_##pin##_PORT = (uint8_t)(SR4094_##pin##_PORT & ~(1 << SR4094_##pin##_BIT))
  20. #define _sr4094_set(pin) \
  21. SR4094_##pin##_PORT = (uint8_t)(SR4094_##pin##_PORT | (1u << SR4094_##pin##_BIT))
  22. static inline void sr4094_transfer_start(void)
  23. {
  24. _sr4094_clear(STROBE);
  25. }
  26. static inline void sr4094_transfer_end(void)
  27. {
  28. _sr4094_set(STROBE);
  29. }
  30. static void sr4094_put_byte(uint8_t data)
  31. {
  32. uint8_t mask = 0x80;
  33. do {
  34. if (data & mask)
  35. _sr4094_set(DATA);
  36. else
  37. _sr4094_clear(DATA);
  38. _sr4094_set(CLOCK);
  39. nop();
  40. nop();
  41. _sr4094_clear(CLOCK);
  42. mask >>= 1;
  43. } while (mask);
  44. }
  45. void sr4094_put_data(void *_data, uint8_t nr_chips)
  46. {
  47. uint8_t *data = _data;
  48. uint8_t i;
  49. sr4094_transfer_start();
  50. for (i = 0; i < nr_chips; i++)
  51. sr4094_put_byte(data ? data[i] : 0);
  52. sr4094_transfer_end();
  53. }
  54. void sr4094_outen(uint8_t enable)
  55. {
  56. if (enable)
  57. _sr4094_set(OUTEN);
  58. else
  59. _sr4094_clear(OUTEN);
  60. }
  61. void sr4094_init(void *initial_data, uint8_t nr_chips)
  62. {
  63. sr4094_outen(0);
  64. SR4094_OUTEN_DDR |= (1 << SR4094_OUTEN_BIT);
  65. _sr4094_clear(DATA);
  66. SR4094_DATA_DDR |= (1 << SR4094_DATA_BIT);
  67. _sr4094_clear(CLOCK);
  68. SR4094_CLOCK_DDR |= (1 << SR4094_CLOCK_BIT);
  69. _sr4094_set(STROBE);
  70. SR4094_STROBE_DDR |= (1 << SR4094_STROBE_BIT);
  71. sr4094_put_data(initial_data, nr_chips);
  72. }