Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
H
Heizung
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
c3pb
Heizung
Commits
e9e2a7d8
Commit
e9e2a7d8
authored
1 year ago
by
Benjamin Koch
Browse files
Options
Downloads
Patches
Plain Diff
add measurement for auto-baud
parent
77f3e320
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
firmware/rust1/src/bin/heizung.rs
+196
-14
196 additions, 14 deletions
firmware/rust1/src/bin/heizung.rs
with
196 additions
and
14 deletions
firmware/rust1/src/bin/heizung.rs
+
196
−
14
View file @
e9e2a7d8
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
use
defmt
::
*
;
use
defmt
::
*
;
use
embassy_executor
::
Spawner
;
use
embassy_executor
::
Spawner
;
//use embassy_futures::join::join;
use
embassy_futures
::
select
::
select
;
use
embassy_futures
::
select
::
select
;
use
embassy_futures
::
select
::
Either
::
*
;
use
embassy_futures
::
select
::
Either
::
*
;
use
embassy_rp
::
gpio
;
use
embassy_rp
::
gpio
;
...
@@ -11,13 +12,18 @@ use embassy_time::{Duration, Timer};
...
@@ -11,13 +12,18 @@ use embassy_time::{Duration, Timer};
use
embassy_rp
::
gpio
::{
Input
,
Level
,
Output
,
Pull
,
Flex
};
use
embassy_rp
::
gpio
::{
Input
,
Level
,
Output
,
Pull
,
Flex
};
use
embassy_rp
::
i2c
;
use
embassy_rp
::
i2c
;
use
embassy_rp
::
interrupt
;
use
embassy_rp
::
interrupt
;
use
embedded_hal_async
::
i2c
::
I2c
;
//
use embedded_hal_async::i2c::I2c;
use
embassy_embedded_hal
::
SetConfig
;
use
embassy_embedded_hal
::
SetConfig
;
use
embassy_rp
::
peripherals
::{
UART0
,
I2C0
};
use
embassy_rp
::
peripherals
::{
UART0
};
use
embassy_rp
::
uart
::{
self
,
UartRx
,
Parity
};
use
embassy_rp
::
uart
::{
self
,
UartRx
,
Parity
};
use
embassy_rp
::
pwm
::{
self
,
Pwm
};
use
embassy_rp
::
pwm
::{
self
,
Pwm
};
use
embassy_rp
::
pio
::{
Config
,
Pio
,
ShiftConfig
,
ShiftDirection
};
use
embassy_rp
::
relocate
::
RelocatedProgram
;
use
embassy_rp
::
Peripheral
;
use
{
defmt_rtt
as
_
,
panic_probe
as
_
};
use
{
defmt_rtt
as
_
,
panic_probe
as
_
};
use
heapless
::
String
;
use
heapless
::
String
;
use
fixed
::
traits
::
ToFixed
;
use
fixed_macro
::
types
::
U56F8
;
#[embassy_executor::task]
#[embassy_executor::task]
async
fn
reader
(
mut
rx
:
UartRx
<
'static
,
UART0
,
uart
::
Async
>
)
{
async
fn
reader
(
mut
rx
:
UartRx
<
'static
,
UART0
,
uart
::
Async
>
)
{
...
@@ -45,7 +51,7 @@ fn append_hex2<const N : usize>(s : &mut String<N>, num : u8) -> Result<(), ()>
...
@@ -45,7 +51,7 @@ fn append_hex2<const N : usize>(s : &mut String<N>, num : u8) -> Result<(), ()>
append_hex1
(
s
,
num
&
0xf
)
append_hex1
(
s
,
num
&
0xf
)
}
}
#[derive(Copy,
Clone,
Debug)]
#[derive(
PartialEq,
Eq,
Copy,
Clone,
Debug)]
#[cfg_attr(feature
=
"defmt"
,
derive(defmt::Format))]
#[cfg_attr(feature
=
"defmt"
,
derive(defmt::Format))]
enum
ScanResult
{
enum
ScanResult
{
NAck
,
NAck
,
...
@@ -204,12 +210,13 @@ async fn i2c_task(mut i2c_peri: embassy_rp::peripherals::I2C0,
...
@@ -204,12 +210,13 @@ async fn i2c_task(mut i2c_peri: embassy_rp::peripherals::I2C0,
use
i2c
::
Error
::
*
;
use
i2c
::
Error
::
*
;
use
i2c
::
AbortReason
::
*
;
use
i2c
::
AbortReason
::
*
;
const
MAX_ADDRESS
:
u8
=
128
;
let
mut
prev_scan_result
=
[
ScanResult
::
Reserved
;
MAX_ADDRESS
as
usize
];
loop
{
loop
{
if
true
{
if
true
{
let
mut
i2c
=
i2c
::
I2c
::
new_async
(
&
mut
i2c_peri
,
&
mut
scl
,
&
mut
sda
,
&
mut
i2c_irq
,
i2c_config
);
let
_
i2c
=
i2c
::
I2c
::
new_async
(
&
mut
i2c_peri
,
&
mut
scl
,
&
mut
sda
,
&
mut
i2c_irq
,
i2c_config
);
}
}
const
MAX_ADDRESS
:
u8
=
128
;
let
mut
scan_result
=
[
ScanResult
::
Error
;
MAX_ADDRESS
as
usize
];
let
mut
scan_result
=
[
ScanResult
::
Error
;
MAX_ADDRESS
as
usize
];
for
i
in
0
..
MAX_ADDRESS
{
for
i
in
0
..
MAX_ADDRESS
{
scan_result
[
i
as
usize
]
=
match
i2c_write_zero_bytes
::
<
_
,
_
,
400_000
>
(
i
as
u16
,
&
mut
scl
,
&
mut
sda
)
.await
{
scan_result
[
i
as
usize
]
=
match
i2c_write_zero_bytes
::
<
_
,
_
,
400_000
>
(
i
as
u16
,
&
mut
scl
,
&
mut
sda
)
.await
{
...
@@ -223,11 +230,14 @@ async fn i2c_task(mut i2c_peri: embassy_rp::peripherals::I2C0,
...
@@ -223,11 +230,14 @@ async fn i2c_task(mut i2c_peri: embassy_rp::peripherals::I2C0,
}
}
}
}
const
MSG_LEN
:
usize
=
(
MAX_ADDRESS
as
usize
)
*
3
+
(
MAX_ADDRESS
as
usize
)
/
16
*
6
;
if
prev_scan_result
.iter
()
.zip
(
scan_result
.iter
())
.any
(|(
x
,
y
)|
x
!=
y
)
{
let
mut
msg
=
String
::
<
MSG_LEN
>
::
new
();
prev_scan_result
=
scan_result
;
match
format_scan_result
(
&
mut
msg
,
scan_result
)
{
const
MSG_LEN
:
usize
=
(
MAX_ADDRESS
as
usize
)
*
3
+
(
MAX_ADDRESS
as
usize
)
/
16
*
6
;
Ok
(())
=>
info!
(
"I2C scan result:
\n
{}"
,
msg
),
let
mut
msg
=
String
::
<
MSG_LEN
>
::
new
();
Err
(())
=>
info!
(
"I2C scan result: too long for our buffer!"
),
match
format_scan_result
(
&
mut
msg
,
scan_result
)
{
Ok
(())
=>
info!
(
"I2C scan result:
\n
{}"
,
msg
),
Err
(())
=>
info!
(
"I2C scan result: too long for our buffer!"
),
}
}
}
Timer
::
after
(
Duration
::
from_secs
(
1
))
.await
;
Timer
::
after
(
Duration
::
from_secs
(
1
))
.await
;
...
@@ -235,7 +245,7 @@ async fn i2c_task(mut i2c_peri: embassy_rp::peripherals::I2C0,
...
@@ -235,7 +245,7 @@ async fn i2c_task(mut i2c_peri: embassy_rp::peripherals::I2C0,
}
}
#[embassy_executor::task]
#[embassy_executor::task]
async
fn
beeper_task
(
mut
pwm_channel
:
embassy_rp
::
peripherals
::
PWM_CH3
,
mut
beeper_pin
:
embassy_rp
::
peripherals
::
PIN_6
)
{
async
fn
beeper_task
(
pwm_channel
:
embassy_rp
::
peripherals
::
PWM_CH3
,
beeper_pin
:
embassy_rp
::
peripherals
::
PIN_6
)
{
let
mut
c
:
pwm
::
Config
=
Default
::
default
();
let
mut
c
:
pwm
::
Config
=
Default
::
default
();
c
.top
=
0x8000
;
c
.top
=
0x8000
;
c
.compare_a
=
8
;
c
.compare_a
=
8
;
...
@@ -258,6 +268,175 @@ async fn beeper_task(mut pwm_channel: embassy_rp::peripherals::PWM_CH3, mut beep
...
@@ -258,6 +268,175 @@ async fn beeper_task(mut pwm_channel: embassy_rp::peripherals::PWM_CH3, mut beep
}
}
}
}
fn
pin_io
<
P
:
embassy_rp
::
gpio
::
Pin
>
(
pin
:
&
P
)
->
embassy_rp
::
pac
::
io
::
Gpio
{
use
embassy_rp
::
gpio
::
Bank
;
use
embassy_rp
::
pac
;
let
block
=
match
pin
.bank
()
{
Bank
::
Bank0
=>
pac
::
IO_BANK0
,
Bank
::
Qspi
=>
pac
::
IO_QSPI
,
};
block
.gpio
(
pin
.pin
()
as
_
)
}
async
fn
debug_print_pio_addr
(
sm
:
embassy_rp
::
pac
::
pio
::
StateMachine
)
{
let
mut
prev
=
42u8
;
loop
{
let
addr
=
unsafe
{
sm
.addr
()
.read
()
.addr
()
};
if
prev
!=
addr
{
prev
=
addr
;
info!
(
"SM addr: {}"
,
addr
);
}
Timer
::
after
(
Duration
::
from_millis
(
200
))
.await
;
}
}
#[embassy_executor::task]
async
fn
autobaud_task
(
pio0
:
embassy_rp
::
peripherals
::
PIO0
,
rx_pin
:
embassy_rp
::
peripherals
::
PIN_17
,
dma_channel
:
embassy_rp
::
peripherals
::
DMA_CH0
)
{
let
Pio
{
mut
common
,
sm0
:
mut
sm
,
..
}
=
Pio
::
new
(
pio0
);
sm
.set_enable
(
false
);
let
prg
=
pio_proc
::
pio_asm!
(
".origin 0"
,
// First, pull waiting time for "long 1" from input FIFO.
"pull"
,
// Send zero to RX FIFO to signal start of next measurement.
".wrap_target"
,
"timeout:"
,
"set x, 0"
,
"mov isr, x"
,
"push"
,
// Wait for pin to be high for a longer time (UART is idle), copy waiting time to X
// and decrement until done, start again when pin changes.
"wait_idle:"
,
"wait 1 pin 0"
,
"mov x, osr"
,
"continue_wait_idle:"
,
"jmp pin still_one"
,
"jmp wait_idle"
,
// we got a zero, start again
"still_one:"
,
"jmp x--, continue_wait_idle"
,
// We have a long 1, i.e. UART is idle. Wait for start bit.
"have_long_high:"
,
"wait 0 pin 0"
,
"nop [4]"
,
"jmp pin wait_idle"
,
// abort if zero was just a glitch
// We want to measure 9 bits (start bit plus eight (or nine) data bits). However, we need
// different code for high and low so it's easier to measure 4x2 bits. Weuse Y as the loop counter.
"set y, 4"
,
// Start counting. We count down from the value in OSR (which is our timeout).
"measure_next:"
,
"mov x, osr"
,
"measure_low:"
,
"jmp pin changed_to_one"
,
//"nop",
"jmp x-- measure_low"
,
"jmp timeout"
,
"changed_to_one:"
,
"mov isr, x"
"push"
,
// Start counting, again, but for a high pulse.
"mov x, osr"
,
"measure_high:"
,
"jmp pin still_high2"
,
"jmp changed_to_low"
,
"still_high2:"
,
"jmp x-- measure_high"
,
"jmp timeout"
,
"changed_to_low:"
,
"mov isr, x"
"push"
,
"jmp y-- measure_next"
,
// We are done.
"irq set 0"
,
".wrap"
,
);
let
relocated
=
RelocatedProgram
::
new
(
&
prg
.program
);
let
mut
cfg
=
Config
::
default
();
cfg
.use_program
(
&
common
.load_program
(
&
relocated
),
&
[]);
const
SM_FREQ
:
u32
=
125_000_000
;
cfg
.clock_divider
=
(
U56F8!
(
125_000_000
)
/
U56F8!
(
125_000_000
/* SM_FREQ */
))
.to_fixed
();
cfg
.shift_in
=
ShiftConfig
{
auto_fill
:
false
,
threshold
:
32
,
direction
:
ShiftDirection
::
Left
,
};
cfg
.shift_out
=
ShiftConfig
{
auto_fill
:
false
,
threshold
:
32
,
direction
:
ShiftDirection
::
Right
,
};
let
rx_pin_pio
=
common
.make_pio_pin
(
unsafe
{
rx_pin
.clone_unchecked
()
});
cfg
.set_in_pins
(
&
[
&
rx_pin_pio
]);
cfg
.set_jmp_pin
(
&
rx_pin_pio
);
sm
.set_config
(
&
cfg
);
sm
.set_enable
(
true
);
// set rx pin function back to UART
unsafe
{
pin_io
(
&
rx_pin
)
.ctrl
()
.write
(|
w
|
w
.set_funcsel
(
embassy_rp
::
pac
::
io
::
vals
::
Gpio17ctrlFuncsel
::
UART0_RX
.0
));
}
// Timeout: Modbus wants 1.5 ms between frames so we make this a bit smaller. SM runs at 25 MHz
// but we need 4 clocks per loop.
let
timeout_start_value
=
(
SM_FREQ
as
f32
*
1.2e-3
/
4.
)
as
u32
;
sm
.tx
()
.push
(
timeout_start_value
);
info!
(
"timeout_start_value: {} = 0x{:08x}"
,
timeout_start_value
,
timeout_start_value
);
let
mut
dma_in_ref
=
dma_channel
.into_ref
();
let
mut
din
=
[
42u32
;
4
];
let
mut
bit_index
=
0
;
loop
{
let
x
=
select
(
sm
.rx
()
.dma_pull
(
dma_in_ref
.reborrow
(),
&
mut
din
),
debug_print_pio_addr
(
embassy_rp
::
pac
::
PIO0
.sm
(
0
)),
)
.await
;
match
x
{
First
(
_
)
=>
{
for
i
in
0
..
din
.len
()
{
if
din
[
i
]
==
0
{
bit_index
=
0
;
info!
(
"SM in {}: {:08x} -> start"
,
i
,
din
[
i
]);
}
else
{
let
mut
delay
=
timeout_start_value
-
din
[
i
];
if
bit_index
==
0
{
delay
+=
7
;
}
else
if
bit_index
%
2
==
1
{
//delay += 4;
delay
+=
3
;
}
else
{
delay
+=
3
;
}
let
millis
=
(
delay
)
as
f32
/
SM_FREQ
as
f32
*
1000.
*
2.
;
let
baud
=
1000.
/
millis
;
info!
(
"SM in {} ({}): {:08x} -> {} -> {} ms -> {}"
,
i
,
bit_index
,
din
[
i
],
delay
,
millis
,
baud
);
bit_index
+=
1
;
}
}
},
_
=>
{
},
}
}
}
#[embassy_executor::main]
#[embassy_executor::main]
async
fn
main
(
spawner
:
Spawner
)
{
async
fn
main
(
spawner
:
Spawner
)
{
let
p
=
embassy_rp
::
init
(
Default
::
default
());
let
p
=
embassy_rp
::
init
(
Default
::
default
());
...
@@ -284,6 +463,7 @@ async fn main(spawner: Spawner) {
...
@@ -284,6 +463,7 @@ async fn main(spawner: Spawner) {
let
_tx_en
=
p
.PIN_15
;
let
_tx_en
=
p
.PIN_15
;
let
_tx
=
p
.PIN_16
;
let
_tx
=
p
.PIN_16
;
let
rx
=
p
.PIN_17
;
let
rx
=
p
.PIN_17
;
let
rx_for_autobaud
=
unsafe
{
rx
.clone_unchecked
()
};
//FIXME move UART and auto-baud into same task
let
_matrix_in2
=
Input
::
new
(
p
.PIN_18
,
Pull
::
Up
);
let
_matrix_in2
=
Input
::
new
(
p
.PIN_18
,
Pull
::
Up
);
let
_reed3
=
Input
::
new
(
p
.PIN_19
,
Pull
::
Up
);
let
_reed3
=
Input
::
new
(
p
.PIN_19
,
Pull
::
Up
);
let
_reed4
=
Input
::
new
(
p
.PIN_20
,
Pull
::
Up
);
let
_reed4
=
Input
::
new
(
p
.PIN_20
,
Pull
::
Up
);
...
@@ -315,14 +495,16 @@ async fn main(spawner: Spawner) {
...
@@ -315,14 +495,16 @@ async fn main(spawner: Spawner) {
);
);
unwrap!
(
spawner
.spawn
(
reader
(
uart_rx
)));
unwrap!
(
spawner
.spawn
(
reader
(
uart_rx
)));
unwrap!
(
spawner
.spawn
(
beeper_task
(
p
.PWM_CH3
,
led_r
)));
if
false
{
unwrap!
(
spawner
.spawn
(
beeper_task
(
p
.PWM_CH3
,
led_r
)));
}
unwrap!
(
spawner
.spawn
(
autobaud_task
(
p
.PIO0
,
rx_for_autobaud
,
p
.DMA_CH0
)));
loop
{
loop
{
info!
(
"led on!"
);
led_b
.set_high
();
led_b
.set_high
();
Timer
::
after
(
Duration
::
from_secs
(
1
))
.await
;
Timer
::
after
(
Duration
::
from_secs
(
1
))
.await
;
info!
(
"led off!"
);
led_b
.set_low
();
led_b
.set_low
();
Timer
::
after
(
Duration
::
from_secs
(
1
))
.await
;
Timer
::
after
(
Duration
::
from_secs
(
1
))
.await
;
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment