diff options
| author | huntc <[email protected]> | 2022-02-04 13:04:55 +1100 |
|---|---|---|
| committer | huntc <[email protected]> | 2022-02-04 13:04:55 +1100 |
| commit | 1af6b23f970d80d881bbc83fe69846e14c512e1c (patch) | |
| tree | dabe8b1b01350098387ff349ca66a2d6be12ffe1 | |
| parent | bc7266394ddba3d6128cc9de131109c2454f3d05 (diff) | |
Introduces a Sequences struct
| -rw-r--r-- | embassy-nrf/src/pwm.rs | 274 | ||||
| -rw-r--r-- | examples/nrf/src/bin/pwm_sequence_ws2812b.rs | 39 |
2 files changed, 161 insertions, 152 deletions
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index e561f0383..b696cbe63 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs | |||
| @@ -31,8 +31,6 @@ pub struct SequencePwm<'d, T: Instance> { | |||
| 31 | ch1: Option<AnyPin>, | 31 | ch1: Option<AnyPin>, |
| 32 | ch2: Option<AnyPin>, | 32 | ch2: Option<AnyPin>, |
| 33 | ch3: Option<AnyPin>, | 33 | ch3: Option<AnyPin>, |
| 34 | sequence0: Option<Sequence<'d>>, | ||
| 35 | sequence1: Option<Sequence<'d>>, | ||
| 36 | } | 34 | } |
| 37 | 35 | ||
| 38 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 36 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| @@ -127,111 +125,9 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | |||
| 127 | ch1: ch1.degrade_optional(), | 125 | ch1: ch1.degrade_optional(), |
| 128 | ch2: ch2.degrade_optional(), | 126 | ch2: ch2.degrade_optional(), |
| 129 | ch3: ch3.degrade_optional(), | 127 | ch3: ch3.degrade_optional(), |
| 130 | sequence0: None, | ||
| 131 | sequence1: None, | ||
| 132 | }) | 128 | }) |
| 133 | } | 129 | } |
| 134 | 130 | ||
| 135 | /// Start or restart playback. Takes at least one sequence along with its | ||
| 136 | /// configuration. Optionally takes a second sequence and its configuration. | ||
| 137 | /// In the case where no second sequence is provided then the first sequence | ||
| 138 | /// is used. The sequence mode applies to both sequences combined as one. | ||
| 139 | #[inline(always)] | ||
| 140 | pub fn start( | ||
| 141 | &mut self, | ||
| 142 | sequence0: Sequence<'d>, | ||
| 143 | sequence1: Option<Sequence<'d>>, | ||
| 144 | times: SequenceMode, | ||
| 145 | ) -> Result<(), Error> { | ||
| 146 | let alt_sequence = sequence1.as_ref().unwrap_or(&sequence0); | ||
| 147 | |||
| 148 | slice_in_ram_or(sequence0.words, Error::DMABufferNotInDataMemory)?; | ||
| 149 | slice_in_ram_or(alt_sequence.words, Error::DMABufferNotInDataMemory)?; | ||
| 150 | |||
| 151 | if sequence0.words.len() > MAX_SEQUENCE_LEN || alt_sequence.words.len() > MAX_SEQUENCE_LEN { | ||
| 152 | return Err(Error::SequenceTooLong); | ||
| 153 | } | ||
| 154 | |||
| 155 | if let SequenceMode::Times(0) = times { | ||
| 156 | return Err(Error::SequenceTimesAtLeastOne); | ||
| 157 | } | ||
| 158 | |||
| 159 | let _ = self.stop(); | ||
| 160 | |||
| 161 | let r = T::regs(); | ||
| 162 | |||
| 163 | r.seq0 | ||
| 164 | .refresh | ||
| 165 | .write(|w| unsafe { w.bits(sequence0.config.refresh) }); | ||
| 166 | r.seq0 | ||
| 167 | .enddelay | ||
| 168 | .write(|w| unsafe { w.bits(sequence0.config.end_delay) }); | ||
| 169 | r.seq0 | ||
| 170 | .ptr | ||
| 171 | .write(|w| unsafe { w.bits(sequence0.words.as_ptr() as u32) }); | ||
| 172 | r.seq0 | ||
| 173 | .cnt | ||
| 174 | .write(|w| unsafe { w.bits(sequence0.words.len() as u32) }); | ||
| 175 | |||
| 176 | r.seq1 | ||
| 177 | .refresh | ||
| 178 | .write(|w| unsafe { w.bits(alt_sequence.config.refresh) }); | ||
| 179 | r.seq1 | ||
| 180 | .enddelay | ||
| 181 | .write(|w| unsafe { w.bits(alt_sequence.config.end_delay) }); | ||
| 182 | r.seq1 | ||
| 183 | .ptr | ||
| 184 | .write(|w| unsafe { w.bits(alt_sequence.words.as_ptr() as u32) }); | ||
| 185 | r.seq1 | ||
| 186 | .cnt | ||
| 187 | .write(|w| unsafe { w.bits(alt_sequence.words.len() as u32) }); | ||
| 188 | |||
| 189 | r.enable.write(|w| w.enable().enabled()); | ||
| 190 | |||
| 191 | // defensive before seqstart | ||
| 192 | compiler_fence(Ordering::SeqCst); | ||
| 193 | |||
| 194 | match times { | ||
| 195 | // just the one time, no loop count | ||
| 196 | SequenceMode::Times(1) => { | ||
| 197 | r.loop_.write(|w| w.cnt().disabled()); | ||
| 198 | // tasks_seqstart() doesn't exist in all svds so write its bit instead | ||
| 199 | r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) }); | ||
| 200 | } | ||
| 201 | // loop count is how many times to play BOTH sequences | ||
| 202 | // 2 total (1 x 2) | ||
| 203 | // 3 total, (2 x 2) - 1 | ||
| 204 | SequenceMode::Times(n) => { | ||
| 205 | let odd = n & 1 == 1; | ||
| 206 | let times = if odd { (n / 2) + 1 } else { n / 2 }; | ||
| 207 | |||
| 208 | r.loop_.write(|w| unsafe { w.cnt().bits(times) }); | ||
| 209 | |||
| 210 | // we can subtract 1 by starting at seq1 instead of seq0 | ||
| 211 | if odd { | ||
| 212 | // tasks_seqstart() doesn't exist in all svds so write its bit instead | ||
| 213 | r.tasks_seqstart[1].write(|w| unsafe { w.bits(0x01) }); | ||
| 214 | } else { | ||
| 215 | // tasks_seqstart() doesn't exist in all svds so write its bit instead | ||
| 216 | r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) }); | ||
| 217 | } | ||
| 218 | } | ||
| 219 | // to play infinitely, repeat the sequence one time, then have loops done self trigger seq0 again | ||
| 220 | SequenceMode::Infinite => { | ||
| 221 | r.loop_.write(|w| unsafe { w.cnt().bits(0x1) }); | ||
| 222 | r.shorts.write(|w| w.loopsdone_seqstart0().enabled()); | ||
| 223 | |||
| 224 | // tasks_seqstart() doesn't exist in all svds so write its bit instead | ||
| 225 | r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) }); | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 229 | self.sequence0 = Some(sequence0); | ||
| 230 | self.sequence1 = sequence1; | ||
| 231 | |||
| 232 | Ok(()) | ||
| 233 | } | ||
| 234 | |||
| 235 | /// Returns reference to `Stopped` event endpoint for PPI. | 131 | /// Returns reference to `Stopped` event endpoint for PPI. |
| 236 | #[inline(always)] | 132 | #[inline(always)] |
| 237 | pub fn event_stopped(&self) -> Event { | 133 | pub fn event_stopped(&self) -> Event { |
| @@ -331,33 +227,12 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | |||
| 331 | 227 | ||
| 332 | Task::from_reg(&r.tasks_stop) | 228 | Task::from_reg(&r.tasks_stop) |
| 333 | } | 229 | } |
| 334 | |||
| 335 | /// Stop playback. Disables the peripheral. Does NOT clear the last duty | ||
| 336 | /// cycle from the pin. Returns any sequences previously provided to | ||
| 337 | /// `start` so that they may be further mutated. | ||
| 338 | #[inline(always)] | ||
| 339 | pub fn stop(&mut self) -> (Option<Sequence<'d>>, Option<Sequence<'d>>) { | ||
| 340 | let r = T::regs(); | ||
| 341 | |||
| 342 | r.shorts.reset(); | ||
| 343 | |||
| 344 | compiler_fence(Ordering::SeqCst); | ||
| 345 | |||
| 346 | // tasks_stop() doesn't exist in all svds so write its bit instead | ||
| 347 | r.tasks_stop.write(|w| unsafe { w.bits(0x01) }); | ||
| 348 | |||
| 349 | r.enable.write(|w| w.enable().disabled()); | ||
| 350 | |||
| 351 | (self.sequence0.take(), self.sequence1.take()) | ||
| 352 | } | ||
| 353 | } | 230 | } |
| 354 | 231 | ||
| 355 | impl<'a, T: Instance> Drop for SequencePwm<'a, T> { | 232 | impl<'a, T: Instance> Drop for SequencePwm<'a, T> { |
| 356 | fn drop(&mut self) { | 233 | fn drop(&mut self) { |
| 357 | let r = T::regs(); | 234 | let r = T::regs(); |
| 358 | 235 | ||
| 359 | let _ = self.stop(); | ||
| 360 | |||
| 361 | if let Some(pin) = &self.ch0 { | 236 | if let Some(pin) = &self.ch0 { |
| 362 | pin.set_low(); | 237 | pin.set_low(); |
| 363 | pin.conf().reset(); | 238 | pin.conf().reset(); |
| @@ -426,21 +301,158 @@ impl Default for SequenceConfig { | |||
| 426 | 301 | ||
| 427 | /// A composition of a sequence buffer and its configuration. | 302 | /// A composition of a sequence buffer and its configuration. |
| 428 | #[non_exhaustive] | 303 | #[non_exhaustive] |
| 429 | pub struct Sequence<'d> { | 304 | pub struct Sequence<'s> { |
| 430 | /// The words comprising the sequence. Must not exceed 32767 words. | 305 | /// The words comprising the sequence. Must not exceed 32767 words. |
| 431 | /// The reason for this buffer to be mutable is so that stopping | 306 | pub words: &'s [u16], |
| 432 | /// the PWM can relinquish the sequence for subsequent modification. | ||
| 433 | pub words: &'d mut [u16], | ||
| 434 | /// Configuration associated with the sequence. | 307 | /// Configuration associated with the sequence. |
| 435 | pub config: SequenceConfig, | 308 | pub config: SequenceConfig, |
| 436 | } | 309 | } |
| 437 | 310 | ||
| 438 | impl<'d> Sequence<'d> { | 311 | impl<'s> Sequence<'s> { |
| 439 | pub fn new(words: &'d mut [u16], config: SequenceConfig) -> Self { | 312 | pub fn new(words: &'s [u16], config: SequenceConfig) -> Self { |
| 440 | Self { words, config } | 313 | Self { words, config } |
| 441 | } | 314 | } |
| 442 | } | 315 | } |
| 443 | 316 | ||
| 317 | /// A composition of sequences that can be started and stopped. | ||
| 318 | /// Takes at least one sequence along with its configuration. | ||
| 319 | /// Optionally takes a second sequence and its configuration. | ||
| 320 | /// In the case where no second sequence is provided then the first sequence | ||
| 321 | /// is used. | ||
| 322 | #[non_exhaustive] | ||
| 323 | pub struct Sequences<'d, 's, T: Instance> { | ||
| 324 | _pwm: &'s mut SequencePwm<'d, T>, | ||
| 325 | sequence0: Sequence<'s>, | ||
| 326 | sequence1: Option<Sequence<'s>>, | ||
| 327 | } | ||
| 328 | |||
| 329 | impl<'d, 's, T: Instance> Sequences<'d, 's, T> { | ||
| 330 | pub fn new( | ||
| 331 | pwm: &'s mut SequencePwm<'d, T>, | ||
| 332 | sequence0: Sequence<'s>, | ||
| 333 | sequence1: Option<Sequence<'s>>, | ||
| 334 | ) -> Self { | ||
| 335 | Sequences { | ||
| 336 | _pwm: pwm, | ||
| 337 | sequence0, | ||
| 338 | sequence1, | ||
| 339 | } | ||
| 340 | } | ||
| 341 | |||
| 342 | /// Start or restart playback. The sequence mode applies to both sequences combined as one. | ||
| 343 | #[inline(always)] | ||
| 344 | pub fn start(&self, times: SequenceMode) -> Result<(), Error> { | ||
| 345 | let sequence0 = &self.sequence0; | ||
| 346 | let alt_sequence = self.sequence1.as_ref().unwrap_or(&self.sequence0); | ||
| 347 | |||
| 348 | slice_in_ram_or(sequence0.words, Error::DMABufferNotInDataMemory)?; | ||
| 349 | slice_in_ram_or(alt_sequence.words, Error::DMABufferNotInDataMemory)?; | ||
| 350 | |||
| 351 | if sequence0.words.len() > MAX_SEQUENCE_LEN || alt_sequence.words.len() > MAX_SEQUENCE_LEN { | ||
| 352 | return Err(Error::SequenceTooLong); | ||
| 353 | } | ||
| 354 | |||
| 355 | if let SequenceMode::Times(0) = times { | ||
| 356 | return Err(Error::SequenceTimesAtLeastOne); | ||
| 357 | } | ||
| 358 | |||
| 359 | let _ = self.stop(); | ||
| 360 | |||
| 361 | let r = T::regs(); | ||
| 362 | |||
| 363 | r.seq0 | ||
| 364 | .refresh | ||
| 365 | .write(|w| unsafe { w.bits(sequence0.config.refresh) }); | ||
| 366 | r.seq0 | ||
| 367 | .enddelay | ||
| 368 | .write(|w| unsafe { w.bits(sequence0.config.end_delay) }); | ||
| 369 | r.seq0 | ||
| 370 | .ptr | ||
| 371 | .write(|w| unsafe { w.bits(sequence0.words.as_ptr() as u32) }); | ||
| 372 | r.seq0 | ||
| 373 | .cnt | ||
| 374 | .write(|w| unsafe { w.bits(sequence0.words.len() as u32) }); | ||
| 375 | |||
| 376 | r.seq1 | ||
| 377 | .refresh | ||
| 378 | .write(|w| unsafe { w.bits(alt_sequence.config.refresh) }); | ||
| 379 | r.seq1 | ||
| 380 | .enddelay | ||
| 381 | .write(|w| unsafe { w.bits(alt_sequence.config.end_delay) }); | ||
| 382 | r.seq1 | ||
| 383 | .ptr | ||
| 384 | .write(|w| unsafe { w.bits(alt_sequence.words.as_ptr() as u32) }); | ||
| 385 | r.seq1 | ||
| 386 | .cnt | ||
| 387 | .write(|w| unsafe { w.bits(alt_sequence.words.len() as u32) }); | ||
| 388 | |||
| 389 | r.enable.write(|w| w.enable().enabled()); | ||
| 390 | |||
| 391 | // defensive before seqstart | ||
| 392 | compiler_fence(Ordering::SeqCst); | ||
| 393 | |||
| 394 | match times { | ||
| 395 | // just the one time, no loop count | ||
| 396 | SequenceMode::Times(1) => { | ||
| 397 | r.loop_.write(|w| w.cnt().disabled()); | ||
| 398 | // tasks_seqstart() doesn't exist in all svds so write its bit instead | ||
| 399 | r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) }); | ||
| 400 | } | ||
| 401 | // loop count is how many times to play BOTH sequences | ||
| 402 | // 2 total (1 x 2) | ||
| 403 | // 3 total, (2 x 2) - 1 | ||
| 404 | SequenceMode::Times(n) => { | ||
| 405 | let odd = n & 1 == 1; | ||
| 406 | let times = if odd { (n / 2) + 1 } else { n / 2 }; | ||
| 407 | |||
| 408 | r.loop_.write(|w| unsafe { w.cnt().bits(times) }); | ||
| 409 | |||
| 410 | // we can subtract 1 by starting at seq1 instead of seq0 | ||
| 411 | if odd { | ||
| 412 | // tasks_seqstart() doesn't exist in all svds so write its bit instead | ||
| 413 | r.tasks_seqstart[1].write(|w| unsafe { w.bits(0x01) }); | ||
| 414 | } else { | ||
| 415 | // tasks_seqstart() doesn't exist in all svds so write its bit instead | ||
| 416 | r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) }); | ||
| 417 | } | ||
| 418 | } | ||
| 419 | // to play infinitely, repeat the sequence one time, then have loops done self trigger seq0 again | ||
| 420 | SequenceMode::Infinite => { | ||
| 421 | r.loop_.write(|w| unsafe { w.cnt().bits(0x1) }); | ||
| 422 | r.shorts.write(|w| w.loopsdone_seqstart0().enabled()); | ||
| 423 | |||
| 424 | // tasks_seqstart() doesn't exist in all svds so write its bit instead | ||
| 425 | r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) }); | ||
| 426 | } | ||
| 427 | } | ||
| 428 | |||
| 429 | Ok(()) | ||
| 430 | } | ||
| 431 | |||
| 432 | /// Stop playback. Disables the peripheral. Does NOT clear the last duty | ||
| 433 | /// cycle from the pin. Returns any sequences previously provided to | ||
| 434 | /// `start` so that they may be further mutated. | ||
| 435 | #[inline(always)] | ||
| 436 | pub fn stop(&self) { | ||
| 437 | let r = T::regs(); | ||
| 438 | |||
| 439 | r.shorts.reset(); | ||
| 440 | |||
| 441 | compiler_fence(Ordering::SeqCst); | ||
| 442 | |||
| 443 | // tasks_stop() doesn't exist in all svds so write its bit instead | ||
| 444 | r.tasks_stop.write(|w| unsafe { w.bits(0x01) }); | ||
| 445 | |||
| 446 | r.enable.write(|w| w.enable().disabled()); | ||
| 447 | } | ||
| 448 | } | ||
| 449 | |||
| 450 | impl<'d, 's, T: Instance> Drop for Sequences<'d, 's, T> { | ||
| 451 | fn drop(&mut self) { | ||
| 452 | let _ = self.stop(); | ||
| 453 | } | ||
| 454 | } | ||
| 455 | |||
| 444 | /// How many times to run the sequence | 456 | /// How many times to run the sequence |
| 445 | #[derive(Debug, Eq, PartialEq, Clone, Copy)] | 457 | #[derive(Debug, Eq, PartialEq, Clone, Copy)] |
| 446 | pub enum SequenceMode { | 458 | pub enum SequenceMode { |
diff --git a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs index 0ce79cbe0..310842d8d 100644 --- a/examples/nrf/src/bin/pwm_sequence_ws2812b.rs +++ b/examples/nrf/src/bin/pwm_sequence_ws2812b.rs | |||
| @@ -9,7 +9,7 @@ use embassy::executor::Spawner; | |||
| 9 | use embassy::time::{Duration, Timer}; | 9 | use embassy::time::{Duration, Timer}; |
| 10 | use embassy_nrf::gpio::NoPin; | 10 | use embassy_nrf::gpio::NoPin; |
| 11 | use embassy_nrf::pwm::{ | 11 | use embassy_nrf::pwm::{ |
| 12 | Config, Prescaler, Sequence, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm, | 12 | Config, Prescaler, Sequence, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm, Sequences, |
| 13 | }; | 13 | }; |
| 14 | use embassy_nrf::Peripherals; | 14 | use embassy_nrf::Peripherals; |
| 15 | 15 | ||
| @@ -30,19 +30,6 @@ const RES: u16 = 0x8000; | |||
| 30 | // line is assumed to be P1_05. | 30 | // line is assumed to be P1_05. |
| 31 | #[embassy::main] | 31 | #[embassy::main] |
| 32 | async fn main(_spawner: Spawner, p: Peripherals) { | 32 | async fn main(_spawner: Spawner, p: Peripherals) { |
| 33 | // Declare the bits of 24 bits | ||
| 34 | let mut color_seq_words = [ | ||
| 35 | T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G | ||
| 36 | T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R | ||
| 37 | T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B | ||
| 38 | ]; | ||
| 39 | let color_seq = Sequence::new(&mut color_seq_words, SequenceConfig::default()); | ||
| 40 | |||
| 41 | let mut reset_seq_words = [RES; 1]; | ||
| 42 | let mut reset_seq_config = SequenceConfig::default(); | ||
| 43 | reset_seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES; | ||
| 44 | let reset_seq = Sequence::new(&mut reset_seq_words, reset_seq_config); | ||
| 45 | |||
| 46 | let mut config = Config::default(); | 33 | let mut config = Config::default(); |
| 47 | config.sequence_load = SequenceLoad::Common; | 34 | config.sequence_load = SequenceLoad::Common; |
| 48 | config.prescaler = Prescaler::Div1; | 35 | config.prescaler = Prescaler::Div1; |
| @@ -51,18 +38,24 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 51 | p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, | 38 | p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, |
| 52 | )); | 39 | )); |
| 53 | 40 | ||
| 54 | unwrap!(pwm.start(color_seq, Some(reset_seq), SequenceMode::Times(2))); | 41 | // Declare the bits of 24 bits in a buffer we'll be |
| 55 | 42 | // mutating later. | |
| 56 | Timer::after(Duration::from_millis(1000)).await; | 43 | let mut seq_words = [ |
| 44 | T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // G | ||
| 45 | T0H, T0H, T0H, T0H, T0H, T0H, T0H, T0H, // R | ||
| 46 | T1H, T1H, T1H, T1H, T1H, T1H, T1H, T1H, // B | ||
| 47 | RES, | ||
| 48 | ]; | ||
| 49 | let mut seq_config = SequenceConfig::default(); | ||
| 50 | seq_config.end_delay = 799; // 50us (20 ticks * 40) - 1 tick because we've already got one RES; | ||
| 57 | 51 | ||
| 58 | let mut color_bit = 16; | 52 | let mut color_bit = 16; |
| 59 | let mut bit_value = T0H; | 53 | let mut bit_value = T0H; |
| 60 | 54 | ||
| 61 | loop { | 55 | loop { |
| 62 | if let (Some(color_seq), Some(reset_seq)) = pwm.stop() { | 56 | let sequence0 = Sequence::new(&seq_words, seq_config.clone()); |
| 63 | color_seq.words[color_bit] = bit_value; | 57 | let sequences = Sequences::new(&mut pwm, sequence0, None); |
| 64 | unwrap!(pwm.start(color_seq, Some(reset_seq), SequenceMode::Times(2))); | 58 | unwrap!(sequences.start(SequenceMode::Times(2))); |
| 65 | } | ||
| 66 | 59 | ||
| 67 | Timer::after(Duration::from_millis(50)).await; | 60 | Timer::after(Duration::from_millis(50)).await; |
| 68 | 61 | ||
| @@ -79,5 +72,9 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 79 | color_bit -= 1; | 72 | color_bit -= 1; |
| 80 | } | 73 | } |
| 81 | } | 74 | } |
| 75 | |||
| 76 | drop(sequences); | ||
| 77 | |||
| 78 | seq_words[color_bit] = bit_value; | ||
| 82 | } | 79 | } |
| 83 | } | 80 | } |
