18
18
#include "gpio_irq_api.h"
19
19
#include "error.h"
20
20
21
+ // The chip is capable of 4 external interrupts.
21
22
#define CHANNEL_NUM 4
22
- #define PININT_IRQ 28+3
23
23
24
24
static uint32_t channel_ids [CHANNEL_NUM ] = {0 };
25
25
static gpio_irq_handler irq_handler ;
26
- static uint32_t channel = 0 ;
27
-
28
- #warning (matthewelse) This code isn't working yet, so don't rely on it, or try to use it.
26
+ static int channel = 0 ;
27
+ static PinName pin_names [CHANNEL_NUM ] = {};
29
28
30
29
static inline void handle_interrupt_in (uint32_t channel ) {
30
+ // Find out whether the interrupt has been triggered by a high or low value...
31
+ // As the LPC1114 doesn't have a specific register for this, we'll just have to read
32
+ // the level of the pin as if it were just a normal input...
31
33
32
- #error (matthewelse) There's no way this code will work now...
33
- uint32_t ch_bit = (1 << channel );
34
- LPC_GPIO_TypeDef * port_reg = ((LPC_GPIO_TypeDef * ) (LPC_GPIO0_BASE + (channel * 0x10000 )));
35
-
34
+ // Get the number of the pin being used and the port typedef
35
+ uint8_t pin_number = (pin_names [channel ] & (0x0f << 8 )) >> 8 ;
36
+ LPC_GPIO_TypeDef * port_reg = ((LPC_GPIO_TypeDef * ) (LPC_GPIO0_BASE + (((pin & 0xF000 ) >> PORT_SHIFT ) * 0x10000 )));
37
+
38
+ if ((port_reg -> MASKED_ACCESS & (1 << pin_number )) >> pin_number ) {
39
+ // High, therefore rising edge...
40
+ irq_handler (channel_ids [channel ], IRQ_RISE );
41
+ }
42
+ else {
43
+ // Low, therefore falling edge...
44
+ irq_handler (channel_ids [channel ], IRQ_FALL );
45
+ }
36
46
}
37
47
38
48
void gpio_irq0 (void ) {handle_interrupt_in (0 );}
@@ -43,17 +53,43 @@ void gpio_irq3(void) {handle_interrupt_in(3);}
43
53
int gpio_irq_init (gpio_irq_t * obj , PinName pin , gpio_irq_handler handler , uint32_t id ) {
44
54
if (pin == NC ) return -1 ;
45
55
46
- channel_ids [ channel ] = id ;
47
- irq_handler = handler ;
56
+ // Firstly, we'll put some data in *obj so we can keep track of stuff.
57
+ obj -> pin = pin ;
48
58
49
- //obj->pin = pin;
59
+ /*
60
+ If there are any ports or pins that aren't able to handle interrupts, put them here and uncomment.
61
+
62
+ if (pin == ... ||
63
+ pin == ...) {
64
+ error("This pin does not suppor interrupts.");
65
+ return -1;
66
+ }
67
+ */
68
+
69
+ channel_ids [channnel ] = id ;
70
+ pin_names [channel ] = pin ;
50
71
obj -> ch = channel ;
51
-
52
- NVIC_EnableIRQ (EINT0_IRQn );
53
- NVIC_EnableIRQ (EINT1_IRQn );
54
- NVIC_EnableIRQ (EINT2_IRQn );
55
- NVIC_EnableIRQ (EINT3_IRQn );
56
-
72
+
73
+ // Which port are we using?
74
+ switch (channel ) {
75
+ case 0 :
76
+ NVIC_SetVector (EINT0_IRQn , (uint32_t )gpio_irq0 );
77
+ NVIC_EnableIrq (EINT0_IRQn );
78
+ break ;
79
+ case 1 :
80
+ NVIC_SetVector (EINT1_IRQn , (uint32_t )gpio_irq1 );
81
+ NVIC_EnableIrq (EINT1_IRQn );
82
+ break ;
83
+ case 2 :
84
+ NVIC_SetVector (EINT2_IRQn , (uint32_t )gpio_irq2 );
85
+ NVIC_EnableIrq (EINT2_IRQn );
86
+ break ;
87
+ case 3 :
88
+ NVIC_SetVector (EINT3_IRQn , (uint32_t )gpio_irq3 );
89
+ NVIC_EnableIrq (EINT3_IRQn );
90
+ break ;
91
+ }
92
+
57
93
channel ++ ;
58
94
return 0 ;
59
95
}
@@ -63,71 +99,30 @@ void gpio_irq_free(gpio_irq_t *obj) {
63
99
}
64
100
65
101
void gpio_irq_set (gpio_irq_t * obj , gpio_irq_event event , uint32_t enable ) {
66
- // TODO: Debug this to find out what data is put in the obj object at runtime...
67
-
68
- LPC_GPIO_TypeDef * gpioReg ;
69
-
70
- // Firstly, clear the interrupts for this pin.
71
- // Then, let the registers know whether we're looking for edge detection...
72
- // And enable the interrupt
73
- // And set it to only respond to interrupts on one edge.
74
- switch (obj -> port ) {
75
- case LPC_GPIO0_BASE :
76
- // Clear
77
- LPC_GPIO0 -> IC |= 1 << obj -> pin ;
78
-
79
- // Edge
80
- LPC_GPIO0 -> IS &= ~(1 << obj -> pin );
81
-
82
- // Enable
83
- if (enable ) LPC_GPIO0 -> IE |= 1 << obj -> pin ;
84
- else LPC_GPIO0 -> IE &= ~(1 << obj -> pin );
85
-
86
- // One edge
87
- LPC_GPIO0 -> IBE &= ~(1 << obj -> pin );
88
-
89
- // Rising/falling?
90
- if (event == IRQ_RISE ) LPC_GPIO0 -> IEV |= 1 << obj -> pin ;
91
- else LPC_GPIO0 -> IEV &= ~(1 << obj -> pin );
92
- break ;
93
- case LPC_GPIO1_BASE :
94
- LPC_GPIO1 -> IC |= 1 << obj -> pin ;
95
-
96
- LPC_GPIO1 -> IS &= ~(1 << obj -> pin );
97
-
98
- if (enable ) LPC_GPIO1 -> IE |= 1 << obj -> pin ;
99
- else LPC_GPIO1 -> IE &= ~(1 << obj -> pin );
100
-
101
- LPC_GPIO1 -> IBE &= ~(1 << obj -> pin );
102
-
103
- if (event == IRQ_RISE ) LPC_GPIO0 -> IEV |= 1 << obj -> pin ;
104
- else LPC_GPIO0 -> IEV &= ~(1 << obj -> pin );
105
- break ;
106
- case LPC_GPIO2_BASE :
107
- LPC_GPIO2 -> IC |= 1 << obj -> pin ;
108
-
109
- LPC_GPIO2 -> IS &= ~(1 << obj -> pin );
110
-
111
- if (enable ) LPC_GPIO2 -> IE |= 1 << obj -> pin ;
112
- else LPC_GPIO2 -> IE &= ~(1 << obj -> pin );
113
-
114
- LPC_GPIO2 -> IBE &= ~(1 << obj -> pin );
115
-
116
- if (event == IRQ_RISE ) LPC_GPIO0 -> IEV |= 1 << obj -> pin ;
117
- else LPC_GPIO0 -> IEV &= ~(1 << obj -> pin );
118
- break ;
119
- case LPC_GPIO3_BASE :
120
- LPC_GPIO3 -> IC |= 1 << obj -> pin ;
121
-
122
- LPC_GPIO3 -> IC &= ~(1 << obj -> pin );
123
-
124
- if (enable ) LPC_GPIO3 -> IE |= 1 << obj -> pin ;
125
- else LPC_GPIO3 -> IE &= ~(1 << obj -> pin );
126
-
127
- LPC_GPIO3 -> IBE &= ~(1 << obj -> pin );
128
-
129
- if (event == IRQ_RISE ) LPC_GPIO0 -> IEV |= 1 << obj -> pin ;
130
- else LPC_GPIO0 -> IEV &= ~(1 << obj -> pin );
131
- break ;
132
- }
102
+ pin = obj -> pin ;
103
+ LPC_GPIO_TypeDef * port_reg = ((LPC_GPIO_TypeDef * ) (LPC_GPIO0_BASE + (((pin & 0xF000 ) >> PORT_SHIFT ) * 0x10000 )));
104
+
105
+ /*
106
+ Firstly, clear the interrupts for this pin,
107
+ Then, let the registers know whether we're looking for edge detection,
108
+ Enable the interrupt,
109
+ And set it to only respond to interrupts on one edge.
110
+ */
111
+
112
+ // Clear
113
+ port_reg -> IC |= 1 << obj -> pin ;
114
+
115
+ // Edge
116
+ port_reg -> IS &= ~(1 << obj -> pin );
117
+
118
+ // Enable
119
+ if (enable ) port_reg -> IE |= 1 << obj -> pin ;
120
+ else port_reg -> IE &= ~(1 << obj -> pin );
121
+
122
+ // One edge
123
+ port_reg -> IBE &= ~(1 << obj -> pin );
124
+
125
+ // Rising/falling?
126
+ if (event == IRQ_RISE ) port_reg -> IEV |= 1 << obj -> pin ;
127
+ else port_reg -> IEV &= ~(1 << obj -> pin );
133
128
}
0 commit comments