Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add audio seed and 5 minute recording #19

Merged
merged 4 commits into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 37 additions & 14 deletions src/attiny_rtc_i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub mod tc2_agent_state {
pub const TAKE_AUDIO: u8 = 1 << 4;
pub const OFFLOAD: u8 = 1 << 5;
pub const THERMAL_MODE: u8 = 1 << 6;
pub const LONG_AUDIO_RECORDING: u8 = 1 << 7;
}

#[repr(u8)]
Expand Down Expand Up @@ -72,6 +73,16 @@ impl From<u8> for CameraState {
}
}

#[repr(u8)]
#[derive(Format)]

pub enum RecordingType {
TestRecording = 0,
LongRecording = 1,
ScheduledRecording = 2,
ThermalRequestedScheduledRecording = 3,
}

#[repr(u8)]
enum CameraConnectionState {
NoConnection = 0x00,
Expand Down Expand Up @@ -475,14 +486,28 @@ impl SharedI2C {
self.try_attiny_read_command(REG_TC2_AGENT_STATE, delay, None)
}

pub fn tc2_agent_requested_test_audio_rec(&mut self, delay: &mut Delay) -> Result<bool, Error> {
pub fn tc2_agent_requested_audio_recording(
&mut self,
delay: &mut Delay,
) -> Result<Option<RecordingType>, Error> {
match self.try_attiny_read_command(REG_TC2_AGENT_STATE, delay, None) {
Ok(state) => {
let rec_state: bool = (state & tc2_agent_state::READY
== state & tc2_agent_state::READY)
&& (state & tc2_agent_state::TEST_AUDIO_RECORDING
== tc2_agent_state::TEST_AUDIO_RECORDING);
Ok(rec_state)
let rec_state: bool =
state & tc2_agent_state::READY == state & tc2_agent_state::READY;
if rec_state {
if state & tc2_agent_state::TEST_AUDIO_RECORDING
== tc2_agent_state::TEST_AUDIO_RECORDING
{
return Ok(Some(RecordingType::TestRecording));
} else if state & tc2_agent_state::LONG_AUDIO_RECORDING
== tc2_agent_state::LONG_AUDIO_RECORDING
{
return Ok(Some(RecordingType::LongRecording));
} else if state & tc2_agent_state::TAKE_AUDIO == tc2_agent_state::TAKE_AUDIO {
return Ok(Some(RecordingType::ThermalRequestedScheduledRecording));
}
}
Ok(None)
}
Err(e) => Err(e),
}
Expand Down Expand Up @@ -514,11 +539,15 @@ impl SharedI2C {
&mut self,
delay: &mut Delay,
clear_flag: u8,
set_flag: u8,
set_flag: Option<u8>,
) -> Result<(), Error> {
match self.try_attiny_read_command(REG_TC2_AGENT_STATE, delay, None) {
Ok(state) => {
let val = (state & !clear_flag) | set_flag;
let mut val = state & !clear_flag;
if let Some(flag) = set_flag {
val = val | flag;
}

match self.try_attiny_write_command(REG_TC2_AGENT_STATE, val, delay) {
Ok(_) => Ok(()),
Err(x) => Err(x),
Expand All @@ -544,12 +573,6 @@ impl SharedI2C {
self.tc2_agent_write_flag(delay, tc2_agent_state::THERMAL_MODE, false)
}

pub fn tc2_agent_requested_audio_rec(&mut self, delay: &mut Delay) -> Result<bool, Error> {
match self.try_attiny_read_command(REG_TC2_AGENT_STATE, delay, None) {
Ok(state) => Ok((state & tc2_agent_state::TAKE_AUDIO) == tc2_agent_state::TAKE_AUDIO),
Err(e) => Err(e),
}
}
pub fn tc2_agent_take_audio_rec(&mut self, delay: &mut Delay) -> Result<(), Error> {
self.tc2_agent_write_flag(delay, tc2_agent_state::TAKE_AUDIO, true)
}
Expand Down
154 changes: 93 additions & 61 deletions src/core0_audio.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::attiny_rtc_i2c::{tc2_agent_state, I2CConfig, SharedI2C};
use crate::attiny_rtc_i2c::{tc2_agent_state, I2CConfig, RecordingType, SharedI2C};
use crate::bsp;
use crate::bsp::pac;
use crate::bsp::pac::Peripherals;
Expand Down Expand Up @@ -169,12 +169,36 @@ pub fn audio_task(
);
}

let mut take_test_rec = false;
if let Ok(test_rec) = shared_i2c.tc2_agent_requested_test_audio_rec(&mut delay) {
take_test_rec = test_rec;
}
let mut do_recording = alarm_triggered;
let mut duration = 60;
let mut recording_type = None;
let mut user_recording_requested = false;
let mut thermal_requested_audio = false;
if alarm_triggered {
recording_type = Some(RecordingType::ScheduledRecording);
} else {
if let Ok(audio_rec) = shared_i2c.tc2_agent_requested_audio_recording(&mut delay) {
recording_type = audio_rec;

if let Some(rec_type) = recording_type.as_mut() {
match rec_type {
RecordingType::LongRecording => {
duration = 60 * 5;
user_recording_requested = true;
}
RecordingType::TestRecording => {
duration = 10;
user_recording_requested = true;
}
RecordingType::ThermalRequestedScheduledRecording => {
duration = 60;
thermal_requested_audio = true;
}
_ => {}
}
}
}
}

let mut reschedule = false;
let mut alarm_date_time: Option<NaiveDateTime> = None;

Expand Down Expand Up @@ -204,9 +228,10 @@ pub fn audio_task(
);
}

if !take_test_rec {
if !user_recording_requested {
if device_config_was_updated {
let reboot;

if device_config.config().is_audio_device() && !thermal_requested_audio {
if let AudioMode::AudioOnly = device_config.config().audio_mode {
reboot = false;
Expand Down Expand Up @@ -349,21 +374,12 @@ pub fn audio_task(
}
}

if let Ok(take_rec) = shared_i2c.tc2_agent_requested_audio_rec(&mut delay) {
thermal_requested_audio = take_rec;
if thermal_requested_audio {
do_recording = true;
}
} else {
thermal_requested_audio = false;
}

info!(
"Alarm triggered {} scheduled {} thermal requested {}",
alarm_triggered, scheduled, thermal_requested_audio
alarm_triggered, scheduled, recording_type
);

if !do_recording && scheduled {
if recording_type.is_none() && scheduled {
// check we haven't missed the alarm somehow
if let Some(alarm) = alarm_date_time {
let synced = synced_date_time.get_adjusted_dt(timer);
Expand All @@ -385,12 +401,12 @@ pub fn audio_task(
),
&mut flash_storage,
);
do_recording = true;
recording_type = Some(RecordingType::ScheduledRecording);
}
}
}
}
if do_recording || take_test_rec {
if recording_type.is_some() {
watchdog.feed();
//should of already offloaded but extra safety check
if !flash_storage.is_too_full_for_audio() {
Expand All @@ -408,10 +424,7 @@ pub fn audio_task(
pio1,
sm1,
);
let mut duration = 60;
if !do_recording && take_test_rec {
duration = 10;
}

event_logger.log_event(
LoggerEvent::new(
LoggerEventKind::StartedAudioRecording,
Expand Down Expand Up @@ -454,48 +467,62 @@ pub fn audio_task(
),
&mut flash_storage,
);
if take_test_rec {
info!("taken test recoridng clearing status");
watchdog.feed();
let _ = shared_i2c.tc2_agent_clear_and_set_flag(
&mut delay,
tc2_agent_state::TEST_AUDIO_RECORDING,
tc2_agent_state::THERMAL_MODE,
);

let mut peripherals: Peripherals = unsafe { Peripherals::steal() };

offload_flash_storage_and_events(
&mut flash_storage,
&mut pi_spi,
&mut peripherals.RESETS,
&mut peripherals.DMA,
clock_freq,
&mut shared_i2c,
&mut delay,
timer,
&mut event_logger,
&synced_date_time,
Some(watchdog),
true,
);
match recording_type.as_mut().unwrap() {
RecordingType::LongRecording | RecordingType::TestRecording => {
info!("taken test recoridng clearing status");
watchdog.feed();
let _ = shared_i2c.tc2_agent_clear_and_set_flag(
&mut delay,
match recording_type.unwrap() {
RecordingType::LongRecording => {
tc2_agent_state::LONG_AUDIO_RECORDING
}
RecordingType::TestRecording => {
tc2_agent_state::TEST_AUDIO_RECORDING
}
_ => 0,
},
if device_config.config().audio_mode != AudioMode::AudioOnly {
Some(tc2_agent_state::THERMAL_MODE)
} else {
None
},
);

restart(watchdog);
} else {
shared_i2c.clear_alarm(&mut delay);
reschedule = true;
clear_audio_alarm(&mut flash_storage);
let mut peripherals: Peripherals = unsafe { Peripherals::steal() };

if thermal_requested_audio {
//if audio requested from thermal, the alarm will be re scheduled there
let _ = shared_i2c.tc2_agent_clear_and_set_flag(
offload_flash_storage_and_events(
&mut flash_storage,
&mut pi_spi,
&mut peripherals.RESETS,
&mut peripherals.DMA,
clock_freq,
&mut shared_i2c,
&mut delay,
tc2_agent_state::TAKE_AUDIO,
tc2_agent_state::THERMAL_MODE,
timer,
&mut event_logger,
&synced_date_time,
Some(watchdog),
true,
);
info!("Audio taken in thermal window clearing flag");

restart(watchdog);
}
_ => {
shared_i2c.clear_alarm(&mut delay);
reschedule = true;
clear_audio_alarm(&mut flash_storage);
if thermal_requested_audio {
//if audio requested from thermal, the alarm will be re scheduled there
let _ = shared_i2c.tc2_agent_clear_and_set_flag(
&mut delay,
tc2_agent_state::TAKE_AUDIO,
Some(tc2_agent_state::THERMAL_MODE),
);
info!("Audio taken in thermal window clearing flag");
restart(watchdog);
}
}
}
}
}
Expand Down Expand Up @@ -696,7 +723,12 @@ pub fn schedule_audio_rec(
error!("Failed to disable alarm");
return Err(());
}
let mut rng = RNG::<WyRand, u16>::new(synced_date_time.date_time_utc.timestamp() as u64);
let seed = if device_config.config().audio_seed == 0 {
synced_date_time.date_time_utc.timestamp() as u64
} else {
device_config.config().audio_seed as u64
};
let mut rng = RNG::<WyRand, u16>::new(seed);
let r = rng.generate();
let r_max: u16 = 65535u16;
let short_chance: u16 = r_max / 4;
Expand Down
18 changes: 9 additions & 9 deletions src/core1_task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,17 +410,17 @@ pub fn core_1_task(
&mut flash_storage,
);
//changing from no audio to audio mode and then clicking test rec quickly
let test_rec = shared_i2c
.tc2_agent_requested_test_audio_rec(&mut delay)
.map_err(|e| error!("Error setting recording flag on attiny: {}", e));
if let Ok(test_rec) = test_rec {
if test_rec {
sio.fifo.write_blocking(Core1Task::RequestReset.into());
loop {
// Wait to be reset
nop();
match shared_i2c.tc2_agent_requested_audio_recording(&mut delay) {
Ok(test_rec) => {
if test_rec.is_some() {
sio.fifo.write_blocking(Core1Task::RequestReset.into());
loop {
// Wait to be reset
nop();
}
}
}
Err(e) => error!("Error getting tc2 agent state: {}", e),
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/device_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub struct DeviceConfigInner {
pub is_continuous_recorder: bool,
pub use_low_power_mode: bool,
pub audio_mode: AudioMode,
pub audio_seed: u32,
}

impl DeviceConfigInner {
Expand Down Expand Up @@ -260,6 +261,7 @@ impl Default for DeviceConfig {
is_continuous_recorder: false,
use_low_power_mode: false,
audio_mode: AudioMode::Disabled,
audio_seed: 0,
},
motion_detection_mask: DetectionMask::new(None),
cursor_position: 0,
Expand Down Expand Up @@ -290,6 +292,7 @@ impl DeviceConfig {
let audio_mode = AudioMode::try_from(cursor.read_u8())
.ok()
.unwrap_or(AudioMode::Disabled);
let audio_seed = cursor.read_u32();
let latitude = cursor.read_f32();
let longitude = cursor.read_f32();
let has_location_timestamp = cursor.read_bool();
Expand Down Expand Up @@ -329,6 +332,7 @@ impl DeviceConfig {
is_continuous_recorder,
use_low_power_mode,
audio_mode,
audio_seed,
},
cursor.position(),
))
Expand Down
3 changes: 2 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ fn main() -> ! {
let in_window = config.time_is_in_recording_window(&date_time, &None);
if in_window {
is_audio = (state
& (tc2_agent_state::TAKE_AUDIO
& (tc2_agent_state::LONG_AUDIO_RECORDING
| tc2_agent_state::TAKE_AUDIO
| tc2_agent_state::TEST_AUDIO_RECORDING))
> 0;
if is_audio {
Expand Down
Loading