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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#include <ioport.h>
#ifdef CONFIG_IOPORTS
#ifdef CONFIG_PCINT
struct PCIW {
uint8_t flags;
uint8_t mask;
void (*change) (uint8_t group, uint8_t mask);
};
// Exploiting implementation of libc malloc
#define PCIW_LEN(INPCIW) (*((uint16_t *) INPCIW - 1) / sizeof(struct PCIW) - 1)
#if (defined MCUSUPPORT_PCINT0 && defined MCUSUPPORT_PCINT1 && defined MCUSUPPORT_PCINT2)
#define PCI_COUNT 3
#elif (defined MCUSUPPORT_PCINT0 && defined MCUSUPPORT_PCINT1 || \
defined MCUSUPPORT_PCINT1 && defined MCUSUPPORT_PCINT2 || \
defined MCUSUPPORT_PCINT2 && defined MCUSUPPORT_PCINT0)
#define PCI_COUNT 2
#elif (defined MCUSUPPORT_PCINT0 || defined MCUSUPPORT_PCINT1 || defined MCUSUPPORT_PCINT2)
#define PCI_COUNT 1
#else
#define PCI_COUNT 0
#endif
#define GROUP2INDEX(GRP) (GRP - MCUSUPPORT_PCINT0)
static struct PCIW *pciw[PCI_COUNT];
static uint8_t pci_state[PCI_COUNT];
static void pci(int8_t group, int8_t pinmax) {
int8_t i, y;
int8_t index = GROUP2INDEX(group);
int8_t len = (int8_t) PCIW_LEN(pciw[index]);
// WARN Is possible that PCINT0 is not corresponding with B group and so on?
uint8_t state = IOE_IO_PIN(group);
for (i = len; i >= 0; i--) {
uint8_t stA = state & pciw[index][i].mask;
uint8_t stB = pci_state[index] & pciw[index][i].mask;
if (((~stA & stB) && pciw[index][i].flags & IOE_IO_RISING) ||
((stA & ~stB) && pciw[index][i].flags & IOE_IO_FALLING)) {
pciw[index][i].change(IOE_IO_B, mask);
}
}
pci_state[index] = state;
}
void io_change_sethook(uint8_t group, uint8_t mask, uint8_t edge,
void (*change) (uint8_t group, uint8_t mask)) {
int8_t index = (int8_t) GROUP2INDEX(group);
int8_t len = (int8_t) PCIW_LEN(pciw[index]);
pciw[index] = realloc(pciw[index], len + 1);
pciw[index][len].flags = edge;
pciw[index][len].mask = mask;
pciw[index][len].change = change;
switch (group) {
#ifdef MCUSUPPORT_PCINT0 // TODO this wont work with attiny4313 and meaby others
case IO_B:
PCICR |= (1<<0);
PCMSK0 |= mask;
break;
#endif
#ifdef MCUSUPPORT_PCINT1
case IO_C:
PCICR |= (1<<1);
PCMSK1 |= mask;
break;
#endif
#ifdef MCUSUPPORT_PCINT2
case IO_D:
PCICR |= (1<<2);
PCMSK2 |= mask;
break
#endif
}
}
void io_change_remhook(void (*change) (uint8_t group, uint8_t mask)) {
int8_t i, y;
int8_t len;
for (i = PCI_COUNT - 1; i >= 0; i--) {
len = (int8_t)PCIW_LEN(pciw[index]);
for (y = len - 1; y >= 0; y--) {
if (pciw[i][y].change == change) {
}
}
}
}
void io_change_clearhooks(void) {
// TODO
}
// WARN This will work only if C is only defined on MCU with also B defined.
#ifdef MCUSUPPORT_PCINT0
ISR(PCINT0_vect, ISR_BLOCK) {
pci(IO_B, MCUSUPPORT_PCINT0);
}
#endif /* MCUSUPPORT_PCINT0 */
#ifdef MCUSUPPORT_PCINT1
ISR(PCINT1_vect, ISR_BLOCK) {
pci(IO_C, MCUSUPPORT_PCINT1);
}
#endif /* MCUSUPPORT_PCINT1 */
#ifdef MCUSUPPORT_PCINT2
ISR(PCINT2_vect, ISR_BLOCK) {
pci(IO_D, MCUSUPPORT_PCINT2);
}
#endif /* MCUSUPPORT_PCINT2 */
#endif /* CONFIG_PCINT */
#endif /* CONFIG_IOPORTS */
|