My other solution

  1. #![deny(unsafe_code)]
  2. #![no_main]
  3. #![no_std]
  4. #[macro_use]
  5. extern crate fixedvec;
  6. #[macro_use]
  7. extern crate pg;
  8. use core::ops::Not;
  9. use fixedvec::FixedVec;
  10. use pg::{Async, Future, Serial, Timer};
  11. use pg::led::LEDS;
  12. #[inline(never)]
  13. #[no_mangle]
  14. pub fn main() -> ! {
  15. let mut timer = Timer::new().unwrap();
  16. let Serial { mut rx, .. } = Serial::new().unwrap();
  17. let mut periodic = timer.periodic(100);
  18. let mut bytes = rx.bytes();
  19. let mut memory = alloc_stack!([u8; 32]);
  20. let mut buffer = FixedVec::new(&mut memory);
  21. let mut direction = Direction::Clockwise;
  22. let mut state = 0;
  23. loop {
  24. if let Async::Ready(()) = periodic.poll() {
  25. match direction {
  26. Direction::Clockwise => {
  27. if state == 7 {
  28. LEDS[state].off();
  29. LEDS[0].on();
  30. state = 0;
  31. } else {
  32. LEDS[state].off();
  33. LEDS[state+1].on();
  34. state += 1;
  35. }
  36. }
  37. Direction::Counterclockwise => {
  38. if state == 0 {
  39. LEDS[state].off();
  40. LEDS[7].on();
  41. state = 7;
  42. } else {
  43. LEDS[state].off();
  44. LEDS[state-1].on();
  45. state -= 1;
  46. }
  47. }
  48. }
  49. }
  50. if let Async::Ready(byte) = bytes.poll() {
  51. if let Err(_) = buffer.push(byte) {
  52. // TODO report error
  53. buffer.clear();
  54. } else if byte == '\r' as u8 {
  55. if buffer.as_slice() == b"reverse\r" {
  56. direction = !direction;
  57. }
  58. buffer.clear();
  59. }
  60. }
  61. }
  62. }
  63. enum Direction {
  64. Clockwise,
  65. Counterclockwise,
  66. }
  67. impl Not for Direction {
  68. type Output = Self;
  69. fn not(self) -> Self {
  70. match self {
  71. Direction::Clockwise => Direction::Counterclockwise,
  72. Direction::Counterclockwise => Direction::Clockwise,
  73. }
  74. }
  75. }