1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! [dma_gpio](index.html) is a library for pi's GPIO that uses DMA ([Direct Memory Access](https://en.wikipedia.org/wiki/Direct_memory_access)) and [PWM via DMA](https://stackoverflow.com/questions/50427275/raspberry-how-does-the-pwm-via-dma-work).
//! By using DMA and interacting directly with hardware memory, it manages to be very fast (Max Raw Speed ≈ 1.6 MHz on Pi3) while having almost no CPU usage ( ~2%).
//! This project was inspired by its predecessor projects in C, such as [PiBits](https://github.com/richardghirst/PiBits), [pi-blaster](https://github.com/sarfata/pi-blaster) and [RPIO](https://github.com/metachris/RPIO/tree/master/source); however, this project bypasses L1 cache which the DMA Controller does not recognize, resulting in a slightly faster GPIO Speed.
//! 
//! [pi](pi/index.html) module will have everything you need.
//! 
//! # Getting Started
//! First, add the crate to the dependencies.
//! ```no_run
//! Cargo.toml
//! 
//! ...
//! [dependencies]
//! dma_gpio = "0.1.6"
//! ```
//! 
//! The easiest way to get started using this library is initializing a [Board](pi/struct.Board.html) using [BoardBuilder](pi/struct.BoardBuilder.html).
//! BoardBuilder will configure the default setting for the DMA, but manual configuration is also available (read more on this in [BoardBuiler](pi/struct.BoardBuilder.html#building-with-custom-settings)).
//! When the Board is initialized, it recognizes which Pi-version it is running on, and interacts with the hardware memory accordingly.
//! 
//! ## Example
//! Below example initializes the board using BoardBuilder with default configurations, set the PWM of gpio pins 21 and 22 to 25%, 50%, 75%, then 100% for 1 second each. Make sure to run the binary file in sudo!!!
//! 
//! ```no_run
//! use std::thread::sleep;
//! use std::time::Duration;
//! use dma_gpio::pi::BoardBuilder;
//! 
//! fn main() {
//!     let mut board = BoardBuilder::new().build_with_pins(vec![21, 22]).unwrap();
//!     board.print_info();
//!     
//!     board.set_all_pwm(0.25).unwrap();
//!     let sec = Duration::from_millis(1000);
//!     sleep(millis);
//!     
//!     board.set_all_pwm(0.5).unwrap();
//!     sleep(millis);
//!     
//!     board.set_all_pwm(0.75).unwrap();
//!     sleep(millis);
//!     
//!     board.set_all_pwm(1.0).unwrap();
//!     sleep(millis);
//! }
//! 
//! ```
//! 
//! # Features
//! There are two features you can enable in this crate: 'debug' and 'bind_process'. To enable these features, write the dependency for this crate as shown below.
//! ```no_run
//! Cargo.toml
//! 
//! ...
//! [dependencies]
//! ...
//! 
//! [dependencies.dma_gpio]
//! version = "0.1.6"
//! features = [debug, bind_process]
//! ```
//! 
//! ## 'debug' feature
//! By enabling this feature, the library will print out the process every step of the way. This feature will be useful when debugging.
//! Also, after enabling this feature in Cargo.toml, you have to call [enable_logger](fn.enable_logger.html) function to see the logs in the terminal.
//! ```no_run
//! use std::thread::sleep;
//! use std::time::Duration;
//! use dma_gpio::pi::BoardBuilder;
//! 
//! fn main() {
//!     dma_gpio::enable_logger();
//!     let mut board = BoardBuilder::new().build_with_pins(vec![21, 22]).unwrap();
//!     
//!     board.set_all_pwm(0.5).unwrap();
//!     let sec = Duration::from_millis(2000);
//!     sleep(millis);
//! }
//! 
//! ```
//! ## 'bind_process' feature
//! This feature lets you access the [pi_core](pi_core/index.html) module which only has one function [bind_process_to_last](pi_core/fn.bind_process_to_last.html). This function binds the process to the last core of the Pi. However, to use this function, you have to first install a C library called [hwloc](https://github.com/daschl/hwloc-rs#install-hwloc-on-os-x). Also, enabling debug feature will print out if you have correctly bound process to the last core.
//! ```no_run
//! use std::thread::sleep;
//! use std::time::Duration;
//! use dma_gpio::{pi::BoardBuilder, pi_core};
//! 
//! fn main() {
//!     dma_gpio::enable_logger();
//!     pi_core::bind_process_to_last();
//!     let mut board = BoardBuilder::new().build_with_pins(vec![21, 22]).unwrap();
//!     
//!     board.set_all_pwm(0.5).unwrap();
//!     let sec = Duration::from_millis(2000);
//!     sleep(millis);
//! }
//! ```
//! 
//! # Cross-Compilation
//! Since compiling a rust project on a pi may take a very long time, it's often a good idea to cross-compile on your computer. Great resources for cross-compilations to Pi that I found helpful are [rust-cross](https://github.com/japaric/rust-cross) and [this blog](https://piers.rocks/docker/containers/raspberry/pi/rust/cross/compile/compilation/2018/12/16/rust-compilation-for-raspberry-pi.html). For pi 2 and 3, use armv7-unknown-linux-gnueabihf, and, for pi 1 and zero, use armv6-unknown-linux-gnueabihf (if you can find one, that is).
//! ## Contact
//! For questions, please email to Jack.Y.L.Dev@gmail.com


#[macro_use] extern crate log;

#[cfg(feature = "debug")]
use env_logger;

pub mod mailbox;
pub mod pi;

// if you wanna bind the process to core for better performance?
#[cfg(feature = "bind_process")]
pub mod pi_core;

/// use it to see traces when running
#[cfg(feature = "debug")]
pub fn enable_logger(){
    env_logger::Builder::new()
    .default_format()
    .default_format_module_path(false)
    .default_format_timestamp(false)
    .filter_level(log::LevelFilter::Warn)
    .filter_module("dma_gpio", log::LevelFilter::Trace)
    .init();
}