forked from M-Labs/ionpak-thermostat
dismantle ionpak, drive PWMs at fixed rate
This commit is contained in:
parent
1a00f5cf1a
commit
2ac3485b30
|
@ -5,6 +5,23 @@ name = "aligned"
|
|||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "aligned"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"as-slice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "as-slice"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bare-metal"
|
||||
version = "0.2.4"
|
||||
|
@ -15,7 +32,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.0.4"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -25,22 +42,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.1"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m"
|
||||
version = "0.5.8"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aligned 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cortex-m 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aligned 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m-rt"
|
||||
version = "0.6.7"
|
||||
version = "0.6.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cortex-m-rt-macros 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -52,10 +80,10 @@ name = "cortex-m-rt-macros"
|
|||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -66,14 +94,22 @@ dependencies = [
|
|||
"build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ionpak-firmware"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"cortex-m 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cortex-m-rt 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cortex-m 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cortex-m-rt 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libm 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libm 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=cd893e6)",
|
||||
"tm4c129x 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -90,7 +126,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.1.2"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -100,7 +136,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.27"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -108,10 +144,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.11"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -175,18 +211,23 @@ name = "smoltcp"
|
|||
version = "0.4.0"
|
||||
source = "git+https://github.com/m-labs/smoltcp?rev=cd893e6#cd893e6ab60f094d684b37be7bc013bf79f0459d"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"managed 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.26"
|
||||
version = "0.15.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -196,11 +237,16 @@ version = "0.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cortex-m 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cortex-m-rt 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cortex-m 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cortex-m-rt 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
|
@ -241,19 +287,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[metadata]
|
||||
"checksum aligned 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d39da9b88ae1a81c03c9c082b8db83f1d0e93914126041962af61034ab44c4a5"
|
||||
"checksum aligned 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a316c7ea8e1e9ece54862c992def5a7ac14de9f5832b69d71760680efeeefa"
|
||||
"checksum as-slice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "293dac66b274fab06f95e7efb05ec439a6b70136081ea522d270bc351ae5bb27"
|
||||
"checksum bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3caf393d93b2d453e80638d0674597020cef3382ada454faacd43d1a55a735a"
|
||||
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
|
||||
"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
|
||||
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
|
||||
"checksum cortex-m 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dab2164a0fc216781a47fc343347365112ae6917421d3fa4bac6faf0fbaaaec7"
|
||||
"checksum cortex-m-rt 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f69d2beca37acc3776c17201c9d1f8904fb9139fa3a4d2cf28c8436a07b21a88"
|
||||
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
||||
"checksum cortex-m 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0b159a1e8306949579de3698c841dba58058197b65c60807194e4fa1e7a554"
|
||||
"checksum cortex-m 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3c18719fdc57db65668bfc977db9a0fa1a41d718c5d9cd4f652c9d4b0e0956a"
|
||||
"checksum cortex-m-rt 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "17805910e3ecf029bdbfcc42b7384d9e3d9e5626153fa810002c1ef9839338ac"
|
||||
"checksum cortex-m-rt-macros 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d7ae692573e0acccb1579fef1abf5a5bf1d2f3f0149a22b16870ec9309aee25f"
|
||||
"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
|
||||
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum libm 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "03c0bb6d5ce1b5cc6fd0578ec1cbc18c9d88b5b591a5c7c1d6c6175e266a0819"
|
||||
"checksum libm 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
|
||||
"checksum managed 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43e2737ecabe4ae36a68061398bf27d2bfd0763f4c3c837a398478459494c4b7"
|
||||
"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
|
||||
"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"
|
||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||
"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
|
||||
"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9"
|
||||
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||
|
@ -263,8 +313,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=cd893e6)" = "<none>"
|
||||
"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9"
|
||||
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
|
||||
"checksum syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)" = "eadc09306ca51a40555dd6fc2b415538e9e18bc9f870e47b1a524a79fe2dcf5e"
|
||||
"checksum tm4c129x 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d430ed4ed06dd9fff3d4517a37343e1b53789218f2f608bf1e0432f67abf624"
|
||||
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum vcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45c297f0afb6928cd08ab1ff9d95e99392595ea25ae1b5ecf822ff8764e57a0d"
|
||||
"checksum volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286"
|
||||
|
|
|
@ -25,7 +25,7 @@ const ERR_LATCHN: u8 = 0x20; // PL5
|
|||
const BTNN: u8 = 0x80; // PL7
|
||||
const ERR_RESN: u8 = 0x01; // PQ0
|
||||
|
||||
const PWM_LOAD: u16 = (/*pwmclk*/120_000_000u32 / /*freq*/100_000) as u16;
|
||||
pub const PWM_LOAD: u16 = (/*pwmclk*/120_000_000u32 / /*freq*/100_000) as u16;
|
||||
const UART_DIV: u32 = (((/*sysclk*/120_000_000 * 8) / /*baud*/115200) + 1) / 2;
|
||||
|
||||
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
use board;
|
||||
|
||||
pub struct Electrometer {
|
||||
range: board::ElectrometerRange,
|
||||
out_of_range_count: u8,
|
||||
ignore_count: u8,
|
||||
ic_buffer: f32,
|
||||
ic_buffer_count: usize,
|
||||
last_ic: Option<f32>
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ElectrometerStatus {
|
||||
pub ic: Option<f32>
|
||||
}
|
||||
|
||||
impl Electrometer {
|
||||
pub const fn new() -> Electrometer {
|
||||
Electrometer {
|
||||
range: board::ElectrometerRange::Med,
|
||||
out_of_range_count: 0,
|
||||
ignore_count: 0,
|
||||
ic_buffer: 0.0,
|
||||
ic_buffer_count: 0,
|
||||
last_ic: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn adc_input(&mut self, ic_sample: u16) {
|
||||
if self.ignore_count > 0 {
|
||||
self.ignore_count -= 1;
|
||||
} else {
|
||||
let mut new_range = if ic_sample > 3100 {
|
||||
match self.range {
|
||||
board::ElectrometerRange::Low => Some(board::ElectrometerRange::Med),
|
||||
board::ElectrometerRange::Med => Some(board::ElectrometerRange::High),
|
||||
board::ElectrometerRange::High => None
|
||||
}
|
||||
} else if ic_sample < 105 {
|
||||
match self.range {
|
||||
board::ElectrometerRange::Low => None,
|
||||
board::ElectrometerRange::Med => Some(board::ElectrometerRange::Low),
|
||||
board::ElectrometerRange::High => Some(board::ElectrometerRange::Med)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if new_range.is_some() {
|
||||
self.out_of_range_count += 1;
|
||||
if self.out_of_range_count < 75 {
|
||||
new_range = None;
|
||||
}
|
||||
} else {
|
||||
self.out_of_range_count = 0;
|
||||
}
|
||||
|
||||
if new_range.is_some() {
|
||||
self.ignore_count = 150;
|
||||
self.ic_buffer = 0.0;
|
||||
self.ic_buffer_count = 0;
|
||||
self.last_ic = None;
|
||||
self.range = new_range.unwrap();
|
||||
board::set_electrometer_range(self.range);
|
||||
} else {
|
||||
let gain = match self.range {
|
||||
board::ElectrometerRange::Low => board::IC_ADC_GAIN_LOW,
|
||||
board::ElectrometerRange::Med => board::IC_ADC_GAIN_MED,
|
||||
board::ElectrometerRange::High => board::IC_ADC_GAIN_HIGH
|
||||
};
|
||||
self.ic_buffer += ((ic_sample as f32) - board::IC_ADC_OFFSET)/gain;
|
||||
self.ic_buffer_count += 1;
|
||||
if self.ic_buffer_count == 512 {
|
||||
self.last_ic = Some(self.ic_buffer/512.0);
|
||||
self.ic_buffer = 0.0;
|
||||
self.ic_buffer_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_status(&self) -> ElectrometerStatus {
|
||||
ElectrometerStatus {
|
||||
ic: self.last_ic
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<title>ionpak</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<body>
|
||||
|
||||
<div class="w3-sidebar w3-light-grey w3-bar-block" style="width:15%">
|
||||
<h3 class="w3-bar-item"><img src="logo.svg"></h3>
|
||||
<a href="/" class="w3-bar-item w3-button">Measure</a>
|
||||
<a href="/gauge_settings.html" class="w3-bar-item w3-button">Gauge settings</a>
|
||||
<a href="/network_settings.html" class="w3-bar-item w3-button">Network settings</a>
|
||||
<a href="/firmware.html" class="w3-bar-item w3-button">Firmware</a>
|
||||
</div>
|
||||
|
||||
<div style="margin-left:15%">
|
||||
|
||||
<div class="w3-container w3-teal">
|
||||
<h1>Firmware</h1>
|
||||
</div>
|
||||
|
||||
<div class="w3-container">
|
||||
<p>Firmware version: {version}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,180 +0,0 @@
|
|||
use core::fmt;
|
||||
|
||||
const MAX_QUERY: usize = 128;
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Eq)]
|
||||
enum State {
|
||||
WaitG,
|
||||
WaitE,
|
||||
WaitT,
|
||||
WaitSpace,
|
||||
GetQuery,
|
||||
WaitCR1,
|
||||
WaitLF1,
|
||||
WaitCR2,
|
||||
WaitLF2,
|
||||
Finished
|
||||
}
|
||||
|
||||
pub struct Request {
|
||||
state: State,
|
||||
query_idx: usize,
|
||||
query: [u8; MAX_QUERY]
|
||||
}
|
||||
|
||||
impl Request {
|
||||
pub fn new() -> Request {
|
||||
Request {
|
||||
state: State::WaitG,
|
||||
query_idx: 0,
|
||||
query: [0; MAX_QUERY]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.state = State::WaitG;
|
||||
self.query_idx = 0;
|
||||
}
|
||||
|
||||
pub fn input_char(&mut self, c: u8) -> Result<bool, &'static str> {
|
||||
match self.state {
|
||||
State::WaitG => {
|
||||
if c == b'G' {
|
||||
self.state = State::WaitE;
|
||||
} else {
|
||||
return Err("invalid character in method")
|
||||
}
|
||||
}
|
||||
State::WaitE => {
|
||||
if c == b'E' {
|
||||
self.state = State::WaitT;
|
||||
} else {
|
||||
return Err("invalid character in method")
|
||||
}
|
||||
}
|
||||
State::WaitT => {
|
||||
if c == b'T' {
|
||||
self.state = State::WaitSpace;
|
||||
} else {
|
||||
return Err("invalid character in method")
|
||||
}
|
||||
}
|
||||
State::WaitSpace => {
|
||||
if c == b' ' {
|
||||
self.state = State::GetQuery;
|
||||
} else {
|
||||
return Err("invalid character in method")
|
||||
}
|
||||
}
|
||||
State::GetQuery => {
|
||||
if c == b'\r' || c == b'\n' {
|
||||
return Err("GET ended prematurely")
|
||||
} else if c == b' ' {
|
||||
if self.query_idx == 0 {
|
||||
return Err("query is empty")
|
||||
} else {
|
||||
self.state = State::WaitCR1;
|
||||
}
|
||||
} else {
|
||||
if self.query_idx >= self.query.len() {
|
||||
return Err("query is too long")
|
||||
} else {
|
||||
self.query[self.query_idx] = c;
|
||||
self.query_idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
State::WaitCR1 => {
|
||||
if c == b'\r' {
|
||||
self.state = State::WaitLF1;
|
||||
}
|
||||
}
|
||||
State::WaitLF1 => {
|
||||
if c == b'\n' {
|
||||
self.state = State::WaitCR2;
|
||||
} else {
|
||||
self.state = State::WaitCR1;
|
||||
}
|
||||
}
|
||||
State::WaitCR2 => {
|
||||
if c == b'\r' {
|
||||
self.state = State::WaitLF2;
|
||||
} else {
|
||||
self.state = State::WaitCR1;
|
||||
}
|
||||
}
|
||||
State::WaitLF2 => {
|
||||
if c == b'\n' {
|
||||
self.state = State::Finished;
|
||||
return Ok(true)
|
||||
} else {
|
||||
self.state = State::WaitCR1;
|
||||
}
|
||||
}
|
||||
State::Finished => return Err("trailing characters")
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
pub fn input(&mut self, buf: &[u8]) -> Result<bool, &'static str> {
|
||||
let mut result = Ok(false);
|
||||
for c in buf.iter() {
|
||||
result = self.input_char(*c);
|
||||
if result.is_err() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn get_query<'a>(&'a self) -> Result<&'a [u8], &'static str> {
|
||||
if self.state != State::Finished {
|
||||
return Err("request is not finished")
|
||||
}
|
||||
Ok(&self.query[..self.query_idx])
|
||||
}
|
||||
|
||||
pub fn get_path<'a>(&'a self) -> Result<&'a [u8], &'static str> {
|
||||
let query = self.get_query()?;
|
||||
Ok(query.split(|b| *b == '?' as u8).next().unwrap())
|
||||
}
|
||||
|
||||
// FIXME: this yields some empty strings
|
||||
pub fn iter_args<'a>(&'a self) -> Result<impl Iterator<Item=(&'a [u8], &'a [u8])>, &'static str> {
|
||||
let query = self.get_query()?;
|
||||
let mut qs = query.split(|b| *b == '?' as u8);
|
||||
qs.next();
|
||||
let args = qs.next().unwrap_or(b"");
|
||||
let args_it = args.split(|b| *b == '&' as u8);
|
||||
Ok(args_it.map(|arg| {
|
||||
let mut eqs = arg.split(|b| *b == '=' as u8);
|
||||
(eqs.next().unwrap(), eqs.next().unwrap_or(b""))
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn get_arg<'a>(&'a self, name: &[u8]) -> Result<&'a [u8], &'static str> {
|
||||
for (current_name, current_value) in self.iter_args()? {
|
||||
if current_name == name {
|
||||
return Ok(current_value)
|
||||
}
|
||||
}
|
||||
Err("argument not found")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn write_reply_header(output: &mut fmt::Write, status: u16, content_type: &str, gzip: bool) -> fmt::Result {
|
||||
let status_text = match status {
|
||||
200 => "OK",
|
||||
404 => "Not Found",
|
||||
500 => "Internal Server Error",
|
||||
_ => return Err(fmt::Error)
|
||||
};
|
||||
write!(output, "HTTP/1.1 {} {}\r\nContent-Type: {}\r\n",
|
||||
status, status_text, content_type)?;
|
||||
if gzip {
|
||||
write!(output, "Content-Encoding: gzip\r\n")?;
|
||||
write!(output, "Cache-Control: public, max-age=600\r\n")?;
|
||||
}
|
||||
write!(output, "\r\n")
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<title>ionpak</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<body>
|
||||
|
||||
<div class="w3-sidebar w3-light-grey w3-bar-block" style="width:15%">
|
||||
<h3 class="w3-bar-item"><img src="logo.svg"></h3>
|
||||
<a href="/" class="w3-bar-item w3-button">Measure</a>
|
||||
<a href="/gauge_settings.html" class="w3-bar-item w3-button">Gauge settings</a>
|
||||
<a href="/network_settings.html" class="w3-bar-item w3-button">Network settings</a>
|
||||
<a href="/firmware.html" class="w3-bar-item w3-button">Firmware</a>
|
||||
</div>
|
||||
|
||||
<div style="margin-left:15%">
|
||||
|
||||
<div class="w3-container w3-teal">
|
||||
<h1>Measure</h1>
|
||||
</div>
|
||||
|
||||
<div class="w3-container">
|
||||
<h3>Pressure</h3>
|
||||
<div class="w3-card w3-xxlarge">
|
||||
{pressure:.1e} mbar
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w3-container">
|
||||
<h3>Details</h3>
|
||||
<table class="w3-table">
|
||||
<tr><th>Parameter</th><th>Current</th><th>Target</th></tr>
|
||||
<tr><td>Anode regulator ready</td><td>{anode_ready}</td></tr>
|
||||
<tr><td>Anode voltage</td><td>{anode_av:.1}V</td></tr>
|
||||
<tr><td>Cathode regulator ready</td><td>{cathode_ready}</td></tr>
|
||||
<tr><td>Electron current</td><td>{cathode_fbi:.0}μA</td></tr>
|
||||
<tr><td>Filament voltage</td><td>{cathode_fv:.2}V</td><td>{cathode_fv_target:.2}V</td></tr>
|
||||
<tr><td>Cathode bias</td><td>{cathode_fbv:.1}V</td></tr>
|
||||
<tr><td>Ion current</td><td>{ion_current:.5}nA</td></tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
At local time:
|
||||
<script language="Javascript">
|
||||
var date = new Date();
|
||||
var n = date.toDateString();
|
||||
var time = date.toLocaleString();
|
||||
document.write(time);
|
||||
</script>
|
||||
</p>
|
||||
<p><a href="/measure.json">JSON</a></p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,69 +0,0 @@
|
|||
use libm::F32Ext;
|
||||
|
||||
use board;
|
||||
use pid;
|
||||
|
||||
const PID_PARAMETERS: pid::Parameters = pid::Parameters {
|
||||
kp: 0.2,
|
||||
ki: 0.05,
|
||||
kd: 0.0,
|
||||
output_min: 0.0,
|
||||
output_max: 225.0,
|
||||
integral_min: -700.0,
|
||||
integral_max: 700.0
|
||||
};
|
||||
|
||||
|
||||
pub struct Controller {
|
||||
pid: pid::Controller,
|
||||
target: f32,
|
||||
last_av: Option<f32>
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ControllerStatus {
|
||||
pub ready: bool,
|
||||
pub av: Option<f32>
|
||||
}
|
||||
|
||||
impl Controller {
|
||||
pub const fn new() -> Controller {
|
||||
Controller {
|
||||
pid: pid::Controller::new(PID_PARAMETERS),
|
||||
target: 0.0,
|
||||
last_av: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn adc_input(&mut self, av_sample: u16) {
|
||||
let av = av_sample as f32/board::AV_ADC_GAIN;
|
||||
self.last_av = Some(av);
|
||||
|
||||
let hv_pwm_duty = self.pid.update(av);
|
||||
board::set_hv_pwm(hv_pwm_duty as u16)
|
||||
}
|
||||
|
||||
pub fn set_target(&mut self, volts: f32) {
|
||||
self.target = volts;
|
||||
self.pid.set_target(volts);
|
||||
}
|
||||
|
||||
fn ready(&self) -> bool {
|
||||
match self.last_av {
|
||||
None => false,
|
||||
Some(last_av) => (last_av - self.target).abs() < 2.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.pid.reset();
|
||||
board::set_hv_pwm(0);
|
||||
}
|
||||
|
||||
pub fn get_status(&self) -> ControllerStatus {
|
||||
ControllerStatus {
|
||||
ready: self.ready(),
|
||||
av: self.last_av
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
use libm::F32Ext;
|
||||
|
||||
use board;
|
||||
use pid;
|
||||
|
||||
const FBI_PID_PARAMETERS: pid::Parameters = pid::Parameters {
|
||||
kp: 200.0,
|
||||
ki: 20.0,
|
||||
kd: 10.0,
|
||||
output_min: 0.5,
|
||||
output_max: 10.0,
|
||||
integral_min: -0.1,
|
||||
integral_max: 0.1
|
||||
};
|
||||
|
||||
const FV_PID_PARAMETERS: pid::Parameters = pid::Parameters {
|
||||
kp: 20.0,
|
||||
ki: 1.5,
|
||||
kd: 0.0,
|
||||
output_min: 0.0,
|
||||
output_max: 150.0,
|
||||
integral_min: -50.0,
|
||||
integral_max: 50.0
|
||||
};
|
||||
|
||||
pub struct Controller {
|
||||
fbi_target: f32,
|
||||
fbi_range: board::EmissionRange,
|
||||
fbi_buffer: [f32; 16],
|
||||
fbi_buffer_count: usize,
|
||||
last_fbi: Option<f32>,
|
||||
fbi_pid: pid::Controller,
|
||||
last_fv_target: Option<f32>,
|
||||
|
||||
fv_pid: pid::Controller,
|
||||
last_fv: Option<f32>,
|
||||
|
||||
fbv_target: f32,
|
||||
last_fbv: Option<f32>
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ControllerStatus {
|
||||
pub ready: bool,
|
||||
pub fbi: Option<f32>,
|
||||
pub fv_target: Option<f32>,
|
||||
pub fv: Option<f32>,
|
||||
pub fbv: Option<f32>
|
||||
}
|
||||
|
||||
impl Controller {
|
||||
pub const fn new() -> Controller {
|
||||
Controller {
|
||||
fbi_target: 0.0,
|
||||
fbi_range: board::EmissionRange::Med,
|
||||
fbi_buffer: [0.0; 16],
|
||||
fbi_buffer_count: 0,
|
||||
last_fbi: None,
|
||||
fbi_pid: pid::Controller::new(FBI_PID_PARAMETERS),
|
||||
last_fv_target: None,
|
||||
|
||||
fv_pid: pid::Controller::new(FV_PID_PARAMETERS),
|
||||
last_fv: None,
|
||||
|
||||
fbv_target: 0.0,
|
||||
last_fbv: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn adc_input(&mut self, fbi_sample: u16, fd_sample: u16, fv_sample: u16, fbv_sample: u16) {
|
||||
let fbi_voltage = ((fbi_sample as f32) - board::FBI_ADC_OFFSET)/board::FBI_ADC_GAIN;
|
||||
let fbi_r225 = fbi_voltage/board::FBI_R225;
|
||||
let fbi = match self.fbi_range {
|
||||
board::EmissionRange::Low => fbi_r225,
|
||||
board::EmissionRange::Med => {
|
||||
let fd_voltage = ((fd_sample as f32) - board::FD_ADC_OFFSET)/board::FD_ADC_GAIN;
|
||||
fbi_r225 + (fbi_voltage - fd_voltage)/board::FBI_R223
|
||||
},
|
||||
board::EmissionRange::High => {
|
||||
let fd_voltage = 0.9;
|
||||
fbi_r225 + (fbi_voltage - fd_voltage)/board::FBI_R224
|
||||
}
|
||||
};
|
||||
self.fbi_buffer[self.fbi_buffer_count] = fbi;
|
||||
self.fbi_buffer_count += 1;
|
||||
if self.fbi_buffer_count == self.fbi_buffer.len() {
|
||||
let mut fbi_avg: f32 = 0.0;
|
||||
for fbi in self.fbi_buffer.iter() {
|
||||
fbi_avg += *fbi;
|
||||
}
|
||||
self.last_fbi = Some(fbi_avg/(self.fbi_buffer.len() as f32));
|
||||
self.fbi_buffer_count = 0;
|
||||
}
|
||||
|
||||
let fv_target = self.fbi_pid.update(fbi);
|
||||
self.last_fv_target = Some(fv_target);
|
||||
self.fv_pid.set_target(fv_target);
|
||||
|
||||
let fv = fv_sample as f32/board::FV_ADC_GAIN;
|
||||
let fv_pwm_duty = self.fv_pid.update(fv);
|
||||
board::set_fv_pwm(120);
|
||||
|
||||
self.last_fv = Some(fv);
|
||||
self.last_fbv = Some(fbv_sample as f32/board::FBV_ADC_GAIN);
|
||||
}
|
||||
|
||||
pub fn set_emission_target(&mut self, amperes: f32) {
|
||||
self.fbi_target = amperes;
|
||||
self.fbi_pid.set_target(amperes);
|
||||
self.fbi_range = board::EmissionRange::Low;
|
||||
if amperes > 120e-6 {
|
||||
self.fbi_range = board::EmissionRange::Med;
|
||||
}
|
||||
if amperes > 8e-3 {
|
||||
self.fbi_range = board::EmissionRange::High;
|
||||
}
|
||||
board::set_emission_range(self.fbi_range);
|
||||
}
|
||||
|
||||
pub fn set_bias_target(&mut self, volts: f32) {
|
||||
self.fbv_target = volts;
|
||||
board::set_fbv_pwm((volts/board::FBV_PWM_GAIN) as u16);
|
||||
}
|
||||
|
||||
fn emission_ready(&self) -> bool {
|
||||
match self.last_fbi {
|
||||
None => false,
|
||||
Some(last_fbi) => (self.fbi_target - last_fbi).abs()/self.fbi_target < 0.05
|
||||
}
|
||||
}
|
||||
|
||||
fn bias_ready(&self) -> bool {
|
||||
match self.last_fbv {
|
||||
None => false,
|
||||
Some(last_fbv) => (self.fbv_target - last_fbv).abs() < 1.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.fbi_pid.reset();
|
||||
self.fv_pid.reset();
|
||||
self.last_fv_target = None;
|
||||
self.fbi_buffer_count = 0;
|
||||
self.last_fbi = None;
|
||||
self.last_fv = None;
|
||||
self.last_fbv = None;
|
||||
}
|
||||
|
||||
pub fn get_status(&self) -> ControllerStatus {
|
||||
ControllerStatus {
|
||||
ready: self.emission_ready() & self.bias_ready(),
|
||||
fbi: self.last_fbi,
|
||||
fv_target: self.last_fv_target,
|
||||
fv: self.last_fv,
|
||||
fbv: self.last_fbv
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -45,12 +45,6 @@ mod board;
|
|||
mod eeprom;
|
||||
mod config;
|
||||
mod ethmac;
|
||||
mod pid;
|
||||
mod loop_anode;
|
||||
mod loop_cathode;
|
||||
mod electrometer;
|
||||
mod http;
|
||||
mod pages;
|
||||
|
||||
static ADC_IRQ_COUNT: Mutex<Cell<u64>> = Mutex::new(Cell::new(0));
|
||||
|
||||
|
@ -61,16 +55,6 @@ fn get_time_ms() -> u64 {
|
|||
adc_irq_count*24/125
|
||||
}
|
||||
|
||||
static LOOP_ANODE: Mutex<RefCell<loop_anode::Controller>> = Mutex::new(RefCell::new(
|
||||
loop_anode::Controller::new()));
|
||||
|
||||
static LOOP_CATHODE: Mutex<RefCell<loop_cathode::Controller>> = Mutex::new(RefCell::new(
|
||||
loop_cathode::Controller::new()));
|
||||
|
||||
static ELECTROMETER: Mutex<RefCell<electrometer::Electrometer>> = Mutex::new(RefCell::new(
|
||||
electrometer::Electrometer::new()));
|
||||
|
||||
|
||||
pub struct UART0;
|
||||
|
||||
impl fmt::Write for UART0 {
|
||||
|
@ -117,35 +101,6 @@ fn main() -> ! {
|
|||
config.load();
|
||||
}
|
||||
|
||||
cortex_m::interrupt::free(|cs| {
|
||||
let mut loop_anode = LOOP_ANODE.borrow(cs).borrow_mut();
|
||||
let mut loop_cathode = LOOP_CATHODE.borrow(cs).borrow_mut();
|
||||
|
||||
// ZJ-10
|
||||
let anode = 165.0;
|
||||
let cathode_bias = 50.0;
|
||||
let emission = 0.5e-3;
|
||||
|
||||
// ZJ-27
|
||||
/*let anode = 225.0;
|
||||
let cathode_bias = 25.0;
|
||||
let emission = 1.0e-3;*/
|
||||
|
||||
// ZJ-12
|
||||
/*let anode = 200.0;
|
||||
let cathode_bias = 50.0;
|
||||
let emission = 4.0e-3;*/
|
||||
|
||||
// G8130
|
||||
/*let anode = 180.0;
|
||||
let cathode_bias = 30.0;
|
||||
let emission = 4.0e-3;*/
|
||||
|
||||
loop_anode.set_target(anode);
|
||||
loop_cathode.set_emission_target(emission);
|
||||
loop_cathode.set_bias_target(cathode_bias);
|
||||
});
|
||||
|
||||
println!(r#"
|
||||
_ _
|
||||
(_) | |
|
||||
|
@ -195,7 +150,7 @@ fn main() -> ! {
|
|||
create_socket!(sockets, tcp_rx_storage6, tcp_tx_storage6, tcp_handle6);
|
||||
create_socket!(sockets, tcp_rx_storage7, tcp_tx_storage7, tcp_handle7);
|
||||
|
||||
let mut sessions = [
|
||||
/*let mut sessions = [
|
||||
(http::Request::new(), tcp_handle0),
|
||||
(http::Request::new(), tcp_handle1),
|
||||
(http::Request::new(), tcp_handle2),
|
||||
|
@ -204,8 +159,11 @@ fn main() -> ! {
|
|||
(http::Request::new(), tcp_handle5),
|
||||
(http::Request::new(), tcp_handle6),
|
||||
(http::Request::new(), tcp_handle7),
|
||||
];
|
||||
];*/
|
||||
|
||||
board::set_hv_pwm(board::PWM_LOAD / 2);
|
||||
board::set_fv_pwm(board::PWM_LOAD / 2);
|
||||
board::set_fbv_pwm(board::PWM_LOAD / 2);
|
||||
board::start_adc();
|
||||
|
||||
let mut fast_blink_count = if button_pressed { 40 } else { 0 };
|
||||
|
@ -215,7 +173,7 @@ fn main() -> ! {
|
|||
loop {
|
||||
let time = get_time_ms();
|
||||
|
||||
for &mut(ref mut request, tcp_handle) in sessions.iter_mut() {
|
||||
/*for &mut(ref mut request, tcp_handle) in sessions.iter_mut() {
|
||||
let socket = &mut *sockets.get::<TcpSocket>(tcp_handle);
|
||||
if !socket.is_open() {
|
||||
socket.listen(80).unwrap()
|
||||
|
@ -241,7 +199,7 @@ fn main() -> ! {
|
|||
request.reset();
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
match iface.poll(&mut sockets, Instant::from_millis(time as i64)) {
|
||||
Ok(_) => (),
|
||||
Err(e) => println!("poll error: {}", e)
|
||||
|
@ -268,11 +226,6 @@ fn main() -> ! {
|
|||
Some(t) => if time > t {
|
||||
latch_reset_time = None;
|
||||
cortex_m::interrupt::free(|cs| {
|
||||
// reset PID loops as they have accumulated large errors
|
||||
// while the protection was active, which would cause
|
||||
// unnecessary overshoots.
|
||||
LOOP_ANODE.borrow(cs).borrow_mut().reset();
|
||||
LOOP_CATHODE.borrow(cs).borrow_mut().reset();
|
||||
board::reset_error();
|
||||
});
|
||||
println!("Protection reset");
|
||||
|
@ -298,13 +251,6 @@ fn adc0_ss0() {
|
|||
let av_sample = adc0.ssfifo0.read().data().bits();
|
||||
let fbv_sample = adc0.ssfifo0.read().data().bits();
|
||||
|
||||
let mut loop_anode = LOOP_ANODE.borrow(cs).borrow_mut();
|
||||
let mut loop_cathode = LOOP_CATHODE.borrow(cs).borrow_mut();
|
||||
let mut electrometer = ELECTROMETER.borrow(cs).borrow_mut();
|
||||
loop_anode.adc_input(av_sample);
|
||||
loop_cathode.adc_input(fbi_sample, fd_sample, fv_sample, fbv_sample);
|
||||
electrometer.adc_input(ic_sample);
|
||||
|
||||
let adc_irq_count = ADC_IRQ_COUNT.borrow(cs);
|
||||
adc_irq_count.set(adc_irq_count.get() + 1);
|
||||
});
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<title>ionpak</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<body>
|
||||
|
||||
<div class="w3-sidebar w3-light-grey w3-bar-block" style="width:15%">
|
||||
<h3 class="w3-bar-item"><img src="logo.svg"></h3>
|
||||
<a href="/" class="w3-bar-item w3-button">Measure</a>
|
||||
<a href="/gauge_settings.html" class="w3-bar-item w3-button">Gauge settings</a>
|
||||
<a href="/network_settings.html" class="w3-bar-item w3-button">Network settings</a>
|
||||
<a href="/firmware.html" class="w3-bar-item w3-button">Firmware</a>
|
||||
</div>
|
||||
|
||||
<div style="margin-left:15%">
|
||||
|
||||
<div class="w3-container w3-teal">
|
||||
<h1>Network settings</h1>
|
||||
</div>
|
||||
|
||||
<div class="w3-container">
|
||||
<p>{status}</p>
|
||||
</div>
|
||||
|
||||
<div class="w3-container">
|
||||
<form class="w3-container w3-card-4" method="GET">
|
||||
<p>
|
||||
<label>IP address</label>
|
||||
<input class="w3-input w3-border" name="ip" type="text" value="{ip}"></p>
|
||||
<p>
|
||||
<button class="w3-btn w3-blue">Update</button></p>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,141 +0,0 @@
|
|||
use core::fmt;
|
||||
use core::fmt::Write;
|
||||
use core::cell::RefCell;
|
||||
use core::str;
|
||||
use cortex_m;
|
||||
use cortex_m::interrupt::Mutex;
|
||||
use smoltcp::wire::IpCidr;
|
||||
use smoltcp::socket::TcpSocket;
|
||||
|
||||
use http;
|
||||
use config;
|
||||
use loop_anode;
|
||||
use loop_cathode;
|
||||
use electrometer;
|
||||
|
||||
macro_rules! opn_fmt {
|
||||
($struct_name:ident, $error:expr) => {
|
||||
struct $struct_name(Option<f32>);
|
||||
|
||||
impl fmt::Display for $struct_name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.0 {
|
||||
None => f.write_str($error),
|
||||
Some(x) => x.fmt(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::LowerExp for $struct_name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.0 {
|
||||
None => f.write_str($error),
|
||||
Some(x) => x.fmt(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
opn_fmt!(OpnFmt, "ERROR");
|
||||
opn_fmt!(OpnFmtJSON, "null");
|
||||
|
||||
pub fn serve(output: &mut TcpSocket, request: &http::Request,
|
||||
config: &mut config::Config,
|
||||
loop_anode_m: &Mutex<RefCell<loop_anode::Controller>>,
|
||||
loop_cathode_m: &Mutex<RefCell<loop_cathode::Controller>>,
|
||||
electrometer_m: &Mutex<RefCell<electrometer::Electrometer>>) {
|
||||
match request.get_path().unwrap() {
|
||||
b"/" => {
|
||||
let (anode, cathode, electrometer) = cortex_m::interrupt::free(|cs| {
|
||||
(loop_anode_m.borrow(cs).borrow().get_status(),
|
||||
loop_cathode_m.borrow(cs).borrow().get_status(),
|
||||
electrometer_m.borrow(cs).borrow().get_status())
|
||||
});
|
||||
|
||||
let pressure = electrometer.ic.and_then(|ic| {
|
||||
if ic > 1.0e-12 {
|
||||
cathode.fbi.and_then(|fbi| Some(ic/fbi/18.75154))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
http::write_reply_header(output, 200, "text/html; charset=utf-8", false).unwrap();
|
||||
write!(output, include_str!("index.html"),
|
||||
pressure=OpnFmt(pressure),
|
||||
anode_ready=anode.ready,
|
||||
anode_av=OpnFmt(anode.av),
|
||||
cathode_ready=cathode.ready,
|
||||
cathode_fbi=OpnFmt(cathode.fbi.and_then(|x| Some(x*1.0e6))),
|
||||
cathode_fv=OpnFmt(cathode.fv),
|
||||
cathode_fv_target=OpnFmt(cathode.fv_target),
|
||||
cathode_fbv=OpnFmt(cathode.fbv),
|
||||
ion_current=OpnFmt(electrometer.ic.and_then(|x| Some(x*1.0e9)))).unwrap();
|
||||
},
|
||||
b"/measure.json" => {
|
||||
let (cathode, electrometer) = cortex_m::interrupt::free(|cs| {
|
||||
(loop_cathode_m.borrow(cs).borrow().get_status(),
|
||||
electrometer_m.borrow(cs).borrow().get_status())
|
||||
});
|
||||
|
||||
// TODO: factor this
|
||||
let pressure = electrometer.ic.and_then(|ic| {
|
||||
if ic > 1.0e-12 {
|
||||
cathode.fbi.and_then(|fbi| Some(ic/fbi/18.75154))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
http::write_reply_header(output, 200, "application/json", false).unwrap();
|
||||
write!(output, "{{\"pressure\": {:.1e}, \"current\": {:.3e}}}",
|
||||
OpnFmtJSON(pressure), OpnFmtJSON(electrometer.ic)).unwrap();
|
||||
}
|
||||
b"/network_settings.html" => {
|
||||
let mut status = "";
|
||||
|
||||
let ip_arg = request.get_arg(b"ip");
|
||||
if ip_arg.is_ok() {
|
||||
let ip_arg = str::from_utf8(ip_arg.unwrap());
|
||||
if ip_arg.is_ok() {
|
||||
let mut ip_arg = ip_arg.unwrap().split("%2F");
|
||||
let ip = ip_arg.next().map(|x| x.parse());
|
||||
let cidr = ip_arg.next().map(|x| x.parse());
|
||||
match (ip, cidr) {
|
||||
(Some(Ok(ip)), Some(Ok(cidr))) => {
|
||||
status = "IP address has been updated and will be active after a reboot.";
|
||||
config.ip = IpCidr::new(ip, cidr);
|
||||
config.save();
|
||||
}
|
||||
_ =>
|
||||
status = "failed to parse IP address"
|
||||
}
|
||||
} else {
|
||||
status = "IP address contains an invalid UTF-8 character";
|
||||
}
|
||||
}
|
||||
|
||||
http::write_reply_header(output, 200, "text/html; charset=utf-8", false).unwrap();
|
||||
write!(output, include_str!("network_settings.html"),
|
||||
status=status, ip=config.ip).unwrap();
|
||||
},
|
||||
b"/firmware.html" => {
|
||||
http::write_reply_header(output, 200, "text/html; charset=utf-8", false).unwrap();
|
||||
write!(output, include_str!("firmware.html"),
|
||||
version=include_str!(concat!(env!("OUT_DIR"), "/git-describe"))).unwrap();
|
||||
}
|
||||
b"/style.css" => {
|
||||
let data = include_bytes!("style.css.gz");
|
||||
http::write_reply_header(output, 200, "text/css", true).unwrap();
|
||||
output.send_slice(data).unwrap();
|
||||
},
|
||||
b"/logo.svg" => {
|
||||
let data = include_bytes!("logo.svg.gz");
|
||||
http::write_reply_header(output, 200, "image/svg+xml", true).unwrap();
|
||||
output.send_slice(data).unwrap();
|
||||
},
|
||||
_ => {
|
||||
http::write_reply_header(output, 404, "text/plain", false).unwrap();
|
||||
write!(output, "Not found").unwrap();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue