├── .gitignore ├── api ├── .gitignore ├── .htpasswd ├── public │ ├── assets │ │ ├── jquery-3.2.1.min.js │ │ ├── styles.css │ │ └── jscookie.js │ ├── admin │ │ ├── .htaccess │ │ ├── save-pump.php │ │ ├── enable-recipe.php │ │ ├── create-recipe.php │ │ ├── index.php │ │ ├── add.php │ │ ├── save-ingredients.php │ │ ├── pumps.php │ │ ├── recipe.php │ │ ├── import-recipe.php │ │ └── recipes.php │ ├── queue │ │ ├── status.php │ │ ├── delete.php │ │ ├── queue.php │ │ ├── current.php │ │ ├── index.php │ │ └── start.php │ ├── log │ │ ├── billable.php │ │ ├── README.txt │ │ └── index.php │ ├── enqueue.php │ ├── manual │ │ ├── queue.php │ │ └── index.php │ ├── api.php │ └── index.php ├── scripts │ ├── init.php │ ├── manual.php │ ├── test-daemon.php │ └── barbot-daemon.php ├── composer.json ├── lib │ ├── config.template.php │ └── helpers.php ├── config │ ├── 001-barbot.conf │ └── barbot ├── db │ └── schema.sql └── composer.lock └── Arduino ├── CapacitiveSensor ├── README.md ├── keywords.txt ├── CapacitiveSensor.h ├── examples │ └── piccolino_touch │ │ └── piccolino_touch.ino └── CapacitiveSensor.cpp ├── HX711 ├── .gitignore ├── examples │ └── HX711Serial │ │ └── HX711Serial.ino ├── HX711.cpp ├── HX711.h ├── README.md └── LICENSE ├── Piccolino_RAM ├── .gitattributes ├── examples │ └── piccolino_ram_test │ │ └── piccolino_ram_test.ino ├── keywords.txt ├── .gitignore ├── Piccolino_RAM.h └── Piccolino_RAM.cpp ├── Piccolino_OLED_SRAM ├── .gitattributes ├── README.txt ├── .gitignore ├── keywords.txt ├── examples │ └── hello_world │ │ └── hello_world.ino ├── Piccolino_OLED_SRAM.h ├── glcdfont.c └── Piccolino_OLED_SRAM.cpp ├── Piccolino_OLED ├── README.txt ├── .gitignore ├── keywords.txt ├── examples │ └── hello_world │ │ └── hello_world.ino ├── Piccolino_OLED.h ├── glcdfont.c └── Piccolino_OLED.cpp ├── SPI ├── keywords.txt ├── SPI.h ├── SPI.cpp └── examples │ ├── DigitalPotControl │ └── DigitalPotControl.ino │ └── BarometricPressureSensor │ ├── BarometricPressureSensor │ └── BarometricPressureSensor.ino │ └── BarometricPressureSensor.ino ├── PCF8575 ├── keywords.txt ├── PCint.h ├── examples │ └── ButtonBlink │ │ └── ButtonBlink.ino ├── PCF8575.cpp └── PCF8575.h └── calibrate └── calibrate.ino /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | -------------------------------------------------------------------------------- /api/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | lib/config.php 3 | -------------------------------------------------------------------------------- /api/.htpasswd: -------------------------------------------------------------------------------- 1 | aaronpk:$apr1$gFMLOkDW$kMgXEeV.l0Mxs7/3P3EP80 2 | -------------------------------------------------------------------------------- /Arduino/CapacitiveSensor/README.md: -------------------------------------------------------------------------------- 1 | CapacitiveSensor 2 | ================ 3 | 4 | CapacitiveSensor -------------------------------------------------------------------------------- /api/public/assets/jquery-3.2.1.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaronpk/BarBot/master/api/public/assets/jquery-3.2.1.min.js -------------------------------------------------------------------------------- /api/public/admin/.htaccess: -------------------------------------------------------------------------------- 1 | AuthType Basic 2 | AuthName "Admins Only" 3 | AuthUserFile /web/barbot/api/.htpasswd 4 | Require valid-user 5 | -------------------------------------------------------------------------------- /Arduino/HX711/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | -------------------------------------------------------------------------------- /api/public/queue/status.php: -------------------------------------------------------------------------------- 1 | get('barbot-status'); 8 | 9 | 10 | -------------------------------------------------------------------------------- /api/public/log/billable.php: -------------------------------------------------------------------------------- 1 | find_one($_POST['id']); 6 | $log->billable = $_POST['billable']; 7 | $log->save(); 8 | -------------------------------------------------------------------------------- /Arduino/CapacitiveSensor/keywords.txt: -------------------------------------------------------------------------------- 1 | CapacitiveSensor KEYWORD1 2 | capacitiveSensorRaw KEYWORD2 3 | capacitiveSensor KEYWORD2 4 | set_CS_Timeout_Millis KEYWORD2 5 | reset_CS_AutoCal KEYWORD2 6 | set_CS_AutocaL_Millis KEYWORD2 7 | -------------------------------------------------------------------------------- /api/scripts/init.php: -------------------------------------------------------------------------------- 1 | find_one($_POST['pump']); 6 | $pump->ingredient_id = $_POST['ingredient'] ?: null; 7 | $pump->save(); 8 | 9 | -------------------------------------------------------------------------------- /api/public/admin/enable-recipe.php: -------------------------------------------------------------------------------- 1 | find_one($_POST['recipe_id']); 6 | $recipe->enabled = $_POST['enabled'] ? 1 : 0; 7 | $recipe->save(); 8 | 9 | -------------------------------------------------------------------------------- /api/public/queue/delete.php: -------------------------------------------------------------------------------- 1 | where('id', $_POST['queue_id']) 7 | ->where_null('date_started') 8 | ->find_one(); 9 | $queue->delete(); 10 | -------------------------------------------------------------------------------- /api/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "predis/predis": "^1.1", 4 | "j4mie/idiorm": "^1.5", 5 | "mf2/mf2": "^0.3.0", 6 | "p3k/http": "^0.1.7" 7 | }, 8 | "autoload": { 9 | "files": [ 10 | "lib/helpers.php" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /api/lib/config.template.php: -------------------------------------------------------------------------------- 1 | 2, 8 | 'weight' => 10000 9 | ]; 10 | 11 | redis()->set('barbot-queue', json_encode([ 12 | 'pumps' => $pumps, 13 | 'queue_id' => 0 14 | ])); 15 | -------------------------------------------------------------------------------- /api/public/log/README.txt: -------------------------------------------------------------------------------- 1 | 2 | SELECT * 3 | FROM log 4 | JOIN recipes ON log.recipe_id = recipes.id 5 | JOIN recipe_ingredients ON recipes.id = recipe_ingredients.recipe_id 6 | JOIN ingredients ON ingredients.id = recipe_ingredients.ingredient_id 7 | WHERE ingredients.id = 8 8 | AND log.date_finished > '2017-04-07 20:00:00' 9 | AND log.date_finished < '2017-04-26 14:36:46' 10 | 11 | -------------------------------------------------------------------------------- /api/public/admin/create-recipe.php: -------------------------------------------------------------------------------- 1 | create(); 6 | $recipe->name = $_POST['name']; 7 | 8 | $photo = md5(time().$_FILES['photo']['tmp_name']).'.jpg'; 9 | copy($_FILES['photo']['tmp_name'], dirname(__FILE__).'/../images/'.$photo); 10 | $recipe->photo = $photo; 11 | 12 | $recipe->save(); 13 | 14 | header('Location: recipe.php?id='.$recipe->id); 15 | -------------------------------------------------------------------------------- /Arduino/Piccolino_RAM/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED_SRAM/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED/README.txt: -------------------------------------------------------------------------------- 1 | OLED Libray for Piccolino. Uses 1K of local RAM. 2 | Feel free to modify/add features. you can send new commits to 3 | admin@wctek.com for inclusion in future releases. 4 | 5 | Revision History 6 | ================ 7 | Version 1.0 - MAY 2015 : Initial Release 8 | Version 1.1 - JUN 2015 : Minor fixes 9 | Version 1.2 - JULY 2015: Added ::displayON, ::displayOFF & ::dim(ON|OFF) to turn display on/off or dimmed (useful for vehicle night driving) 10 | Version 1.3 - JULY 2015: Added ::drawRect, GRAY flag (draws lines every sesond pixel) 11 | -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED_SRAM/README.txt: -------------------------------------------------------------------------------- 1 | OLED Libray for Piccolino. Uses 1K of SRAM and only about 128 bytes of local 2 | RAM. Feel free to modify/add features. you can send new commits to 3 | admin@wctek.com for inclusion in future releases. 4 | 5 | Revision History 6 | ================ 7 | Version 1.0 - MAY 2015 : Initial Release 8 | Version 1.1 - JUN 2015 : Minor fixes 9 | Version 1.2 - JULY 2015: Added ::displayON, ::displayOFF & ::dim(ON|OFF) to turn display on/off or dimmed (useful for vehicle night driving) 10 | Version 1.3 - JULY 2015: Added ::drawRect, GRAY flag (draws lines every sesond pixel) 11 | -------------------------------------------------------------------------------- /Arduino/Piccolino_RAM/examples/piccolino_ram_test/piccolino_ram_test.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | Piccolino_RAM ram; 5 | 6 | void setup() { 7 | Serial.begin(9600); 8 | ram.begin(); // offset start at 0 9 | } 10 | 11 | void loop() 12 | { 13 | byte data_to_chip[17] = "Testing 90123456"; 14 | byte data_from_chip[17] = " "; 15 | int i = 0; 16 | 17 | // write to memory chip 18 | ram.write(0,data_to_chip,16); 19 | 20 | // read it back ... 21 | ram.read(0,data_from_chip,16); 22 | 23 | Serial.println((char *)data_from_chip); 24 | 25 | delay(1000); 26 | } 27 | -------------------------------------------------------------------------------- /Arduino/Piccolino_RAM/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For Piccolino_RAM 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | Piccolino_RAM KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | read KEYWORD2 16 | write KEYWORD2 17 | begin KEYWORD2 18 | 19 | ####################################### 20 | # Instances (KEYWORD2) 21 | ####################################### 22 | 23 | 24 | ####################################### 25 | # Constants (LITERAL1) 26 | ####################################### 27 | -------------------------------------------------------------------------------- /Arduino/Piccolino_RAM/.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED_SRAM/.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /api/config/001-barbot.conf: -------------------------------------------------------------------------------- 1 | 2 | ServerName bar.bot 3 | ServerAlias barbot.pad 4 | 5 | DocumentRoot /web/barbot/api/public 6 | 7 | Options FollowSymLinks 8 | AllowOverride None 9 | 10 | 11 | Options Indexes FollowSymLinks 12 | AllowOverride All 13 | Order allow,deny 14 | allow from all 15 | 16 | 17 | ErrorLog ${APACHE_LOG_DIR}/error.log 18 | 19 | # Possible values include: debug, info, notice, warn, error, crit, 20 | # alert, emerg. 21 | LogLevel warn 22 | 23 | CustomLog ${APACHE_LOG_DIR}/access.log combined 24 | 25 | 26 | -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED/.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | 45 | # VIM temp files 46 | *.swp 47 | 48 | # Linux ctags 49 | tags 50 | -------------------------------------------------------------------------------- /api/public/admin/index.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | Recipes 11 | 12 | 25 | 26 | 27 | 28 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /api/public/enqueue.php: -------------------------------------------------------------------------------- 1 | where('username', $_POST['username']) 11 | ->find_one(); 12 | if(!$user) { 13 | $user = ORM::for_table('users')->create(); 14 | $user->username = $_POST['username']; 15 | $user->date_created = date('Y-m-d H:i:s'); 16 | $user->remote_addr = $_SERVER['REMOTE_ADDR']; 17 | $user->user_agent = $_SERVER['HTTP_USER_AGENT']; 18 | $user->save(); 19 | } 20 | 21 | $queue = ORM::for_table('log')->create(); 22 | $queue->recipe_id = $_POST['recipe_id']; 23 | $queue->user_id = $user->id; 24 | $queue->date_queued = date('Y-m-d H:i:s'); 25 | $queue->user_agent = $_SERVER['HTTP_USER_AGENT']; 26 | $queue->cost = calculate_drink_cost($_POST['recipe_id']); 27 | $queue->save(); 28 | 29 | echo json_encode([ 30 | 'result' => 'queued' 31 | ]); 32 | -------------------------------------------------------------------------------- /Arduino/SPI/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map SPI 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | SPI KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | begin KEYWORD2 15 | end KEYWORD2 16 | transfer KEYWORD2 17 | setBitOrder KEYWORD2 18 | setDataMode KEYWORD2 19 | setClockDivider KEYWORD2 20 | 21 | 22 | ####################################### 23 | # Constants (LITERAL1) 24 | ####################################### 25 | SPI_CLOCK_DIV4 LITERAL1 26 | SPI_CLOCK_DIV16 LITERAL1 27 | SPI_CLOCK_DIV64 LITERAL1 28 | SPI_CLOCK_DIV128 LITERAL1 29 | SPI_CLOCK_DIV2 LITERAL1 30 | SPI_CLOCK_DIV8 LITERAL1 31 | SPI_CLOCK_DIV32 LITERAL1 32 | SPI_CLOCK_DIV64 LITERAL1 33 | SPI_MODE0 LITERAL1 34 | SPI_MODE1 LITERAL1 35 | SPI_MODE2 LITERAL1 36 | SPI_MODE3 LITERAL1 -------------------------------------------------------------------------------- /api/public/manual/queue.php: -------------------------------------------------------------------------------- 1 | get('barbot-active'); 6 | if($active) { 7 | echo json_encode([ 8 | 'error' => 'in progress' 9 | ]); 10 | die(); 11 | } 12 | 13 | $queue = ORM::for_table('log')->create(); 14 | $queue->ingredient_id = $_POST['ingredient_id']; 15 | $queue->date_queued = date('Y-m-d H:i:s'); 16 | $queue->user_agent = $_SERVER['HTTP_USER_AGENT']; 17 | $queue->cost = calculate_ingredient_cost($_POST['ingredient_id'], $_POST['amount']); 18 | $queue->save(); 19 | 20 | $pumps = []; 21 | 22 | $ingredient = ORM::for_table('ingredients') 23 | ->join('pumps', ['pumps.ingredient_id', '=', 'ingredients.id']) 24 | ->find_one($_POST['ingredient_id']); 25 | 26 | $pumps[] = build_redis_queue_item($ingredient, $_POST['amount']); 27 | 28 | redis()->set('barbot-queue', json_encode([ 29 | 'pumps' => $pumps, 30 | 'queue_id' => $queue->id 31 | ])); 32 | 33 | echo json_encode($pumps, JSON_PRETTY_PRINT); 34 | -------------------------------------------------------------------------------- /Arduino/PCF8575/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For PCF8574/PCF8575 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | PCF8574 KEYWORD1 10 | PCF8575 KEYWORD1 11 | 12 | ####################################### 13 | # Methods and Functions (KEYWORD2) 14 | ####################################### 15 | 16 | begin KEYWORD2 17 | pinMode KEYWORD2 18 | digitalWrite KEYWORD2 19 | digitalRead KEYWORD2 20 | write KEYWORD2 21 | read KEYWORD2 22 | clear KEYWORD2 23 | set KEYWORD2 24 | toggle KEYWORD2 25 | blink KEYWORD2 26 | attachInterrupt KEYWORD2 27 | detachInterrupt KEYWORD2 28 | disableInterrupt KEYWORD2 29 | enableInterrupt KEYWORD2 30 | checkForInterrupt KEYWORD2 31 | pullUp KEYWORD2 32 | pullDown KEYWORD2 33 | 34 | ####################################### 35 | # Constants (LITERAL1) 36 | ####################################### 37 | 38 | INPUT_PULLUP LITERAL1 39 | -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED_SRAM/keywords.txt: -------------------------------------------------------------------------------- 1 | ######################################## 2 | # Syntax Coloring Map For Piccolino_OLED 3 | ######################################## 4 | 5 | ######################################## 6 | # Datatypes (KEYWORD1) 7 | ######################################## 8 | Piccolino_OLED KEYWORD1 9 | 10 | ######################################## 11 | # Methods and Functions (KEYWORD2) 12 | ######################################## 13 | 14 | update KEYWORD2 15 | clear KEYWORD2 16 | setTextSize KEYWORD2 17 | setCursor KEYWORD2 18 | clearpart KEYWORD2 19 | clearline KEYWORD2 20 | drawPixel KEYWORD2 21 | drawLine KEYWORD2 22 | drawChar KEYWORD2 23 | fillRect KEYWORD2 24 | updateRow KEYWORD2 25 | displayON KEYWORD2 26 | displayOff KEYWORD2 27 | dim KEYWORD2 28 | 29 | ######################################## 30 | # Constants (LITERAL1) 31 | ######################################## 32 | 33 | ON LITERAL1 34 | OFF LITERAL1 35 | NORMAL LITERAL1 36 | INVERSE LITERAL1 37 | BLACK LITERAL1 38 | WHITE LITERAL1 -------------------------------------------------------------------------------- /api/public/admin/add.php: -------------------------------------------------------------------------------- 1 | create(); 6 | $recipe->name = $_POST['recipe_name']; 7 | 8 | $photo = basename($_POST['recipe_photo']); 9 | $img = file_get_contents($_POST['recipe_photo']); 10 | file_put_contents(dirname(__FILE__).'/../images/'.$photo, $img); 11 | 12 | $recipe->photo = $photo; 13 | $recipe->save(); 14 | 15 | foreach($_POST['ingredient'] as $i=>$ingredient_id) { 16 | if($_POST['amount'][$i] !== '-') { 17 | $ingredient = ORM::for_table('recipe_ingredients')->create(); 18 | $ingredient->recipe_id = $recipe->id; 19 | $ingredient->ingredient_id = $ingredient_id; 20 | $ingredient->fluid_oz = (double)$_POST['amount'][$i]; 21 | $ingredient->order = $i; 22 | $ingredient->ingredient_name = $_POST['ingredient_name'][$i]; 23 | $ingredient->measurement = $_POST['ingredient_amount'][$i]; 24 | $ingredient->save(); 25 | } 26 | } 27 | 28 | header('Location: /admin/recipe.php?id='.$recipe->id); 29 | -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED/keywords.txt: -------------------------------------------------------------------------------- 1 | ######################################## 2 | # Syntax Coloring Map For Piccolino_OLED 3 | ######################################## 4 | 5 | ######################################## 6 | # Datatypes (KEYWORD1) 7 | ######################################## 8 | Piccolino_OLED KEYWORD1 9 | 10 | ######################################## 11 | # Methods and Functions (KEYWORD2) 12 | ######################################## 13 | 14 | update KEYWORD2 15 | clear KEYWORD2 16 | setTextSize KEYWORD2 17 | setCursor KEYWORD2 18 | clearpart KEYWORD2 19 | clearline KEYWORD2 20 | drawPixel KEYWORD2 21 | drawLine KEYWORD2 22 | drawChar KEYWORD2 23 | fillRect KEYWORD2 24 | drawRect KEYWORD2 25 | updateRow KEYWORD2 26 | displayON KEYWORD2 27 | displayOff KEYWORD2 28 | dim KEYWORD2 29 | 30 | ######################################## 31 | # Constants (LITERAL1) 32 | ######################################## 33 | 34 | ON LITERAL1 35 | OFF LITERAL1 36 | NORMAL LITERAL1 37 | INVERSE LITERAL1 38 | BLACK LITERAL1 39 | WHITE LITERAL1 40 | GRAY LITERAL1 -------------------------------------------------------------------------------- /api/public/admin/save-ingredients.php: -------------------------------------------------------------------------------- 1 | $data) { 6 | if($id == 'new') { 7 | if($data['ingredient_id']) { 8 | $ingredient = ORM::for_table('recipe_ingredients')->create(); 9 | $ingredient->recipe_id = $_POST['recipe_id']; 10 | $ingredient->ingredient_id = $data['ingredient_id']; 11 | $ingredient->fluid_oz = $data['fluid_oz']; 12 | $ingredient->measurement = $data['measurement']; 13 | $ingredient->order = $data['order']; 14 | $ingredient->save(); 15 | } 16 | } else { 17 | $ingredient = ORM::for_table('recipe_ingredients')->find_one($id); 18 | if($data['order'] == 0) { 19 | $ingredient->delete(); 20 | } else { 21 | $ingredient->fluid_oz = $data['fluid_oz']; 22 | $ingredient->measurement = $data['measurement']; 23 | $ingredient->order = $data['order']; 24 | $ingredient->save(); 25 | } 26 | } 27 | } 28 | 29 | header('Location: /admin/recipe.php?id='.$_POST['recipe_id']); 30 | -------------------------------------------------------------------------------- /Arduino/Piccolino_RAM/Piccolino_RAM.h: -------------------------------------------------------------------------------- 1 | 2 | /* built-in SRAM is 32K mostly free, but a couple of libraries benefit from it as follows 3 | 4 | Oled Library uses 0x7c00 - 0x7fff (1K) 5 | WIFI Library uses 0x7400 - 0x7bff (2K) 6 | 7 | The addresses can be changed in their respective headers of course, but this is how 8 | the mapping is set by default 9 | */ 10 | 11 | #ifndef _PICCOLINO_RAM_H 12 | #define _PICCOLINO_RAM_H 13 | 14 | #define CMD_WREN 0x06 //0000 0110 Set Write Enable Latch 15 | #define CMD_WRDI 0x04 //0000 0100 Write Disable 16 | #define CMD_RDSR 0x05 //0000 0101 Read Status Register 17 | #define CMD_WRSR 0x01 //0000 0001 Write Status Register 18 | #define CMD_READ 0x03 //0000 0011 Read Memory Data 19 | #define CMD_WRITE 0x02 //0000 0010 Write Memory Data 20 | 21 | #define BYTE_MODE (0x00) 22 | #define PAGE_MODE (0x80) 23 | #define STREAM_MODE (0x40) 24 | 25 | #define RAM_CS 8 //chip select 26 | 27 | class Piccolino_RAM { 28 | public: 29 | 30 | Piccolino_RAM(); 31 | ~Piccolino_RAM(); 32 | 33 | void begin(int addr=0); 34 | int write(int addr, byte *buf, int count=1); 35 | int read(int addr, byte *buf, int count=1); 36 | 37 | private: 38 | int _ram_start_addr; 39 | }; 40 | 41 | #endif -------------------------------------------------------------------------------- /api/scripts/test-daemon.php: -------------------------------------------------------------------------------- 1 | get('barbot-queue'))) { 8 | usleep(50000); 9 | } 10 | 11 | redis()->set('barbot-active', 1); 12 | 13 | $job = json_decode($data); 14 | print_r($job); 15 | echo "\n"; 16 | 17 | $queue = ORM::for_table('log')->find_one($job->queue_id); 18 | $queue->date_started = date('Y-m-d H:i:s'); 19 | $queue->save(); 20 | 21 | foreach($job->pumps as $pump) { 22 | $line = sprintf("%02d %05d go", $pump->number, $pump->weight)."\n"; 23 | echo $line; 24 | $complete = false; 25 | 26 | sleep(4); 27 | 28 | $data = @json_decode($line); 29 | if(trim($line)) { 30 | redis()->publish('barbot-output', $line); 31 | redis()->set('barbot-status', $line); 32 | } 33 | if($data && property_exists($data, 'mode') && $data->mode == 'complete') { 34 | #print_r($data); 35 | $complete = true; 36 | echo "Finished!\n"; 37 | 38 | sleep(1); 39 | } 40 | 41 | } 42 | 43 | redis()->set('barbot-active', 0); 44 | 45 | $queue->date_finished = date('Y-m-d H:i:s'); 46 | $queue->save(); 47 | 48 | echo "Completed drink\n"; 49 | redis()->del('barbot-queue'); 50 | sleep(1); 51 | } 52 | 53 | -------------------------------------------------------------------------------- /api/public/queue/queue.php: -------------------------------------------------------------------------------- 1 | 6 | 7 | select('log.id', 'log_id') 10 | ->select_expr('log.*') 11 | ->select_many('recipes.name', 'recipes.photo') 12 | ->select_many('users.username') 13 | ->join('recipes', ['recipes.id', '=', 'log.recipe_id']) 14 | ->join('users', ['users.id', '=', 'log.user_id']) 15 | ->where_null('date_started') 16 | ->where_null('date_finished') 17 | ->order_by_asc('date_queued') 18 | ->find_many(); 19 | 20 | if(count($queue) == 0) { 21 | echo '

Visit http://bar.bot
to add a drink!

'; 22 | } else { 23 | echo '
Tap to make the drink!
'; 24 | } 25 | 26 | foreach($queue as $recipe): 27 | ?> 28 | 43 | = 100 13 | #include "Arduino.h" 14 | #else 15 | #include "WProgram.h" 16 | #endif 17 | 18 | // library interface description 19 | class CapacitiveSensor 20 | { 21 | // user-accessible "public" interface 22 | public: 23 | // methods 24 | CapacitiveSensor(uint8_t sendPin, uint8_t receivePin); 25 | long capacitiveSensorRaw(uint8_t samples); 26 | long capacitiveSensor(uint8_t samples); 27 | void set_CS_Timeout_Millis(unsigned long timeout_millis); 28 | void reset_CS_AutoCal(); 29 | void set_CS_AutocaL_Millis(unsigned long autoCal_millis); 30 | // library-accessible "private" interface 31 | private: 32 | // variables 33 | int error; 34 | unsigned long leastTotal; 35 | unsigned int loopTimingFactor; 36 | unsigned long CS_Timeout_Millis; 37 | unsigned long CS_AutocaL_Millis; 38 | unsigned long lastCal; 39 | unsigned long total; 40 | uint8_t sBit; // send pin's ports and bitmask 41 | volatile uint8_t *sReg; 42 | volatile uint8_t *sOut; 43 | uint8_t rBit; // receive pin's ports and bitmask 44 | volatile uint8_t *rReg; 45 | volatile uint8_t *rIn; 46 | volatile uint8_t *rOut; 47 | // methods 48 | int SenseOneCycle(void); 49 | }; 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /api/db/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `ingredients` ( 2 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 3 | `name` varchar(255) DEFAULT NULL, 4 | `available` tinyint(4) NOT NULL DEFAULT '1', 5 | `details` varchar(255) DEFAULT NULL, 6 | `gravity` double DEFAULT NULL, 7 | `cost` double DEFAULT NULL, 8 | `ml` int(11) DEFAULT NULL, 9 | PRIMARY KEY (`id`) 10 | ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4; 11 | 12 | CREATE TABLE `recipes` ( 13 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 14 | `name` varchar(255) DEFAULT NULL, 15 | `photo` varchar(255) DEFAULT NULL, 16 | `enabled` tinyint(4) NOT NULL DEFAULT '1', 17 | PRIMARY KEY (`id`) 18 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; 19 | 20 | CREATE TABLE `recipe_ingredients` ( 21 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 22 | `recipe_id` int(11) DEFAULT NULL, 23 | `ingredient_id` int(11) DEFAULT NULL, 24 | `fluid_oz` double DEFAULT NULL, 25 | `order` int(11) DEFAULT NULL, 26 | `ingredient_name` varchar(255) DEFAULT NULL, 27 | `measurement` varchar(255) DEFAULT NULL, 28 | PRIMARY KEY (`id`) 29 | ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4; 30 | 31 | CREATE TABLE `pumps` ( 32 | `number` int(11) unsigned NOT NULL, 33 | `ingredient_id` int(11) DEFAULT NULL, 34 | PRIMARY KEY (`number`) 35 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 36 | 37 | INSERT INTO `pumps` (`number`, `ingredient_id`) 38 | VALUES 39 | (1, NULL), 40 | (2, NULL), 41 | (3, NULL), 42 | (4, NULL), 43 | (5, NULL), 44 | (6, NULL), 45 | (7, NULL), 46 | (8, NULL), 47 | (9, NULL), 48 | (10, NULL), 49 | (11, NULL), 50 | (12, NULL), 51 | (13, NULL), 52 | (14, NULL), 53 | (15, NULL), 54 | (16, NULL); 55 | -------------------------------------------------------------------------------- /Arduino/CapacitiveSensor/examples/piccolino_touch/piccolino_touch.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | /* 5 | * CapitiveSense Library Demo Sketch 6 | * Paul Badger 2008 7 | * Uses a high value resistor e.g. 10M between send pin and receive pin 8 | * Resistor effects sensitivity, experiment with values, 50K - 50M. Larger resistor values yield larger sensor values. 9 | * Receive pin is the sensor pin - try different amounts of foil/metal on this pin 10 | * Modified for Piccolino bezel-touch by Alex Sardo March 2015 11 | */ 12 | 13 | Piccolino_OLED screen; 14 | CapacitiveSensor tleft = CapacitiveSensor(2,3); 15 | CapacitiveSensor tright = CapacitiveSensor(2,4); 16 | 17 | #define TRIGGER_LEVEL 50 // change as appropriate 18 | 19 | void setup() 20 | { 21 | Serial.begin(9600); 22 | screen.begin(); 23 | delay(100); 24 | Serial.print(F("Go ahead, touch my face-plate...\n")); 25 | screen.setTextSize(3); 26 | } 27 | 28 | void loop() 29 | { 30 | long start = millis(); 31 | long t1 = tleft.capacitiveSensor(30)/10; 32 | long t2 = tright.capacitiveSensor(30)/10; 33 | 34 | screen.clear(); 35 | 36 | if(t1>TRIGGER_LEVEL&&t2>TRIGGER_LEVEL) { 37 | Serial.print(F("BOTH\n")); 38 | screen.setCursor(30,20); 39 | screen.print(F("BOTH")); 40 | } else { 41 | if(t1>TRIGGER_LEVEL) { 42 | Serial.print(F("LEFT\n")); 43 | screen.setCursor(0,20); 44 | screen.print(F("LEFT")); 45 | } 46 | if(t2>TRIGGER_LEVEL) { 47 | Serial.print(F("RIGHT\n")); 48 | screen.setCursor(40,20); 49 | screen.print(F("RIGHT")); 50 | } 51 | } 52 | 53 | screen.update(); 54 | } 55 | -------------------------------------------------------------------------------- /api/public/queue/current.php: -------------------------------------------------------------------------------- 1 | join('recipes', ['recipes.id', '=', 'log.recipe_id']) 7 | ->join('users', ['users.id', '=', 'log.user_id']) 8 | ->where_not_null('date_started') 9 | ->where_null('date_finished') 10 | ->find_one(); 11 | 12 | if($current): 13 | 14 | $ingredients = ORM::for_table('recipe_ingredients') 15 | ->join('ingredients', ['ingredients.id', '=', 'recipe_ingredients.ingredient_id']) 16 | ->where('recipe_id', $current->recipe_id) 17 | ->order_by_asc('order') 18 | ->find_many(); 19 | 20 | ?> 21 | 22 |
23 |

Dispensing

24 | 25 |
26 | name ?> 27 | cost) ?> 28 |
29 |
for username ?>
30 | 31 |
32 | name; }, $ingredients)) ?> 33 |
34 | 35 | 36 |
37 | 38 | 39 | 40 |
41 |
42 |
43 | join('recipes', ['recipes.id', '=', 'log.recipe_id']) 46 | ->join('users', ['users.id', '=', 'log.user_id']) 47 | ->where_not_null('date_started') 48 | ->where_not_null('date_finished') 49 | ->order_by_desc('date_finished') 50 | ->find_one(); 51 | if($last): 52 | ?> 53 | 54 |

Last Made

55 |
56 | name ?> 57 | cost) ?> 58 |
59 |
for username ?>
60 | 61 | 64 |
65 | 66 | -------------------------------------------------------------------------------- /api/config/barbot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: barbot 4 | # Required-Start: $syslog $remote_fs $network 5 | # Required-Stop: $syslog $remote_fs $network 6 | # Should-Start: $local_fs 7 | # Should-Stop: $local_fs 8 | # Default-Start: 2 3 4 5 9 | # Default-Stop: 0 1 6 10 | # Short-Description: barbot 11 | # Description: barbot 12 | ### END INIT INFO 13 | 14 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 15 | DAEMON=/web/barbot/api/scripts/barbot-daemon.php 16 | NAME=barbot 17 | RUNDIR=/var/run/barbot 18 | PIDFILE=$RUNDIR/barbot.pid 19 | 20 | test -x $DAEMON || exit 0 21 | 22 | set -e 23 | 24 | case "$1" in 25 | start) 26 | echo -n "Starting $NAME: " 27 | mkdir -p $RUNDIR 28 | touch $PIDFILE 29 | chown pi:pi $RUNDIR $PIDFILE 30 | chmod 755 $RUNDIR 31 | 32 | if start-stop-daemon --start --background --quiet --umask 007 --pidfile $PIDFILE --chuid pi:pi --exec $DAEMON -- 33 | then 34 | echo "$NAME." 35 | else 36 | echo "failed" 37 | fi 38 | ;; 39 | 40 | stop) 41 | echo -n "Stopping $NAME: " 42 | if start-stop-daemon --stop --retry forever/TERM/1 --quiet --oknodo --pidfile $PIDFILE --exec $DAEMON 43 | then 44 | echo "$NAME." 45 | else 46 | echo "failed" 47 | fi 48 | rm -f $PIDFILE 49 | sleep 1 50 | ;; 51 | 52 | restart|force-reload) 53 | ${0} stop 54 | ${0} start 55 | ;; 56 | 57 | status) 58 | echo -n "$DESC is " 59 | if start-stop-daemon --stop --quiet --signal 0 --name ${NAME} --pidfile ${PIDFILE} 60 | then 61 | echo "running" 62 | else 63 | echo "not running" 64 | exit 1 65 | fi 66 | ;; 67 | 68 | *) 69 | echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload}" >&2 70 | exit 1 71 | ;; 72 | esac 73 | 74 | exit 0 75 | 76 | -------------------------------------------------------------------------------- /Arduino/SPI/SPI.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010 by Cristian Maglie 3 | * SPI Master library for arduino. 4 | * 5 | * This file is free software; you can redistribute it and/or modify 6 | * it under the terms of either the GNU General Public License version 2 7 | * or the GNU Lesser General Public License version 2.1, both as 8 | * published by the Free Software Foundation. 9 | */ 10 | 11 | #ifndef _SPI_H_INCLUDED 12 | #define _SPI_H_INCLUDED 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #define SPI_CLOCK_DIV4 0x00 19 | #define SPI_CLOCK_DIV16 0x01 20 | #define SPI_CLOCK_DIV64 0x02 21 | #define SPI_CLOCK_DIV128 0x03 22 | #define SPI_CLOCK_DIV2 0x04 23 | #define SPI_CLOCK_DIV8 0x05 24 | #define SPI_CLOCK_DIV32 0x06 25 | //#define SPI_CLOCK_DIV64 0x07 26 | 27 | #define SPI_MODE0 0x00 28 | #define SPI_MODE1 0x04 29 | #define SPI_MODE2 0x08 30 | #define SPI_MODE3 0x0C 31 | 32 | #define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR 33 | #define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR 34 | #define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR 35 | 36 | class SPIClass { 37 | public: 38 | inline static byte transfer(byte _data); 39 | 40 | // SPI Configuration methods 41 | 42 | inline static void attachInterrupt(); 43 | inline static void detachInterrupt(); // Default 44 | 45 | static void begin(); // Default 46 | static void end(); 47 | 48 | static void setBitOrder(uint8_t); 49 | static void setDataMode(uint8_t); 50 | static void setClockDivider(uint8_t); 51 | }; 52 | 53 | extern SPIClass SPI; 54 | 55 | byte SPIClass::transfer(byte _data) { 56 | SPDR = _data; 57 | while (!(SPSR & _BV(SPIF))) 58 | ; 59 | return SPDR; 60 | } 61 | 62 | void SPIClass::attachInterrupt() { 63 | SPCR |= _BV(SPIE); 64 | } 65 | 66 | void SPIClass::detachInterrupt() { 67 | SPCR &= ~_BV(SPIE); 68 | } 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED/examples/hello_world/hello_world.ino: -------------------------------------------------------------------------------- 1 | // For the OLED, we need I2C 2 | #include 3 | 4 | // For the FRAM we need SPI 5 | #include 6 | 7 | // I2C OLED library 8 | #include 9 | 10 | Piccolino_OLED display; // our OLED object ... 11 | 12 | 13 | void setup() { 14 | 15 | display.begin(); 16 | 17 | } 18 | 19 | 20 | void loop () { 21 | 22 | display.clear(); 23 | display.setCursor(0,16); // skip yellow portion of display 24 | 25 | for(int f=0; f<14; f+=3) { 26 | display.drawLine(0,0,127,f,WHITE); 27 | display.drawLine(0,14-f,127,0,WHITE); 28 | } 29 | display.update(); 30 | 31 | display.setTextColor(WHITE); 32 | display.setTextSize(1); 33 | display.print("Size 1\n"); 34 | display.update(); 35 | display.setTextSize(2); 36 | display.print("Size 2\n"); 37 | display.update(); 38 | display.setTextSize(3); 39 | display.print("Size 3\n"); 40 | display.update(); 41 | delay(3000); 42 | 43 | display.setTextSize(1); 44 | display.clear(); 45 | 46 | for(char f=0; f<50; f++) { 47 | display.drawLine(0,random(60),127,random(60),WHITE); 48 | display.update(); 49 | } 50 | 51 | delay(3000); 52 | display.clear(); 53 | display.update(); 54 | 55 | for(char f=0; f<3; f++) { 56 | display.clear(); 57 | display.update(); 58 | 59 | display.setCursor(0,16); 60 | display.setTextSize(1); 61 | display.print("Size 1\n"); 62 | display.setTextSize(2); 63 | display.print("Size 2\n"); 64 | display.setTextSize(3); 65 | display.print("Size 3\n"); 66 | display.update(); 67 | delay(500); 68 | } 69 | delay(3000); 70 | display.setTextSize(1); 71 | 72 | for(char f=0; f<20; f++) { 73 | display.clear(); 74 | display.setCursor(random(50),random(45)+16); // just move the text around ... 75 | display.print(F("Hello, world!")); 76 | display.update(); 77 | delay(10); 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED_SRAM/examples/hello_world/hello_world.ino: -------------------------------------------------------------------------------- 1 | // For the OLED, we need I2C 2 | #include 3 | 4 | // For the FRAM we need SPI 5 | #include 6 | 7 | // I2C OLED library 8 | #include 9 | #include 10 | 11 | Piccolino_OLED_SRAM display; // our OLED object ... 12 | 13 | 14 | void setup() { 15 | 16 | display.begin(); 17 | 18 | } 19 | 20 | 21 | void loop () { 22 | 23 | display.clear(); 24 | display.setCursor(0,16); // skip yellow portion of display 25 | 26 | for(int f=0; f<14; f+=3) { 27 | display.drawLine(0,0,127,f,WHITE); 28 | display.drawLine(0,14-f,127,0,WHITE); 29 | } 30 | display.update(); 31 | 32 | display.setTextColor(WHITE); 33 | display.setTextSize(1); 34 | display.print("Size 1\n"); 35 | display.update(); 36 | display.setTextSize(2); 37 | display.print("Size 2\n"); 38 | display.update(); 39 | display.setTextSize(3); 40 | display.print("Size 3\n"); 41 | display.update(); 42 | delay(3000); 43 | 44 | display.setTextSize(1); 45 | display.clear(); 46 | 47 | for(char f=0; f<50; f++) { 48 | display.drawLine(0,random(60),127,random(60),WHITE); 49 | display.update(); 50 | } 51 | 52 | delay(3000); 53 | display.clear(); 54 | display.update(); 55 | 56 | for(char f=0; f<3; f++) { 57 | display.clear(); 58 | display.update(); 59 | 60 | display.setCursor(0,16); 61 | display.setTextSize(1); 62 | display.print("Size 1\n"); 63 | display.setTextSize(2); 64 | display.print("Size 2\n"); 65 | display.setTextSize(3); 66 | display.print("Size 3\n"); 67 | display.update(); 68 | delay(500); 69 | } 70 | delay(3000); 71 | display.setTextSize(1); 72 | 73 | for(char f=0; f<20; f++) { 74 | display.clear(); 75 | display.setCursor(random(50),random(45)+16); // just move the text around ... 76 | display.print(F("Hello, world!")); 77 | display.update(); 78 | delay(10); 79 | } 80 | 81 | } -------------------------------------------------------------------------------- /api/public/api.php: -------------------------------------------------------------------------------- 1 | get('barbot-active'); 9 | if($active) { 10 | echo json_encode([ 11 | 'error' => 'in progress' 12 | ]); 13 | die(); 14 | } 15 | 16 | $pumps = []; 17 | 18 | $recipe = ORM::for_table('recipes') 19 | ->where('name', $_POST['recipe']) 20 | ->find_one(); 21 | 22 | $ingredients = ORM::for_table('recipe_ingredients') 23 | ->join('ingredients', ['ingredients.id', '=', 'recipe_ingredients.ingredient_id']) 24 | ->join('pumps', ['pumps.ingredient_id', '=', 'ingredients.id']) 25 | ->where('recipe_id', $recipe->id) 26 | ->order_by_asc('order') 27 | ->find_many(); 28 | 29 | foreach($ingredients as $g) { 30 | $oz = (double)$g->fluid_oz; 31 | $gravity = (double)$g->gravity; 32 | 33 | $ml = oz_to_ml($oz); 34 | $grams = round($ml * 1000 / $gravity); 35 | 36 | $pumps[] = [ 37 | 'number' => (int)$g->number, 38 | 'name' => $g->name, 39 | 'gravity' => (double)$g->gravity, 40 | 'oz' => (double)$g->fluid_oz, 41 | 'ml' => $ml, 42 | 'weight' => $grams 43 | ]; 44 | } 45 | 46 | redis()->set('barbot-queue', json_encode([ 47 | 'pumps' => $pumps 48 | ])); 49 | 50 | 51 | echo json_encode($pumps, JSON_PRETTY_PRINT); 52 | die(); 53 | */ 54 | 55 | 56 | /* 57 | $recipes = [ 58 | 'boulevardier' => [ 59 | [ 60 | 'number' => 8, 61 | 'weight' => 21310 62 | ], 63 | [ 64 | 'number' => 13, 65 | 'weight' => 42620, 66 | ], 67 | [ 68 | 'number' => 15, 69 | 'weight' => 21310 70 | ], 71 | [ 72 | 'number' => 7, 73 | 'weight' => 500 74 | ] 75 | ] 76 | ]; 77 | 78 | if(array_key_exists($_POST['recipe'], $recipes)) { 79 | $recipe = $recipes[$_POST['recipe']]; 80 | 81 | redis()->set('barbot-queue', json_encode([ 82 | 'pumps' => $recipe 83 | ])); 84 | 85 | echo "Making a ".$_POST['recipe']."\n"; 86 | } else { 87 | echo "Recipe Not Found\n"; 88 | } 89 | */ 90 | 91 | -------------------------------------------------------------------------------- /api/lib/helpers.php: -------------------------------------------------------------------------------- 1 | join('ingredients', ['ingredients.id', '=', 'recipe_ingredients.ingredient_id']) 30 | ->where('recipe_id', $id) 31 | ->find_many(); 32 | return array_sum(array_map(function($g) { 33 | return oz_to_ml($g->fluid_oz) * ($g->cost / $g->ml); 34 | }, $ingredients)); 35 | } 36 | 37 | function calculate_ingredient_cost($id, $fluid_oz) { 38 | $ingredient = ORM::for_table('ingredients')->find_one($id); 39 | return oz_to_ml($fluid_oz) * ($ingredient->cost / $ingredient->ml); 40 | } 41 | 42 | function build_redis_queue_item($ingredient, $fluid_oz) { 43 | $oz = (double)$fluid_oz; 44 | $gravity = (double)$ingredient->gravity; 45 | 46 | $ml = oz_to_ml($oz); 47 | $grams = round($ml * 1000 / $gravity); 48 | 49 | // temporary fix since it seems to be overpouring 50 | $grams = $grams * 0.85; 51 | 52 | return [ 53 | 'number' => (int)$ingredient->number, 54 | 'name' => $ingredient->name, 55 | 'gravity' => (double)$ingredient->gravity, 56 | 'oz' => (double)$fluid_oz, 57 | 'ml' => $ml, 58 | 'weight' => $grams 59 | ]; 60 | } 61 | 62 | function tz() { 63 | static $tz; 64 | if(!isset($tz)) 65 | $tz = new DateTimeZone('America/Los_Angeles'); 66 | return $tz; 67 | } 68 | -------------------------------------------------------------------------------- /Arduino/SPI/SPI.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010 by Cristian Maglie 3 | * SPI Master library for arduino. 4 | * 5 | * This file is free software; you can redistribute it and/or modify 6 | * it under the terms of either the GNU General Public License version 2 7 | * or the GNU Lesser General Public License version 2.1, both as 8 | * published by the Free Software Foundation. 9 | */ 10 | 11 | #include "pins_arduino.h" 12 | #include "SPI.h" 13 | 14 | SPIClass SPI; 15 | 16 | void SPIClass::begin() { 17 | 18 | // Set SS to high so a connected chip will be "deselected" by default 19 | digitalWrite(SS, HIGH); 20 | 21 | // When the SS pin is set as OUTPUT, it can be used as 22 | // a general purpose output port (it doesn't influence 23 | // SPI operations). 24 | pinMode(SS, OUTPUT); 25 | 26 | // Warning: if the SS pin ever becomes a LOW INPUT then SPI 27 | // automatically switches to Slave, so the data direction of 28 | // the SS pin MUST be kept as OUTPUT. 29 | SPCR |= _BV(MSTR); 30 | SPCR |= _BV(SPE); 31 | 32 | // Set direction register for SCK and MOSI pin. 33 | // MISO pin automatically overrides to INPUT. 34 | // By doing this AFTER enabling SPI, we avoid accidentally 35 | // clocking in a single bit since the lines go directly 36 | // from "input" to SPI control. 37 | // http://code.google.com/p/arduino/issues/detail?id=888 38 | pinMode(SCK, OUTPUT); 39 | pinMode(MOSI, OUTPUT); 40 | } 41 | 42 | 43 | void SPIClass::end() { 44 | SPCR &= ~_BV(SPE); 45 | } 46 | 47 | void SPIClass::setBitOrder(uint8_t bitOrder) 48 | { 49 | if(bitOrder == LSBFIRST) { 50 | SPCR |= _BV(DORD); 51 | } else { 52 | SPCR &= ~(_BV(DORD)); 53 | } 54 | } 55 | 56 | void SPIClass::setDataMode(uint8_t mode) 57 | { 58 | SPCR = (SPCR & ~SPI_MODE_MASK) | mode; 59 | } 60 | 61 | void SPIClass::setClockDivider(uint8_t rate) 62 | { 63 | /* 64 | SPCR = (SPCR & ~SPI_CLOCK_MASK) | (rate & SPI_CLOCK_MASK); 65 | SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate >> 2) & SPI_2XCLOCK_MASK); 66 | */ 67 | SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate & (1<<2)) ? SPI_2XCLOCK_MASK : 0); 68 | } 69 | 70 | -------------------------------------------------------------------------------- /Arduino/HX711/examples/HX711Serial/HX711Serial.ino: -------------------------------------------------------------------------------- 1 | #include "HX711.h" 2 | 3 | // HX711.DOUT - pin #A1 4 | // HX711.PD_SCK - pin #A0 5 | 6 | HX711 scale(A1, A0); // parameter "gain" is ommited; the default value 128 is used by the library 7 | 8 | void setup() { 9 | Serial.begin(38400); 10 | Serial.println("HX711 Demo"); 11 | 12 | Serial.println("Before setting up the scale:"); 13 | Serial.print("read: \t\t"); 14 | Serial.println(scale.read()); // print a raw reading from the ADC 15 | 16 | Serial.print("read average: \t\t"); 17 | Serial.println(scale.read_average(20)); // print the average of 20 readings from the ADC 18 | 19 | Serial.print("get value: \t\t"); 20 | Serial.println(scale.get_value(5)); // print the average of 5 readings from the ADC minus the tare weight (not set yet) 21 | 22 | Serial.print("get units: \t\t"); 23 | Serial.println(scale.get_units(5), 1); // print the average of 5 readings from the ADC minus tare weight (not set) divided 24 | // by the SCALE parameter (not set yet) 25 | 26 | scale.set_scale(2280.f); // this value is obtained by calibrating the scale with known weights; see the README for details 27 | scale.tare(); // reset the scale to 0 28 | 29 | Serial.println("After setting up the scale:"); 30 | 31 | Serial.print("read: \t\t"); 32 | Serial.println(scale.read()); // print a raw reading from the ADC 33 | 34 | Serial.print("read average: \t\t"); 35 | Serial.println(scale.read_average(20)); // print the average of 20 readings from the ADC 36 | 37 | Serial.print("get value: \t\t"); 38 | Serial.println(scale.get_value(5)); // print the average of 5 readings from the ADC minus the tare weight, set with tare() 39 | 40 | Serial.print("get units: \t\t"); 41 | Serial.println(scale.get_units(5), 1); // print the average of 5 readings from the ADC minus tare weight, divided 42 | // by the SCALE parameter set with set_scale 43 | 44 | Serial.println("Readings:"); 45 | } 46 | 47 | void loop() { 48 | Serial.print("one reading:\t"); 49 | Serial.print(scale.get_units(), 1); 50 | Serial.print("\t| average:\t"); 51 | Serial.println(scale.get_units(10), 1); 52 | 53 | scale.power_down(); // put the ADC in sleep mode 54 | delay(5000); 55 | scale.power_up(); 56 | } -------------------------------------------------------------------------------- /Arduino/SPI/examples/DigitalPotControl/DigitalPotControl.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Digital Pot Control 3 | 4 | This example controls an Analog Devices AD5206 digital potentiometer. 5 | The AD5206 has 6 potentiometer channels. Each channel's pins are labeled 6 | A - connect this to voltage 7 | W - this is the pot's wiper, which changes when you set it 8 | B - connect this to ground. 9 | 10 | The AD5206 is SPI-compatible,and to command it, you send two bytes, 11 | one with the channel number (0 - 5) and one with the resistance value for the 12 | channel (0 - 255). 13 | 14 | The circuit: 15 | * All A pins of AD5206 connected to +5V 16 | * All B pins of AD5206 connected to ground 17 | * An LED and a 220-ohm resisor in series connected from each W pin to ground 18 | * CS - to digital pin 10 (SS pin) 19 | * SDI - to digital pin 11 (MOSI pin) 20 | * CLK - to digital pin 13 (SCK pin) 21 | 22 | created 10 Aug 2010 23 | by Tom Igoe 24 | 25 | Thanks to Heather Dewey-Hagborg for the original tutorial, 2005 26 | 27 | */ 28 | 29 | 30 | // inslude the SPI library: 31 | #include 32 | 33 | 34 | // set pin 10 as the slave select for the digital pot: 35 | const int slaveSelectPin = 10; 36 | 37 | void setup() { 38 | // set the slaveSelectPin as an output: 39 | pinMode (slaveSelectPin, OUTPUT); 40 | // initialize SPI: 41 | SPI.begin(); 42 | } 43 | 44 | void loop() { 45 | // go through the six channels of the digital pot: 46 | for (int channel = 0; channel < 6; channel++) { 47 | // change the resistance on this channel from min to max: 48 | for (int level = 0; level < 255; level++) { 49 | digitalPotWrite(channel, level); 50 | delay(10); 51 | } 52 | // wait a second at the top: 53 | delay(100); 54 | // change the resistance on this channel from max to min: 55 | for (int level = 0; level < 255; level++) { 56 | digitalPotWrite(channel, 255 - level); 57 | delay(10); 58 | } 59 | } 60 | 61 | } 62 | 63 | void digitalPotWrite(int address, int value) { 64 | // take the SS pin low to select the chip: 65 | digitalWrite(slaveSelectPin,LOW); 66 | // send in the address and value via SPI: 67 | SPI.transfer(address); 68 | SPI.transfer(value); 69 | // take the SS pin high to de-select the chip: 70 | digitalWrite(slaveSelectPin,HIGH); 71 | } 72 | -------------------------------------------------------------------------------- /Arduino/HX711/HX711.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | HX711::HX711(byte dout, byte pd_sck, byte gain) { 5 | PD_SCK = pd_sck; 6 | DOUT = dout; 7 | 8 | pinMode(PD_SCK, OUTPUT); 9 | pinMode(DOUT, INPUT); 10 | 11 | set_gain(gain); 12 | } 13 | 14 | HX711::~HX711() { 15 | 16 | } 17 | 18 | bool HX711::is_ready() { 19 | return digitalRead(DOUT) == LOW; 20 | } 21 | 22 | void HX711::set_gain(byte gain) { 23 | switch (gain) { 24 | case 128: // channel A, gain factor 128 25 | GAIN = 1; 26 | break; 27 | case 64: // channel A, gain factor 64 28 | GAIN = 3; 29 | break; 30 | case 32: // channel B, gain factor 32 31 | GAIN = 2; 32 | break; 33 | } 34 | 35 | digitalWrite(PD_SCK, LOW); 36 | read(); 37 | } 38 | 39 | long HX711::read() { 40 | // wait for the chip to become ready 41 | while (!is_ready()); 42 | 43 | byte data[3]; 44 | 45 | // pulse the clock pin 24 times to read the data 46 | for (byte j = 3; j--;) { 47 | for (char i = 8; i--;) { 48 | digitalWrite(PD_SCK, HIGH); 49 | bitWrite(data[j], i, digitalRead(DOUT)); 50 | digitalWrite(PD_SCK, LOW); 51 | } 52 | } 53 | 54 | // set the channel and the gain factor for the next reading using the clock pin 55 | for (int i = 0; i < GAIN; i++) { 56 | digitalWrite(PD_SCK, HIGH); 57 | digitalWrite(PD_SCK, LOW); 58 | } 59 | 60 | data[2] ^= 0x80; 61 | 62 | return ((uint32_t) data[2] << 16) | ((uint32_t) data[1] << 8) | (uint32_t) data[0]; 63 | } 64 | 65 | long HX711::read_average(byte times) { 66 | long sum = 0; 67 | for (byte i = 0; i < times; i++) { 68 | sum += read(); 69 | } 70 | return sum / times; 71 | } 72 | 73 | double HX711::get_value(byte times) { 74 | return read_average(times) - OFFSET; 75 | } 76 | 77 | float HX711::get_units(byte times) { 78 | return get_value(times) / SCALE; 79 | } 80 | 81 | void HX711::tare(byte times) { 82 | double sum = read_average(times); 83 | set_offset(sum); 84 | } 85 | 86 | void HX711::set_scale(float scale) { 87 | SCALE = scale; 88 | } 89 | 90 | void HX711::set_offset(long offset) { 91 | OFFSET = offset; 92 | } 93 | 94 | void HX711::power_down() { 95 | digitalWrite(PD_SCK, LOW); 96 | digitalWrite(PD_SCK, HIGH); 97 | } 98 | 99 | void HX711::power_up() { 100 | digitalWrite(PD_SCK, LOW); 101 | } -------------------------------------------------------------------------------- /Arduino/Piccolino_RAM/Piccolino_RAM.cpp: -------------------------------------------------------------------------------- 1 | //#include 2 | 3 | /************************************************************* 4 | * This library supports FRAM and SRAM devices on the new * 5 | * WCT Pro Mini+ and Piccolino devices * 6 | * * 7 | * To use FRAM, add a #define FRAM entry before including the * 8 | * header in your sketch * 9 | * * 10 | * Written by Alex Sardo - WCTEK.com * 11 | *************************************************************/ 12 | #include 13 | 14 | #include "Piccolino_RAM.h" 15 | 16 | Piccolino_RAM::Piccolino_RAM() { 17 | // nothing here now -- all done in 'begin' 18 | } 19 | 20 | 21 | void Piccolino_RAM::begin(int addr) { 22 | pinMode(RAM_CS, OUTPUT); 23 | digitalWrite(RAM_CS, HIGH); 24 | 25 | _ram_start_addr=addr; 26 | 27 | //Setting up the SPI bus 28 | SPI.begin(); 29 | SPI.setDataMode(SPI_MODE0); 30 | SPI.setBitOrder(MSBFIRST); 31 | SPI.setClockDivider(SPI_CLOCK_DIV2); 32 | 33 | #ifndef FRAM 34 | digitalWrite(RAM_CS, LOW); 35 | SPI.transfer(CMD_WRSR); 36 | SPI.transfer(0x40); // stream mode implicit 37 | digitalWrite(RAM_CS, HIGH); 38 | #endif 39 | 40 | } 41 | 42 | int Piccolino_RAM::write(int addr, byte *buf, int count) 43 | { 44 | 45 | addr+=_ram_start_addr; 46 | 47 | #ifdef RAM 48 | digitalWrite(RAM_CS, LOW); 49 | SPI.transfer(CMD_WREN); //write enable 50 | digitalWrite(RAM_CS, HIGH); 51 | #endif 52 | 53 | digitalWrite(RAM_CS, LOW); 54 | SPI.transfer(CMD_WRITE); //write command 55 | SPI.transfer((char)(addr >> 8)); 56 | SPI.transfer((char)addr); 57 | 58 | for (int i = 0;i < count;i++) 59 | SPI.transfer(buf[i]); 60 | 61 | digitalWrite(RAM_CS, HIGH); 62 | 63 | return 0; 64 | } 65 | 66 | int Piccolino_RAM::read(int addr, byte *buf, int count) 67 | { 68 | 69 | addr+=_ram_start_addr; 70 | 71 | digitalWrite(RAM_CS, LOW); 72 | 73 | SPI.transfer(CMD_READ); 74 | SPI.transfer((char)(addr >> 8)); 75 | SPI.transfer((char)addr); 76 | 77 | for (int i=0; i < count; i++) 78 | buf[i] = SPI.transfer(0xff); // anything will trigger a byte to be sent back ... 79 | 80 | digitalWrite(RAM_CS, HIGH); 81 | 82 | return 0; 83 | } 84 | 85 | Piccolino_RAM::~Piccolino_RAM() { 86 | // nothing here now -- all done in 'begin' 87 | } 88 | 89 | 90 | -------------------------------------------------------------------------------- /api/scripts/barbot-daemon.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | publish('barbot-output', $line); 29 | echo $line; 30 | if(trim($line) == '{"mode":"ready"}') 31 | $ready = true; 32 | } 33 | */ 34 | 35 | echo "BarBot Initialized\n"; 36 | 37 | while(true) { 38 | 39 | while(!($data=redis()->get('barbot-queue'))) { 40 | usleep(500000); 41 | } 42 | 43 | ORM::set_db(new_db()); 44 | 45 | redis()->set('barbot-active', 1); 46 | 47 | $job = json_decode($data); 48 | print_r($job); 49 | echo "\n"; 50 | 51 | $queue = ORM::for_table('log')->find_one($job->queue_id); 52 | if($queue) { 53 | $queue->date_started = date('Y-m-d H:i:s'); 54 | $queue->save(); 55 | } 56 | 57 | $final_weights = []; 58 | 59 | foreach($job->pumps as $pump) { 60 | echo "Pump $pump->number Weight $pump->weight\n"; 61 | fwrite($ser, sprintf("%02d %05d go", $pump->number, $pump->weight)."\r"); 62 | $complete = false; 63 | while(($line = fgets($ser)) !== false && !$complete) { 64 | $data = @json_decode($line); 65 | if(trim($line)) { 66 | redis()->publish('barbot-output', $line); 67 | if($data) { 68 | redis()->set('barbot-status', $line); 69 | } 70 | } 71 | if($data && property_exists($data, 'mode') && $data->mode == 'complete') { 72 | #print_r($data); 73 | $complete = true; 74 | $final_weights[] = $data; 75 | 76 | echo "Finished!\n"; 77 | sleep(1); 78 | } 79 | } 80 | } 81 | 82 | redis()->set('barbot-active', 0); 83 | 84 | if($queue) { 85 | $queue->date_finished = date('Y-m-d H:i:s'); 86 | $queue->final_weights = json_encode($final_weights); 87 | $queue->save(); 88 | } 89 | 90 | echo "Completed drink\n"; 91 | redis()->del('barbot-queue'); 92 | 93 | // Disconnect from the DB 94 | ORM::set_db(null); 95 | 96 | sleep(1); 97 | } 98 | -------------------------------------------------------------------------------- /Arduino/HX711/HX711.h: -------------------------------------------------------------------------------- 1 | #ifndef HX711_h 2 | #define HX711_h 3 | 4 | #if ARDUINO >= 100 5 | #include "Arduino.h" 6 | #else 7 | #include "WProgram.h" 8 | #endif 9 | 10 | class HX711 11 | { 12 | private: 13 | byte PD_SCK; // Power Down and Serial Clock Input Pin 14 | byte DOUT; // Serial Data Output Pin 15 | byte GAIN; // amplification factor 16 | long OFFSET; // used for tare weight 17 | float SCALE; // used to return weight in grams, kg, ounces, whatever 18 | 19 | public: 20 | // define clock and data pin, channel, and gain factor 21 | // channel selection is made by passing the appropriate gain: 128 or 64 for channel A, 32 for channel B 22 | // gain: 128 or 64 for channel A; channel B works with 32 gain factor only 23 | HX711(byte dout, byte pd_sck, byte gain = 128); 24 | 25 | virtual ~HX711(); 26 | 27 | // check if HX711 is ready 28 | // from the datasheet: When output data is not ready for retrieval, digital output pin DOUT is high. Serial clock 29 | // input PD_SCK should be low. When DOUT goes to low, it indicates data is ready for retrieval. 30 | bool is_ready(); 31 | 32 | // set the gain factor; takes effect only after a call to read() 33 | // channel A can be set for a 128 or 64 gain; channel B has a fixed 32 gain 34 | // depending on the parameter, the channel is also set to either A or B 35 | void set_gain(byte gain = 128); 36 | 37 | // waits for the chip to be ready and returns a reading 38 | long read(); 39 | 40 | // returns an average reading; times = how many times to read 41 | long read_average(byte times = 10); 42 | 43 | // returns (read_average() - OFFSET), that is the current value without the tare weight; times = how many readings to do 44 | double get_value(byte times = 1); 45 | 46 | // returns get_value() divided by SCALE, that is the raw value divided by a value obtained via calibration 47 | // times = how many readings to do 48 | float get_units(byte times = 1); 49 | 50 | // set the OFFSET value for tare weight; times = how many times to read the tare value 51 | void tare(byte times = 10); 52 | 53 | // set the SCALE value; this value is used to convert the raw data to "human readable" data (measure units) 54 | void set_scale(float scale = 1.f); 55 | 56 | // set OFFSET, the value that's subtracted from the actual reading (tare weight) 57 | void set_offset(long offset = 0); 58 | 59 | // puts the chip into power down mode 60 | void power_down(); 61 | 62 | // wakes up the chip after power down mode 63 | void power_up(); 64 | }; 65 | 66 | #endif /* HX711_h */ -------------------------------------------------------------------------------- /api/public/log/index.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | BarBot Log 11 | 12 | 35 | 36 | 37 | 38 | where('billable', 1) 41 | ->sum('cost'); 42 | ?> 43 | 44 |
45 | 46 |
$
47 | 48 | 49 | select('log.id', 'logid') 52 | ->select_expr('users.*') 53 | ->select_expr('recipes.*') 54 | ->select_expr('log.*') 55 | ->left_outer_join('recipes', ['recipes.id', '=', 'log.recipe_id']) 56 | ->join('users', ['users.id', '=', 'log.user_id']) 57 | ->order_by_desc('date_finished') 58 | ->find_many(); 59 | foreach($logs as $log): 60 | ?> 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 71 |
username ?>name ?>$cost) ?>date_finished ?: $log->date_queued))->setTimeZone(tz())->format('M j, Y g:ia') ?>billable ? 'checked="checked"' : '' ?>>
72 |
73 | 74 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /api/public/admin/pumps.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | Configure Pumps 11 | 12 | 36 | 37 | 38 | 39 | 40 |

Configure Pumps

41 | 42 | 43 | order_by_asc('name')->find_many(); 46 | 47 | function show_pump($pump) { 48 | global $ingredients; 49 | ?> 50 | 64 | left_outer_join('ingredients', ['pumps.ingredient_id','=','ingredients.id']) 69 | ->order_by_asc('pumps.number') 70 | ->find_many(); 71 | foreach($pumps as $i=>$pump): 72 | if($i % 4 == 0) echo ''."\n"; 73 | show_pump($pump); 74 | if($i % 4 == 3) echo ''."\n"; 75 | endforeach; 76 | ?> 77 |
51 | number ?> 52 | 63 |
78 | 92 | 93 | -------------------------------------------------------------------------------- /api/public/manual/index.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | Manual Pour - BarBot 11 | 12 | 36 | 37 | 38 | 39 | 40 | 41 | select('ingredients.*')->select('pumps.number') 44 | ->join('pumps', ['ingredients.id', '=', 'pumps.ingredient_id']) 45 | ->where('available', 1) 46 | ->order_by_asc('name') 47 | ->find_many(); 48 | $amounts = [ 49 | 'dash' => 0.02, 50 | '¼ oz' => 0.25, 51 | '½ oz' => 0.5, 52 | '¾ oz' => 0.75, 53 | '1 oz' => 1, 54 | '1½ oz' => 1.5, 55 | '2 oz' => 2 56 | ]; 57 | foreach($ingredients as $g): 58 | ?> 59 | 60 | 64 | $amt): ?> 65 | 69 | 70 | 71 | 74 |
61 | name ?>
62 | (Pump number ?>) 63 |
66 |
67 |
id, $amt)) ?>
68 |
75 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /Arduino/HX711/README.md: -------------------------------------------------------------------------------- 1 | HX711 2 | ===== 3 | 4 | An Arduino library to interface the Avia Semiconductor HX711 24-Bit Analog-to-Digital Converter (ADC) for Weight Scales. 5 | 6 | This is my humble attempt at creating an Arduino library for this ADC: 7 | http://www.dfrobot.com/image/data/SEN0160/hx711_english.pdf 8 | 9 | Other libraries exist, including this very good one, which I first used and which is the starting point for my library: 10 | https://github.com/aguegu/ardulibs/tree/master/hx711 11 | 12 | Although other libraries exist, I needed a slightly different approach, so here's how my library is different than others: 13 | 14 | 1. It provides a tare() function, which "resets" the scale to 0. Many other implementations calculate the tare weight when the ADC is initialized only. I needed a way to be able to set the tare weight at any time. Use case: place an empty container on the scale, call tare() to reset the readings to 0, fill the container and get the weight of the content. 15 | 16 | 2. It provides a power_down() function, to put the ADC into a low power mode. According to the datasheet, "When PD_SCK pin changes from low to high and stays at high for longer than 60μs, HX711 enters power down mode". Use case: battery powered scales. Accordingly, there is a power_up() function to get the chip out of the low power mode. 17 | 18 | 3. It has a set_gain(byte gain) function that allows you to set the gain factor and select the channel. According to the datasheet, "Channel A can be programmed with a gain of 128 or 64, corresponding to a full-scale differential input voltage of ±20mV or ±40mV respectively, when a 5V supply is connected to AVDD analog power supply pin. Channel B has a fixed gain of 32.". The same function is used to select the channel A or channel B, by passing 128 or 64 for channel A, or 32 for channel B as the parameter. The default value is 128, which means "channel A with a gain factor of 128", so one can simply call set_gain(). Also, the function is called from the constructor. 19 | 20 | 4. The constructor has an extra parameter "gain" that allows you to set the gain factor and channel. The constructor calls the "set_gain" function mentioned above. 21 | 22 | 5. The "get_value" and "get_units" functions can receive an extra parameter "times", and they will return the average of multiple readings instead of a single reading. 23 | 24 | How to Calibrate Your Scale 25 | 26 | 1. Call set_scale() with no parameter. 27 | 2. Call tare() with no parameter. 28 | 3. Place a known weight on the scale and call get_units(10). 29 | 4. Divide the result in step 3 to your known weight. You should get about the parameter you need to pass to set_scale. 30 | 5. Adjust the parameter in step 4 until you get an accurate reading. 31 | -------------------------------------------------------------------------------- /api/public/queue/index.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | BarBot Queue 11 | 12 | 13 | 14 | 15 | 20 | 21 | 22 |
23 |
24 |
25 |

Queued

26 | 27 |
28 |
29 |
30 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /api/public/queue/start.php: -------------------------------------------------------------------------------- 1 | get('barbot-active'); 11 | if($active) { 12 | echo json_encode([ 13 | 'error' => 'in progress' 14 | ]); 15 | die(); 16 | } 17 | 18 | 19 | $queue = ORM::for_table('log') 20 | ->where('id', $_POST['queue_id']) 21 | ->where_null('date_started') 22 | ->find_one(); 23 | 24 | if(!$queue) { 25 | echo json_encode([ 26 | 'error' => 'Could not find item' 27 | ]); 28 | die(); 29 | } 30 | 31 | $recipe = ORM::for_table('recipes') 32 | ->where('id', $queue->recipe_id) 33 | ->find_one(); 34 | 35 | $ingredients = ORM::for_table('recipe_ingredients') 36 | ->join('ingredients', ['ingredients.id', '=', 'recipe_ingredients.ingredient_id']) 37 | ->join('pumps', ['pumps.ingredient_id', '=', 'ingredients.id']) 38 | ->where('recipe_id', $recipe->id) 39 | ->order_by_asc('order') 40 | ->find_many(); 41 | 42 | $pumps = []; 43 | 44 | foreach($ingredients as $g) { 45 | $pumps[] = build_redis_queue_item($g, $g->fluid_oz); 46 | } 47 | 48 | redis()->set('barbot-queue', json_encode([ 49 | 'pumps' => $pumps, 50 | 'queue_id' => $queue->id 51 | ])); 52 | 53 | 54 | echo json_encode($pumps, JSON_PRETTY_PRINT); 55 | 56 | 57 | if($queue->user_id == 2) { 58 | // Send to YNAB and my website 59 | $cost = round($queue->cost, 2); 60 | $name = $recipe->name; 61 | 62 | $http = new p3k\HTTP(); 63 | 64 | $today = new DateTime(); 65 | $today->setTimeZone(new DateTimeZone('US/Pacific')); 66 | 67 | $http->post(Config::$micropubEndpoint, json_encode([ 68 | 'type' => ['h-entry'], 69 | 'properties' => [ 70 | 'summary' => ['Just drank: '.$name], 71 | 'drank' => [[ 72 | 'type' => ['h-food'], 73 | 'properties' => [ 74 | 'name' => [$name] 75 | ] 76 | ]] 77 | ] 78 | ]), [ 79 | 'Content-type: application/json', 80 | 'Authorization: Bearer '.Config::$micropubToken, 81 | ]); 82 | 83 | $http->post('https://api.youneedabudget.com/v1/budgets/'.Config::$ynabBudgetID.'/transactions', json_encode([ 84 | 'transaction' => [ 85 | 'account_id' => Config::$ynabAccountID, 86 | 'date' => $today->format('Y-m-d'), 87 | 'amount' => round($cost*(-1000)), 88 | 'payee_id' => Config::$ynabPayeeID, 89 | 'category_id' => Config::$ynabCategoryID, 90 | 'memo' => $name, 91 | 'cleared' => 'cleared', 92 | 'approved' => false, 93 | 'import_id' => 'barbot:'.$queue->id, 94 | ] 95 | ]), [ 96 | 'Content-type: application/json', 97 | 'Authorization: Bearer '.Config::$ynabToken 98 | ]); 99 | 100 | } 101 | 102 | -------------------------------------------------------------------------------- /api/public/admin/recipe.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | Edit Recipes 11 | 12 | 25 | 26 | 27 | 28 | 29 | find_one($_GET['id']); 31 | ?> 32 | 33 |

name ?>

34 | 35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | select('recipe_ingredients.*')->select('ingredients.name') 47 | ->left_outer_join('ingredients', ['ingredients.id', '=', 'recipe_ingredients.ingredient_id']) 48 | ->where('recipe_id', $_GET['id']) 49 | ->order_by_asc('order') 50 | ->find_many(); 51 | foreach($ingredients as $g): 52 | $order = max($order, $g->order); 53 | ?> 54 | 55 | 56 | 57 | 58 | 59 | 60 | 63 | 64 | 75 | 76 | 77 | 78 | 79 |
IngredientOuncesMeasurementOrder
name ?>
65 | 74 |
80 | 81 | 82 | 83 |
84 | 85 | 86 |

87 |
    88 |
  • Set order=0 to delete an ingredient
  • 89 |
90 | 91 | 92 | back to recipes 93 | 94 | 95 | -------------------------------------------------------------------------------- /Arduino/PCF8575/PCint.h: -------------------------------------------------------------------------------- 1 | #include "pins_arduino.h" 2 | 3 | volatile uint8_t *port_to_pcmask[] = { &PCMSK0, &PCMSK1, &PCMSK2 }; 4 | 5 | static int PCintMode[24]; 6 | 7 | typedef void (*voidFuncPtr)(void); 8 | 9 | volatile static voidFuncPtr PCintFunc[24] = { NULL }; 10 | 11 | volatile static uint8_t PCintLast[3]; 12 | 13 | /* 14 | * attach an interrupt to a specific pin using pin change interrupts. 15 | */ 16 | void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) { 17 | uint8_t bit = digitalPinToBitMask(pin); 18 | uint8_t port = digitalPinToPort(pin); 19 | uint8_t slot; 20 | volatile uint8_t *pcmask; 21 | 22 | // map pin to PCIR register 23 | if (port == NOT_A_PORT) { 24 | return; 25 | } else { 26 | port -= 2; 27 | pcmask = port_to_pcmask[port]; 28 | } 29 | 30 | // -- Fix by Baziki. In the original sources it was a little bug, which cause analog ports to work incorrectly. 31 | if (port == 1) { 32 | slot = port * 8 + (pin - 14); 33 | } else { 34 | slot = port * 8 + (pin % 8); 35 | } 36 | // --Fix end 37 | PCintMode[slot] = mode; 38 | PCintFunc[slot] = userFunc; 39 | // set the mask 40 | *pcmask |= bit; 41 | // enable the interrupt 42 | PCICR |= 0x01 << port; 43 | 44 | // Fix init by SkyWodd 45 | PCintLast[0] = *portInputRegister(2); 46 | PCintLast[1] = *portInputRegister(3); 47 | PCintLast[2] = *portInputRegister(4); 48 | } 49 | 50 | void PCdetachInterrupt(uint8_t pin) { 51 | uint8_t bit = digitalPinToBitMask(pin); 52 | uint8_t port = digitalPinToPort(pin); 53 | volatile uint8_t *pcmask; 54 | 55 | // map pin to PCIR register 56 | if (port == NOT_A_PORT) { 57 | return; 58 | } else { 59 | port -= 2; 60 | pcmask = port_to_pcmask[port]; 61 | } 62 | 63 | // disable the mask. 64 | *pcmask &= ~bit; 65 | // if that's the last one, disable the interrupt. 66 | if (*pcmask == 0) { 67 | PCICR &= ~(0x01 << port); 68 | } 69 | } 70 | 71 | // common code for isr handler. "port" is the PCINT number. 72 | // there isn't really a good way to back-map ports and masks to pins. 73 | static void PCint(uint8_t port) { 74 | uint8_t bit; 75 | uint8_t curr; 76 | uint8_t mask; 77 | uint8_t pin; 78 | 79 | // get the pin states for the indicated port. 80 | curr = *portInputRegister(port + 2); 81 | mask = curr ^ PCintLast[port]; 82 | PCintLast[port] = curr; 83 | // mask is pins that have changed. screen out non pcint pins. 84 | if ((mask &= *port_to_pcmask[port]) == 0) { 85 | return; 86 | } 87 | // mask is pcint pins that have changed. 88 | for (uint8_t i = 0; i < 8; i++) { 89 | bit = 0x01 << i; 90 | if (bit & mask) { 91 | pin = port * 8 + i; 92 | // Trigger interrupt if mode is CHANGE, or if mode is RISING and 93 | // the bit is currently high, or if mode is FALLING and bit is low. 94 | if ((PCintMode[pin] == CHANGE 95 | || ((PCintMode[pin] == RISING) && (curr & bit)) 96 | || ((PCintMode[pin] == FALLING) && !(curr & bit))) 97 | && (PCintFunc[pin] != NULL)) { 98 | PCintFunc[pin](); 99 | } 100 | } 101 | } 102 | } 103 | 104 | SIGNAL(PCINT0_vect) { 105 | PCint(0); 106 | } 107 | SIGNAL(PCINT1_vect) { 108 | PCint(1); 109 | } 110 | SIGNAL(PCINT2_vect) { 111 | PCint(2); 112 | } 113 | -------------------------------------------------------------------------------- /api/public/assets/styles.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-family: "AmericanTypewriter", "Baskerville", "Roboto"; 3 | font-weight: bold; 4 | font-size: 42px; 5 | text-transform: uppercase; 6 | text-align: center; 7 | padding: 0; 8 | border-bottom: 1px dotted #222; 9 | margin: 0; 10 | margin-bottom: 20px; 11 | } 12 | h2 { 13 | text-align: center; 14 | } 15 | 16 | .hidden { 17 | display: none; 18 | } 19 | 20 | 21 | 22 | 23 | body.barbot { 24 | display: flex; 25 | flex-direction: row; 26 | height: 100vh; 27 | padding: 0; 28 | margin: 0; 29 | } 30 | 31 | body.barbot .current { 32 | flex: 0.8 0; 33 | background: #000; 34 | height: 100vh; 35 | } 36 | 37 | body.barbot .queue { 38 | flex: 1.2 0; 39 | background: #fdf5e8; 40 | height: 100vh; 41 | } 42 | 43 | .queue h1, .current h1 { 44 | margin-bottom: 0; 45 | margin-top: 20px; 46 | } 47 | .current h1 { 48 | border-color: #888; 49 | } 50 | .current h2 { 51 | font-family: "AmericanTypewriter", "Baskerville", "Roboto"; 52 | font-weight: bold; 53 | font-size: 28px; 54 | text-transform: uppercase; 55 | } 56 | 57 | .queue-list .menu-item { 58 | margin: 0 auto; 59 | padding: 10px; 60 | border-bottom: 1px dotted #222; 61 | font-size: 22px; 62 | } 63 | 64 | .queue-list .details { 65 | position: relative; 66 | } 67 | .queue-list .details .delete { 68 | position: absolute; 69 | bottom: 2px; 70 | right: 2px; 71 | } 72 | .queue-list .details .delete a { 73 | text-decoration: none; 74 | color: #aaa; 75 | } 76 | 77 | .current .name { 78 | font-family: "AmericanTypewriter", "Baskerville", "Roboto"; 79 | font-weight: normal; 80 | text-align: center; 81 | margin-top: 12px; 82 | font-size: 22px; 83 | } 84 | .current .cost { 85 | color: #E97E6B; 86 | } 87 | .current .cost:before { 88 | content: " — "; 89 | } 90 | .current .for-user { 91 | text-align: center; 92 | margin: 8px 0; 93 | font-size: 22px; 94 | } 95 | .current .photo { 96 | width: 100%; 97 | } 98 | .current .ingredients { 99 | text-align: center; 100 | margin-bottom: 8px; 101 | } 102 | 103 | .current { 104 | position: relative; 105 | } 106 | .current .dispensing { 107 | } 108 | .current .last-made { 109 | position: absolute; 110 | width: 100%; 111 | bottom: 0; 112 | padding-bottom: 20px; 113 | } 114 | 115 | 116 | 117 | .menu-item { 118 | display: flex; 119 | flex-direction: row; 120 | margin-bottom: 10px; 121 | cursor: pointer; 122 | } 123 | .menu-item.missing { 124 | opacity: 0.3; 125 | cursor: auto; 126 | } 127 | .menu-item .photo { 128 | width: 120px; 129 | display: block; 130 | margin-right: 10px; 131 | } 132 | .menu-item .photo img { 133 | width: 100%; 134 | border-radius: 4px; 135 | } 136 | .menu-item .details { 137 | display: flex; 138 | flex-direction: column; 139 | width: 100%; 140 | } 141 | .menu-item .name { 142 | font-family: "AmericanTypewriter", "Baskerville", "Roboto"; 143 | } 144 | .menu-item .cost { 145 | color: #A1311D; 146 | font-family: "AmericanTypewriter", "Baskerville", "Roboto"; 147 | font-size: 0.8em; 148 | } 149 | .menu-item .cost:before { 150 | content: " — "; 151 | } 152 | .ingredients, .for-user { 153 | font-style: italic; 154 | font-family: serif; 155 | } 156 | .not-in-cabinet { 157 | color: #a1311d; 158 | } 159 | -------------------------------------------------------------------------------- /Arduino/PCF8575/examples/ButtonBlink/ButtonBlink.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * This demo code demonstrate all functionnalities of the PCF8575 library. 3 | * 4 | * PCF8575 pins map : 5 | * 0: led 6 | * 1: led 7 | * 2: led 8 | * 3: button + pull-up resistor 9 | */ 10 | 11 | /* Dependencies */ 12 | #include // Required for I2C communication 13 | #include "PCF8575.h" // Required for PCF8575 14 | 15 | /** PCF8575 instance */ 16 | PCF8575 expander; 17 | 18 | /** setup() */ 19 | void setup() { 20 | 21 | /* Setup serial for debug */ 22 | Serial.begin(115200); 23 | 24 | /* Start I2C bus and PCF8575 instance */ 25 | expander.begin(0x20); 26 | 27 | /* Setup some PCF8575 pins for demo */ 28 | expander.pinMode(0, OUTPUT); 29 | expander.pinMode(1, OUTPUT); 30 | expander.pinMode(2, OUTPUT); 31 | expander.pinMode(3, INPUT_PULLUP); 32 | 33 | /* Enable PCF8575 interrupts, use pin D8 as "INT" pin and ISRgateway() as callback function */ 34 | expander.enableInterrupt(8, ISRgateway); 35 | 36 | /* Attach a software interrupt on pin 3 of the PCF8575 */ 37 | expander.attachInterrupt(3, ISRdemo, FALLING); 38 | expander.digitalWrite(0, HIGH); // Turn off led 1 39 | } 40 | 41 | /** This function will be called each time the state of a pin of the PCF8575 change */ 42 | void ISRgateway() { 43 | expander.checkForInterrupt(); 44 | } 45 | 46 | /** This function will be called each time the button on pin 3 is pressed (LOW-to-HIGH transition) */ 47 | void ISRdemo() { 48 | 49 | /* Blink hardware LED for debug */ 50 | digitalWrite(13, HIGH); 51 | 52 | /* Toggle PCF8575 output 0 for demo */ 53 | expander.toggle(); 54 | 55 | /* Blink hardware LED for debug */ 56 | digitalWrite(13, LOW); 57 | } 58 | 59 | /** loop() */ 60 | void loop() { 61 | 62 | /* Blink demo */ 63 | expander.blink(1, 5, 500); // Blink led 2 64 | delay(1000); 65 | expander.blink(2, 5, 500); // Blink led 3 66 | delay(1000); 67 | 68 | /* DigitalWrite demo */ 69 | expander.digitalWrite(1, HIGH); // Turn off led 2 70 | delay(500); 71 | expander.digitalWrite(2, HIGH); // Turn off led 3 72 | delay(500); 73 | expander.digitalWrite(1, LOW); // Turn on led 2 74 | delay(500); 75 | expander.digitalWrite(2, LOW); // Turn on led 3 76 | delay(500); 77 | 78 | /* Toggle demo */ 79 | expander.toggle(1); // Toggle led 2 80 | expander.toggle(2); // Toggle led 3 81 | delay(1000); 82 | expander.toggle(1); // Toggle led 2 83 | expander.toggle(2); // Toggle led 3 84 | delay(1000); 85 | 86 | /* Direct pins acces demo (does not with input setup) */ 87 | //expander.write(255); // All led off 88 | //delay(1000); 89 | //expander.write(0); // All led on 90 | //delay(1000); 91 | 92 | /* DigitalRead demo */ 93 | expander.detachInterrupt(3); // Temporaly disable button interrupt 94 | delay(1000); // PRESS THE BUTTON NOW (if you want to press it) ! 95 | Serial.println(expander.digitalRead(3) ? "HIGH" : "LOW"); // Print button pin state 96 | Serial.println(expander.read(), DEC); // Read the whole pins input register 97 | expander.attachInterrupt(3, ISRdemo, FALLING); // Re-enable interrupt on button pin 98 | 99 | /* Final demo (warning: will make button bug) */ 100 | //expander.set(); // All led off 101 | //delay(1000); 102 | //expander.clear(); // All led on 103 | delay(5000); 104 | } 105 | -------------------------------------------------------------------------------- /api/public/admin/import-recipe.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | Recipes 11 | 12 | 37 | 38 | 39 | 40 | order_by_asc('name')->find_many(); 44 | 45 | $html = file_get_contents($_GET['add']); 46 | $data = Mf2\parse($html); 47 | if($data && isset($data['items']) && count($data['items'])): 48 | $recipe = $data['items'][0]['properties']; 49 | ?> 50 | 51 |
52 | 53 |
54 | Recipe Name
55 | 56 |
57 | 58 |
59 | Photo
60 | 61 | 62 |
63 | 64 |
65 | Ingredients 66 |
67 | $g): 69 | if(preg_match('/(.+) - (.+)/', $g, $match)) { 70 | $name = $match[1]; 71 | $amount = $match[2]; 72 | } else { 73 | $name = ''; 74 | $amount = ''; 75 | } 76 | ?> 77 |
78 |
79 | 85 | 86 | 87 | 88 |
89 | 92 |
93 |
94 | 95 |
96 | 97 | 98 |
99 | 100 | 101 |

Could not find an h-recipe on the page

102 | 103 | 104 | 107 |
108 |
109 | 110 |
111 | 114 | 115 | -------------------------------------------------------------------------------- /api/public/admin/recipes.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | Edit Recipes 11 | 12 | 25 | 26 | 27 | 28 | 29 |

Edit Recipes

30 | 31 | 32 | order_by_asc('name') 35 | ->find_many(); 36 | foreach($recipes as $recipe): 37 | $ingredients = ORM::for_table('recipe_ingredients') 38 | ->left_outer_join('ingredients', ['ingredients.id', '=', 'recipe_ingredients.ingredient_id']) 39 | ->left_outer_join('pumps', ['ingredients.id', '=', 'pumps.ingredient_id']) 40 | ->where('recipe_id', $recipe->id) 41 | ->order_by_asc('order') 42 | ->find_many(); 43 | $all_ingredients_present = array_reduce($ingredients, function($carry, $g){ 44 | return $carry && $g->available; 45 | }, true); 46 | ?> 47 | 75 | 78 | 79 |

80 | 81 |

New Recipe

82 |
83 | 84 | 85 | 86 |
87 | 88 |

89 | 90 |

Import from h-recipe

91 |
92 |
93 | 94 |
95 | 96 |

97 |

98 | 99 | 109 | 110 | -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED_SRAM/Piccolino_OLED_SRAM.h: -------------------------------------------------------------------------------- 1 | #include "Arduino.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #ifndef _Piccolino_OLED_SRAM_H 7 | #define _Piccolino_OLED_SRAM_H 8 | 9 | #define ADDR_VIDEOBUFFER 0x7c00 10 | 11 | #define SSD1306_I2C_ADDRESS 0x3C // 011110+SA0+RW - 0x3C or 0x3D 12 | #define SSD1306_128_64 13 | #define SSD1306_LCDWIDTH 128 14 | #define SSD1306_LCDHEIGHT 64 15 | #define SSD1306_SETCONTRAST 0x81 16 | #define SSD1306_DISPLAYALLON_RESUME 0xA4 17 | #define SSD1306_DISPLAYALLON 0xA5 18 | #define SSD1306_NORMALDISPLAY 0xA6 19 | #define SSD1306_INVERTDISPLAY 0xA7 20 | #define SSD1306_DISPLAYOFF 0xAE 21 | #define SSD1306_DISPLAYON 0xAF 22 | #define SSD1306_SETDISPLAYOFFSET 0xD3 23 | #define SSD1306_SETCOMPINS 0xDA 24 | #define SSD1306_SETVCOMDETECT 0xDB 25 | #define SSD1306_SETDISPLAYCLOCKDIV 0xD5 26 | #define SSD1306_SETPRECHARGE 0xD9 27 | #define SSD1306_SETMULTIPLEX 0xA8 28 | #define SSD1306_SETLOWCOLUMN 0x00 29 | #define SSD1306_SETHIGHCOLUMN 0x10 30 | #define SSD1306_SETSTARTLINE 0x40 31 | #define SSD1306_MEMORYMODE 0x20 32 | #define SSD1306_COMSCANINC 0xC0 33 | #define SSD1306_COMSCANDEC 0xC8 34 | #define SSD1306_SEGREMAP 0xA0 35 | #define SSD1306_CHARGEPUMP 0x8D 36 | #define SSD1306_EXTERNALVCC 0x1 37 | #define SSD1306_SWITCHCAPVCC 0x2 38 | 39 | // Scrolling #defines 40 | #define SSD1306_ACTIVATE_SCROLL 0x2F 41 | #define SSD1306_DEACTIVATE_SCROLL 0x2E 42 | #define SSD1306_SET_VERTICAL_SCROLL_AREA 0xA3 43 | #define SSD1306_RIGHT_HORIZONTAL_SCROLL 0x26 44 | #define SSD1306_LEFT_HORIZONTAL_SCROLL 0x27 45 | #define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29 46 | #define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A 47 | 48 | #define swap(a, b) { int16_t t = a; a = b; b = t; } 49 | 50 | #define WHITE 1 51 | #define BLACK 0 52 | #define GRAY 2 53 | 54 | class Piccolino_OLED_SRAM : public Print { 55 | public: 56 | 57 | Piccolino_OLED_SRAM(); 58 | ~Piccolino_OLED_SRAM(); 59 | 60 | void begin(uint8_t switchvcc = SSD1306_SWITCHCAPVCC, uint8_t i2caddr = SSD1306_I2C_ADDRESS); 61 | void ssd1306_command(uint8_t c); 62 | void ssd1306_data(uint8_t c); 63 | 64 | void invertDisplay(uint8_t i); 65 | 66 | void update(); 67 | void clearBuffer(); 68 | 69 | //void setCursor(byte column, byte line); 70 | void clear(); 71 | void clearpart(int from); 72 | void clearpart(int from, int tto); 73 | void clearLine(byte line); 74 | void drawPixel(int16_t x, int16_t y, uint16_t color); 75 | void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size); 76 | void setCursor(int16_t x, int16_t y); 77 | void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); 78 | void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); 79 | void setTextSize(uint8_t s); 80 | void setTextColor(uint16_t c); 81 | void setTextColor(uint16_t c, uint16_t bg); 82 | void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color); 83 | virtual size_t write(uint8_t); 84 | void updateRow(int rowID); 85 | void updateRow(int startID, int endID); 86 | byte buff[128]; // video buffer 87 | 88 | protected: 89 | uint8_t _i2caddr; 90 | int16_t cursor_x, cursor_y, textcolor, textbgcolor; 91 | uint8_t textsize; 92 | boolean wrap; // If set, 'wrap' text at right edge of display 93 | 94 | private: 95 | int8_t sclk, dc, rst, cs; 96 | byte m_col; 97 | byte m_row; 98 | }; 99 | 100 | #endif -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED/Piccolino_OLED.h: -------------------------------------------------------------------------------- 1 | #include "Arduino.h" 2 | #include 3 | 4 | #ifndef _PICCOLINO_OLED_H 5 | #define _PICCOLINO_OLED_H 6 | 7 | #define ADDR_VIDEOBUFFER 0x7c00 8 | 9 | #define SSD1306_I2C_ADDRESS 0x3C // 011110+SA0+RW - 0x3C or 0x3D 10 | #define SSD1306_128_64 11 | #define SSD1306_LCDWIDTH 128 12 | #define SSD1306_LCDHEIGHT 64 13 | #define SSD1306_SETCONTRAST 0x81 14 | #define SSD1306_DISPLAYALLON_RESUME 0xA4 15 | #define SSD1306_DISPLAYALLON 0xA5 16 | #define SSD1306_NORMALDISPLAY 0xA6 17 | #define SSD1306_INVERTDISPLAY 0xA7 18 | #define SSD1306_DISPLAYOFF 0xAE 19 | #define SSD1306_DISPLAYON 0xAF 20 | #define SSD1306_SETDISPLAYOFFSET 0xD3 21 | #define SSD1306_SETCOMPINS 0xDA 22 | #define SSD1306_SETVCOMDETECT 0xDB 23 | #define SSD1306_SETDISPLAYCLOCKDIV 0xD5 24 | #define SSD1306_SETPRECHARGE 0xD9 25 | #define SSD1306_SETMULTIPLEX 0xA8 26 | #define SSD1306_SETLOWCOLUMN 0x00 27 | #define SSD1306_SETHIGHCOLUMN 0x10 28 | #define SSD1306_SETSTARTLINE 0x40 29 | #define SSD1306_MEMORYMODE 0x20 30 | #define SSD1306_COMSCANINC 0xC0 31 | #define SSD1306_COMSCANDEC 0xC8 32 | #define SSD1306_SEGREMAP 0xA0 33 | #define SSD1306_CHARGEPUMP 0x8D 34 | #define SSD1306_EXTERNALVCC 0x1 35 | #define SSD1306_SWITCHCAPVCC 0x2 36 | 37 | // Scrolling #defines 38 | #define SSD1306_ACTIVATE_SCROLL 0x2F 39 | #define SSD1306_DEACTIVATE_SCROLL 0x2E 40 | #define SSD1306_SET_VERTICAL_SCROLL_AREA 0xA3 41 | #define SSD1306_RIGHT_HORIZONTAL_SCROLL 0x26 42 | #define SSD1306_LEFT_HORIZONTAL_SCROLL 0x27 43 | #define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29 44 | #define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A 45 | 46 | #define swap(a, b) { int16_t t = a; a = b; b = t; } 47 | 48 | #define GRAY 2 49 | #define WHITE 1 50 | #define BLACK 0 51 | 52 | #define ON 1 53 | #define OFF 0 54 | 55 | class Piccolino_OLED : public Print { 56 | public: 57 | 58 | Piccolino_OLED(); 59 | ~Piccolino_OLED(); 60 | 61 | void begin(uint8_t switchvcc = SSD1306_SWITCHCAPVCC, uint8_t i2caddr = SSD1306_I2C_ADDRESS); 62 | void ssd1306_command(uint8_t c); 63 | void ssd1306_data(uint8_t c); 64 | 65 | void invertDisplay(uint8_t i); 66 | 67 | void update(); 68 | void clearBuffer(); 69 | 70 | //void setCursor(byte column, byte line); 71 | void clear(); 72 | void clearpart(int from); 73 | void clearpart(int from, int tto); 74 | void clearLine(byte line); 75 | void drawPixel(int16_t x, int16_t y, uint16_t color); 76 | void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size); 77 | void setCursor(int16_t x, int16_t y); 78 | void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); 79 | void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); 80 | void setTextSize(uint8_t s); 81 | void setTextColor(uint16_t c); 82 | void setTextColor(uint16_t c, uint16_t bg); 83 | void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color); 84 | virtual size_t write(uint8_t); 85 | void updateRow(int rowID); 86 | void updateRow(int startID, int endID); 87 | byte buff[1024]; // video buffer 88 | void displayOFF(); 89 | void displayON(); 90 | void dim(bool how); 91 | uint16_t getColor(uint16_t color, uint32_t index); 92 | void drawCircle(int16_t cx, int16_t cy, int16_t radius, 93 | uint16_t color, bool fill); 94 | 95 | protected: 96 | uint8_t _i2caddr; 97 | int16_t cursor_x, cursor_y, textcolor, textbgcolor; 98 | uint8_t textsize; 99 | boolean wrap; // If set, 'wrap' text at right edge of display 100 | 101 | private: 102 | int8_t sclk, dc, rst, cs; 103 | byte m_col; 104 | byte m_row; 105 | }; 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /Arduino/calibrate/calibrate.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define SCALE_DATA 3 9 | #define SCALE_CLK 4 10 | 11 | #define SCALE_CALIBRATION 0 12 | 13 | HX711 scale(SCALE_DATA, SCALE_CLK); 14 | // PCF8575 expander; 15 | Piccolino_OLED_SRAM display; 16 | 17 | /* 18 | How to Calibrate Your Scale 19 | 20 | 1. Call set_scale() with no parameter. 21 | 2. Call tare() with no parameter. 22 | 3. Place a known weight on the scale and call get_units(10). 23 | 4. Divide the result in step 3 to your known weight. You should get about the parameter you need to pass to set_scale. 24 | 5. Adjust the parameter in step 4 until you get an accurate reading. 25 | */ 26 | 27 | 28 | const byte expanderAddress = 0x20; 29 | 30 | const int button1pin = 14; 31 | const int button2pin = 15; 32 | 33 | void setup() { 34 | Serial.begin(57600); 35 | 36 | Serial.println("*-*-*-*-*-*-*-*-*-*-*-*-*"); 37 | Serial.println("*-*-*-*-*-*-*-*-*-*-*-*-*"); 38 | Serial.println("BarBot Calibration"); 39 | Serial.println("*-*-*-*-*-*-*-*-*-*-*-*-*"); 40 | Serial.println("*-*-*-*-*-*-*-*-*-*-*-*-*"); 41 | 42 | Wire.begin(); 43 | 44 | // expander.begin(expanderAddress); 45 | // expander.pinMode(0, OUTPUT); 46 | // expander.pinMode(1, OUTPUT); 47 | 48 | display.begin(); 49 | display.clear(); 50 | 51 | display.setTextSize(2); 52 | display.setTextColor(WHITE); 53 | 54 | pinMode(button1pin, INPUT); 55 | pinMode(button2pin, INPUT); 56 | 57 | 58 | /* 59 | Serial.println("Before setting up the scale:"); 60 | Serial.print("read: \t\t"); 61 | Serial.println(scale.read()); // print a raw reading from the ADC 62 | 63 | Serial.print("read average: \t\t"); 64 | Serial.println(scale.read_average(20)); // print the average of 20 readings from the ADC 65 | 66 | Serial.print("get value: \t\t"); 67 | Serial.println(scale.get_value(5)); // print the average of 5 readings from the ADC minus the tare weight (not set yet) 68 | 69 | Serial.print("get units: \t\t"); 70 | Serial.println(scale.get_units(5), 1); // print the average of 5 readings from the ADC minus tare weight (not set) divided 71 | // by the SCALE parameter (not set yet) 72 | */ 73 | 74 | Serial.println("Resetting scale..."); 75 | scale.set_scale(SCALE_CALIBRATION); 76 | 77 | /* 78 | Serial.println("After setting up the scale:"); 79 | 80 | Serial.print("read: \t\t"); 81 | Serial.println(scale.read()); // print a raw reading from the ADC 82 | 83 | Serial.print("read average: \t\t"); 84 | Serial.println(scale.read_average(20)); // print the average of 20 readings from the ADC 85 | 86 | Serial.print("get value: \t\t"); 87 | Serial.println(scale.get_value(5)); // print the average of 5 readings from the ADC minus the tare weight, set with tare() 88 | 89 | Serial.print("get units: \t\t"); 90 | Serial.println(scale.get_units(5), 1); // print the average of 5 readings from the ADC minus tare weight, divided 91 | // by the SCALE parameter set with set_scale 92 | */ 93 | 94 | Serial.println("Tare..."); 95 | scale.tare(); 96 | Serial.println("Ready"); 97 | } 98 | 99 | double currentWeight; 100 | float currentValue; 101 | char oledValueString[10]; 102 | char oledWeightString[10]; 103 | 104 | int lastButton1 = LOW; 105 | int lastButton2 = LOW; 106 | 107 | void loop() { 108 | /* 109 | int button1 = digitalRead(button1pin); 110 | int button2 = digitalRead(button2pin); 111 | 112 | if(button1 != lastButton1) { 113 | Serial.println("Button 1 changed"); 114 | lastButton1 = button1; 115 | } 116 | if(button2 != lastButton2) { 117 | Serial.println("Button 2 changed"); 118 | lastButton2 = button2; 119 | if(button2 == HIGH) { 120 | scale.tare(); 121 | } 122 | } 123 | 124 | expander.digitalWrite(0, button1); 125 | */ 126 | 127 | currentWeight = scale.get_units(2); 128 | Serial.println(currentWeight); 129 | 130 | sprintf(oledWeightString, "%01d.%03dg ", (int)(currentWeight), abs((int)(currentWeight*1000)%1000)); 131 | 132 | display.setCursor(0, 0); 133 | display.print(oledWeightString); 134 | 135 | //display.setCursor(0,52); 136 | //display.print(oledWeightString); 137 | display.update(); 138 | } 139 | -------------------------------------------------------------------------------- /api/public/assets/jscookie.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * JavaScript Cookie v2.1.3 3 | * https://github.com/js-cookie/js-cookie 4 | * 5 | * Copyright 2006, 2015 Klaus Hartl & Fagner Brack 6 | * Released under the MIT license 7 | */ 8 | ;(function (factory) { 9 | var registeredInModuleLoader = false; 10 | if (typeof define === 'function' && define.amd) { 11 | define(factory); 12 | registeredInModuleLoader = true; 13 | } 14 | if (typeof exports === 'object') { 15 | module.exports = factory(); 16 | registeredInModuleLoader = true; 17 | } 18 | if (!registeredInModuleLoader) { 19 | var OldCookies = window.Cookies; 20 | var api = window.Cookies = factory(); 21 | api.noConflict = function () { 22 | window.Cookies = OldCookies; 23 | return api; 24 | }; 25 | } 26 | }(function () { 27 | function extend () { 28 | var i = 0; 29 | var result = {}; 30 | for (; i < arguments.length; i++) { 31 | var attributes = arguments[ i ]; 32 | for (var key in attributes) { 33 | result[key] = attributes[key]; 34 | } 35 | } 36 | return result; 37 | } 38 | 39 | function init (converter) { 40 | function api (key, value, attributes) { 41 | var result; 42 | if (typeof document === 'undefined') { 43 | return; 44 | } 45 | 46 | // Write 47 | 48 | if (arguments.length > 1) { 49 | attributes = extend({ 50 | path: '/' 51 | }, api.defaults, attributes); 52 | 53 | if (typeof attributes.expires === 'number') { 54 | var expires = new Date(); 55 | expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); 56 | attributes.expires = expires; 57 | } 58 | 59 | try { 60 | result = JSON.stringify(value); 61 | if (/^[\{\[]/.test(result)) { 62 | value = result; 63 | } 64 | } catch (e) {} 65 | 66 | if (!converter.write) { 67 | value = encodeURIComponent(String(value)) 68 | .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); 69 | } else { 70 | value = converter.write(value, key); 71 | } 72 | 73 | key = encodeURIComponent(String(key)); 74 | key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); 75 | key = key.replace(/[\(\)]/g, escape); 76 | 77 | return (document.cookie = [ 78 | key, '=', value, 79 | attributes.expires ? '; expires=' + attributes.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE 80 | attributes.path ? '; path=' + attributes.path : '', 81 | attributes.domain ? '; domain=' + attributes.domain : '', 82 | attributes.secure ? '; secure' : '' 83 | ].join('')); 84 | } 85 | 86 | // Read 87 | 88 | if (!key) { 89 | result = {}; 90 | } 91 | 92 | // To prevent the for loop in the first place assign an empty array 93 | // in case there are no cookies at all. Also prevents odd result when 94 | // calling "get()" 95 | var cookies = document.cookie ? document.cookie.split('; ') : []; 96 | var rdecode = /(%[0-9A-Z]{2})+/g; 97 | var i = 0; 98 | 99 | for (; i < cookies.length; i++) { 100 | var parts = cookies[i].split('='); 101 | var cookie = parts.slice(1).join('='); 102 | 103 | if (cookie.charAt(0) === '"') { 104 | cookie = cookie.slice(1, -1); 105 | } 106 | 107 | try { 108 | var name = parts[0].replace(rdecode, decodeURIComponent); 109 | cookie = converter.read ? 110 | converter.read(cookie, name) : converter(cookie, name) || 111 | cookie.replace(rdecode, decodeURIComponent); 112 | 113 | if (this.json) { 114 | try { 115 | cookie = JSON.parse(cookie); 116 | } catch (e) {} 117 | } 118 | 119 | if (key === name) { 120 | result = cookie; 121 | break; 122 | } 123 | 124 | if (!key) { 125 | result[name] = cookie; 126 | } 127 | } catch (e) {} 128 | } 129 | 130 | return result; 131 | } 132 | 133 | api.set = api; 134 | api.get = function (key) { 135 | return api.call(api, key); 136 | }; 137 | api.getJSON = function () { 138 | return api.apply({ 139 | json: true 140 | }, [].slice.call(arguments)); 141 | }; 142 | api.defaults = {}; 143 | 144 | api.remove = function (key, attributes) { 145 | api(key, '', extend(attributes, { 146 | expires: -1 147 | })); 148 | }; 149 | 150 | api.withConverter = init; 151 | 152 | return api; 153 | } 154 | 155 | return init(function () {}); 156 | })); -------------------------------------------------------------------------------- /Arduino/SPI/examples/BarometricPressureSensor/BarometricPressureSensor/BarometricPressureSensor.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SCP1000 Barometric Pressure Sensor Display 3 | 4 | Shows the output of a Barometric Pressure Sensor on a 5 | Uses the SPI library. For details on the sensor, see: 6 | http://www.sparkfun.com/commerce/product_info.php?products_id=8161 7 | http://www.vti.fi/en/support/obsolete_products/pressure_sensors/ 8 | 9 | This sketch adapted from Nathan Seidle's SCP1000 example for PIC: 10 | http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip 11 | 12 | Circuit: 13 | SCP1000 sensor attached to pins 6, 7, 10 - 13: 14 | DRDY: pin 6 15 | CSB: pin 7 16 | MOSI: pin 11 17 | MISO: pin 12 18 | SCK: pin 13 19 | 20 | created 31 July 2010 21 | modified 14 August 2010 22 | by Tom Igoe 23 | */ 24 | 25 | // the sensor communicates using SPI, so include the library: 26 | #include 27 | 28 | //Sensor's memory register addresses: 29 | const int PRESSURE = 0x1F; //3 most significant bits of pressure 30 | const int PRESSURE_LSB = 0x20; //16 least significant bits of pressure 31 | const int TEMPERATURE = 0x21; //16 bit temperature reading 32 | cont byte READ = 0b00000000; // SCP1000's read command 33 | const byte WRITE = 0b00000010; // SCP1000's write command 34 | // pins used for the connection with the sensor 35 | // the other you need are controlled by the SPI library): 36 | const int dataReadyPin = 6; 37 | const int chipSelectPin = 7; 38 | 39 | void setup() { 40 | Serial.begin(9600); 41 | 42 | // start the SPI library: 43 | SPI.begin(); 44 | 45 | // initalize the data ready and chip select pins: 46 | pinMode(dataReadyPin, INPUT); 47 | pinMode(chipSelectPin, OUTPUT); 48 | 49 | //Configure SCP1000 for low noise configuration: 50 | writeRegister(0x02, 0x2D); 51 | writeRegister(0x01, 0x03); 52 | writeRegister(0x03, 0x02); 53 | // give the sensor time to set up: 54 | delay(100); 55 | } 56 | 57 | void loop() { 58 | //Select High Resolution Mode 59 | writeRegister(0x03, 0x0A); 60 | 61 | // don't do anything until the data ready pin is high: 62 | if (digitalRead(dataReadyPin) == HIGH) { 63 | //Read the temperature data 64 | int tempData = readRegister(0x21, 2); 65 | 66 | // convert the temperature to celsius and display it: 67 | float realTemp = (float)tempData / 20.0; 68 | Serial.print("Temp[C]="); 69 | Serial.print(realTemp); 70 | 71 | 72 | //Read the pressure data highest 3 bits: 73 | byte pressure_data_high = readRegister(0x1F, 1); 74 | pressure_data_high &= 0b00000111; //you only needs bits 2 to 0 75 | 76 | //Read the pressure data lower 16 bits: 77 | unsigned int pressure_data_low = readRegister(0x20, 2); 78 | //combine the two parts into one 19-bit number: 79 | long pressure = ((pressure_data_high << 16) | pressure_data_low)/4; 80 | 81 | // display the temperature: 82 | Serial.println("\tPressure [Pa]=" + String(pressure)); 83 | } 84 | } 85 | 86 | //Read from or write to register from the SCP1000: 87 | unsigned int readRegister(byte thisRegister, int bytesToRead ) { 88 | byte inByte = 0; // incoming byte from the SPI 89 | unsigned int result = 0; // result to return 90 | 91 | // SCP1000 expects the register name in the upper 6 bits 92 | // of the byte. So shift the bits left by two bits: 93 | thisRegister = thisRegister << 2; 94 | // now combine the address and the command into one byte 95 | dataToSend = thisRegister & READ; 96 | 97 | // take the chip select low to select the device: 98 | digitalWrite(chipSelectPin, LOW); 99 | // send the device the register you want to read: 100 | SPI.transfer(dataToSend); 101 | // send a value of 0 to read the first byte returned: 102 | result = SPI.transfer(0x00); 103 | // decrement the number of bytes left to read: 104 | bytesToRead--; 105 | // if you still have another byte to read: 106 | if (bytesToRead > 0) { 107 | // shift the first byte left, then get the second byte: 108 | result = result << 8; 109 | inByte = SPI.transfer(0x00); 110 | // combine the byte you just got with the previous one: 111 | result = result | inByte; 112 | // decrement the number of bytes left to read: 113 | bytesToRead--; 114 | } 115 | // take the chip select high to de-select: 116 | digitalWrite(chipSelectPin, HIGH); 117 | // return the result: 118 | return(result); 119 | } 120 | 121 | 122 | //Sends a write command to SCP1000 123 | 124 | void writeRegister(byte thisRegister, byte thisValue) { 125 | 126 | // SCP1000 expects the register address in the upper 6 bits 127 | // of the byte. So shift the bits left by two bits: 128 | thisRegister = thisRegister << 2; 129 | // now combine the register address and the command into one byte: 130 | dataToSend = thisRegister | WRITE; 131 | 132 | // take the chip select low to select the device: 133 | digitalWrite(chipSelectPin, LOW); 134 | 135 | SPI.transfer(dataToSend); //Send register location 136 | SPI.transfer(thisValue); //Send value to record into register 137 | 138 | // take the chip select high to de-select: 139 | digitalWrite(chipSelectPin, HIGH); 140 | } 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /Arduino/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SCP1000 Barometric Pressure Sensor Display 3 | 4 | Shows the output of a Barometric Pressure Sensor on a 5 | Uses the SPI library. For details on the sensor, see: 6 | http://www.sparkfun.com/commerce/product_info.php?products_id=8161 7 | http://www.vti.fi/en/support/obsolete_products/pressure_sensors/ 8 | 9 | This sketch adapted from Nathan Seidle's SCP1000 example for PIC: 10 | http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip 11 | 12 | Circuit: 13 | SCP1000 sensor attached to pins 6, 7, 10 - 13: 14 | DRDY: pin 6 15 | CSB: pin 7 16 | MOSI: pin 11 17 | MISO: pin 12 18 | SCK: pin 13 19 | 20 | created 31 July 2010 21 | modified 14 August 2010 22 | by Tom Igoe 23 | */ 24 | 25 | // the sensor communicates using SPI, so include the library: 26 | #include 27 | 28 | //Sensor's memory register addresses: 29 | const int PRESSURE = 0x1F; //3 most significant bits of pressure 30 | const int PRESSURE_LSB = 0x20; //16 least significant bits of pressure 31 | const int TEMPERATURE = 0x21; //16 bit temperature reading 32 | const byte READ = 0b11111100; // SCP1000's read command 33 | const byte WRITE = 0b00000010; // SCP1000's write command 34 | 35 | // pins used for the connection with the sensor 36 | // the other you need are controlled by the SPI library): 37 | const int dataReadyPin = 6; 38 | const int chipSelectPin = 7; 39 | 40 | void setup() { 41 | Serial.begin(9600); 42 | 43 | // start the SPI library: 44 | SPI.begin(); 45 | 46 | // initalize the data ready and chip select pins: 47 | pinMode(dataReadyPin, INPUT); 48 | pinMode(chipSelectPin, OUTPUT); 49 | 50 | //Configure SCP1000 for low noise configuration: 51 | writeRegister(0x02, 0x2D); 52 | writeRegister(0x01, 0x03); 53 | writeRegister(0x03, 0x02); 54 | // give the sensor time to set up: 55 | delay(100); 56 | } 57 | 58 | void loop() { 59 | //Select High Resolution Mode 60 | writeRegister(0x03, 0x0A); 61 | 62 | // don't do anything until the data ready pin is high: 63 | if (digitalRead(dataReadyPin) == HIGH) { 64 | //Read the temperature data 65 | int tempData = readRegister(0x21, 2); 66 | 67 | // convert the temperature to celsius and display it: 68 | float realTemp = (float)tempData / 20.0; 69 | Serial.print("Temp[C]="); 70 | Serial.print(realTemp); 71 | 72 | 73 | //Read the pressure data highest 3 bits: 74 | byte pressure_data_high = readRegister(0x1F, 1); 75 | pressure_data_high &= 0b00000111; //you only needs bits 2 to 0 76 | 77 | //Read the pressure data lower 16 bits: 78 | unsigned int pressure_data_low = readRegister(0x20, 2); 79 | //combine the two parts into one 19-bit number: 80 | long pressure = ((pressure_data_high << 16) | pressure_data_low)/4; 81 | 82 | // display the temperature: 83 | Serial.println("\tPressure [Pa]=" + String(pressure)); 84 | } 85 | } 86 | 87 | //Read from or write to register from the SCP1000: 88 | unsigned int readRegister(byte thisRegister, int bytesToRead ) { 89 | byte inByte = 0; // incoming byte from the SPI 90 | unsigned int result = 0; // result to return 91 | Serial.print(thisRegister, BIN); 92 | Serial.print("\t"); 93 | // SCP1000 expects the register name in the upper 6 bits 94 | // of the byte. So shift the bits left by two bits: 95 | thisRegister = thisRegister << 2; 96 | // now combine the address and the command into one byte 97 | byte dataToSend = thisRegister & READ; 98 | Serial.println(thisRegister, BIN); 99 | // take the chip select low to select the device: 100 | digitalWrite(chipSelectPin, LOW); 101 | // send the device the register you want to read: 102 | SPI.transfer(dataToSend); 103 | // send a value of 0 to read the first byte returned: 104 | result = SPI.transfer(0x00); 105 | // decrement the number of bytes left to read: 106 | bytesToRead--; 107 | // if you still have another byte to read: 108 | if (bytesToRead > 0) { 109 | // shift the first byte left, then get the second byte: 110 | result = result << 8; 111 | inByte = SPI.transfer(0x00); 112 | // combine the byte you just got with the previous one: 113 | result = result | inByte; 114 | // decrement the number of bytes left to read: 115 | bytesToRead--; 116 | } 117 | // take the chip select high to de-select: 118 | digitalWrite(chipSelectPin, HIGH); 119 | // return the result: 120 | return(result); 121 | } 122 | 123 | 124 | //Sends a write command to SCP1000 125 | 126 | void writeRegister(byte thisRegister, byte thisValue) { 127 | 128 | // SCP1000 expects the register address in the upper 6 bits 129 | // of the byte. So shift the bits left by two bits: 130 | thisRegister = thisRegister << 2; 131 | // now combine the register address and the command into one byte: 132 | byte dataToSend = thisRegister | WRITE; 133 | 134 | // take the chip select low to select the device: 135 | digitalWrite(chipSelectPin, LOW); 136 | 137 | SPI.transfer(dataToSend); //Send register location 138 | SPI.transfer(thisValue); //Send value to record into register 139 | 140 | // take the chip select high to de-select: 141 | digitalWrite(chipSelectPin, HIGH); 142 | } 143 | 144 | -------------------------------------------------------------------------------- /api/public/index.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | BarBot 11 | 12 | 13 | 36 | 37 | 38 | 39 | 94 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /Arduino/CapacitiveSensor/CapacitiveSensor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | CapacitiveSense.h v.04 - Capacitive Sensing Library for 'duino / Wiring 3 | Copyright (c) 2009 Paul Bagder All right reserved. 4 | Version 04 by Paul Stoffregen - Arduino 1.0 compatibility, issue 146 fix 5 | vim: set ts=4: 6 | */ 7 | 8 | #if ARDUINO >= 100 9 | #include "Arduino.h" 10 | #else 11 | #include "WProgram.h" 12 | #include "pins_arduino.h" 13 | #include "WConstants.h" 14 | #endif 15 | 16 | #include "CapacitiveSensor.h" 17 | 18 | // Constructor ///////////////////////////////////////////////////////////////// 19 | // Function that handles the creation and setup of instances 20 | 21 | CapacitiveSensor::CapacitiveSensor(uint8_t sendPin, uint8_t receivePin) 22 | { 23 | uint8_t sPort, rPort; 24 | 25 | // initialize this instance's variables 26 | // Serial.begin(9600); // for debugging 27 | error = 1; 28 | loopTimingFactor = 310; // determined empirically - a hack 29 | 30 | CS_Timeout_Millis = (2000 * (float)loopTimingFactor * (float)F_CPU) / 16000000; 31 | CS_AutocaL_Millis = 20000; 32 | 33 | // Serial.print("timwOut = "); 34 | // Serial.println(CS_Timeout_Millis); 35 | 36 | // get pin mapping and port for send Pin - from PinMode function in core 37 | 38 | #ifdef NUM_DIGITAL_PINS 39 | if (sendPin >= NUM_DIGITAL_PINS) error = -1; 40 | if (receivePin >= NUM_DIGITAL_PINS) error = -1; 41 | #endif 42 | 43 | sBit = digitalPinToBitMask(sendPin); // get send pin's ports and bitmask 44 | sPort = digitalPinToPort(sendPin); 45 | sReg = portModeRegister(sPort); 46 | sOut = portOutputRegister(sPort); // get pointer to output register 47 | 48 | rBit = digitalPinToBitMask(receivePin); // get receive pin's ports and bitmask 49 | rPort = digitalPinToPort(receivePin); 50 | rReg = portModeRegister(rPort); 51 | rIn = portInputRegister(rPort); 52 | rOut = portOutputRegister(rPort); 53 | 54 | // get pin mapping and port for receive Pin - from digital pin functions in Wiring.c 55 | noInterrupts(); 56 | *sReg |= sBit; // set sendpin to OUTPUT 57 | interrupts(); 58 | leastTotal = 0x0FFFFFFFL; // input large value for autocalibrate begin 59 | lastCal = millis(); // set millis for start 60 | } 61 | 62 | // Public Methods ////////////////////////////////////////////////////////////// 63 | // Functions available in Wiring sketches, this library, and other libraries 64 | 65 | long CapacitiveSensor::capacitiveSensor(uint8_t samples) 66 | { 67 | total = 0; 68 | if (samples == 0) return 0; 69 | if (error < 0) return -1; // bad pin 70 | 71 | 72 | for (uint8_t i = 0; i < samples; i++) { // loop for samples parameter - simple lowpass filter 73 | if (SenseOneCycle() < 0) return -2; // variable over timeout 74 | } 75 | 76 | // only calibrate if time is greater than CS_AutocaL_Millis and total is less than 10% of baseline 77 | // this is an attempt to keep from calibrating when the sensor is seeing a "touched" signal 78 | 79 | if ( (millis() - lastCal > CS_AutocaL_Millis) && abs(total - leastTotal) < (int)(.10 * (float)leastTotal) ) { 80 | 81 | // Serial.println(); // debugging 82 | // Serial.println("auto-calibrate"); 83 | // Serial.println(); 84 | // delay(2000); */ 85 | 86 | leastTotal = 0x0FFFFFFFL; // reset for "autocalibrate" 87 | lastCal = millis(); 88 | } 89 | /*else{ // debugging 90 | Serial.print(" total = "); 91 | Serial.print(total); 92 | 93 | Serial.print(" leastTotal = "); 94 | Serial.println(leastTotal); 95 | 96 | Serial.print("total - leastTotal = "); 97 | x = total - leastTotal ; 98 | Serial.print(x); 99 | Serial.print(" .1 * leastTotal = "); 100 | x = (int)(.1 * (float)leastTotal); 101 | Serial.println(x); 102 | } */ 103 | 104 | // routine to subtract baseline (non-sensed capacitance) from sensor return 105 | if (total < leastTotal) leastTotal = total; // set floor value to subtract from sensed value 106 | return(total - leastTotal); 107 | 108 | } 109 | 110 | long CapacitiveSensor::capacitiveSensorRaw(uint8_t samples) 111 | { 112 | total = 0; 113 | if (samples == 0) return 0; 114 | if (error < 0) return -1; // bad pin - this appears not to work 115 | 116 | for (uint8_t i = 0; i < samples; i++) { // loop for samples parameter - simple lowpass filter 117 | if (SenseOneCycle() < 0) return -2; // variable over timeout 118 | } 119 | 120 | return total; 121 | } 122 | 123 | 124 | void CapacitiveSensor::reset_CS_AutoCal(void){ 125 | leastTotal = 0x0FFFFFFFL; 126 | } 127 | 128 | void CapacitiveSensor::set_CS_AutocaL_Millis(unsigned long autoCal_millis){ 129 | CS_AutocaL_Millis = autoCal_millis; 130 | } 131 | 132 | void CapacitiveSensor::set_CS_Timeout_Millis(unsigned long timeout_millis){ 133 | CS_Timeout_Millis = (timeout_millis * (float)loopTimingFactor * (float)F_CPU) / 16000000; // floats to deal with large numbers 134 | } 135 | 136 | // Private Methods ///////////////////////////////////////////////////////////// 137 | // Functions only available to other functions in this library 138 | 139 | int CapacitiveSensor::SenseOneCycle(void) 140 | { 141 | noInterrupts(); 142 | *sOut &= ~sBit; // set Send Pin Register low 143 | 144 | *rReg &= ~rBit; // set receivePin to input 145 | *rOut &= ~rBit; // set receivePin Register low to make sure pullups are off 146 | 147 | *rReg |= rBit; // set pin to OUTPUT - pin is now LOW AND OUTPUT 148 | *rReg &= ~rBit; // set pin to INPUT 149 | 150 | *sOut |= sBit; // set send Pin High 151 | interrupts(); 152 | 153 | while ( !(*rIn & rBit) && (total < CS_Timeout_Millis) ) { // while receive pin is LOW AND total is positive value 154 | total++; 155 | } 156 | 157 | if (total > CS_Timeout_Millis) { 158 | return -2; // total variable over timeout 159 | } 160 | 161 | // set receive pin HIGH briefly to charge up fully - because the while loop above will exit when pin is ~ 2.5V 162 | noInterrupts(); 163 | *rOut |= rBit; // set receive pin HIGH - turns on pullup 164 | *rReg |= rBit; // set pin to OUTPUT - pin is now HIGH AND OUTPUT 165 | *rReg &= ~rBit; // set pin to INPUT 166 | *rOut &= ~rBit; // turn off pullup 167 | 168 | *sOut &= ~sBit; // set send Pin LOW 169 | interrupts(); 170 | 171 | while ( (*rIn & rBit) && (total < CS_Timeout_Millis) ) { // while receive pin is HIGH AND total is less than timeout 172 | total++; 173 | } 174 | // Serial.println(total); 175 | 176 | if (total >= CS_Timeout_Millis) { 177 | return -2; // total variable over timeout 178 | } else { 179 | return 1; 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /Arduino/PCF8575/PCF8575.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * See header file for details 3 | * 4 | * This program is free software: you can redistribute it and/or modify\n 5 | * it under the terms of the GNU General Public License as published by\n 6 | * the Free Software Foundation, either version 3 of the License, or\n 7 | * (at your option) any later version.\n 8 | * 9 | * This program is distributed in the hope that it will be useful,\n 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of\n 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n 12 | * GNU General Public License for more details.\n 13 | * 14 | * You should have received a copy of the GNU General Public License\n 15 | * along with this program. If not, see .\n 16 | */ 17 | 18 | /* Dependencies */ 19 | #include 20 | #include "PCF8575.h" 21 | #ifdef PCF8575_INTERRUPT_SUPPORT 22 | #include "PCint.h" 23 | #endif 24 | 25 | PCF8575::PCF8575() : 26 | _PORT(0), _PIN(0), _DDR(0), _address(0) 27 | #ifdef PCF8575_INTERRUPT_SUPPORT 28 | , _oldPIN(0), _isrIgnore(0), _pcintPin(0), _intMode(), _intCallback() 29 | #endif 30 | { 31 | } 32 | 33 | void PCF8575::begin(uint8_t address) { 34 | 35 | /* Store the I2C address and init the Wire library */ 36 | _address = address; 37 | Wire.begin(); 38 | readGPIO(); 39 | } 40 | 41 | void PCF8575::pinMode(uint8_t pin, uint8_t mode) { 42 | 43 | /* Switch according mode */ 44 | switch (mode) { 45 | case INPUT: 46 | _DDR &= ~(1 << pin); 47 | _PORT &= ~(1 << pin); 48 | break; 49 | 50 | case INPUT_PULLUP: 51 | _DDR &= ~(1 << pin); 52 | _PORT |= (1 << pin); 53 | break; 54 | 55 | case OUTPUT: 56 | _DDR |= (1 << pin); 57 | _PORT &= ~(1 << pin); 58 | break; 59 | 60 | default: 61 | break; 62 | } 63 | 64 | /* Update GPIO values */ 65 | updateGPIO(); 66 | } 67 | 68 | void PCF8575::digitalWrite(uint8_t pin, uint8_t value) { 69 | 70 | /* Set PORT bit value */ 71 | if (value) 72 | _PORT |= (1 << pin); 73 | else 74 | _PORT &= ~(1 << pin); 75 | 76 | /* Update GPIO values */ 77 | updateGPIO(); 78 | } 79 | 80 | uint8_t PCF8575::digitalRead(uint8_t pin) { 81 | 82 | /* Read GPIO */ 83 | readGPIO(); 84 | 85 | #ifdef PCF8575_INTERRUPT_SUPPORT 86 | /* Check for interrupt (manual detection) */ 87 | //checkForInterrupt(); 88 | #endif 89 | 90 | /* Read and return the pin state */ 91 | return (_PIN & (1 << pin)) ? HIGH : LOW; 92 | } 93 | 94 | void PCF8575::write(uint16_t value) { 95 | 96 | /* Store pins values and apply */ 97 | _PORT = value; 98 | 99 | /* Update GPIO values */ 100 | updateGPIO(); 101 | } 102 | 103 | uint16_t PCF8575::read() { 104 | 105 | /* Read GPIO */ 106 | readGPIO(); 107 | 108 | #ifdef PCF8575_INTERRUPT_SUPPORT 109 | /* Check for interrupt (manual detection) */ 110 | //checkForInterrupt(); 111 | #endif 112 | 113 | /* Return current pins values */ 114 | return _PIN; 115 | } 116 | 117 | void PCF8575::pullUp(uint8_t pin) { 118 | 119 | /* Same as pinMode(INPUT_PULLUP) */ 120 | pinMode(pin, INPUT_PULLUP); // /!\ pinMode form THE LIBRARY 121 | } 122 | 123 | void PCF8575::pullDown(uint8_t pin) { 124 | 125 | /* Same as pinMode(INPUT) */ 126 | pinMode(pin, INPUT); // /!\ pinMode form THE LIBRARY 127 | } 128 | 129 | void PCF8575::clear() { 130 | 131 | /* User friendly wrapper for write() */ 132 | write(0x0000); 133 | } 134 | 135 | void PCF8575::set() { 136 | 137 | /* User friendly wrapper for write() */ 138 | write(0xFFFF); 139 | } 140 | 141 | void PCF8575::toggle(uint8_t pin) { 142 | 143 | /* Toggle pin state */ 144 | _PORT ^= (1 << pin); 145 | 146 | /* Update GPIO values */ 147 | updateGPIO(); 148 | } 149 | 150 | void PCF8575::blink(uint8_t pin, uint16_t count, uint32_t duration) { 151 | 152 | /* Compute steps duration */ 153 | duration /= count * 2; 154 | 155 | /* Loop n times */ 156 | while (count--) { 157 | 158 | /* Toggle pin 2 times */ 159 | toggle(pin); 160 | delay(duration); 161 | toggle(pin); 162 | delay(duration); 163 | } 164 | } 165 | 166 | #ifdef PCF8575_INTERRUPT_SUPPORT 167 | void PCF8575::enableInterrupt(uint8_t pin, void (*selfCheckFunction)(void)) { 168 | 169 | /* Store interrupt pin number */ 170 | _pcintPin = pin; 171 | 172 | /* Setup interrupt pin */ 173 | #if ARDUINO >= 100 174 | ::pinMode(pin, INPUT_PULLUP); // /!\ pinMode form THE ARDUINO CORE 175 | #else 176 | ::pinMode(pin, INPUT); // /!\ pinMode form THE ARDUINO CORE 177 | ::digitalWrite(pin, HIGH); // /!\ digitalWrite form THE ARDUINO CORE 178 | #endif 179 | 180 | /* Attach interrupt handler */ 181 | PCattachInterrupt(pin, selfCheckFunction, FALLING); 182 | } 183 | 184 | void PCF8575::disableInterrupt() { 185 | 186 | /* Detach interrupt handler */ 187 | PCdetachInterrupt(_pcintPin); 188 | } 189 | 190 | void PCF8575::checkForInterrupt() { 191 | 192 | /* Avoid nested interrupt triggered by I2C read/write */ 193 | if(_isrIgnore) 194 | return; 195 | else 196 | _isrIgnore = 1; 197 | 198 | /* Re-enable interrupts to allow Wire library to work */ 199 | sei(); 200 | 201 | /* Read current pins values */ 202 | readGPIO(); 203 | 204 | /* Check all pins */ 205 | for (uint8_t i = 0; i < 16; ++i) { 206 | 207 | /* Check for interrupt handler */ 208 | if (!_intCallback[i]) 209 | continue; 210 | 211 | /* Check for interrupt event */ 212 | switch (_intMode[i]) { 213 | case CHANGE: 214 | if ((1 << i) & (_PIN ^ _oldPIN)) 215 | _intCallback[i](); 216 | break; 217 | 218 | case LOW: 219 | if (!(_PIN & (1 << i))) 220 | _intCallback[i](); 221 | break; 222 | 223 | case FALLING: 224 | if ((_oldPIN & (1 << i)) && !(_PIN & (1 << i))) 225 | _intCallback[i](); 226 | break; 227 | 228 | case RISING: 229 | if (!(_oldPIN & (1 << i)) && (_PIN & (1 << i))) 230 | _intCallback[i](); 231 | break; 232 | } 233 | } 234 | 235 | /* Turn off ISR ignore flag */ 236 | _isrIgnore = 0; 237 | } 238 | 239 | void PCF8575::attachInterrupt(uint8_t pin, void (*userFunc)(void), 240 | uint8_t mode) { 241 | 242 | /* Store interrupt mode and callback */ 243 | _intMode[pin] = mode; 244 | _intCallback[pin] = userFunc; 245 | } 246 | 247 | void PCF8575::detachInterrupt(uint8_t pin) { 248 | 249 | /* Void interrupt handler */ 250 | _intCallback[pin] = 0; 251 | } 252 | #endif 253 | 254 | void PCF8575::readGPIO() { 255 | 256 | #ifdef PCF8575_INTERRUPT_SUPPORT 257 | /* Store old _PIN value */ 258 | _oldPIN = _PIN; 259 | #endif 260 | 261 | /* Start request, wait for data and receive GPIO values as byte */ 262 | Wire.requestFrom(_address, (uint8_t) 0x02); 263 | while (Wire.available() < 2) 264 | ; 265 | _PIN = I2CREAD(); /* LSB first */ 266 | _PIN |= I2CREAD() << 8; 267 | } 268 | 269 | void PCF8575::updateGPIO() { 270 | 271 | /* Read current GPIO states */ 272 | //readGPIO(); // Experimental 273 | 274 | /* Compute new GPIO states */ 275 | //uint8_t value = ((_PIN & ~_DDR) & ~(~_DDR & _PORT)) | _PORT; // Experimental 276 | uint16_t value = (_PIN & ~_DDR) | _PORT; 277 | 278 | /* Start communication and send GPIO values as byte */ 279 | Wire.beginTransmission(_address); 280 | I2CWRITE(value & 0x00FF); 281 | I2CWRITE((value & 0xFF00) >> 8); 282 | Wire.endTransmission(); 283 | } 284 | -------------------------------------------------------------------------------- /Arduino/PCF8575/PCF8575.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief PCF8575 arduino library 3 | * @author SkyWodd 4 | * @version 2.0 5 | * @link http://skyduino.wordpress.com/ 6 | * 7 | * @section intro_sec Introduction 8 | * This class is designed to allow user to use PCF8575 gpio expander like any standard arduino pins.\n 9 | * This class provided standards arduino functions like pinMode, digitalWrite, digitalRead, ...\n 10 | * This new version is fully optimized and documented.\n 11 | * \n 12 | * Please report bug to 13 | * 14 | * @section license_sec License 15 | * This program is free software: you can redistribute it and/or modify\n 16 | * it under the terms of the GNU General Public License as published by\n 17 | * the Free Software Foundation, either version 3 of the License, or\n 18 | * (at your option) any later version.\n 19 | * \n 20 | * This program is distributed in the hope that it will be useful,\n 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of\n 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n 23 | * GNU General Public License for more details.\n 24 | * \n 25 | * You should have received a copy of the GNU General Public License\n 26 | * along with this program. If not, see .\n 27 | * 28 | * @section other_sec Others notes and compatibility warning 29 | * Compatible with arduino 1.0.x and >=0023\n 30 | * Retro-compatible with the previous library version 31 | */ 32 | #ifndef PCF8575_H 33 | #define PCF8575_H 34 | 35 | /** Comment this define to disable interrupt support */ 36 | #define PCF8575_INTERRUPT_SUPPORT 37 | 38 | /* Retro-compatibility with arduino 0023 and previous version */ 39 | #if ARDUINO >= 100 40 | #include "Arduino.h" 41 | #define I2CWRITE(x) Wire.write(x) 42 | #define I2CREAD() Wire.read() 43 | #else 44 | #include "WProgram.h" 45 | #define I2CWRITE(x) Wire.send(x) 46 | #define I2CREAD() Wire.receive() 47 | #define INPUT_PULLUP 2 48 | #endif 49 | 50 | /** 51 | * @brief PCF8575 Arduino class 52 | */ 53 | class PCF8575 { 54 | public: 55 | /** 56 | * Create a new PCF8575 instance 57 | */ 58 | PCF8575(); 59 | 60 | /** 61 | * Start the I2C controller and store the PCF8575 chip address 62 | */ 63 | void begin(uint8_t address = 0x21); 64 | 65 | /** 66 | * Set the direction of a pin (OUTPUT, INPUT or INPUT_PULLUP) 67 | * 68 | * @param pin The pin to set 69 | * @param mode The new mode of the pin 70 | * @remarks INPUT_PULLUP does physicaly the same thing as INPUT (no software pull-up resistors available) but is REQUIRED if you use external pull-up resistor 71 | */ 72 | void pinMode(uint8_t pin, uint8_t mode); 73 | 74 | /** 75 | * Set the state of a pin (HIGH or LOW) 76 | * 77 | * @param pin The pin to set 78 | * @param value The new state of the pin 79 | * @remarks Software pull-up resistors are not available on the PCF8575 80 | */ 81 | void digitalWrite(uint8_t pin, uint8_t value); 82 | 83 | /** 84 | * Read the state of a pin 85 | * 86 | * @param pin The pin to read back 87 | * @return 88 | */ 89 | uint8_t digitalRead(uint8_t pin); 90 | 91 | /** 92 | * Set the state of all pins in one go 93 | * 94 | * @param value The new value of all pins (1 bit = 1 pin, '1' = HIGH, '0' = LOW) 95 | */ 96 | void write(uint16_t value); 97 | 98 | /** 99 | * Read the state of all pins in one go 100 | * 101 | * @return The current value of all pins (1 bit = 1 pin, '1' = HIGH, '0' = LOW) 102 | */ 103 | uint16_t read(); 104 | 105 | /** 106 | * Exactly like write(0x00), set all pins to LOW 107 | */ 108 | void clear(); 109 | 110 | /** 111 | * Exactly like write(0xFF), set all pins to HIGH 112 | */ 113 | void set(); 114 | 115 | /** 116 | * Toggle the state of a pin 117 | */ 118 | void toggle(uint8_t pin); 119 | 120 | /** 121 | * Mark a pin as "pulled up" 122 | * 123 | * @warning DO NOTHING - FOR RETRO COMPATIBILITY PURPOSE ONLY 124 | * @deprecated 125 | * @param pin Pin the mark as "pulled up" 126 | */ 127 | void pullUp(uint8_t pin); 128 | 129 | /** 130 | * Mark a pin as "pulled down" 131 | * 132 | * @warning DO NOTHING - FOR RETRO COMPATIBILITY PURPOSE ONLY 133 | * @deprecated 134 | * @param pin Pin the mark as "pulled down" 135 | */ 136 | void pullDown(uint8_t pin); 137 | 138 | /** 139 | * Make a pin blink N times for T duration 140 | * 141 | * @warning Blocking function, not recommended for new code 142 | * @deprecated 143 | * @param pin The pin to blink 144 | * @param count The number of ON/OFF couples to execute 145 | * @param duration The duration of the whole blink action in milliseconds 146 | */ 147 | void blink(uint8_t pin, uint16_t count, uint32_t duration); 148 | 149 | #ifdef PCF8575_INTERRUPT_SUPPORT 150 | /** 151 | * Enable interrupts support and setup interrupts handler 152 | * 153 | * @remarks Any pin can be used as "INT" pin, internally the library use PCINT to work. 154 | * @warning The check wrapping routine must be provided by user and define in the global scope space. 155 | * @param pin The pin OF YOUR ARDUINO (not the PCF8575) to use as "INT" pin for interrupts detection 156 | * @param selfCheckFunction The wrapping routine used to process interrupts events. 157 | * @remarks For best performances you should avoid this "user friendly" fonction and use the standard attachInterrupt() fonction ;) 158 | * @remarks If multiple PCF8575 are wired on the same "INT" pin this function should be called only one time 159 | */ 160 | void enableInterrupt(uint8_t pin, void (*selfCheckFunction)(void)); 161 | 162 | /** 163 | * Disable interrupts support 164 | */ 165 | void disableInterrupt(); 166 | 167 | /** 168 | * Check for interrupt and process routine 169 | * 170 | * @remarks Call this routine from your wrapping routine to detect and process interrupts (if any) of this PCF8575 instance. 171 | */ 172 | void checkForInterrupt(); 173 | 174 | /** 175 | * Attach a function to an interrupt event of a pin of the PCF8575 176 | * 177 | * @param pin The pin to attach the interrupt event on 178 | * @param userFunc The callback function to call when the interrupt event is triggered 179 | * @param mode The interrupt mode to check for, only interrupts events coming from the specified pin and with the specified mode will call the callback function. 180 | * @remarks 1 PCF8575 pin = 1 interrupt, multiple interrupts on the same pin is not supported 181 | */ 182 | void attachInterrupt(uint8_t pin, void (*userFunc)(void), uint8_t mode); 183 | 184 | /** 185 | * Detach any interrupt attached to the specified pin 186 | * 187 | * @param pin The pin to detach any interrupt from 188 | */ 189 | void detachInterrupt(uint8_t pin); 190 | #endif 191 | 192 | protected: 193 | /** Output pins values */ 194 | volatile uint16_t _PORT; 195 | 196 | /** Current input pins values */ 197 | volatile uint16_t _PIN; 198 | 199 | /** Pins modes values (OUTPUT or INPUT) */ 200 | volatile uint16_t _DDR; 201 | 202 | /** PCF8575 I2C address */ 203 | uint8_t _address; 204 | 205 | #ifdef PCF8575_INTERRUPT_SUPPORT 206 | /** Old value of _PIN variable */ 207 | volatile uint16_t _oldPIN; 208 | 209 | /** ISR ignore flag */ 210 | volatile uint8_t _isrIgnore; 211 | 212 | /** PCINT pin used for "INT" pin handling */ 213 | uint8_t _pcintPin; 214 | 215 | /** Interrupts modes of pins ( LOW, CHANGE, FALLING, RISING) */ 216 | uint8_t _intMode[16]; 217 | 218 | /** Interrupts callback functions */ 219 | void (*_intCallback[16])(void); 220 | #endif 221 | 222 | /** 223 | * Read GPIO states and store them in _PIN variable 224 | * 225 | * @remarks Before reading current GPIO states, current _PIN variable value is moved to _oldPIN variable 226 | */ 227 | void readGPIO(); 228 | 229 | /** 230 | * Write value of _PORT variable to the GPIO 231 | * 232 | * @remarks Only pin marked as OUTPUT are set, for INPUT pins their value are unchanged 233 | * @warning To work properly (and avoid any states conflicts) readGPIO() MUST be called before call this function ! 234 | */ 235 | void updateGPIO(); 236 | }; 237 | 238 | #endif 239 | -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED/glcdfont.c: -------------------------------------------------------------------------------- 1 | #ifndef FONT5X7_H 2 | #define FONT5X7_H 3 | 4 | #ifdef __AVR__ 5 | #include 6 | #include 7 | #else 8 | #define PROGMEM 9 | #endif 10 | 11 | // Standard ASCII 5x7 font 12 | 13 | static const unsigned char font[] PROGMEM = { 14 | 0x00, 0x00, 0x00, 0x00, 0x00, 15 | 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 16 | 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 17 | 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 18 | 0x18, 0x3C, 0x7E, 0x3C, 0x18, 19 | 0x1C, 0x57, 0x7D, 0x57, 0x1C, 20 | 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 21 | 0x00, 0x18, 0x3C, 0x18, 0x00, 22 | 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 23 | 0x00, 0x18, 0x24, 0x18, 0x00, 24 | 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 25 | 0x30, 0x48, 0x3A, 0x06, 0x0E, 26 | 0x26, 0x29, 0x79, 0x29, 0x26, 27 | 0x40, 0x7F, 0x05, 0x05, 0x07, 28 | 0x40, 0x7F, 0x05, 0x25, 0x3F, 29 | 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 30 | 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 31 | 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 32 | 0x14, 0x22, 0x7F, 0x22, 0x14, 33 | 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 34 | 0x06, 0x09, 0x7F, 0x01, 0x7F, 35 | 0x00, 0x66, 0x89, 0x95, 0x6A, 36 | 0x60, 0x60, 0x60, 0x60, 0x60, 37 | 0x94, 0xA2, 0xFF, 0xA2, 0x94, 38 | 0x08, 0x04, 0x7E, 0x04, 0x08, 39 | 0x10, 0x20, 0x7E, 0x20, 0x10, 40 | 0x08, 0x08, 0x2A, 0x1C, 0x08, 41 | 0x08, 0x1C, 0x2A, 0x08, 0x08, 42 | 0x1E, 0x10, 0x10, 0x10, 0x10, 43 | 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 44 | 0x30, 0x38, 0x3E, 0x38, 0x30, 45 | 0x06, 0x0E, 0x3E, 0x0E, 0x06, 46 | 0x00, 0x00, 0x00, 0x00, 0x00, 47 | 0x00, 0x00, 0x5F, 0x00, 0x00, 48 | 0x00, 0x07, 0x00, 0x07, 0x00, 49 | 0x14, 0x7F, 0x14, 0x7F, 0x14, 50 | 0x24, 0x2A, 0x7F, 0x2A, 0x12, 51 | 0x23, 0x13, 0x08, 0x64, 0x62, 52 | 0x36, 0x49, 0x56, 0x20, 0x50, 53 | 0x00, 0x08, 0x07, 0x03, 0x00, 54 | 0x00, 0x1C, 0x22, 0x41, 0x00, 55 | 0x00, 0x41, 0x22, 0x1C, 0x00, 56 | 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 57 | 0x08, 0x08, 0x3E, 0x08, 0x08, 58 | 0x00, 0x80, 0x70, 0x30, 0x00, 59 | 0x08, 0x08, 0x08, 0x08, 0x08, 60 | 0x00, 0x00, 0x60, 0x60, 0x00, 61 | 0x20, 0x10, 0x08, 0x04, 0x02, 62 | 0x3E, 0x51, 0x49, 0x45, 0x3E, 63 | 0x00, 0x42, 0x7F, 0x40, 0x00, 64 | 0x72, 0x49, 0x49, 0x49, 0x46, 65 | 0x21, 0x41, 0x49, 0x4D, 0x33, 66 | 0x18, 0x14, 0x12, 0x7F, 0x10, 67 | 0x27, 0x45, 0x45, 0x45, 0x39, 68 | 0x3C, 0x4A, 0x49, 0x49, 0x31, 69 | 0x41, 0x21, 0x11, 0x09, 0x07, 70 | 0x36, 0x49, 0x49, 0x49, 0x36, 71 | 0x46, 0x49, 0x49, 0x29, 0x1E, 72 | 0x00, 0x00, 0x14, 0x00, 0x00, 73 | 0x00, 0x40, 0x34, 0x00, 0x00, 74 | 0x00, 0x08, 0x14, 0x22, 0x41, 75 | 0x14, 0x14, 0x14, 0x14, 0x14, 76 | 0x00, 0x41, 0x22, 0x14, 0x08, 77 | 0x02, 0x01, 0x59, 0x09, 0x06, 78 | 0x3E, 0x41, 0x5D, 0x59, 0x4E, 79 | 0x7C, 0x12, 0x11, 0x12, 0x7C, 80 | 0x7F, 0x49, 0x49, 0x49, 0x36, 81 | 0x3E, 0x41, 0x41, 0x41, 0x22, 82 | 0x7F, 0x41, 0x41, 0x41, 0x3E, 83 | 0x7F, 0x49, 0x49, 0x49, 0x41, 84 | 0x7F, 0x09, 0x09, 0x09, 0x01, 85 | 0x3E, 0x41, 0x41, 0x51, 0x73, 86 | 0x7F, 0x08, 0x08, 0x08, 0x7F, 87 | 0x00, 0x41, 0x7F, 0x41, 0x00, 88 | 0x20, 0x40, 0x41, 0x3F, 0x01, 89 | 0x7F, 0x08, 0x14, 0x22, 0x41, 90 | 0x7F, 0x40, 0x40, 0x40, 0x40, 91 | 0x7F, 0x02, 0x1C, 0x02, 0x7F, 92 | 0x7F, 0x04, 0x08, 0x10, 0x7F, 93 | 0x3E, 0x41, 0x41, 0x41, 0x3E, 94 | 0x7F, 0x09, 0x09, 0x09, 0x06, 95 | 0x3E, 0x41, 0x51, 0x21, 0x5E, 96 | 0x7F, 0x09, 0x19, 0x29, 0x46, 97 | 0x26, 0x49, 0x49, 0x49, 0x32, 98 | 0x03, 0x01, 0x7F, 0x01, 0x03, 99 | 0x3F, 0x40, 0x40, 0x40, 0x3F, 100 | 0x1F, 0x20, 0x40, 0x20, 0x1F, 101 | 0x3F, 0x40, 0x38, 0x40, 0x3F, 102 | 0x63, 0x14, 0x08, 0x14, 0x63, 103 | 0x03, 0x04, 0x78, 0x04, 0x03, 104 | 0x61, 0x59, 0x49, 0x4D, 0x43, 105 | 0x00, 0x7F, 0x41, 0x41, 0x41, 106 | 0x02, 0x04, 0x08, 0x10, 0x20, 107 | 0x00, 0x41, 0x41, 0x41, 0x7F, 108 | 0x04, 0x02, 0x01, 0x02, 0x04, 109 | 0x40, 0x40, 0x40, 0x40, 0x40, 110 | 0x00, 0x03, 0x07, 0x08, 0x00, 111 | 0x20, 0x54, 0x54, 0x78, 0x40, 112 | 0x7F, 0x28, 0x44, 0x44, 0x38, 113 | 0x38, 0x44, 0x44, 0x44, 0x28, 114 | 0x38, 0x44, 0x44, 0x28, 0x7F, 115 | 0x38, 0x54, 0x54, 0x54, 0x18, 116 | 0x00, 0x08, 0x7E, 0x09, 0x02, 117 | 0x18, 0xA4, 0xA4, 0x9C, 0x78, 118 | 0x7F, 0x08, 0x04, 0x04, 0x78, 119 | 0x00, 0x44, 0x7D, 0x40, 0x00, 120 | 0x20, 0x40, 0x40, 0x3D, 0x00, 121 | 0x7F, 0x10, 0x28, 0x44, 0x00, 122 | 0x00, 0x41, 0x7F, 0x40, 0x00, 123 | 0x7C, 0x04, 0x78, 0x04, 0x78, 124 | 0x7C, 0x08, 0x04, 0x04, 0x78, 125 | 0x38, 0x44, 0x44, 0x44, 0x38, 126 | 0xFC, 0x18, 0x24, 0x24, 0x18, 127 | 0x18, 0x24, 0x24, 0x18, 0xFC, 128 | 0x7C, 0x08, 0x04, 0x04, 0x08, 129 | 0x48, 0x54, 0x54, 0x54, 0x24, 130 | 0x04, 0x04, 0x3F, 0x44, 0x24, 131 | 0x3C, 0x40, 0x40, 0x20, 0x7C, 132 | 0x1C, 0x20, 0x40, 0x20, 0x1C, 133 | 0x3C, 0x40, 0x30, 0x40, 0x3C, 134 | 0x44, 0x28, 0x10, 0x28, 0x44, 135 | 0x4C, 0x90, 0x90, 0x90, 0x7C, 136 | 0x44, 0x64, 0x54, 0x4C, 0x44, 137 | 0x00, 0x08, 0x36, 0x41, 0x00, 138 | 0x00, 0x00, 0x77, 0x00, 0x00, 139 | 0x00, 0x41, 0x36, 0x08, 0x00, 140 | 0x02, 0x01, 0x02, 0x04, 0x02, 141 | 0x3C, 0x26, 0x23, 0x26, 0x3C, 142 | 0x1E, 0xA1, 0xA1, 0x61, 0x12, 143 | 0x3A, 0x40, 0x40, 0x20, 0x7A, 144 | 0x38, 0x54, 0x54, 0x55, 0x59, 145 | 0x21, 0x55, 0x55, 0x79, 0x41, 146 | 0x21, 0x54, 0x54, 0x78, 0x41, 147 | 0x21, 0x55, 0x54, 0x78, 0x40, 148 | 0x20, 0x54, 0x55, 0x79, 0x40, 149 | 0x0C, 0x1E, 0x52, 0x72, 0x12, 150 | 0x39, 0x55, 0x55, 0x55, 0x59, 151 | 0x39, 0x54, 0x54, 0x54, 0x59, 152 | 0x39, 0x55, 0x54, 0x54, 0x58, 153 | 0x00, 0x00, 0x45, 0x7C, 0x41, 154 | 0x00, 0x02, 0x45, 0x7D, 0x42, 155 | 0x00, 0x01, 0x45, 0x7C, 0x40, 156 | 0xF0, 0x29, 0x24, 0x29, 0xF0, 157 | 0xF0, 0x28, 0x25, 0x28, 0xF0, 158 | 0x7C, 0x54, 0x55, 0x45, 0x00, 159 | 0x20, 0x54, 0x54, 0x7C, 0x54, 160 | 0x7C, 0x0A, 0x09, 0x7F, 0x49, 161 | 0x32, 0x49, 0x49, 0x49, 0x32, 162 | 0x32, 0x48, 0x48, 0x48, 0x32, 163 | 0x32, 0x4A, 0x48, 0x48, 0x30, 164 | 0x3A, 0x41, 0x41, 0x21, 0x7A, 165 | 0x3A, 0x42, 0x40, 0x20, 0x78, 166 | 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 167 | 0x39, 0x44, 0x44, 0x44, 0x39, 168 | 0x3D, 0x40, 0x40, 0x40, 0x3D, 169 | 0x3C, 0x24, 0xFF, 0x24, 0x24, 170 | 0x48, 0x7E, 0x49, 0x43, 0x66, 171 | 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 172 | 0xFF, 0x09, 0x29, 0xF6, 0x20, 173 | 0xC0, 0x88, 0x7E, 0x09, 0x03, 174 | 0x20, 0x54, 0x54, 0x79, 0x41, 175 | 0x00, 0x00, 0x44, 0x7D, 0x41, 176 | 0x30, 0x48, 0x48, 0x4A, 0x32, 177 | 0x38, 0x40, 0x40, 0x22, 0x7A, 178 | 0x00, 0x7A, 0x0A, 0x0A, 0x72, 179 | 0x7D, 0x0D, 0x19, 0x31, 0x7D, 180 | 0x26, 0x29, 0x29, 0x2F, 0x28, 181 | 0x26, 0x29, 0x29, 0x29, 0x26, 182 | 0x30, 0x48, 0x4D, 0x40, 0x20, 183 | 0x38, 0x08, 0x08, 0x08, 0x08, 184 | 0x08, 0x08, 0x08, 0x08, 0x38, 185 | 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 186 | 0x2F, 0x10, 0x28, 0x34, 0xFA, 187 | 0x00, 0x00, 0x7B, 0x00, 0x00, 188 | 0x08, 0x14, 0x2A, 0x14, 0x22, 189 | 0x22, 0x14, 0x2A, 0x14, 0x08, 190 | 0xAA, 0x00, 0x55, 0x00, 0xAA, 191 | 0xAA, 0x55, 0xAA, 0x55, 0xAA, 192 | 0x00, 0x00, 0x00, 0xFF, 0x00, 193 | 0x10, 0x10, 0x10, 0xFF, 0x00, 194 | 0x14, 0x14, 0x14, 0xFF, 0x00, 195 | 0x10, 0x10, 0xFF, 0x00, 0xFF, 196 | 0x10, 0x10, 0xF0, 0x10, 0xF0, 197 | 0x14, 0x14, 0x14, 0xFC, 0x00, 198 | 0x14, 0x14, 0xF7, 0x00, 0xFF, 199 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 200 | 0x14, 0x14, 0xF4, 0x04, 0xFC, 201 | 0x14, 0x14, 0x17, 0x10, 0x1F, 202 | 0x10, 0x10, 0x1F, 0x10, 0x1F, 203 | 0x14, 0x14, 0x14, 0x1F, 0x00, 204 | 0x10, 0x10, 0x10, 0xF0, 0x00, 205 | 0x00, 0x00, 0x00, 0x1F, 0x10, 206 | 0x10, 0x10, 0x10, 0x1F, 0x10, 207 | 0x10, 0x10, 0x10, 0xF0, 0x10, 208 | 0x00, 0x00, 0x00, 0xFF, 0x10, 209 | 0x10, 0x10, 0x10, 0x10, 0x10, 210 | 0x10, 0x10, 0x10, 0xFF, 0x10, 211 | 0x00, 0x00, 0x00, 0xFF, 0x14, 212 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 213 | 0x00, 0x00, 0x1F, 0x10, 0x17, 214 | 0x00, 0x00, 0xFC, 0x04, 0xF4, 215 | 0x14, 0x14, 0x17, 0x10, 0x17, 216 | 0x14, 0x14, 0xF4, 0x04, 0xF4, 217 | 0x00, 0x00, 0xFF, 0x00, 0xF7, 218 | 0x14, 0x14, 0x14, 0x14, 0x14, 219 | 0x14, 0x14, 0xF7, 0x00, 0xF7, 220 | 0x14, 0x14, 0x14, 0x17, 0x14, 221 | 0x10, 0x10, 0x1F, 0x10, 0x1F, 222 | 0x14, 0x14, 0x14, 0xF4, 0x14, 223 | 0x10, 0x10, 0xF0, 0x10, 0xF0, 224 | 0x00, 0x00, 0x1F, 0x10, 0x1F, 225 | 0x00, 0x00, 0x00, 0x1F, 0x14, 226 | 0x00, 0x00, 0x00, 0xFC, 0x14, 227 | 0x00, 0x00, 0xF0, 0x10, 0xF0, 228 | 0x10, 0x10, 0xFF, 0x10, 0xFF, 229 | 0x14, 0x14, 0x14, 0xFF, 0x14, 230 | 0x10, 0x10, 0x10, 0x1F, 0x00, 231 | 0x00, 0x00, 0x00, 0xF0, 0x10, 232 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 233 | 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 234 | 0xFF, 0xFF, 0xFF, 0x00, 0x00, 235 | 0x00, 0x00, 0x00, 0xFF, 0xFF, 236 | 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 237 | 0x38, 0x44, 0x44, 0x38, 0x44, 238 | 0x7C, 0x2A, 0x2A, 0x3E, 0x14, 239 | 0x7E, 0x02, 0x02, 0x06, 0x06, 240 | 0x02, 0x7E, 0x02, 0x7E, 0x02, 241 | 0x63, 0x55, 0x49, 0x41, 0x63, 242 | 0x38, 0x44, 0x44, 0x3C, 0x04, 243 | 0x40, 0x7E, 0x20, 0x1E, 0x20, 244 | 0x06, 0x02, 0x7E, 0x02, 0x02, 245 | 0x99, 0xA5, 0xE7, 0xA5, 0x99, 246 | 0x1C, 0x2A, 0x49, 0x2A, 0x1C, 247 | 0x4C, 0x72, 0x01, 0x72, 0x4C, 248 | 0x30, 0x4A, 0x4D, 0x4D, 0x30, 249 | 0x30, 0x48, 0x78, 0x48, 0x30, 250 | 0xBC, 0x62, 0x5A, 0x46, 0x3D, 251 | 0x3E, 0x49, 0x49, 0x49, 0x00, 252 | 0x7E, 0x01, 0x01, 0x01, 0x7E, 253 | 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 254 | 0x44, 0x44, 0x5F, 0x44, 0x44, 255 | 0x40, 0x51, 0x4A, 0x44, 0x40, 256 | 0x40, 0x44, 0x4A, 0x51, 0x40, 257 | 0x00, 0x00, 0xFF, 0x01, 0x03, 258 | 0xE0, 0x80, 0xFF, 0x00, 0x00, 259 | 0x08, 0x08, 0x6B, 0x6B, 0x08, 260 | 0x36, 0x12, 0x36, 0x24, 0x36, 261 | 0x06, 0x0F, 0x09, 0x0F, 0x06, 262 | 0x00, 0x00, 0x18, 0x18, 0x00, 263 | 0x00, 0x00, 0x10, 0x10, 0x00, 264 | 0x30, 0x40, 0xFF, 0x01, 0x01, 265 | 0x00, 0x1F, 0x01, 0x01, 0x1E, 266 | 0x00, 0x19, 0x1D, 0x17, 0x12, 267 | 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 268 | 0x00, 0x00, 0x00, 0x00, 0x00 269 | }; 270 | #endif // FONT5X7_H 271 | -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED_SRAM/glcdfont.c: -------------------------------------------------------------------------------- 1 | #ifndef FONT5X7_H 2 | #define FONT5X7_H 3 | 4 | #ifdef __AVR__ 5 | #include 6 | #include 7 | #else 8 | #define PROGMEM 9 | #endif 10 | 11 | // Standard ASCII 5x7 font 12 | 13 | static const unsigned char font[] PROGMEM = { 14 | 0x00, 0x00, 0x00, 0x00, 0x00, 15 | 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 16 | 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 17 | 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 18 | 0x18, 0x3C, 0x7E, 0x3C, 0x18, 19 | 0x1C, 0x57, 0x7D, 0x57, 0x1C, 20 | 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 21 | 0x00, 0x18, 0x3C, 0x18, 0x00, 22 | 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 23 | 0x00, 0x18, 0x24, 0x18, 0x00, 24 | 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 25 | 0x30, 0x48, 0x3A, 0x06, 0x0E, 26 | 0x26, 0x29, 0x79, 0x29, 0x26, 27 | 0x40, 0x7F, 0x05, 0x05, 0x07, 28 | 0x40, 0x7F, 0x05, 0x25, 0x3F, 29 | 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 30 | 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 31 | 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 32 | 0x14, 0x22, 0x7F, 0x22, 0x14, 33 | 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 34 | 0x06, 0x09, 0x7F, 0x01, 0x7F, 35 | 0x00, 0x66, 0x89, 0x95, 0x6A, 36 | 0x60, 0x60, 0x60, 0x60, 0x60, 37 | 0x94, 0xA2, 0xFF, 0xA2, 0x94, 38 | 0x08, 0x04, 0x7E, 0x04, 0x08, 39 | 0x10, 0x20, 0x7E, 0x20, 0x10, 40 | 0x08, 0x08, 0x2A, 0x1C, 0x08, 41 | 0x08, 0x1C, 0x2A, 0x08, 0x08, 42 | 0x1E, 0x10, 0x10, 0x10, 0x10, 43 | 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 44 | 0x30, 0x38, 0x3E, 0x38, 0x30, 45 | 0x06, 0x0E, 0x3E, 0x0E, 0x06, 46 | 0x00, 0x00, 0x00, 0x00, 0x00, 47 | 0x00, 0x00, 0x5F, 0x00, 0x00, 48 | 0x00, 0x07, 0x00, 0x07, 0x00, 49 | 0x14, 0x7F, 0x14, 0x7F, 0x14, 50 | 0x24, 0x2A, 0x7F, 0x2A, 0x12, 51 | 0x23, 0x13, 0x08, 0x64, 0x62, 52 | 0x36, 0x49, 0x56, 0x20, 0x50, 53 | 0x00, 0x08, 0x07, 0x03, 0x00, 54 | 0x00, 0x1C, 0x22, 0x41, 0x00, 55 | 0x00, 0x41, 0x22, 0x1C, 0x00, 56 | 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 57 | 0x08, 0x08, 0x3E, 0x08, 0x08, 58 | 0x00, 0x80, 0x70, 0x30, 0x00, 59 | 0x08, 0x08, 0x08, 0x08, 0x08, 60 | 0x00, 0x00, 0x60, 0x60, 0x00, 61 | 0x20, 0x10, 0x08, 0x04, 0x02, 62 | 0x3E, 0x51, 0x49, 0x45, 0x3E, 63 | 0x00, 0x42, 0x7F, 0x40, 0x00, 64 | 0x72, 0x49, 0x49, 0x49, 0x46, 65 | 0x21, 0x41, 0x49, 0x4D, 0x33, 66 | 0x18, 0x14, 0x12, 0x7F, 0x10, 67 | 0x27, 0x45, 0x45, 0x45, 0x39, 68 | 0x3C, 0x4A, 0x49, 0x49, 0x31, 69 | 0x41, 0x21, 0x11, 0x09, 0x07, 70 | 0x36, 0x49, 0x49, 0x49, 0x36, 71 | 0x46, 0x49, 0x49, 0x29, 0x1E, 72 | 0x00, 0x00, 0x14, 0x00, 0x00, 73 | 0x00, 0x40, 0x34, 0x00, 0x00, 74 | 0x00, 0x08, 0x14, 0x22, 0x41, 75 | 0x14, 0x14, 0x14, 0x14, 0x14, 76 | 0x00, 0x41, 0x22, 0x14, 0x08, 77 | 0x02, 0x01, 0x59, 0x09, 0x06, 78 | 0x3E, 0x41, 0x5D, 0x59, 0x4E, 79 | 0x7C, 0x12, 0x11, 0x12, 0x7C, 80 | 0x7F, 0x49, 0x49, 0x49, 0x36, 81 | 0x3E, 0x41, 0x41, 0x41, 0x22, 82 | 0x7F, 0x41, 0x41, 0x41, 0x3E, 83 | 0x7F, 0x49, 0x49, 0x49, 0x41, 84 | 0x7F, 0x09, 0x09, 0x09, 0x01, 85 | 0x3E, 0x41, 0x41, 0x51, 0x73, 86 | 0x7F, 0x08, 0x08, 0x08, 0x7F, 87 | 0x00, 0x41, 0x7F, 0x41, 0x00, 88 | 0x20, 0x40, 0x41, 0x3F, 0x01, 89 | 0x7F, 0x08, 0x14, 0x22, 0x41, 90 | 0x7F, 0x40, 0x40, 0x40, 0x40, 91 | 0x7F, 0x02, 0x1C, 0x02, 0x7F, 92 | 0x7F, 0x04, 0x08, 0x10, 0x7F, 93 | 0x3E, 0x41, 0x41, 0x41, 0x3E, 94 | 0x7F, 0x09, 0x09, 0x09, 0x06, 95 | 0x3E, 0x41, 0x51, 0x21, 0x5E, 96 | 0x7F, 0x09, 0x19, 0x29, 0x46, 97 | 0x26, 0x49, 0x49, 0x49, 0x32, 98 | 0x03, 0x01, 0x7F, 0x01, 0x03, 99 | 0x3F, 0x40, 0x40, 0x40, 0x3F, 100 | 0x1F, 0x20, 0x40, 0x20, 0x1F, 101 | 0x3F, 0x40, 0x38, 0x40, 0x3F, 102 | 0x63, 0x14, 0x08, 0x14, 0x63, 103 | 0x03, 0x04, 0x78, 0x04, 0x03, 104 | 0x61, 0x59, 0x49, 0x4D, 0x43, 105 | 0x00, 0x7F, 0x41, 0x41, 0x41, 106 | 0x02, 0x04, 0x08, 0x10, 0x20, 107 | 0x00, 0x41, 0x41, 0x41, 0x7F, 108 | 0x04, 0x02, 0x01, 0x02, 0x04, 109 | 0x40, 0x40, 0x40, 0x40, 0x40, 110 | 0x00, 0x03, 0x07, 0x08, 0x00, 111 | 0x20, 0x54, 0x54, 0x78, 0x40, 112 | 0x7F, 0x28, 0x44, 0x44, 0x38, 113 | 0x38, 0x44, 0x44, 0x44, 0x28, 114 | 0x38, 0x44, 0x44, 0x28, 0x7F, 115 | 0x38, 0x54, 0x54, 0x54, 0x18, 116 | 0x00, 0x08, 0x7E, 0x09, 0x02, 117 | 0x18, 0xA4, 0xA4, 0x9C, 0x78, 118 | 0x7F, 0x08, 0x04, 0x04, 0x78, 119 | 0x00, 0x44, 0x7D, 0x40, 0x00, 120 | 0x20, 0x40, 0x40, 0x3D, 0x00, 121 | 0x7F, 0x10, 0x28, 0x44, 0x00, 122 | 0x00, 0x41, 0x7F, 0x40, 0x00, 123 | 0x7C, 0x04, 0x78, 0x04, 0x78, 124 | 0x7C, 0x08, 0x04, 0x04, 0x78, 125 | 0x38, 0x44, 0x44, 0x44, 0x38, 126 | 0xFC, 0x18, 0x24, 0x24, 0x18, 127 | 0x18, 0x24, 0x24, 0x18, 0xFC, 128 | 0x7C, 0x08, 0x04, 0x04, 0x08, 129 | 0x48, 0x54, 0x54, 0x54, 0x24, 130 | 0x04, 0x04, 0x3F, 0x44, 0x24, 131 | 0x3C, 0x40, 0x40, 0x20, 0x7C, 132 | 0x1C, 0x20, 0x40, 0x20, 0x1C, 133 | 0x3C, 0x40, 0x30, 0x40, 0x3C, 134 | 0x44, 0x28, 0x10, 0x28, 0x44, 135 | 0x4C, 0x90, 0x90, 0x90, 0x7C, 136 | 0x44, 0x64, 0x54, 0x4C, 0x44, 137 | 0x00, 0x08, 0x36, 0x41, 0x00, 138 | 0x00, 0x00, 0x77, 0x00, 0x00, 139 | 0x00, 0x41, 0x36, 0x08, 0x00, 140 | 0x02, 0x01, 0x02, 0x04, 0x02, 141 | 0x3C, 0x26, 0x23, 0x26, 0x3C, 142 | 0x1E, 0xA1, 0xA1, 0x61, 0x12, 143 | 0x3A, 0x40, 0x40, 0x20, 0x7A, 144 | 0x38, 0x54, 0x54, 0x55, 0x59, 145 | 0x21, 0x55, 0x55, 0x79, 0x41, 146 | 0x21, 0x54, 0x54, 0x78, 0x41, 147 | 0x21, 0x55, 0x54, 0x78, 0x40, 148 | 0x20, 0x54, 0x55, 0x79, 0x40, 149 | 0x0C, 0x1E, 0x52, 0x72, 0x12, 150 | 0x39, 0x55, 0x55, 0x55, 0x59, 151 | 0x39, 0x54, 0x54, 0x54, 0x59, 152 | 0x39, 0x55, 0x54, 0x54, 0x58, 153 | 0x00, 0x00, 0x45, 0x7C, 0x41, 154 | 0x00, 0x02, 0x45, 0x7D, 0x42, 155 | 0x00, 0x01, 0x45, 0x7C, 0x40, 156 | 0xF0, 0x29, 0x24, 0x29, 0xF0, 157 | 0xF0, 0x28, 0x25, 0x28, 0xF0, 158 | 0x7C, 0x54, 0x55, 0x45, 0x00, 159 | 0x20, 0x54, 0x54, 0x7C, 0x54, 160 | 0x7C, 0x0A, 0x09, 0x7F, 0x49, 161 | 0x32, 0x49, 0x49, 0x49, 0x32, 162 | 0x32, 0x48, 0x48, 0x48, 0x32, 163 | 0x32, 0x4A, 0x48, 0x48, 0x30, 164 | 0x3A, 0x41, 0x41, 0x21, 0x7A, 165 | 0x3A, 0x42, 0x40, 0x20, 0x78, 166 | 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 167 | 0x39, 0x44, 0x44, 0x44, 0x39, 168 | 0x3D, 0x40, 0x40, 0x40, 0x3D, 169 | 0x3C, 0x24, 0xFF, 0x24, 0x24, 170 | 0x48, 0x7E, 0x49, 0x43, 0x66, 171 | 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 172 | 0xFF, 0x09, 0x29, 0xF6, 0x20, 173 | 0xC0, 0x88, 0x7E, 0x09, 0x03, 174 | 0x20, 0x54, 0x54, 0x79, 0x41, 175 | 0x00, 0x00, 0x44, 0x7D, 0x41, 176 | 0x30, 0x48, 0x48, 0x4A, 0x32, 177 | 0x38, 0x40, 0x40, 0x22, 0x7A, 178 | 0x00, 0x7A, 0x0A, 0x0A, 0x72, 179 | 0x7D, 0x0D, 0x19, 0x31, 0x7D, 180 | 0x26, 0x29, 0x29, 0x2F, 0x28, 181 | 0x26, 0x29, 0x29, 0x29, 0x26, 182 | 0x30, 0x48, 0x4D, 0x40, 0x20, 183 | 0x38, 0x08, 0x08, 0x08, 0x08, 184 | 0x08, 0x08, 0x08, 0x08, 0x38, 185 | 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 186 | 0x2F, 0x10, 0x28, 0x34, 0xFA, 187 | 0x00, 0x00, 0x7B, 0x00, 0x00, 188 | 0x08, 0x14, 0x2A, 0x14, 0x22, 189 | 0x22, 0x14, 0x2A, 0x14, 0x08, 190 | 0xAA, 0x00, 0x55, 0x00, 0xAA, 191 | 0xAA, 0x55, 0xAA, 0x55, 0xAA, 192 | 0x00, 0x00, 0x00, 0xFF, 0x00, 193 | 0x10, 0x10, 0x10, 0xFF, 0x00, 194 | 0x14, 0x14, 0x14, 0xFF, 0x00, 195 | 0x10, 0x10, 0xFF, 0x00, 0xFF, 196 | 0x10, 0x10, 0xF0, 0x10, 0xF0, 197 | 0x14, 0x14, 0x14, 0xFC, 0x00, 198 | 0x14, 0x14, 0xF7, 0x00, 0xFF, 199 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 200 | 0x14, 0x14, 0xF4, 0x04, 0xFC, 201 | 0x14, 0x14, 0x17, 0x10, 0x1F, 202 | 0x10, 0x10, 0x1F, 0x10, 0x1F, 203 | 0x14, 0x14, 0x14, 0x1F, 0x00, 204 | 0x10, 0x10, 0x10, 0xF0, 0x00, 205 | 0x00, 0x00, 0x00, 0x1F, 0x10, 206 | 0x10, 0x10, 0x10, 0x1F, 0x10, 207 | 0x10, 0x10, 0x10, 0xF0, 0x10, 208 | 0x00, 0x00, 0x00, 0xFF, 0x10, 209 | 0x10, 0x10, 0x10, 0x10, 0x10, 210 | 0x10, 0x10, 0x10, 0xFF, 0x10, 211 | 0x00, 0x00, 0x00, 0xFF, 0x14, 212 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 213 | 0x00, 0x00, 0x1F, 0x10, 0x17, 214 | 0x00, 0x00, 0xFC, 0x04, 0xF4, 215 | 0x14, 0x14, 0x17, 0x10, 0x17, 216 | 0x14, 0x14, 0xF4, 0x04, 0xF4, 217 | 0x00, 0x00, 0xFF, 0x00, 0xF7, 218 | 0x14, 0x14, 0x14, 0x14, 0x14, 219 | 0x14, 0x14, 0xF7, 0x00, 0xF7, 220 | 0x14, 0x14, 0x14, 0x17, 0x14, 221 | 0x10, 0x10, 0x1F, 0x10, 0x1F, 222 | 0x14, 0x14, 0x14, 0xF4, 0x14, 223 | 0x10, 0x10, 0xF0, 0x10, 0xF0, 224 | 0x00, 0x00, 0x1F, 0x10, 0x1F, 225 | 0x00, 0x00, 0x00, 0x1F, 0x14, 226 | 0x00, 0x00, 0x00, 0xFC, 0x14, 227 | 0x00, 0x00, 0xF0, 0x10, 0xF0, 228 | 0x10, 0x10, 0xFF, 0x10, 0xFF, 229 | 0x14, 0x14, 0x14, 0xFF, 0x14, 230 | 0x10, 0x10, 0x10, 0x1F, 0x00, 231 | 0x00, 0x00, 0x00, 0xF0, 0x10, 232 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 233 | 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 234 | 0xFF, 0xFF, 0xFF, 0x00, 0x00, 235 | 0x00, 0x00, 0x00, 0xFF, 0xFF, 236 | 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 237 | 0x38, 0x44, 0x44, 0x38, 0x44, 238 | 0x7C, 0x2A, 0x2A, 0x3E, 0x14, 239 | 0x7E, 0x02, 0x02, 0x06, 0x06, 240 | 0x02, 0x7E, 0x02, 0x7E, 0x02, 241 | 0x63, 0x55, 0x49, 0x41, 0x63, 242 | 0x38, 0x44, 0x44, 0x3C, 0x04, 243 | 0x40, 0x7E, 0x20, 0x1E, 0x20, 244 | 0x06, 0x02, 0x7E, 0x02, 0x02, 245 | 0x99, 0xA5, 0xE7, 0xA5, 0x99, 246 | 0x1C, 0x2A, 0x49, 0x2A, 0x1C, 247 | 0x4C, 0x72, 0x01, 0x72, 0x4C, 248 | 0x30, 0x4A, 0x4D, 0x4D, 0x30, 249 | 0x30, 0x48, 0x78, 0x48, 0x30, 250 | 0xBC, 0x62, 0x5A, 0x46, 0x3D, 251 | 0x3E, 0x49, 0x49, 0x49, 0x00, 252 | 0x7E, 0x01, 0x01, 0x01, 0x7E, 253 | 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 254 | 0x44, 0x44, 0x5F, 0x44, 0x44, 255 | 0x40, 0x51, 0x4A, 0x44, 0x40, 256 | 0x40, 0x44, 0x4A, 0x51, 0x40, 257 | 0x00, 0x00, 0xFF, 0x01, 0x03, 258 | 0xE0, 0x80, 0xFF, 0x00, 0x00, 259 | 0x08, 0x08, 0x6B, 0x6B, 0x08, 260 | 0x36, 0x12, 0x36, 0x24, 0x36, 261 | 0x06, 0x0F, 0x09, 0x0F, 0x06, 262 | 0x00, 0x00, 0x18, 0x18, 0x00, 263 | 0x00, 0x00, 0x10, 0x10, 0x00, 264 | 0x30, 0x40, 0xFF, 0x01, 0x01, 265 | 0x00, 0x1F, 0x01, 0x01, 0x1E, 266 | 0x00, 0x19, 0x1D, 0x17, 0x12, 267 | 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 268 | 0x00, 0x00, 0x00, 0x00, 0x00 269 | }; 270 | #endif // FONT5X7_H 271 | -------------------------------------------------------------------------------- /api/composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "dbda8de82545808171123a0f1f51db60", 8 | "packages": [ 9 | { 10 | "name": "indieweb/link-rel-parser", 11 | "version": "0.1.3", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/indieweb/link-rel-parser-php.git", 15 | "reference": "295420e4f16d9a9d262a3c25a7a583794428f055" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/indieweb/link-rel-parser-php/zipball/295420e4f16d9a9d262a3c25a7a583794428f055", 20 | "reference": "295420e4f16d9a9d262a3c25a7a583794428f055", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3.0" 25 | }, 26 | "type": "library", 27 | "autoload": { 28 | "files": [ 29 | "src/IndieWeb/link_rel_parser.php" 30 | ] 31 | }, 32 | "notification-url": "https://packagist.org/downloads/", 33 | "license": [ 34 | "Apache-2.0" 35 | ], 36 | "authors": [ 37 | { 38 | "name": "Aaron Parecki", 39 | "homepage": "http://aaronparecki.com" 40 | }, 41 | { 42 | "name": "Tantek Çelik", 43 | "homepage": "http://tantek.com" 44 | } 45 | ], 46 | "description": "Parse rel values from HTTP headers", 47 | "homepage": "https://github.com/indieweb/link-rel-parser-php", 48 | "keywords": [ 49 | "http", 50 | "indieweb", 51 | "microformats2" 52 | ], 53 | "time": "2017-01-11T17:14:49+00:00" 54 | }, 55 | { 56 | "name": "j4mie/idiorm", 57 | "version": "v1.5.6", 58 | "source": { 59 | "type": "git", 60 | "url": "https://github.com/j4mie/idiorm.git", 61 | "reference": "ee3022fcf71232309112714ca4a7760105002f99" 62 | }, 63 | "dist": { 64 | "type": "zip", 65 | "url": "https://api.github.com/repos/j4mie/idiorm/zipball/ee3022fcf71232309112714ca4a7760105002f99", 66 | "reference": "ee3022fcf71232309112714ca4a7760105002f99", 67 | "shasum": "" 68 | }, 69 | "require": { 70 | "php": ">=5.2.0" 71 | }, 72 | "require-dev": { 73 | "ext-pdo_sqlite": "*", 74 | "phpunit/phpunit": "^4.8" 75 | }, 76 | "type": "library", 77 | "autoload": { 78 | "classmap": [ 79 | "idiorm.php" 80 | ] 81 | }, 82 | "notification-url": "https://packagist.org/downloads/", 83 | "license": [ 84 | "BSD-2-Clause", 85 | "BSD-3-Clause", 86 | "BSD-4-Clause" 87 | ], 88 | "authors": [ 89 | { 90 | "name": "Simon Holywell", 91 | "email": "treffynnon@php.net", 92 | "homepage": "http://simonholywell.com", 93 | "role": "Maintainer" 94 | }, 95 | { 96 | "name": "Jamie Matthews", 97 | "email": "jamie.matthews@gmail.com", 98 | "homepage": "http://j4mie.org", 99 | "role": "Developer" 100 | }, 101 | { 102 | "name": "Durham Hale", 103 | "email": "me@durhamhale.com", 104 | "homepage": "http://durhamhale.com", 105 | "role": "Maintainer" 106 | } 107 | ], 108 | "description": "A lightweight nearly-zero-configuration object-relational mapper and fluent query builder for PHP5", 109 | "homepage": "http://j4mie.github.com/idiormandparis", 110 | "keywords": [ 111 | "idiorm", 112 | "orm", 113 | "query builder" 114 | ], 115 | "time": "2018-05-30T23:57:49+00:00" 116 | }, 117 | { 118 | "name": "mf2/mf2", 119 | "version": "v0.3.2", 120 | "source": { 121 | "type": "git", 122 | "url": "https://github.com/indieweb/php-mf2.git", 123 | "reference": "dc0d90d4ee30864bcf37cd3a8fc8db94f9134cc4" 124 | }, 125 | "dist": { 126 | "type": "zip", 127 | "url": "https://api.github.com/repos/indieweb/php-mf2/zipball/dc0d90d4ee30864bcf37cd3a8fc8db94f9134cc4", 128 | "reference": "dc0d90d4ee30864bcf37cd3a8fc8db94f9134cc4", 129 | "shasum": "" 130 | }, 131 | "require": { 132 | "php": ">=5.4.0" 133 | }, 134 | "require-dev": { 135 | "mf2/tests": "@dev", 136 | "phpdocumentor/phpdocumentor": "v2.8.4", 137 | "phpunit/phpunit": "4.8.*" 138 | }, 139 | "suggest": { 140 | "barnabywalters/mf-cleaner": "To more easily handle the canonical data php-mf2 gives you" 141 | }, 142 | "bin": [ 143 | "bin/fetch-mf2", 144 | "bin/parse-mf2" 145 | ], 146 | "type": "library", 147 | "autoload": { 148 | "files": [ 149 | "Mf2/Parser.php" 150 | ] 151 | }, 152 | "notification-url": "https://packagist.org/downloads/", 153 | "license": [ 154 | "CC0" 155 | ], 156 | "authors": [ 157 | { 158 | "name": "Barnaby Walters", 159 | "homepage": "http://waterpigs.co.uk" 160 | } 161 | ], 162 | "description": "A pure, generic microformats2 parser — makes HTML as easy to consume as a JSON API", 163 | "keywords": [ 164 | "html", 165 | "microformats", 166 | "microformats 2", 167 | "parser", 168 | "semantic" 169 | ], 170 | "time": "2017-05-27T15:27:47+00:00" 171 | }, 172 | { 173 | "name": "p3k/http", 174 | "version": "0.1.7", 175 | "source": { 176 | "type": "git", 177 | "url": "https://github.com/aaronpk/p3k-http.git", 178 | "reference": "1826647c4902a18dea5ec532f21509ba4d51210b" 179 | }, 180 | "dist": { 181 | "type": "zip", 182 | "url": "https://api.github.com/repos/aaronpk/p3k-http/zipball/1826647c4902a18dea5ec532f21509ba4d51210b", 183 | "reference": "1826647c4902a18dea5ec532f21509ba4d51210b", 184 | "shasum": "" 185 | }, 186 | "require": { 187 | "indieweb/link-rel-parser": "0.1.*", 188 | "mf2/mf2": ">=0.3.2" 189 | }, 190 | "type": "library", 191 | "autoload": { 192 | "psr-4": { 193 | "p3k\\": "src/p3k" 194 | } 195 | }, 196 | "notification-url": "https://packagist.org/downloads/", 197 | "license": [ 198 | "MIT" 199 | ], 200 | "authors": [ 201 | { 202 | "name": "Aaron Parecki", 203 | "homepage": "https://aaronparecki.com" 204 | } 205 | ], 206 | "description": "A simple wrapper API around the PHP curl functions", 207 | "homepage": "https://github.com/aaronpk/p3k-http", 208 | "time": "2018-03-04T15:21:58+00:00" 209 | }, 210 | { 211 | "name": "predis/predis", 212 | "version": "v1.1.1", 213 | "source": { 214 | "type": "git", 215 | "url": "https://github.com/nrk/predis.git", 216 | "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1" 217 | }, 218 | "dist": { 219 | "type": "zip", 220 | "url": "https://api.github.com/repos/nrk/predis/zipball/f0210e38881631afeafb56ab43405a92cafd9fd1", 221 | "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1", 222 | "shasum": "" 223 | }, 224 | "require": { 225 | "php": ">=5.3.9" 226 | }, 227 | "require-dev": { 228 | "phpunit/phpunit": "~4.8" 229 | }, 230 | "suggest": { 231 | "ext-curl": "Allows access to Webdis when paired with phpiredis", 232 | "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol" 233 | }, 234 | "type": "library", 235 | "autoload": { 236 | "psr-4": { 237 | "Predis\\": "src/" 238 | } 239 | }, 240 | "notification-url": "https://packagist.org/downloads/", 241 | "license": [ 242 | "MIT" 243 | ], 244 | "authors": [ 245 | { 246 | "name": "Daniele Alessandri", 247 | "email": "suppakilla@gmail.com", 248 | "homepage": "http://clorophilla.net" 249 | } 250 | ], 251 | "description": "Flexible and feature-complete Redis client for PHP and HHVM", 252 | "homepage": "http://github.com/nrk/predis", 253 | "keywords": [ 254 | "nosql", 255 | "predis", 256 | "redis" 257 | ], 258 | "time": "2016-06-16T16:22:20+00:00" 259 | } 260 | ], 261 | "packages-dev": [], 262 | "aliases": [], 263 | "minimum-stability": "stable", 264 | "stability-flags": [], 265 | "prefer-stable": false, 266 | "prefer-lowest": false, 267 | "platform": [], 268 | "platform-dev": [] 269 | } 270 | -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED_SRAM/Piccolino_OLED_SRAM.cpp: -------------------------------------------------------------------------------- 1 | //#include 2 | 3 | 4 | /************************************************************* 5 | * VERY (very) basic I2C library for the SSD1306 OLED LCD * 6 | * Some of the functions were borrowed from Adafruit's GFX * 7 | * Library, so thank her for them (see below). * 8 | * This version of the OLED library uses 1K of SRAM freeing * 9 | * almost 1K of local RAM - it's slower but good enough for * 10 | * most occasions! * 11 | * * 12 | * Version: 1.2 - June 2015 * 13 | * Version: 1.3 - July 2015 * 14 | * - Added drawRect (draw a rectangle) * 15 | * - Added GRAY color flag (draw lines every second pixel) * 16 | * * 17 | * Written by fr333n3rgy@yahoo.com for WCTEK.com * 18 | *************************************************************/ 19 | 20 | 21 | #include "Piccolino_OLED_SRAM.h" 22 | #include "glcdfont.c" 23 | 24 | Piccolino_RAM _v_ram; 25 | 26 | Piccolino_OLED_SRAM::Piccolino_OLED_SRAM() { 27 | // nothing here now- all done in 'begin' 28 | } 29 | 30 | 31 | void Piccolino_OLED_SRAM::begin(uint8_t vccstate, uint8_t i2caddr) { 32 | _i2caddr = i2caddr; 33 | cursor_x=0; 34 | cursor_y=0; 35 | textcolor=WHITE; 36 | textbgcolor=BLACK; 37 | 38 | _v_ram.begin(ADDR_VIDEOBUFFER); 39 | 40 | // set pin directions 41 | // I2C Init 42 | Wire.begin(); // Is this the right place for this? 43 | 44 | // Init sequence for 128x64 OLED module 45 | ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE 46 | ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5 47 | ssd1306_command(0x80); // the suggested ratio 0x80 48 | ssd1306_command(SSD1306_SETMULTIPLEX); // 0xA8 49 | ssd1306_command(0x3F); 50 | ssd1306_command(SSD1306_SETDISPLAYOFFSET); // 0xD3 51 | ssd1306_command(0x0); // offset 52 | ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0 53 | ssd1306_command(SSD1306_CHARGEPUMP); // 0x8D 54 | if (vccstate == SSD1306_EXTERNALVCC) 55 | { ssd1306_command(0x10); } 56 | else 57 | { ssd1306_command(0x14); } 58 | ssd1306_command(SSD1306_MEMORYMODE); // 0x20 59 | ssd1306_command(0x00); // 0x0 act like ks0108 60 | ssd1306_command(SSD1306_SEGREMAP | 0x1); 61 | ssd1306_command(SSD1306_COMSCANDEC); 62 | ssd1306_command(SSD1306_SETCOMPINS); // 0xDA 63 | ssd1306_command(0x12); 64 | ssd1306_command(SSD1306_SETCONTRAST); // 0x81 65 | if (vccstate == SSD1306_EXTERNALVCC) 66 | { ssd1306_command(0x9F); } 67 | else 68 | { ssd1306_command(0xCF); } 69 | ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9 70 | if (vccstate == SSD1306_EXTERNALVCC) 71 | { ssd1306_command(0x22); } 72 | else 73 | { ssd1306_command(0xF1); } 74 | ssd1306_command(SSD1306_SETVCOMDETECT); // 0xDB 75 | ssd1306_command(0x40); 76 | ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4 77 | ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6 78 | 79 | clear(); // clear sram ... 80 | setTextColor(WHITE); 81 | setTextSize(1); 82 | update(); 83 | 84 | ssd1306_command(SSD1306_DISPLAYON);//--turn on oled panel 85 | 86 | } 87 | 88 | void Piccolino_OLED_SRAM::clearpart(int from) 89 | { 90 | clearpart(from,7); 91 | } 92 | 93 | void Piccolino_OLED_SRAM::clearpart(int from, int tto) 94 | { 95 | memset(buff,0,128);//clear the back buffer. 96 | for(int f=from; f<=tto; f++) 97 | _v_ram.write(f*SSD1306_LCDWIDTH, buff, 128); 98 | } 99 | 100 | void Piccolino_OLED_SRAM::invertDisplay(uint8_t i) { 101 | if (i) { 102 | ssd1306_command(SSD1306_INVERTDISPLAY); 103 | } else { 104 | ssd1306_command(SSD1306_NORMALDISPLAY); 105 | } 106 | } 107 | 108 | void Piccolino_OLED_SRAM::ssd1306_command(uint8_t c) { 109 | // I2C 110 | uint8_t control = 0x00; // Co = 0, D/C = 0 111 | Wire.beginTransmission(_i2caddr); 112 | Wire.write(control); 113 | Wire.write(c); 114 | Wire.endTransmission(); 115 | } 116 | 117 | 118 | void Piccolino_OLED_SRAM::ssd1306_data(uint8_t c) { 119 | // I2C 120 | uint8_t control = 0x40; // Co = 0, D/C = 1 121 | Wire.beginTransmission(_i2caddr); 122 | Wire.write(control); 123 | Wire.write(c); 124 | Wire.endTransmission(); 125 | } 126 | 127 | void Piccolino_OLED_SRAM::update() 128 | { 129 | unsigned char x; 130 | int pos=0; 131 | 132 | ssd1306_command(SSD1306_SETLOWCOLUMN | 0x0); // low col = 0 133 | ssd1306_command(SSD1306_SETHIGHCOLUMN | 0x0); // hi col = 0 134 | ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0 135 | 136 | // save I2C bitrate 137 | uint8_t twbrbackup = TWBR; 138 | TWBR = 18; // upgrade to 400KHz! 139 | 140 | for (char rowID=0; rowID<8; rowID++){ 141 | 142 | pos=0; 143 | 144 | Wire.beginTransmission(_i2caddr); 145 | Wire.write(0x00); // send command 146 | Wire.write(0xB0+rowID); 147 | Wire.write(0); 148 | Wire.endTransmission(); 149 | 150 | _v_ram.read(rowID*SSD1306_LCDWIDTH, buff, 128); 151 | 152 | for(byte j = 0; j < 8; j++){ 153 | Wire.beginTransmission(_i2caddr); 154 | Wire.write(0x40); 155 | for (byte k = 0; k < 16; k++) { 156 | Wire.write(buff[pos++]); 157 | } 158 | Wire.endTransmission(); 159 | } 160 | 161 | } 162 | 163 | TWBR = twbrbackup; 164 | } 165 | 166 | void Piccolino_OLED_SRAM::clearLine(byte line) 167 | { 168 | ssd1306_command(SSD1306_SETLOWCOLUMN | 0x0); // low col = 0 169 | ssd1306_command(SSD1306_SETHIGHCOLUMN | 0x0); // hi col = 0 170 | ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0 171 | 172 | // save I2C bitrate 173 | uint8_t twbrbackup = TWBR; 174 | TWBR = 18; // upgrade to 400KHz! 175 | 176 | // send a bunch of data in one xmission 177 | ssd1306_command(0xB0 + line);//set page address 178 | ssd1306_command(0);//set lower column address 179 | ssd1306_command(0x10);//set higher column address 180 | 181 | for(byte j = 0; j < 8; j++){ 182 | Wire.beginTransmission(_i2caddr); 183 | Wire.write(0x40); 184 | for (byte k = 0; k < 16; k++) { 185 | Wire.write(0); 186 | } 187 | Wire.endTransmission(); 188 | } 189 | 190 | TWBR = twbrbackup; 191 | } 192 | 193 | 194 | void Piccolino_OLED_SRAM::updateRow(int rowID) 195 | { 196 | unsigned char x; 197 | int pos=0; 198 | 199 | ssd1306_command(SSD1306_SETLOWCOLUMN | 0x0); // low col = 0 200 | ssd1306_command(SSD1306_SETHIGHCOLUMN | 0x0); // hi col = 0 201 | ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0 202 | 203 | // save I2C bitrate 204 | uint8_t twbrbackup = TWBR; 205 | TWBR = 18; // upgrade to 400KHz! 206 | 207 | 208 | Wire.beginTransmission(_i2caddr); 209 | Wire.write(0x00); // send command 210 | Wire.write(0xB0+rowID); 211 | Wire.write(0); 212 | Wire.endTransmission(); 213 | 214 | _v_ram.read(rowID*SSD1306_LCDWIDTH, buff, 128); 215 | 216 | for(byte j = 0; j < 8; j++){ 217 | Wire.beginTransmission(_i2caddr); 218 | Wire.write(0x40); 219 | for (byte k = 0; k < 16; k++) { 220 | Wire.write(buff[pos++]); 221 | } 222 | Wire.endTransmission(); 223 | } 224 | 225 | 226 | TWBR = twbrbackup; 227 | } 228 | 229 | void Piccolino_OLED_SRAM::updateRow(int startID, int endID) 230 | { 231 | unsigned char y =0; 232 | for(y=startID; y127||y>63) return; 247 | if (x<0||y<0) return; 248 | 249 | row = y/8; 250 | offset =y%8; 251 | 252 | _v_ram.read((row*SSD1306_LCDWIDTH)+x, buff); 253 | preData = buff[0]; 254 | 255 | //set pixel; 256 | val = 1<>= 1; 308 | } 309 | } 310 | } 311 | 312 | void Piccolino_OLED_SRAM::setCursor(int16_t x, int16_t y) { 313 | cursor_x = x; 314 | cursor_y = y; 315 | } 316 | 317 | void Piccolino_OLED_SRAM::setTextSize(uint8_t s) { 318 | textsize = (s > 0) ? s : 1; 319 | } 320 | 321 | void Piccolino_OLED_SRAM::setTextColor(uint16_t c) { 322 | textcolor = c; 323 | } 324 | void Piccolino_OLED_SRAM::setTextColor(uint16_t c,uint16_t b) { 325 | textcolor = c; 326 | textbgcolor = b; 327 | } 328 | 329 | void Piccolino_OLED_SRAM::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { 330 | for (int16_t i=x; i abs(x1 - x0); 338 | 339 | if (steep) { 340 | swap(x0, y0); 341 | swap(x1, y1); 342 | } 343 | 344 | if (x0 > x1) { 345 | swap(x0, x1); 346 | swap(y0, y1); 347 | } 348 | 349 | int16_t dx, dy; 350 | dx = x1 - x0; 351 | dy = abs(y1 - y0); 352 | 353 | int16_t err = dx / 2; 354 | int16_t ystep; 355 | 356 | if (y0 < y1) { 357 | ystep = 1; 358 | } else { 359 | ystep = -1; 360 | } 361 | 362 | for (; x0<=x1; x0++) { 363 | if (steep) { 364 | if(color==GRAY) 365 | drawPixel(y0, x0, !(x0%2)); 366 | else 367 | drawPixel(y0, x0, color); 368 | } else { 369 | if(color==GRAY) 370 | drawPixel(x0, y0, !(x0%2)); 371 | else 372 | drawPixel(x0, y0, color); 373 | } 374 | err -= dy; 375 | if (err < 0) { 376 | y0 += ystep; 377 | err += dx; 378 | } 379 | } 380 | } 381 | 382 | 383 | size_t Piccolino_OLED_SRAM::write(uint8_t c) { 384 | if (c == '\n') { 385 | cursor_y += textsize*8; 386 | cursor_x = 0; 387 | } else if (c == '\r') { 388 | // skip em 389 | } else { 390 | drawChar(1+cursor_x, 1+cursor_y, c, textcolor, textbgcolor, textsize); 391 | cursor_x += textsize*6; 392 | if (wrap && (cursor_x > (SSD1306_LCDWIDTH - textsize*6))) { 393 | cursor_y += textsize*8; 394 | cursor_x = 0; 395 | } 396 | } 397 | return 1; 398 | } 399 | 400 | Piccolino_OLED_SRAM::~Piccolino_OLED_SRAM() 401 | { 402 | 403 | } 404 | -------------------------------------------------------------------------------- /Arduino/Piccolino_OLED/Piccolino_OLED.cpp: -------------------------------------------------------------------------------- 1 | //#include 2 | 3 | /************************************************************* 4 | * VERY (very) basic I2C library for the SSD1306 OLED LCD * 5 | * Some of the functions were borrowed from Adafruit's GFX * 6 | * Library, so thank her for them (see below). * 7 | * * 8 | * Version: 1.2 - June 2015 * 9 | * * 10 | * Written by fr333n3rgy@yahoo.com for WCTEK.com * 11 | *************************************************************/ 12 | 13 | 14 | #include "Piccolino_OLED.h" 15 | #include "glcdfont.c" 16 | 17 | Piccolino_OLED::Piccolino_OLED() { 18 | // nothing here now- all done in 'begin' 19 | } 20 | 21 | 22 | void Piccolino_OLED::begin(uint8_t vccstate, uint8_t i2caddr) { 23 | _i2caddr = i2caddr; 24 | cursor_x=0; 25 | cursor_y=0; 26 | textcolor=WHITE; 27 | textbgcolor=BLACK; 28 | 29 | // set pin directions 30 | // I2C Init 31 | Wire.begin(); // Is this the right place for this? 32 | 33 | // Init sequence for 128x64 OLED module 34 | ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE 35 | ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5 36 | ssd1306_command(0x80); // the suggested ratio 0x80 37 | ssd1306_command(SSD1306_SETMULTIPLEX); // 0xA8 38 | ssd1306_command(0x3F); 39 | ssd1306_command(SSD1306_SETDISPLAYOFFSET); // 0xD3 40 | ssd1306_command(0x0); // offset 41 | ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0 42 | ssd1306_command(SSD1306_CHARGEPUMP); // 0x8D 43 | ssd1306_command(0x14); 44 | ssd1306_command(SSD1306_MEMORYMODE); // 0x20 45 | ssd1306_command(0x00); // 0x0 act like ks0108 46 | ssd1306_command(SSD1306_SEGREMAP | 0x1); 47 | ssd1306_command(SSD1306_COMSCANDEC); 48 | ssd1306_command(SSD1306_SETCOMPINS); // 0xDA 49 | ssd1306_command(0x12); 50 | ssd1306_command(SSD1306_SETCONTRAST); // 0x81 51 | ssd1306_command(0xCF); 52 | ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9 53 | ssd1306_command(0xF1); 54 | ssd1306_command(SSD1306_SETVCOMDETECT); // 0xDB 55 | ssd1306_command(0x40); 56 | ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4 57 | ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6 58 | 59 | clear(); // clear sram ... 60 | setTextColor(WHITE); 61 | setTextSize(1); 62 | update(); 63 | 64 | ssd1306_command(SSD1306_DISPLAYON);//--turn on oled panel 65 | 66 | } 67 | 68 | void Piccolino_OLED::clearpart(int from) 69 | { 70 | clearpart(from,7); 71 | } 72 | 73 | void Piccolino_OLED::dim(bool how) 74 | { 75 | ssd1306_command(SSD1306_SETCONTRAST); 76 | 77 | if(how==ON) 78 | ssd1306_command(0x25); 79 | else 80 | ssd1306_command(0xCF); 81 | } 82 | void Piccolino_OLED::clearpart(int from, int tto) 83 | { 84 | int bytestoclear=((tto+1)-from)*128; 85 | memset(&buff[from*128],0,bytestoclear);//clear the back buffer. 86 | } 87 | 88 | void Piccolino_OLED::displayOFF() 89 | { 90 | ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE 91 | } 92 | 93 | void Piccolino_OLED::displayON() 94 | { 95 | ssd1306_command(SSD1306_DISPLAYON); // 0xAE 96 | } 97 | 98 | void Piccolino_OLED::invertDisplay(uint8_t i) { 99 | if (i) { 100 | ssd1306_command(SSD1306_INVERTDISPLAY); 101 | } else { 102 | ssd1306_command(SSD1306_NORMALDISPLAY); 103 | } 104 | } 105 | 106 | void Piccolino_OLED::ssd1306_command(uint8_t c) { 107 | // I2C 108 | uint8_t control = 0x00; // Co = 0, D/C = 0 109 | Wire.beginTransmission(_i2caddr); 110 | Wire.write(control); 111 | Wire.write(c); 112 | Wire.endTransmission(); 113 | } 114 | 115 | 116 | void Piccolino_OLED::ssd1306_data(uint8_t c) { 117 | // I2C 118 | uint8_t control = 0x40; // Co = 0, D/C = 1 119 | Wire.beginTransmission(_i2caddr); 120 | Wire.write(control); 121 | Wire.write(c); 122 | Wire.endTransmission(); 123 | } 124 | 125 | void Piccolino_OLED::update() 126 | { 127 | unsigned char x; 128 | int pos=0; 129 | 130 | ssd1306_command(SSD1306_SETLOWCOLUMN | 0x0); // low col = 0 131 | ssd1306_command(SSD1306_SETHIGHCOLUMN | 0x0); // hi col = 0 132 | ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0 133 | 134 | // save I2C bitrate 135 | uint8_t twbrbackup = TWBR; 136 | TWBR = 18; // upgrade to 400KHz! 137 | 138 | for (char rowID=0; rowID<8; rowID++){ 139 | 140 | pos=0; 141 | 142 | Wire.beginTransmission(_i2caddr); 143 | Wire.write(0x00); // send command 144 | Wire.write(0xB0+rowID); 145 | Wire.write(0); 146 | Wire.endTransmission(); 147 | 148 | pos=rowID*SSD1306_LCDWIDTH; 149 | 150 | for(byte j = 0; j < 8; j++){ 151 | Wire.beginTransmission(_i2caddr); 152 | Wire.write(0x40); 153 | for (byte k = 0; k < 16; k++) { 154 | Wire.write(buff[pos++]); 155 | } 156 | Wire.endTransmission(); 157 | } 158 | } 159 | 160 | TWBR = twbrbackup; 161 | } 162 | 163 | void Piccolino_OLED::clearLine(byte line) 164 | { 165 | ssd1306_command(SSD1306_SETLOWCOLUMN | 0x0); // low col = 0 166 | ssd1306_command(SSD1306_SETHIGHCOLUMN | 0x0); // hi col = 0 167 | ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0 168 | 169 | // save I2C bitrate 170 | uint8_t twbrbackup = TWBR; 171 | TWBR = 18; // upgrade to 400KHz! 172 | 173 | // send a bunch of data in one xmission 174 | ssd1306_command(0xB0 + line);//set page address 175 | ssd1306_command(0);//set lower column address 176 | ssd1306_command(0x10);//set higher column address 177 | 178 | for(byte j = 0; j < 8; j++){ 179 | Wire.beginTransmission(_i2caddr); 180 | Wire.write(0x40); 181 | for (byte k = 0; k < 16; k++) { 182 | Wire.write(0); 183 | } 184 | Wire.endTransmission(); 185 | } 186 | 187 | TWBR = twbrbackup; 188 | } 189 | 190 | 191 | void Piccolino_OLED::updateRow(int rowID) 192 | { 193 | unsigned char x; 194 | int pos=0; 195 | 196 | ssd1306_command(SSD1306_SETLOWCOLUMN | 0x0); // low col = 0 197 | ssd1306_command(SSD1306_SETHIGHCOLUMN | 0x0); // hi col = 0 198 | ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0 199 | 200 | // save I2C bitrate 201 | uint8_t twbrbackup = TWBR; 202 | TWBR = 18; // upgrade to 400KHz! 203 | 204 | 205 | Wire.beginTransmission(_i2caddr); 206 | Wire.write(0x00); // send command 207 | Wire.write(0xB0+rowID); 208 | Wire.write(0); 209 | Wire.endTransmission(); 210 | 211 | pos=rowID*SSD1306_LCDWIDTH; 212 | 213 | for(byte j = 0; j < 8; j++){ 214 | Wire.beginTransmission(_i2caddr); 215 | Wire.write(0x40); 216 | for (byte k = 0; k < 16; k++) { 217 | Wire.write(buff[pos++]); 218 | } 219 | Wire.endTransmission(); 220 | } 221 | 222 | 223 | TWBR = twbrbackup; 224 | } 225 | 226 | void Piccolino_OLED::updateRow(int startID, int endID) 227 | { 228 | unsigned char y =0; 229 | for(y=startID; y127||y>63) return; 245 | if (x<0||y<0) return; 246 | 247 | row = y/8; 248 | offset =y%8; 249 | 250 | x+=row*SSD1306_LCDWIDTH; 251 | preData = buff[x]; 252 | 253 | //set pixel; 254 | val = 1<>= 1; 297 | } 298 | } 299 | } 300 | 301 | void Piccolino_OLED::setCursor(int16_t x, int16_t y) { 302 | cursor_x = x; 303 | cursor_y = y; 304 | } 305 | 306 | void Piccolino_OLED::setTextSize(uint8_t s) { 307 | textsize = (s > 0) ? s : 1; 308 | } 309 | 310 | void Piccolino_OLED::setTextColor(uint16_t c) { 311 | textcolor = c; 312 | } 313 | void Piccolino_OLED::setTextColor(uint16_t c,uint16_t b) { 314 | textcolor = c; 315 | textbgcolor = b; 316 | } 317 | 318 | void Piccolino_OLED::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { 319 | for (int16_t i=x; i abs(x1 - x0); 335 | 336 | if (steep) { 337 | swap(x0, y0); 338 | swap(x1, y1); 339 | } 340 | 341 | if (x0 > x1) { 342 | swap(x0, x1); 343 | swap(y0, y1); 344 | } 345 | 346 | int16_t dx, dy; 347 | dx = x1 - x0; 348 | dy = abs(y1 - y0); 349 | 350 | int16_t err = dx / 2; 351 | int16_t ystep; 352 | 353 | if (y0 < y1) { 354 | ystep = 1; 355 | } else { 356 | ystep = -1; 357 | } 358 | 359 | for (; x0<=x1; x0++) { 360 | if (steep) { 361 | if(color==GRAY) 362 | drawPixel(y0, x0, !(x0%2)); 363 | else 364 | drawPixel(y0, x0, color); 365 | } else { 366 | if(color==GRAY) 367 | drawPixel(x0, y0, !(x0%2)); 368 | else 369 | drawPixel(x0, y0, color); 370 | } 371 | err -= dy; 372 | if (err < 0) { 373 | y0 += ystep; 374 | err += dx; 375 | } 376 | } 377 | } 378 | 379 | /** 380 | * Get the color that should be used 381 | * 382 | * This function is to deal with Gray since every other pixel is printed 383 | * 384 | * @param color The color that is requested 385 | * @param index Current index of the pixel that is to be printed 386 | * @return The color to be used 387 | */ 388 | uint16_t Piccolino_OLED::getColor(uint16_t color, uint32_t index) 389 | { 390 | if(color == GRAY) { 391 | return !(index % 2); 392 | } 393 | return color; 394 | } 395 | 396 | /** 397 | * Draw a circle with an option to fill it 398 | * 399 | * NOTE: The caller must call the display update function 400 | * in order for the circle to be displayed. 401 | * 402 | * @param cx The center of the circle - X 403 | * @param cy The center of the circle - Y 404 | * @param radius The radius of the circle 405 | * @param color The color of the circle and fill if applicable 406 | * @param fill Whether to fill the circle 407 | */ 408 | void Piccolino_OLED::drawCircle( 409 | int16_t cx, int16_t cy, int16_t radius, 410 | uint16_t color, bool fill) 411 | { 412 | int deg; 413 | double px, py; 414 | uint16_t cur_color; 415 | for(deg = 0; deg < 360; deg++) { 416 | px = cx + (cos(deg) * radius); 417 | py = cy + (sin(deg) * radius); 418 | cur_color = getColor(color, deg); 419 | drawPixel(px, py, cur_color); 420 | 421 | // Filling 422 | if(fill) { 423 | int ix; 424 | if(px >= cx) { 425 | for(ix = cx; ix < px; ix++) { 426 | drawPixel(ix, py, cur_color); 427 | } 428 | } else { 429 | for(ix = cx; ix > px; ix--) { 430 | drawPixel(ix, py, cur_color); 431 | } 432 | } 433 | } 434 | } 435 | } 436 | 437 | 438 | size_t Piccolino_OLED::write(uint8_t c) { 439 | if (c == '\n') { 440 | cursor_y += textsize*8; 441 | cursor_x = 0; 442 | } else if (c == '\r') { 443 | // skip em 444 | } else { 445 | drawChar(1+cursor_x, 1+cursor_y, c, textcolor, textbgcolor, textsize); 446 | cursor_x += textsize*6; 447 | if (wrap && (cursor_x > (SSD1306_LCDWIDTH - textsize*6))) { 448 | cursor_y += textsize*8; 449 | cursor_x = 0; 450 | } 451 | } 452 | return 1; 453 | } 454 | 455 | Piccolino_OLED::~Piccolino_OLED() 456 | { 457 | 458 | } 459 | -------------------------------------------------------------------------------- /Arduino/HX711/LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | --------------------------------------------------------------------------------