-
Notifications
You must be signed in to change notification settings - Fork 158
/
interrupt_handling.dot
139 lines (113 loc) · 6.19 KB
/
interrupt_handling.dot
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
digraph {
label = <
<font point-size="42">Interrupt Handling</font><br />
<font point-size="22">For GPIO libraries with software interrupt callbacks,<br />and how they handle being an interrupt for other modules</font>
>;
labelloc = "t";
newrank=true;
node[shape=box, style=rounded]
mcp_gpio_input [label="MCP input pin logic level changes"];
mcp_int_output [label="MCP interrupt output pin logic level changes"];
pi_gpio_input [label="Pi input pin logic level changes"];
pi_int_callback [label="Pi interrupt callback is triggered"];
# server.MqttIo
subgraph cluster_main_int_callback {
label = <<font point-size="22">MqttIo.interrupt_callback()</font>>
node [shape=diamond]
q_is_remote_int [label="Configured as interrupt for other module's pin(s)?"];
q_acquire_interrupt_lock [label="Acquire lock for this interrupt pin?"];
node [shape=box, style=rounded]
main_int_callback [label="Gets called by module's software\ncallback with whichever args supplied"];
ignore_interrupt [label="Ignore this interrupt", style=striped];
fire_digital_input_changed_event_main [label="Fire DigitalInputChangedEvent", style="striped"];
get_all_interrupt_for_pins [label="Get list of pin names that this pin_name is an interrupt for"]
get_interrupt_value [label="Get value of pin that caused the interrupt\nusing [module].GPIO.get_interrupt_value(pin)"];
}
subgraph cluster_handle_remote_int {
label = <<font point-size="22">MqttIo.handle_remote_interrupt()</font>>
node [shape=box, style=rounded]
organise_into_modules [label="Organise pins by module"]
make_funcs_to_get_pin_vals_and_fire_event [label="Make async closure functions to call get_interrupt_values_remote(pins)\non each module and fire events if/when the values are received"]
add_the_functions_to_a_list [label="Add these functions to a list"];
make_func_to_await_the_funcs [label="Make async closure function to await all of the functions"];
add_awaiting_func_to_task_list [label="Add the awaiting function to the task list"];
subgraph cluster_handle_remote_int_closure_func {
label = <<font point-size="22">handle_remote_interrupt_task()</font>>
node [shape=box, style=rounded]
call_modules_to_get_int_values [label="Call get_interrupt_values_remote(pins) on the module"];
fire_digital_input_changed_event_closure [label="Fire DigitalInputChangedEvent", style=striped];
}
subgraph cluster_await_remote_ints {
label = <<font point-size="22">await_remote_interrupts()</font>>
await_all_remote_int_tasks [label="Await all remote interrupt tasks"];
release_int_lock [label="Release interrupt lock", style="striped"];
}
}
# END server.MqttIO
# modules.gpio.GenericGPIO
subgraph cluster_get_int_pin_values {
label = <<font point-size="22">GenericGPIO.get_interrupt_values_remote(pins)</font>>;
node[shape=diamond]
q_can_identify_pin [label="Can identify which pin caused the interrupt?\n(InterruptSupport.FLAG_REGISTER)"];
q_can_capture_pin_val [label="Can get captured pin interrupt value?\n(InterruptSupport.CAPTURE_REGISTER)"];
q_which_edge [label="Which edge(s) were these interrupt(s) configured for?"];
q_any_pins_changed [label="Pin(s) value changed?"]
node[shape=box, style=rounded]
check_all_possible_pins [label="Check all pins on this module that\ncould have triggered the interrupt"]
poll_pin [label="Poll the pin for its current value"];
get_flagged_pins [label=<
<b>gpio_module.get_int_pins()</b><br />
Get flagged interrupt pins
>]
capture_pin_value [label=<
<b>gpio_module.get_captured_int_pin_values(pins)</b><br />
Get captured pin value at time of interrupt
>]
pin_value_high [label="Pin's value is 'high'"]
pin_value_low [label="Pin's value is 'low'"]
return_pin_values [label="Return pin numbers and their values", style="striped"];
do_nothing [label="Return empty list?\nTODO: Make this behaviour configurable", style="striped"]
}
# END modules.gpio.GenericGPIO
mcp_gpio_input ->
mcp_int_output ->
pi_gpio_input ->
pi_int_callback ->
main_int_callback ->
q_acquire_interrupt_lock;
q_acquire_interrupt_lock -> q_is_remote_int [label="Acquired"];
q_acquire_interrupt_lock -> ignore_interrupt [label="Locked"];
q_is_remote_int -> get_all_interrupt_for_pins [label="Yes"];
get_all_interrupt_for_pins ->
organise_into_modules ->
make_funcs_to_get_pin_vals_and_fire_event ->
add_the_functions_to_a_list ->
make_func_to_await_the_funcs ->
add_awaiting_func_to_task_list ->
await_all_remote_int_tasks ->
call_modules_to_get_int_values ->
q_can_identify_pin;
q_is_remote_int -> get_interrupt_value [label="No"];
get_interrupt_value -> fire_digital_input_changed_event_main;
# GenericGPIO.get_int_pin_values()
q_can_identify_pin -> get_flagged_pins [label="Yes"];
q_can_identify_pin -> check_all_possible_pins [label="No"];
get_flagged_pins -> q_can_capture_pin_val;
check_all_possible_pins -> q_can_capture_pin_val;
q_any_pins_changed -> return_pin_values [label="Yes"];
q_any_pins_changed -> do_nothing [label="No"];
q_can_capture_pin_val -> capture_pin_value [label="Yes"];
q_can_capture_pin_val -> q_which_edge [label="No"];
capture_pin_value -> return_pin_values;
q_which_edge -> pin_value_high [label="Rising"];
q_which_edge -> pin_value_low [label="Falling"];
q_which_edge -> poll_pin [label="Both"];
poll_pin -> q_any_pins_changed;
pin_value_high -> return_pin_values;
pin_value_low -> return_pin_values;
# END GenericGPIO.get_int_pin_values()
return_pin_values -> fire_digital_input_changed_event_closure -> release_int_lock;
# Do we want to call the callback, even though this could be the wrong value?
# The alternative is to only call the callback if it's changed.
# Perhaps this should be a config option?
}