/
bms.pio
70 lines (64 loc) · 3.1 KB
/
bms.pio
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
.program daisychain_tx
.side_set 1
.wrap_target
pull block sideset 0 // Block until we get a word from the CPU, and put it on the shift register (OSR), meanwhile don't control the line
mov pins, !NULL [15] sideset 1 // Wait a while, but start controlling the line (sideset)
mov pins, !NULL [15] sideset 1 // Wait a while longer
set y, 7 sideset 1 // Loop counter
mov pins, NULL [4] sideset 1 // Set data pin LOW. This is the first half of the start bit
mov pins, ! NULL [3] sideset 1 // Set data pin HIGH. This is the second half of the start bit
bitloop:
out x, 1 sideset 1 // Shift one bit off the OSR to register X
mov pins, x [4] sideset 1 // Output x to the data pin
mov pins, ! x [2] sideset 1 // Output inverse of x to the data pin
jmp y-- bitloop sideset 1 // Loop for 8 bits
out x, 1 sideset 1 // Load bit 9, this is the framing bit, if it's set, we transmit LH, else we transmit nothing (HH)
mov pins, ! x [4] sideset 1 // Send first half of final bit (a 1 in bit 9 activates the framing)
mov pins, ! NULL [4] sideset 1 // Last half of final but is always high. Add a short delay before wrapping and releasing the line
nop [15] sideset 0
.wrap
% c-sdk {
static inline void daisychain_tx_program_init(PIO pio, uint sm, uint offset, uint datapin, uint masterpin) {
pio_sm_set_consecutive_pindirs(pio, sm, datapin, 1, true);
pio_sm_set_consecutive_pindirs(pio, sm, masterpin, 1, true);
pio_gpio_init(pio, datapin);
pio_gpio_init(pio, masterpin);
pio_sm_config c = daisychain_tx_program_get_default_config(offset);
sm_config_set_sideset_pins(&c, masterpin);
sm_config_set_out_pins(&c, datapin, 1);
sm_config_set_out_shift(&c, true, false, 9);
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
sm_config_set_clkdiv(&c, 2);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
%}
.program daisychain_rx
.wrap_target
beginning:
wait 0 pin 0 // Wait for data input to go low
jmp pin beginning // Start over if we're transmitting
nop [8] // Delay 9 cycles (nop + 8 more)
set y, 7 // Initialize loop counter
bitloop:
in pins, 1 // Read the bit into the ISR
nop [7] // Delay 8 cycles for a total loop length of 10
jmp y-- bitloop // Loop 8 times
in null, 24 // Dump 24 bits of zero into the ISR to right align the byte
push noblock [3] // Push to FIFO, delay 3 more cycles to fully skip first half of framing bit
nop [15]
.wrap
% c-sdk {
static inline void daisychain_rx_program_init(PIO pio, uint sm, uint offset, uint datapin, uint masterpin) {
pio_sm_set_consecutive_pindirs(pio, sm, datapin, 1, false);
pio_gpio_init(pio, datapin);
pio_sm_config c = daisychain_rx_program_get_default_config(offset);
sm_config_set_in_pins(&c, datapin);
sm_config_set_jmp_pin(&c, masterpin);
sm_config_set_in_shift(&c, true, false, 8);
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
sm_config_set_clkdiv(&c, 2);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
%}