├── README ├── arduino_video_game ├── Demo │ └── Demo.pde └── Lc │ ├── Lc.pde │ ├── nunchuk.cpp │ └── nunchuk.h ├── hacking_arduino ├── part1 │ ├── HelloWorld │ │ ├── HelloWorld.pde │ │ └── Makefile │ ├── Makefile.master │ └── sample │ │ └── HelloWorld_pde.cpp └── part2 │ ├── Makefile.master │ ├── park_distance_control │ ├── Makefile │ ├── infrared_sensor.cpp │ ├── infrared_sensor.h │ ├── park_distance_control.pde │ ├── pdc.cpp │ ├── pdc.h │ ├── ring_buffer.h │ └── speaker.h │ └── pdc │ └── pdc.pde └── shootduino ├── assets ├── asteroid │ ├── asteroid_anim1.png │ ├── asteroid_anim1.wbmp │ ├── asteroid_anim2.png │ ├── asteroid_anim2.wbmp │ ├── asteroid_anim3.png │ └── asteroid_anim3.wbmp ├── explosion │ ├── explosion_anim1.png │ ├── explosion_anim1.wbmp │ ├── explosion_anim2.png │ ├── explosion_anim2.wbmp │ ├── explosion_anim3.png │ ├── explosion_anim3.wbmp │ ├── explosion_anim4.png │ └── explosion_anim4.wbmp ├── img2cpp.rb ├── spaceship.png └── spaceship.wbmp └── code ├── Shootduino ├── Shootduino.ino ├── gfx.cpp ├── gfx.h ├── joystick.cpp └── joystick.h └── Starfield └── Starfield.ino /README: -------------------------------------------------------------------------------- 1 | This repository contains all code I've needed for my PragPub articles. 2 | -------------------------------------------------------------------------------- /arduino_video_game/Demo/Demo.pde: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | const uint8_t WIDTH = 128; 6 | const uint8_t HEIGHT = 96; 7 | 8 | TVout tv; 9 | 10 | void setup() { 11 | tv.begin(PAL, WIDTH, HEIGHT); 12 | tv.select_font(font4x6); 13 | } 14 | 15 | void loop() { 16 | tv.clear_screen(); 17 | tv.print(0, 0, " Welcome to our little demo!"); 18 | delay(3000); 19 | tv.clear_screen(); 20 | tv.print(0, 0, " Let's draw a line:"); 21 | tv.draw_line(0, 10, WIDTH - 1, HEIGHT - 1, WHITE); 22 | delay(3000); 23 | tv.clear_screen(); 24 | tv.print(0, 0, " Now let's draw a rectangle:"); 25 | tv.draw_rect(0, 10, WIDTH - 11, HEIGHT - 11, WHITE); 26 | delay(3000); 27 | tv.clear_screen(); 28 | tv.print(0, 0, " And here we have a circle:"); 29 | tv.draw_circle(WIDTH / 2, HEIGHT / 2, 20, WHITE); 30 | delay(3000); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /arduino_video_game/Lc/Lc.pde: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "nunchuk.h" 6 | 7 | class Player { 8 | public: 9 | enum Direction { 10 | NORTH, WEST, EAST, SOUTH 11 | }; 12 | 13 | enum Behavior { 14 | MANUALLY, PREFERRED_ORDER 15 | }; 16 | 17 | uint8_t px, py; 18 | Direction direction; 19 | Behavior behavior; 20 | 21 | void move(void) { 22 | switch (direction) { 23 | case NORTH: py -= 1; break; 24 | case WEST: px -= 1; break; 25 | case EAST: px += 1; break; 26 | case SOUTH: py += 1; break; 27 | } 28 | } 29 | 30 | bool draw(TVout& tv) { 31 | if (tv.get_pixel(px, py) == 1) 32 | return true; 33 | tv.set_pixel(px, py, 1); 34 | return false; 35 | } 36 | 37 | void control(TVout& tv, const Nunchuk& controller) { 38 | switch (behavior) { 39 | case MANUALLY: 40 | control_manually(controller); 41 | break; 42 | case PREFERRED_ORDER: 43 | control_preferred_order(tv); 44 | break; 45 | } 46 | } 47 | 48 | private: 49 | 50 | void control_manually(const Nunchuk& controller) { 51 | if (controller.left()) { 52 | direction = WEST; 53 | } else if (controller.right()) { 54 | direction = EAST; 55 | } else if (controller.up()) { 56 | direction = NORTH; 57 | } else if (controller.down()) { 58 | direction = SOUTH; 59 | } 60 | } 61 | 62 | void control_preferred_order(TVout& tv) { 63 | if (is_passable(tv, NORTH)) 64 | direction = NORTH; 65 | else if (is_passable(tv, WEST)) 66 | direction = WEST; 67 | else if (is_passable(tv, EAST)) 68 | direction = EAST; 69 | else if (is_passable(tv, SOUTH)) 70 | direction = SOUTH; 71 | else 72 | direction = NORTH; 73 | } 74 | 75 | bool is_passable(TVout& tv, const uint8_t direction) { 76 | switch (direction) { 77 | case NORTH: return (tv.get_pixel(px, py - 1) == 0); 78 | case WEST: return (tv.get_pixel(px - 1, py) == 0); 79 | case EAST: return (tv.get_pixel(px + 1, py) == 0); 80 | case SOUTH: return (tv.get_pixel(px, py + 1) == 0); 81 | } 82 | } 83 | }; 84 | 85 | class Game { 86 | public: 87 | static const uint8_t SCREEN_WIDTH = 128; 88 | static const uint8_t SCREEN_HEIGHT = 96; 89 | static const uint8_t FONT_HEIGHT = 6; 90 | 91 | enum GameState { 92 | INTRO, STARTING, RUNNING, PAUSED, DONE 93 | }; 94 | 95 | void initialize() { 96 | reset_game(); 97 | _tv.begin(PAL, SCREEN_WIDTH, SCREEN_HEIGHT); 98 | _tv.select_font(font4x6); 99 | _controller.initialize(); 100 | } 101 | 102 | void reset_game(void) { 103 | _game_state = INTRO; 104 | _player1.px = SCREEN_WIDTH / 2 - 4; 105 | _player1.py = SCREEN_HEIGHT / 2; 106 | _player1.direction = Player::NORTH; 107 | _player1.behavior = Player::MANUALLY; 108 | _player2.px = SCREEN_WIDTH / 2 + 4; 109 | _player2.py = SCREEN_HEIGHT / 2; 110 | _player2.direction = Player::NORTH; 111 | _player2.behavior = Player::PREFERRED_ORDER; 112 | } 113 | 114 | void intro(void) { 115 | reset_game(); 116 | _tv.print(0, 20, " Arduino Light Cycle Race"); 117 | _tv.print(0, 46, " by Maik Schmidt"); 118 | _tv.print(0, 72, " Press Button to Start"); 119 | if (_controller.c_button()) { 120 | _game_state = STARTING; 121 | _tv.clear_screen(); 122 | _tv.draw_rect( 123 | 0, 0, 124 | SCREEN_WIDTH - 1, SCREEN_HEIGHT - 8, 125 | 1 126 | ); 127 | delay(150); 128 | } 129 | } 130 | 131 | void pause(void) { 132 | if (_controller.c_button()) { 133 | _game_state = RUNNING; 134 | print_message(" "); 135 | delay(150); 136 | } 137 | } 138 | 139 | void done(void) { 140 | if (_controller.c_button()) { 141 | _game_state = INTRO; 142 | _tv.clear_screen(); 143 | delay(150); 144 | } 145 | } 146 | 147 | void start(void) { 148 | _player1.draw(_tv); 149 | _player2.draw(_tv); 150 | print_message("3"); 151 | delay(1000); 152 | print_message("2"); 153 | delay(1000); 154 | print_message("1"); 155 | delay(1000); 156 | print_message("Go!"); 157 | delay(1000); 158 | print_message(" "); 159 | _game_state = RUNNING; 160 | } 161 | 162 | void play(void) { 163 | _player1.control(_tv, _controller); 164 | _player1.move(); 165 | const bool player1_hit = _player1.draw(_tv); 166 | _player2.control(_tv, _controller); 167 | _player2.move(); 168 | const bool player2_hit = _player2.draw(_tv); 169 | if (player1_hit && player2_hit) { 170 | _game_state = DONE; 171 | print_message("Tie Game"); 172 | delay(1000); 173 | } else if (player1_hit) { 174 | _game_state = DONE; 175 | print_message("You Lose!"); 176 | delay(1000); 177 | } else if (player2_hit) { 178 | _game_state = DONE; 179 | print_message("You Win!"); 180 | delay(1000); 181 | } 182 | if (_controller.c_button()) { 183 | _game_state = PAUSED; 184 | print_message("Paused"); 185 | delay(150); 186 | } 187 | } 188 | 189 | void run(void) { 190 | _controller.update(); 191 | switch (_game_state) { 192 | case INTRO: intro(); break; 193 | case PAUSED: pause(); break; 194 | case DONE: done(); break; 195 | case STARTING: start(); break; 196 | default: play(); break; 197 | } 198 | _tv.delay_frame(1); 199 | } 200 | 201 | private: 202 | 203 | void print_message(const char* message) { 204 | _tv.print( 205 | 0, 206 | SCREEN_HEIGHT - FONT_HEIGHT, 207 | message 208 | ); 209 | } 210 | 211 | GameState _game_state; 212 | TVout _tv; 213 | Nunchuk _controller; 214 | Player _player1, _player2; 215 | }; 216 | 217 | Game game; 218 | 219 | void setup() { 220 | game.initialize(); 221 | } 222 | 223 | void loop() { 224 | game.run(); 225 | } 226 | -------------------------------------------------------------------------------- /arduino_video_game/Lc/nunchuk.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "nunchuk.h" 4 | 5 | #define NUNCHUK_DEVICE_ID 0x52 6 | 7 | void Nunchuk::initialize() { 8 | Wire.begin(); 9 | Wire.beginTransmission(NUNCHUK_DEVICE_ID); 10 | Wire.send(0x40); 11 | Wire.send(0x00); 12 | Wire.endTransmission(); 13 | update(); 14 | } 15 | 16 | bool Nunchuk::update() { 17 | delay(1); 18 | Wire.requestFrom(NUNCHUK_DEVICE_ID, NUNCHUK_BUFFER_SIZE); 19 | int byte_counter = 0; 20 | while (Wire.available() && byte_counter < NUNCHUK_BUFFER_SIZE) 21 | _buffer[byte_counter++] = decode_byte(Wire.receive()); 22 | request_data(); 23 | return byte_counter == NUNCHUK_BUFFER_SIZE; 24 | } 25 | 26 | void Nunchuk::request_data() { 27 | Wire.beginTransmission(NUNCHUK_DEVICE_ID); 28 | Wire.send(0x00); 29 | Wire.endTransmission(); 30 | } 31 | 32 | char Nunchuk::decode_byte(const char b) { 33 | return (b ^ 0x17) + 0x17; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /arduino_video_game/Lc/nunchuk.h: -------------------------------------------------------------------------------- 1 | #define NUNCHUK_BUFFER_SIZE 6 2 | 3 | class Nunchuk { 4 | public: 5 | void initialize(); 6 | bool update(); 7 | 8 | int joystick_x() const { return _buffer[0]; } 9 | int joystick_y() const { return _buffer[1]; } 10 | 11 | bool left() const { return _buffer[0] < 50; } 12 | bool right() const { return _buffer[0] > 200; } 13 | bool up() const { return _buffer[1] > 200; } 14 | bool down() const { return _buffer[1] < 60; } 15 | 16 | int x_acceleration() const { 17 | return ((int)(_buffer[2]) << 2) | ((_buffer[5] >> 2) & 0x03); 18 | } 19 | 20 | int y_acceleration() const { 21 | return ((int)(_buffer[3]) << 2) | ((_buffer[5] >> 4) & 0x03); 22 | } 23 | 24 | int z_acceleration() const { 25 | return ((int)(_buffer[4]) << 2) | ((_buffer[5] >> 6) & 0x03); 26 | } 27 | 28 | bool z_button() const { return !(_buffer[5] & 0x01); } 29 | bool c_button() const { return !(_buffer[5] & 0x02); } 30 | 31 | private: 32 | void request_data(); 33 | char decode_byte(const char); 34 | 35 | unsigned char _buffer[NUNCHUK_BUFFER_SIZE]; 36 | }; 37 | 38 | -------------------------------------------------------------------------------- /hacking_arduino/part1/HelloWorld/HelloWorld.pde: -------------------------------------------------------------------------------- 1 | // START:main 2 | void setup() { 3 | Serial.begin(9600); 4 | } 5 | 6 | void loop() { 7 | Serial.println("Hello, world!"); 8 | delay(1000); 9 | } 10 | // END:main 11 | 12 | // vim:ft=arduino 13 | -------------------------------------------------------------------------------- /hacking_arduino/part1/HelloWorld/Makefile: -------------------------------------------------------------------------------- 1 | # Your Arduino environment. 2 | ARD_REV = 22 3 | ARD_HOME = /Applications/Arduino.app/Contents/Resources/Java 4 | AVR_HOME = $(ARD_HOME)/hardware/tools/avr 5 | ARD_BIN = $(AVR_HOME)/bin 6 | AVRDUDE = $(ARD_BIN)/avrdude 7 | AVRDUDE_CONF = $(AVR_HOME)/etc/avrdude.conf 8 | 9 | # Your favorite serial monitor. 10 | MON_CMD = screen 11 | MON_SPEED = 9600 12 | 13 | # Board settings. 14 | BOARD = diecimila 15 | PORT = /dev/tty.usbserial-A60061a3 16 | PROGRAMMER = stk500v1 17 | 18 | # Where to find header files and libraries. 19 | INC_DIRS = ./inc 20 | LIB_DIRS = $(addprefix $(ARD_HOME)/libraries/, $(LIBS)) 21 | LIBS = 22 | 23 | include ../Makefile.master 24 | 25 | -------------------------------------------------------------------------------- /hacking_arduino/part1/Makefile.master: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011 Alan Burlison, alan@bleaklow.com. All rights reserved. 3 | # Subsequently modified by Matthieu Weber, matthieu.weber@jyu.fi. 4 | # Use is subject to license terms. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are met: 8 | # 9 | # 1. Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # 12 | # 2. Redistributions in binary form must reproduce the above copyright notice, 13 | # this list of conditions and the following disclaimer in the documentation 14 | # and/or other materials provided with the distribution. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY ALAN BURLISON "AS IS" AND ANY EXPRESS OR IMPLIED 17 | # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | # EVENT SHALL ALAN BURLISON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 22 | # OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 25 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | # 27 | # Minor adjustments for Mac OS X and for educational purposes by Maik Schmidt, 28 | # contact@maik-schmidt.de. 29 | # 30 | # Makefile for building Arduino projects outside of the Arduino environment 31 | # 32 | # This makefile should be included into a per-project Makefile of the following 33 | # form: 34 | # 35 | # ---------- 36 | # BOARD = mega 37 | # PORT = /dev/term/0 38 | # INC_DIRS = ../common 39 | # LIB_DIRS = ../libraries/Task ../../libraries/VirtualWire 40 | # include ../../Makefile.master 41 | # ---------- 42 | # 43 | # Where: 44 | # BOARD : Arduino board type, from $(ARD_HOME)/hardware/boards.txt 45 | # PORT : USB port 46 | # INC_DIRS : List pf directories containing header files 47 | # LIB_DIRS : List of directories containing library source 48 | # 49 | # Before using this Makefile you can adjust the following macros to suit 50 | # your environment, either by editing this file directly or by defining them in 51 | # the Makefile that includes this one, in which case they will override the 52 | # definitions below: 53 | # ARD_REV : arduino software revision, e.g. 0017, 0018 54 | # ARD_HOME : installation directory of the Arduino software. 55 | # ARD_BIN : location of compiler binaries 56 | # AVRDUDE : location of avrdude executable 57 | # AVRDUDE_CONF : location of avrdude configuration file 58 | # PROGRAMMER : avrdude programmer type 59 | # MON_CMD : serial monitor command 60 | # MON_SPEED : serial monitor speed 61 | # 62 | 63 | # Global configuration. 64 | ARD_REV ?= 0022 65 | ARD_HOME ?= /Applications/Arduino.app/Contents/Resources/Java 66 | ARD_BIN ?= /usr/local/CrossPack-AVR/bin 67 | AVRDUDE ?= $(ARD_HOME)/hardware/tools/avr/bin/avrdude 68 | AVRDUDE_CONF ?= $(ARD_HOME)/hardware/tools/avr/etc/avrdude.conf 69 | PROGRAMMER ?= stk500v1 70 | MON_SPEED ?= 57600 71 | MON_CMD ?= picocom 72 | PORT ?= /dev/tty.usbserial-A60061a3 73 | BOARD ?= atmega328 74 | 75 | ### Nothing below here should require editing. ### 76 | 77 | # Check for the required definitions. 78 | 79 | ifndef BOARD 80 | $(error $$(BOARD) not defined) 81 | endif 82 | ifndef PORT 83 | $(error $$(PORT) not defined) 84 | endif 85 | 86 | # Version-specific settings 87 | ARD_BOARDS = $(ARD_HOME)/hardware/arduino/boards.txt 88 | ARD_SRC_DIR = $(ARD_HOME)/hardware/arduino/cores/arduino 89 | ARD_MAIN = $(ARD_SRC_DIR)/main.cpp 90 | 91 | # Standard macros. 92 | SKETCH = $(notdir $(CURDIR)) 93 | BUILD_DIR = build 94 | VPATH = $(LIB_DIRS) 95 | 96 | # Macros derived from boards.txt 97 | MCU := $(shell sed -n 's/$(BOARD)\.build\.mcu=\(.*\)/\1/p' < $(ARD_BOARDS)) 98 | F_CPU := $(shell sed -n 's/$(BOARD)\.build\.f_cpu=\(.*\)/\1/p' < $(ARD_BOARDS)) 99 | UPLOAD_SPEED := \ 100 | $(shell sed -n 's/$(BOARD)\.upload\.speed=\(.*\)/\1/p' < $(ARD_BOARDS)) 101 | 102 | # Build tools. 103 | CC = $(ARD_BIN)/avr-gcc 104 | CXX = $(ARD_BIN)/avr-g++ 105 | CXXFILT = $(ARD_BIN)/avr-c++filt 106 | OBJCOPY = $(ARD_BIN)/avr-objcopy 107 | OBJDUMP = $(ARD_BIN)/avr-objdump 108 | AR = $(ARD_BIN)/avr-ar 109 | SIZE = $(ARD_BIN)/avr-size 110 | NM = $(ARD_BIN)/avr-nm 111 | MKDIR = mkdir -p 112 | RM = rm -rf 113 | MV = mv -f 114 | LN = ln -f 115 | 116 | # Compiler flags. 117 | INC_FLAGS = \ 118 | $(addprefix -I,$(INC_DIRS)) $(addprefix -I,$(LIB_DIRS)) -I$(ARD_SRC_DIR) 119 | ARD_FLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU) -DARDUINO=$(ARD_REV) 120 | C_CXX_FLAGS = \ 121 | -Wall -Wextra -Wundef -Wno-unused-parameter \ 122 | -fdiagnostics-show-option -g -Wa,-adhlns=$(BUILD_DIR)/$*.lst 123 | C_FLAGS = \ 124 | $(C_CXX_FLAGS) -std=gnu99 -Wstrict-prototypes -Wno-old-style-declaration 125 | CXX_FLAGS = $(C_CXX_FLAGS) 126 | 127 | # Optimiser flags. 128 | # optimise for size, unsigned by default, pack data. 129 | # separate sections, drop unused ones, shorten branches, jumps. 130 | # don't inline, vectorise loops. no exceptions. 131 | # no os preamble, use function calls in prologues. 132 | # http://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc/ 133 | # http://www.tty1.net/blog/2008-04-29-avr-gcc-optimisations_en.html 134 | OPT_FLAGS = \ 135 | -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \ 136 | -ffunction-sections -fdata-sections -Wl,--gc-sections,--relax \ 137 | -fno-inline-small-functions -fno-tree-scev-cprop -fno-exceptions \ 138 | -ffreestanding -mcall-prologues 139 | 140 | # Build parameters. 141 | IMAGE = $(BUILD_DIR)/$(SKETCH) 142 | ARD_C_SRC = $(wildcard $(ARD_SRC_DIR)/*.c) 143 | ARD_CXX_SRC = $(wildcard $(ARD_SRC_DIR)/*.cpp) 144 | ARD_C_OBJ = $(patsubst %.c,%.o,$(notdir $(ARD_C_SRC))) 145 | ARD_CXX_OBJ = $(patsubst %.cpp,%.o,$(notdir $(ARD_CXX_SRC))) 146 | ARD_LIB = arduino 147 | ARD_AR = $(BUILD_DIR)/lib$(ARD_LIB).a 148 | ARD_AR_OBJ = $(ARD_AR)($(ARD_C_OBJ) $(ARD_CXX_OBJ)) 149 | ARD_LD_FLAG = -l$(ARD_LIB) 150 | 151 | # Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734 152 | $(ARD_AR)(Tone.o) : CXX_FLAGS += -w 153 | 154 | # Sketch libraries. 155 | LIB_C_SRC = $(foreach ld,$(LIB_DIRS),$(wildcard $(ld)/*.c)) 156 | LIB_CXX_SRC = $(foreach ld,$(LIB_DIRS),$(wildcard $(ld)/*.cpp)) 157 | LIB_SRC = $(LIB_C_SRC) $(LIB_CXX_SRC) 158 | ifneq "$(strip $(LIB_C_SRC) $(LIB_CXX_SRC))" "" 159 | LIB_C_OBJ = $(patsubst %.c,%.o,$(notdir $(LIB_C_SRC))) 160 | LIB_CXX_OBJ = $(patsubst %.cpp,%.o,$(notdir $(LIB_CXX_SRC))) 161 | LIB_LIB = library 162 | LIB_AR = $(BUILD_DIR)/lib$(LIB_LIB).a 163 | LIB_AR_OBJ = $(LIB_AR)($(LIB_C_OBJ)$(LIB_CXX_OBJ)) 164 | LIB_LD_FLAG = -l$(LIB_LIB) 165 | endif 166 | 167 | # Sketch PDE source. 168 | SKT_PDE_SRC = $(wildcard *.pde) 169 | ifneq "$(strip $(SKT_PDE_SRC))" "" 170 | SKT_PDE_OBJ = $(BUILD_DIR)/$(SKETCH)_pde.o 171 | endif 172 | 173 | # C and C++ source. 174 | SKT_C_SRC = $(wildcard *.c) 175 | SKT_CXX_SRC = $(wildcard *.cpp) 176 | ifneq "$(strip $(SKT_C_SRC) $(SKT_CXX_SRC))" "" 177 | SKT_C_OBJ = $(patsubst %.c,%.o,$(SKT_C_SRC)) 178 | SKT_CXX_OBJ = $(patsubst %.cpp,%.o,$(SKT_CXX_SRC)) 179 | SKT_LIB = sketch 180 | SKT_AR = $(BUILD_DIR)/lib$(SKT_LIB).a 181 | SKT_AR_OBJ = $(SKT_AR)($(SKT_C_OBJ) $(SKT_CXX_OBJ)) 182 | SKT_LD_FLAG = -l$(SKT_LIB) 183 | endif 184 | 185 | # Definitions. 186 | define run-cc 187 | @ $(CC) $(ARD_FLAGS) $(INC_FLAGS) -M -MT '$@($%)' -MF $@_$*.dep $< 188 | $(CC) -c $(C_FLAGS) $(OPT_FLAGS) $(ARD_FLAGS) $(INC_FLAGS) \ 189 | $< -o $(BUILD_DIR)/$% 190 | @ $(AR) rc $@ $(BUILD_DIR)/$% 191 | @ $(RM) $(BUILD_DIR)/$% 192 | @ $(CXXFILT) < $(BUILD_DIR)/$*.lst > $(BUILD_DIR)/$*.lst.tmp 193 | @ $(MV) $(BUILD_DIR)/$*.lst.tmp $(BUILD_DIR)/$*.lst 194 | endef 195 | 196 | define run-cxx 197 | @ $(CXX) $(ARD_FLAGS) $(INC_FLAGS) -M -MT '$@($%)' -MF $@_$*.dep $< 198 | $(CXX) -c $(CXX_FLAGS) $(OPT_FLAGS) $(ARD_FLAGS) $(INC_FLAGS) \ 199 | $< -o $(BUILD_DIR)/$% 200 | @ $(AR) rc $@ $(BUILD_DIR)/$% 201 | @ $(RM) $(BUILD_DIR)/$% 202 | @ $(CXXFILT) < $(BUILD_DIR)/$*.lst > $(BUILD_DIR)/$*.lst.tmp 203 | @ $(MV) $(BUILD_DIR)/$*.lst.tmp $(BUILD_DIR)/$*.lst 204 | endef 205 | 206 | # Rules. 207 | .PHONY : all clean upload monitor upload_monitor 208 | 209 | all : $(BUILD_DIR) $(IMAGE).hex 210 | 211 | clean : 212 | $(RM) $(BUILD_DIR) 213 | 214 | $(BUILD_DIR) : 215 | $(MKDIR) $@ 216 | 217 | $(SKT_PDE_OBJ) : $(SKT_PDE_SRC) 218 | echo '#include ' > $(BUILD_DIR)/$(SKETCH)_pde.cpp 219 | echo '#include "$(SKT_PDE_SRC)"' >> $(BUILD_DIR)/$(SKETCH)_pde.cpp 220 | $(LN) $(SKT_PDE_SRC) $(BUILD_DIR)/$(SKT_PDE_SRC) 221 | cd $(BUILD_DIR) && $(CXX) -c $(subst build/,,$(CXX_FLAGS)) \ 222 | $(OPT_FLAGS) $(ARD_FLAGS) -I.. \ 223 | $(patsubst -I..%,-I../..%,$(INC_FLAGS)) \ 224 | $(SKETCH)_pde.cpp -o $(@F) 225 | 226 | (%.o) : $(ARD_SRC_DIR)/%.c 227 | $(run-cc) 228 | 229 | (%.o) : $(ARD_SRC_DIR)/%.cpp 230 | $(run-cxx) 231 | 232 | (%.o) : %.c 233 | $(run-cc) 234 | 235 | (%.o) : %.cpp 236 | $(run-cxx) 237 | 238 | $(BUILD_DIR)/%.d : %.c 239 | $(run-cc-d) 240 | 241 | $(BUILD_DIR)/%.d : %.cpp 242 | $(run-cxx-d) 243 | 244 | $(IMAGE).hex : $(ARD_AR_OBJ) $(LIB_AR_OBJ) $(SKT_AR_OBJ) $(SKT_PDE_OBJ) 245 | $(CC) $(CXX_FLAGS) $(OPT_FLAGS) $(ARD_FLAGS) -L$(BUILD_DIR) \ 246 | $(SKT_PDE_OBJ) $(SKT_LD_FLAG) $(LIB_LD_FLAG) $(ARD_LD_FLAG) -lm \ 247 | -o $(IMAGE).elf 248 | $(OBJCOPY) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load \ 249 | --no-change-warnings --change-section-lma .eeprom=0 $(IMAGE).elf \ 250 | $(IMAGE).eep 251 | $(OBJCOPY) -O ihex -R .eeprom $(IMAGE).elf $(IMAGE).hex 252 | $(OBJDUMP) -h -S $(IMAGE).elf | $(CXXFILT) -t > $(IMAGE).lst 253 | $(SIZE) $(IMAGE).hex 254 | 255 | # START:makemods 256 | upload : all 257 | - pkill -f '$(MON_CMD).*$(PORT)' 258 | - sleep 1 259 | - stty -f $(PORT) hupcl 260 | - $(AVRDUDE) -V -C$(AVRDUDE_CONF) -p$(MCU) -c$(PROGRAMMER) \ 261 | -P$(PORT) -b$(UPLOAD_SPEED) -D -Uflash:w:$(IMAGE).hex:i 262 | 263 | monitor : 264 | $(MON_CMD) $(PORT) $(MON_SPEED) 265 | # END:makemods 266 | 267 | upload_monitor : upload monitor 268 | 269 | -include $(wildcard $(BUILD_DIR)/*.dep)) 270 | 271 | # vim:ft=make 272 | -------------------------------------------------------------------------------- /hacking_arduino/part1/sample/HelloWorld_pde.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "HelloWorld.pde" 3 | -------------------------------------------------------------------------------- /hacking_arduino/part2/Makefile.master: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011 Alan Burlison, alan@bleaklow.com. All rights reserved. 3 | # Subsequently modified by Matthieu Weber, matthieu.weber@jyu.fi. 4 | # Use is subject to license terms. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are met: 8 | # 9 | # 1. Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # 12 | # 2. Redistributions in binary form must reproduce the above copyright notice, 13 | # this list of conditions and the following disclaimer in the documentation 14 | # and/or other materials provided with the distribution. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY ALAN BURLISON "AS IS" AND ANY EXPRESS OR IMPLIED 17 | # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | # EVENT SHALL ALAN BURLISON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 22 | # OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 25 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | # 27 | # Minor adjustments for Mac OS X and for educational purposes by Maik Schmidt, 28 | # contact@maik-schmidt.de. 29 | # 30 | # Makefile for building Arduino projects outside of the Arduino environment 31 | # 32 | # This makefile should be included into a per-project Makefile of the following 33 | # form: 34 | # 35 | # ---------- 36 | # BOARD = mega 37 | # PORT = /dev/term/0 38 | # INC_DIRS = ../common 39 | # LIB_DIRS = ../libraries/Task ../../libraries/VirtualWire 40 | # include ../../Makefile.master 41 | # ---------- 42 | # 43 | # Where: 44 | # BOARD : Arduino board type, from $(ARD_HOME)/hardware/boards.txt 45 | # PORT : USB port 46 | # INC_DIRS : List pf directories containing header files 47 | # LIB_DIRS : List of directories containing library source 48 | # 49 | # Before using this Makefile you can adjust the following macros to suit 50 | # your environment, either by editing this file directly or by defining them in 51 | # the Makefile that includes this one, in which case they will override the 52 | # definitions below: 53 | # ARD_REV : arduino software revision, e.g. 0017, 0018 54 | # ARD_HOME : installation directory of the Arduino software. 55 | # ARD_BIN : location of compiler binaries 56 | # AVRDUDE : location of avrdude executable 57 | # AVRDUDE_CONF : location of avrdude configuration file 58 | # PROGRAMMER : avrdude programmer type 59 | # MON_CMD : serial monitor command 60 | # MON_SPEED : serial monitor speed 61 | # 62 | 63 | # Global configuration. 64 | ARD_REV ?= 0022 65 | ARD_HOME ?= /Applications/Arduino.app/Contents/Resources/Java 66 | ARD_BIN ?= /usr/local/CrossPack-AVR/bin 67 | AVRDUDE ?= $(ARD_HOME)/hardware/tools/avr/bin/avrdude 68 | AVRDUDE_CONF ?= $(ARD_HOME)/hardware/tools/avr/etc/avrdude.conf 69 | PROGRAMMER ?= stk500v1 70 | MON_SPEED ?= 57600 71 | MON_CMD ?= picocom 72 | PORT ?= /dev/tty.usbserial-A60061a3 73 | BOARD ?= atmega328 74 | 75 | ### Nothing below here should require editing. ### 76 | 77 | # Check for the required definitions. 78 | 79 | ifndef BOARD 80 | $(error $$(BOARD) not defined) 81 | endif 82 | ifndef PORT 83 | $(error $$(PORT) not defined) 84 | endif 85 | 86 | # Version-specific settings 87 | ARD_BOARDS = $(ARD_HOME)/hardware/arduino/boards.txt 88 | ARD_SRC_DIR = $(ARD_HOME)/hardware/arduino/cores/arduino 89 | ARD_MAIN = $(ARD_SRC_DIR)/main.cpp 90 | 91 | # Standard macros. 92 | SKETCH = $(notdir $(CURDIR)) 93 | BUILD_DIR = build 94 | VPATH = $(LIB_DIRS) 95 | 96 | # Macros derived from boards.txt 97 | MCU := $(shell sed -n 's/$(BOARD)\.build\.mcu=\(.*\)/\1/p' < $(ARD_BOARDS)) 98 | F_CPU := $(shell sed -n 's/$(BOARD)\.build\.f_cpu=\(.*\)/\1/p' < $(ARD_BOARDS)) 99 | UPLOAD_SPEED := \ 100 | $(shell sed -n 's/$(BOARD)\.upload\.speed=\(.*\)/\1/p' < $(ARD_BOARDS)) 101 | 102 | # Build tools. 103 | CC = $(ARD_BIN)/avr-gcc 104 | CXX = $(ARD_BIN)/avr-g++ 105 | CXXFILT = $(ARD_BIN)/avr-c++filt 106 | OBJCOPY = $(ARD_BIN)/avr-objcopy 107 | OBJDUMP = $(ARD_BIN)/avr-objdump 108 | AR = $(ARD_BIN)/avr-ar 109 | SIZE = $(ARD_BIN)/avr-size 110 | NM = $(ARD_BIN)/avr-nm 111 | MKDIR = mkdir -p 112 | RM = rm -rf 113 | MV = mv -f 114 | LN = ln -f 115 | 116 | # Compiler flags. 117 | INC_FLAGS = \ 118 | $(addprefix -I,$(INC_DIRS)) $(addprefix -I,$(LIB_DIRS)) -I$(ARD_SRC_DIR) 119 | ARD_FLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU) -DARDUINO=$(ARD_REV) 120 | C_CXX_FLAGS = \ 121 | -Wall -Wextra -Wundef -Wno-unused-parameter \ 122 | -fdiagnostics-show-option -g -Wa,-adhlns=$(BUILD_DIR)/$*.lst 123 | C_FLAGS = \ 124 | $(C_CXX_FLAGS) -std=gnu99 -Wstrict-prototypes -Wno-old-style-declaration 125 | CXX_FLAGS = $(C_CXX_FLAGS) 126 | 127 | # Optimiser flags. 128 | # optimise for size, unsigned by default, pack data. 129 | # separate sections, drop unused ones, shorten branches, jumps. 130 | # don't inline, vectorise loops. no exceptions. 131 | # no os preamble, use function calls in prologues. 132 | # http://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc/ 133 | # http://www.tty1.net/blog/2008-04-29-avr-gcc-optimisations_en.html 134 | OPT_FLAGS = \ 135 | -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \ 136 | -ffunction-sections -fdata-sections -Wl,--gc-sections,--relax \ 137 | -fno-inline-small-functions -fno-tree-scev-cprop -fno-exceptions \ 138 | -ffreestanding -mcall-prologues 139 | 140 | # Build parameters. 141 | IMAGE = $(BUILD_DIR)/$(SKETCH) 142 | ARD_C_SRC = $(wildcard $(ARD_SRC_DIR)/*.c) 143 | ARD_CXX_SRC = $(wildcard $(ARD_SRC_DIR)/*.cpp) 144 | ARD_C_OBJ = $(patsubst %.c,%.o,$(notdir $(ARD_C_SRC))) 145 | ARD_CXX_OBJ = $(patsubst %.cpp,%.o,$(notdir $(ARD_CXX_SRC))) 146 | ARD_LIB = arduino 147 | ARD_AR = $(BUILD_DIR)/lib$(ARD_LIB).a 148 | ARD_AR_OBJ = $(ARD_AR)($(ARD_C_OBJ) $(ARD_CXX_OBJ)) 149 | ARD_LD_FLAG = -l$(ARD_LIB) 150 | 151 | # Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734 152 | $(ARD_AR)(Tone.o) : CXX_FLAGS += -w 153 | 154 | # Sketch libraries. 155 | LIB_C_SRC = $(foreach ld,$(LIB_DIRS),$(wildcard $(ld)/*.c)) 156 | LIB_CXX_SRC = $(foreach ld,$(LIB_DIRS),$(wildcard $(ld)/*.cpp)) 157 | LIB_SRC = $(LIB_C_SRC) $(LIB_CXX_SRC) 158 | ifneq "$(strip $(LIB_C_SRC) $(LIB_CXX_SRC))" "" 159 | LIB_C_OBJ = $(patsubst %.c,%.o,$(notdir $(LIB_C_SRC))) 160 | LIB_CXX_OBJ = $(patsubst %.cpp,%.o,$(notdir $(LIB_CXX_SRC))) 161 | LIB_LIB = library 162 | LIB_AR = $(BUILD_DIR)/lib$(LIB_LIB).a 163 | LIB_AR_OBJ = $(LIB_AR)($(LIB_C_OBJ) $(LIB_CXX_OBJ)) 164 | LIB_LD_FLAG = -l$(LIB_LIB) 165 | endif 166 | 167 | # Sketch PDE source. 168 | SKT_PDE_SRC = $(wildcard *.pde) 169 | ifneq "$(strip $(SKT_PDE_SRC))" "" 170 | SKT_PDE_OBJ = $(BUILD_DIR)/$(SKETCH)_pde.o 171 | endif 172 | 173 | # C and C++ source. 174 | SKT_C_SRC = $(wildcard *.c) 175 | SKT_CXX_SRC = $(wildcard *.cpp) 176 | ifneq "$(strip $(SKT_C_SRC) $(SKT_CXX_SRC))" "" 177 | SKT_C_OBJ = $(patsubst %.c,%.o,$(SKT_C_SRC)) 178 | SKT_CXX_OBJ = $(patsubst %.cpp,%.o,$(SKT_CXX_SRC)) 179 | SKT_LIB = sketch 180 | SKT_AR = $(BUILD_DIR)/lib$(SKT_LIB).a 181 | SKT_AR_OBJ = $(SKT_AR)($(SKT_C_OBJ) $(SKT_CXX_OBJ)) 182 | SKT_LD_FLAG = -l$(SKT_LIB) 183 | endif 184 | 185 | # Definitions. 186 | define run-cc 187 | @ $(CC) $(ARD_FLAGS) $(INC_FLAGS) -M -MT '$@($%)' -MF $@_$*.dep $< 188 | $(CC) -c $(C_FLAGS) $(OPT_FLAGS) $(ARD_FLAGS) $(INC_FLAGS) \ 189 | $< -o $(BUILD_DIR)/$% 190 | @ $(AR) rc $@ $(BUILD_DIR)/$% 191 | @ $(RM) $(BUILD_DIR)/$% 192 | @ $(CXXFILT) < $(BUILD_DIR)/$*.lst > $(BUILD_DIR)/$*.lst.tmp 193 | @ $(MV) $(BUILD_DIR)/$*.lst.tmp $(BUILD_DIR)/$*.lst 194 | endef 195 | 196 | define run-cxx 197 | @ $(CXX) $(ARD_FLAGS) $(INC_FLAGS) -M -MT '$@($%)' -MF $@_$*.dep $< 198 | $(CXX) -c $(CXX_FLAGS) $(OPT_FLAGS) $(ARD_FLAGS) $(INC_FLAGS) \ 199 | $< -o $(BUILD_DIR)/$% 200 | @ $(AR) rc $@ $(BUILD_DIR)/$% 201 | @ $(RM) $(BUILD_DIR)/$% 202 | @ $(CXXFILT) < $(BUILD_DIR)/$*.lst > $(BUILD_DIR)/$*.lst.tmp 203 | @ $(MV) $(BUILD_DIR)/$*.lst.tmp $(BUILD_DIR)/$*.lst 204 | endef 205 | 206 | # Rules. 207 | .PHONY : all clean upload monitor upload_monitor 208 | 209 | all : $(BUILD_DIR) $(IMAGE).hex 210 | 211 | clean : 212 | $(RM) $(BUILD_DIR) 213 | 214 | $(BUILD_DIR) : 215 | $(MKDIR) $@ 216 | 217 | $(SKT_PDE_OBJ) : $(SKT_PDE_SRC) 218 | echo '#include ' > $(BUILD_DIR)/$(SKETCH)_pde.cpp 219 | echo '#include "$(SKT_PDE_SRC)"' >> $(BUILD_DIR)/$(SKETCH)_pde.cpp 220 | $(LN) $(SKT_PDE_SRC) $(BUILD_DIR)/$(SKT_PDE_SRC) 221 | cd $(BUILD_DIR) && $(CXX) -c $(subst build/,,$(CXX_FLAGS)) \ 222 | $(OPT_FLAGS) $(ARD_FLAGS) -I.. \ 223 | $(patsubst -I..%,-I../..%,$(INC_FLAGS)) \ 224 | $(SKETCH)_pde.cpp -o $(@F) 225 | 226 | (%.o) : $(ARD_SRC_DIR)/%.c 227 | $(run-cc) 228 | 229 | (%.o) : $(ARD_SRC_DIR)/%.cpp 230 | $(run-cxx) 231 | 232 | (%.o) : %.c 233 | $(run-cc) 234 | 235 | (%.o) : %.cpp 236 | $(run-cxx) 237 | 238 | $(BUILD_DIR)/%.d : %.c 239 | $(run-cc-d) 240 | 241 | $(BUILD_DIR)/%.d : %.cpp 242 | $(run-cxx-d) 243 | 244 | $(IMAGE).hex : $(ARD_AR_OBJ) $(LIB_AR_OBJ) $(SKT_AR_OBJ) $(SKT_PDE_OBJ) 245 | $(CC) $(CXX_FLAGS) $(OPT_FLAGS) $(ARD_FLAGS) -L$(BUILD_DIR) \ 246 | $(SKT_PDE_OBJ) $(SKT_LD_FLAG) $(LIB_LD_FLAG) $(ARD_LD_FLAG) -lm \ 247 | -o $(IMAGE).elf 248 | $(OBJCOPY) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load \ 249 | --no-change-warnings --change-section-lma .eeprom=0 $(IMAGE).elf \ 250 | $(IMAGE).eep 251 | $(OBJCOPY) -O ihex -R .eeprom $(IMAGE).elf $(IMAGE).hex 252 | $(OBJDUMP) -h -S $(IMAGE).elf | $(CXXFILT) -t > $(IMAGE).lst 253 | $(SIZE) $(IMAGE).hex 254 | 255 | # START:makemods 256 | upload : all 257 | - pkill -f '$(MON_CMD).*$(PORT)' 258 | - sleep 1 259 | - stty -f $(PORT) hupcl 260 | - $(AVRDUDE) -V -C$(AVRDUDE_CONF) -p$(MCU) -c$(PROGRAMMER) -P$(PORT) \ 261 | -b$(UPLOAD_SPEED) -D -Uflash:w:$(IMAGE).hex:i 262 | 263 | monitor : 264 | $(MON_CMD) $(PORT) $(MON_SPEED) 265 | # END:makemods 266 | 267 | upload_monitor : upload monitor 268 | 269 | -include $(wildcard $(BUILD_DIR)/*.dep)) 270 | 271 | # vim:ft=make 272 | -------------------------------------------------------------------------------- /hacking_arduino/part2/park_distance_control/Makefile: -------------------------------------------------------------------------------- 1 | ARD_REV = 22 2 | ARD_HOME = /Applications/Arduino.app/Contents/Resources/Java 3 | AVR_HOME = $(ARD_HOME)/hardware/tools/avr 4 | ARD_BIN = $(AVR_HOME)/bin 5 | AVRDUDE = $(ARD_BIN)/avrdude 6 | AVRDUDE_CONF = $(AVR_HOME)/etc/avrdude.conf 7 | PROGRAMMER = stk500v1 8 | MON_CMD = screen 9 | MON_SPEED = 57600 10 | PORT = /dev/tty.usbmodemfa141 11 | BOARD = uno 12 | LIB_DIRS = $(addprefix $(ARD_HOME)/libraries/, $(LIBS)) 13 | include ../Makefile.master 14 | 15 | -------------------------------------------------------------------------------- /hacking_arduino/part2/park_distance_control/infrared_sensor.cpp: -------------------------------------------------------------------------------- 1 | // START:main 2 | #include 3 | #include 4 | #include "infrared_sensor.h" 5 | 6 | namespace arduino { 7 | namespace sensors { 8 | InfraredSensor::InfraredSensor(const uint8_t pin) : _pin(pin) { 9 | for (uint16_t i = 0; i < _buffer.getBufferSize(); i++) 10 | update(); 11 | } 12 | 13 | void InfraredSensor::update(void) { 14 | _buffer.addValue(analogRead(_pin)); 15 | } 16 | 17 | float InfraredSensor::getDistance(void) const { 18 | const float voltage = 19 | _buffer.getAverageValue() * SUPPLY_VOLTAGE / 1024.0; 20 | return VOLTS_PER_CM / voltage; 21 | } 22 | } 23 | } 24 | // END:main 25 | 26 | // vim:ft=arduino 27 | -------------------------------------------------------------------------------- /hacking_arduino/part2/park_distance_control/infrared_sensor.h: -------------------------------------------------------------------------------- 1 | #ifndef INFRARED_SENSOR 2 | #define INFRARED_SENSOR 3 | 4 | // START:main 5 | #include 6 | #include "ring_buffer.h" 7 | 8 | using namespace arduino::util; 9 | 10 | namespace arduino { 11 | namespace sensors { 12 | class InfraredSensor { 13 | private: 14 | uint8_t _pin; 15 | RingBuffer _buffer; 16 | public: 17 | static const float SUPPLY_VOLTAGE = 4.7; 18 | static const float VOLTS_PER_CM = 27.0; 19 | 20 | InfraredSensor(const uint8_t pin); 21 | 22 | void update(void); 23 | float getDistance(void) const; 24 | }; 25 | } 26 | } 27 | // END:main 28 | 29 | #endif 30 | 31 | // vim:ft=arduino 32 | -------------------------------------------------------------------------------- /hacking_arduino/part2/park_distance_control/park_distance_control.pde: -------------------------------------------------------------------------------- 1 | // START:main 2 | #include 3 | #include "pdc.h" 4 | 5 | const uint16_t BAUD_RATE = 57600; 6 | const uint8_t IR_SENSOR_PIN = A0; 7 | const uint8_t SPEAKER_PIN = 13; 8 | const float MOUNTING_GAP = 3.0; 9 | 10 | arduino::ParkDistanceControl pdc( 11 | InfraredSensor(IR_SENSOR_PIN), 12 | Speaker(SPEAKER_PIN), 13 | MOUNTING_GAP 14 | ); 15 | 16 | void setup(void) { 17 | Serial.begin(BAUD_RATE); 18 | } 19 | 20 | void loop(void) { 21 | pdc.check(); 22 | delay(50); 23 | } 24 | // END:main 25 | 26 | // vim:ft=arduino 27 | -------------------------------------------------------------------------------- /hacking_arduino/part2/park_distance_control/pdc.cpp: -------------------------------------------------------------------------------- 1 | // START:main 2 | #include 3 | #include "pdc.h" 4 | 5 | namespace arduino { 6 | void ParkDistanceControl::check(void) { 7 | _ir_sensor.update(); 8 | const float distance = 9 | _ir_sensor.getDistance() - _mounting_gap; 10 | if (distance <= MIN_DISTANCE) { 11 | Serial.println("Too close!"); 12 | _speaker.beep(); 13 | } else if (distance >= MAX_DISTANCE) { 14 | Serial.println("OK."); 15 | } else { 16 | Serial.print(distance); 17 | Serial.println(" cm"); 18 | } 19 | } 20 | } 21 | // END:main 22 | 23 | // vim:ft=arduino 24 | -------------------------------------------------------------------------------- /hacking_arduino/part2/park_distance_control/pdc.h: -------------------------------------------------------------------------------- 1 | #ifndef PARK_DISTANCE_CONTROL 2 | #define PARK_DISTANCE_CONTROL 3 | 4 | // START:main 5 | #include "infrared_sensor.h" 6 | #include "speaker.h" 7 | 8 | using namespace arduino::sensors; 9 | using namespace arduino::actuators; 10 | 11 | namespace arduino { 12 | class ParkDistanceControl { 13 | private: 14 | InfraredSensor _ir_sensor; 15 | Speaker _speaker; 16 | float _mounting_gap; 17 | public: 18 | static const float MIN_DISTANCE = 8.0; 19 | static const float MAX_DISTANCE = 80.0; 20 | 21 | ParkDistanceControl( 22 | const InfraredSensor& ir_sensor, 23 | const Speaker& speaker, 24 | const float mounting_gap = 0.0) : 25 | _ir_sensor(ir_sensor), 26 | _speaker(speaker), 27 | _mounting_gap(mounting_gap) {} 28 | 29 | void check(void); 30 | }; 31 | } 32 | // END:main 33 | 34 | #endif 35 | 36 | // vim:ft=arduino 37 | -------------------------------------------------------------------------------- /hacking_arduino/part2/park_distance_control/ring_buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef RING_BUFFER 2 | #define RING_BUFFER 3 | 4 | #include 5 | #include 6 | 7 | // START:main 8 | namespace arduino { 9 | namespace util { 10 | template //