blob: 193c8420f80c6c092e7cd7d80cf07c1862510b2b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
/*
* 74HCT4094 shift register driver
*
* Copyright (C) 2013 Michael Buesch <m@bues.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "4094.h"
#include <avr/io.h>
#include <avr/cpufunc.h>
/* Hardware pin configuration */
#define SR4094_DATA_PORT PORTB
#define SR4094_DATA_DDR DDRB
#define SR4094_DATA_BIT 2
#define SR4094_CLOCK_PORT PORTB
#define SR4094_CLOCK_DDR DDRB
#define SR4094_CLOCK_BIT 3
#define SR4094_STROBE_PORT PORTB
#define SR4094_STROBE_DDR DDRB
#define SR4094_STROBE_BIT 0
void sr4094_put_data(sr4094_t old_state, sr4094_t new_state)
{
sr4094_t mask = (sr4094_t)1 << (sizeof(sr4094_t) * 8 - 1);
sr4094_t current_state = old_state;
if (new_state == old_state) {
/* Neue Daten sind bereits aktiv. */
return;
}
/* Daten in das Schieberegister laden. */
SR4094_STROBE_PORT &= ~(1 << SR4094_STROBE_BIT);
do {
current_state <<= 1;
/* Datenpin setzen. */
if (new_state & mask) {
SR4094_DATA_PORT |= (1 << SR4094_DATA_BIT);
current_state |= 1;
} else
SR4094_DATA_PORT &= ~(1 << SR4094_DATA_BIT);
/* Taktflanke ausgeben. */
SR4094_CLOCK_PORT |= (1 << SR4094_CLOCK_BIT);
_NOP();
SR4094_CLOCK_PORT &= ~(1 << SR4094_CLOCK_BIT);
mask >>= 1;
} while (new_state != current_state);
SR4094_STROBE_PORT |= (1 << SR4094_STROBE_BIT);
}
void sr4094_init(void)
{
/* Ports initialisieren. */
SR4094_DATA_PORT &= ~(1 << SR4094_DATA_BIT);
SR4094_DATA_DDR |= (1 << SR4094_DATA_BIT);
SR4094_CLOCK_PORT &= ~(1 << SR4094_CLOCK_BIT);
SR4094_CLOCK_DDR |= (1 << SR4094_CLOCK_BIT);
SR4094_STROBE_PORT |= (1 << SR4094_STROBE_BIT);
SR4094_STROBE_DDR |= (1 << SR4094_STROBE_BIT);
/* Alle Bits loeschen. */
sr4094_put_data((sr4094_t)-1ul, 0);
}
|