├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── Robot ├── .gitignore ├── build.gradle ├── libs │ └── nanoHttpd.jar ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── magc.html │ └── wscontrol.html │ ├── java │ └── com │ │ └── samgol │ │ └── robot │ │ ├── Inputs │ │ ├── InputData.java │ │ ├── InputDataObserver.java │ │ ├── InputKb.java │ │ ├── InputSource.java │ │ ├── InputType.java │ │ └── command │ │ │ ├── Command.java │ │ │ └── CommandSource.java │ │ ├── RobotActivity.java │ │ ├── button │ │ ├── AlarmButton.java │ │ └── AlarmData.java │ │ ├── camera │ │ ├── CamInputType.java │ │ ├── CameraInputData.java │ │ ├── RobotCamera.java │ │ └── ServoCamera.java │ │ ├── chassis │ │ ├── DcMotorMock.java │ │ ├── DcMotorOnOff.java │ │ ├── DcMotorWithSpeed.java │ │ ├── RobotChassisMotorBased.java │ │ ├── RobotChassisPid.java │ │ ├── RobotChassisSimple.java │ │ ├── RobotMotor.java │ │ └── RobotСhassis.java │ │ ├── compass │ │ ├── HMC5883L.java │ │ └── RotationSensor.java │ │ ├── controller │ │ └── FinalStateMachine.java │ │ ├── lcd │ │ ├── Font.java │ │ ├── Fonts.java │ │ └── RobotLcd.java │ │ ├── ledrgb │ │ └── LedRGB.java │ │ ├── obstacle │ │ ├── Hcsr04.java │ │ ├── ObstacleInput.java │ │ ├── ObstacleInputDataType.java │ │ └── ObstacleSensor.java │ │ └── remoteControl │ │ ├── CommandListener.java │ │ ├── ImageConsumer.java │ │ ├── Server.java │ │ └── Ws.java │ └── res │ ├── layout │ └── activity_robot.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ └── strings.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── img ├── btn.jpg ├── h-bridge.jpg ├── hc-sr04-02.jpg ├── motor.jpg ├── raspberry_pi_3.jpg ├── rgb.jpg ├── robot.jpg ├── servo.jpg └── ssd1306.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # Intellij 36 | *.iml 37 | .idea/workspace.xml 38 | .idea/tasks.xml 39 | .idea/gradle.xml 40 | .idea/libraries 41 | 42 | # Keystore files 43 | *.jks 44 | 45 | # External native build folder generated in Android Studio 2.2 and later 46 | .externalNativeBuild 47 | 48 | # Google Services (e.g. APIs or Firebase) 49 | google-services.json 50 | 51 | # Freeline 52 | freeline.py 53 | freeline/ 54 | freeline_project_description.json 55 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 1.8 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android Things Robot 2 | Android Things robot, controlled by web interface with: camera, servo, distance sensor(hc-sr04), lcd display(ssd1306), rgb led, halt button, motor-driver (h-bridge), dc motors. 3 | 4 | ###Click on image below to play video. 5 | [![androd things robot video ](/img/robot.jpg?raw=true "Android Things Robot")](https://www.youtube.com/watch?v=kqzAsOs99Dc) 6 | 7 | ### SSD1306 8 | ![Android Things lcd ssd 1306](/img/ssd1306.jpg?raw=true "") 9 | 10 | ### HC-SR04 11 | ![Android Things HC-SR04](/img/hc-sr04-02.jpg?raw=true "") 12 | 13 | ### RGB Led 14 | ![Android Things RGB led](/img/rgb.jpg?raw=true "") 15 | 16 | ### halt button 17 | ![Android Things push button](/img/btn.jpg?raw=true "") 18 | 19 | ### Motor driver 20 | ![Android Things motor driver H-bridge ](/img/h-bridge.jpg?raw=true "") 21 | 22 | ### DC Motor 23 | ![Android Things DC motor ](/img/motor.jpg?raw=true "") 24 | 25 | ### Micro Servo 9g 26 | ![Android Things micro servo 9g](/img/servo.jpg?raw=true "") 27 | 28 | ### Raspberry Pi 3 with Camera 29 | ![Android Things Raspberry Pi 3 with Camera](/img/raspberry_pi_3.jpg?raw=true "") 30 | 31 | #Wiring 32 | 33 | #Software Architecture 34 | 35 | -------------------------------------------------------------------------------- /Robot/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Robot/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion "25.0.1" 6 | defaultConfig { 7 | applicationId "com.samgol.robot" 8 | minSdkVersion 24 9 | targetSdkVersion 24 10 | versionCode 1 11 | versionName "1.0" 12 | jackOptions { 13 | enabled true 14 | } 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | compileOptions { 23 | targetCompatibility 1.8 24 | sourceCompatibility 1.8 25 | } 26 | } 27 | 28 | dependencies { 29 | provided 'com.google.android.things:androidthings:0.1-devpreview' 30 | compile 'com.google.android.things.contrib:driver-pwmservo:0.1' 31 | compile 'com.google.android.things.contrib:driver-ssd1306:0.1' 32 | compile fileTree(dir: 'libs', include: ['*.jar']) 33 | } -------------------------------------------------------------------------------- /Robot/libs/nanoHttpd.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euler2dot7/android_things_robot/6bbdf767f5a61e0893942e7be248d95765a72702/Robot/libs/nanoHttpd.jar -------------------------------------------------------------------------------- /Robot/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/x/Android/Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /Robot/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Robot/src/main/assets/magc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Robot Control 5 | 6 | 7 | 40 | 41 | 42 | 43 |
44 |
45 | 46 |
47 | 48 | 49 | 108 | -------------------------------------------------------------------------------- /Robot/src/main/assets/wscontrol.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Robot Control 4 | 37 | 82 | 83 | 84 |
85 | 86 |
87 | 88 |
89 |
90 | 91 | 92 | 93 |
94 |
95 | 96 |
97 |
98 | 99 | 100 |
101 |
102 | 103 | 104 |
105 | 106 |
107 | 108 | 124 | 125 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/Inputs/InputData.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.Inputs; 2 | 3 | public class InputData { 4 | private InputType inputType; 5 | protected String defStringRep; 6 | protected boolean permanent = true; 7 | 8 | 9 | public InputData(InputType inputType) { 10 | this(inputType, true); 11 | } 12 | 13 | public InputData(InputType inputType, boolean permanent) { 14 | this.inputType = inputType; 15 | defStringRep = inputType.name(); 16 | this.permanent = permanent; 17 | 18 | } 19 | 20 | 21 | public InputType getInputType() { 22 | return inputType; 23 | } 24 | 25 | public String getDefStringRep() { 26 | return defStringRep; 27 | } 28 | 29 | public boolean eq(InputData ev) { 30 | boolean result = false; 31 | if (ev != null && defStringRep != null) { 32 | result = defStringRep.equalsIgnoreCase(ev.getDefStringRep()); 33 | } 34 | return result; 35 | } 36 | 37 | public boolean isPermanent() { 38 | return permanent; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/Inputs/InputDataObserver.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.Inputs; 2 | 3 | public interface InputDataObserver { 4 | void onInput(I Input); 5 | } 6 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/Inputs/InputKb.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.Inputs; 2 | 3 | import com.samgol.robot.Inputs.command.Command; 4 | import com.samgol.robot.button.AlarmData; 5 | import com.samgol.robot.camera.CameraInputData; 6 | import com.samgol.robot.obstacle.ObstacleInput; 7 | 8 | import static com.samgol.robot.Inputs.command.CommandSource.BACKWARD; 9 | import static com.samgol.robot.Inputs.command.CommandSource.CAM_DOWN; 10 | import static com.samgol.robot.Inputs.command.CommandSource.CAM_UP; 11 | import static com.samgol.robot.Inputs.command.CommandSource.FORWARD; 12 | import static com.samgol.robot.Inputs.command.CommandSource.LEFT; 13 | import static com.samgol.robot.Inputs.command.CommandSource.RIGHT; 14 | import static com.samgol.robot.Inputs.command.CommandSource.STOP; 15 | import static com.samgol.robot.Inputs.command.CommandSource.TAKE_A_SHOT; 16 | import static com.samgol.robot.camera.CamInputType.SHOT_COMPLETED; 17 | import static com.samgol.robot.obstacle.ObstacleInputDataType.CLOSE; 18 | import static com.samgol.robot.obstacle.ObstacleInputDataType.FAR; 19 | import static com.samgol.robot.obstacle.ObstacleInputDataType.NEAR; 20 | 21 | /** 22 | * Created by x on 1/8/17. 23 | */ 24 | 25 | public class InputKb { 26 | 27 | public static final ObstacleInput OBS_CLOSE = new ObstacleInput(CLOSE); 28 | public static final ObstacleInput OBS_NEAR = new ObstacleInput(NEAR); 29 | public static final ObstacleInput OBS_FAR = new ObstacleInput(FAR); 30 | 31 | public static final Command CMD_STOP = new Command(STOP); 32 | public static final Command CMD_FORWARD = new Command(FORWARD); 33 | public static final Command CMD_BACKWARD = new Command(BACKWARD); 34 | public static final Command CMD_LEFT = new Command(LEFT); 35 | public static final Command CMD_RIGHT = new Command(RIGHT); 36 | public static final Command CMD_CAM_UP = new Command(CAM_UP); 37 | public static final Command CMD_CAM_DOWN = new Command(CAM_DOWN); 38 | public static final Command CMD_CAM_SHOT = new Command(TAKE_A_SHOT); 39 | 40 | public static final CameraInputData CAM_COMPLETED = new CameraInputData(SHOT_COMPLETED); 41 | public static final AlarmData HALT = new AlarmData(); 42 | } 43 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/Inputs/InputSource.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.Inputs; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | public abstract class InputSource { 7 | private Set> observers = new HashSet>(); 8 | 9 | protected void onInput(T inputData) { 10 | for (InputDataObserver observer : observers) { 11 | observer.onInput(inputData); 12 | } 13 | } 14 | 15 | public boolean addObserver(InputDataObserver inputObserver) { 16 | return observers.add(inputObserver); 17 | } 18 | 19 | public boolean removeHandler(InputDataObserver inputObserver) { 20 | return observers.remove(inputObserver); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/Inputs/InputType.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.Inputs; 2 | 3 | public enum InputType { 4 | COMMAND, OBSTACLE, HALT, TIME, CAMERA 5 | } 6 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/Inputs/command/Command.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.Inputs.command; 2 | 3 | import com.samgol.robot.Inputs.InputData; 4 | import com.samgol.robot.Inputs.InputType; 5 | 6 | /** 7 | * Created by x on 1/8/17. 8 | */ 9 | 10 | public class Command extends InputData { 11 | public Command(@CommandSource.CommandType String commandType) { 12 | super(InputType.COMMAND); 13 | defStringRep += "_" + commandType; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/Inputs/command/CommandSource.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.Inputs.command; 2 | 3 | import android.support.annotation.StringDef; 4 | 5 | import com.samgol.robot.Inputs.InputSource; 6 | import com.samgol.robot.remoteControl.CommandListener; 7 | 8 | import java.lang.annotation.Retention; 9 | 10 | import static com.samgol.robot.Inputs.InputKb.CMD_BACKWARD; 11 | import static com.samgol.robot.Inputs.InputKb.CMD_CAM_DOWN; 12 | import static com.samgol.robot.Inputs.InputKb.CMD_CAM_SHOT; 13 | import static com.samgol.robot.Inputs.InputKb.CMD_CAM_UP; 14 | import static com.samgol.robot.Inputs.InputKb.CMD_FORWARD; 15 | import static com.samgol.robot.Inputs.InputKb.CMD_LEFT; 16 | import static com.samgol.robot.Inputs.InputKb.CMD_RIGHT; 17 | import static com.samgol.robot.Inputs.InputKb.CMD_STOP; 18 | import static java.lang.annotation.RetentionPolicy.SOURCE; 19 | 20 | /** 21 | * Created by x on 1/8/17. 22 | */ 23 | 24 | 25 | public class CommandSource extends InputSource implements CommandListener { 26 | 27 | @Retention(SOURCE) 28 | @StringDef({STOP, FORWARD, BACKWARD, LEFT, RIGHT, CAM_UP, CAM_DOWN, TAKE_A_SHOT}) 29 | 30 | public @interface CommandType { 31 | } 32 | 33 | public static final String STOP = "STOP"; 34 | public static final String FORWARD = "FORWARD"; 35 | public static final String BACKWARD = "BACKWARD"; 36 | public static final String LEFT = "LEFT"; 37 | public static final String RIGHT = "RIGHT"; 38 | public static final String CAM_UP = "CAM_UP"; 39 | public static final String CAM_DOWN = "CAM_DOWN"; 40 | public static final String TAKE_A_SHOT = "TAKE_A_SHOT"; 41 | 42 | @Override 43 | public void onCommand(String command) { 44 | command = command.toLowerCase().trim(); 45 | // System.out.println("command = " + command); 46 | 47 | switch (command) { 48 | case "w": 49 | onInput(CMD_FORWARD); 50 | break; 51 | case "s": 52 | onInput(CMD_BACKWARD); 53 | break; 54 | case "a": 55 | onInput(CMD_LEFT); 56 | break; 57 | case "d": 58 | onInput(CMD_RIGHT); 59 | break; 60 | case "j": 61 | onInput(CMD_CAM_DOWN); 62 | break; 63 | case "k": 64 | onInput(CMD_CAM_UP); 65 | break; 66 | case "p": 67 | onInput(CMD_CAM_SHOT); 68 | break; 69 | default: 70 | onInput(CMD_STOP); 71 | break; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/RobotActivity.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.content.pm.PackageManager; 6 | import android.os.Bundle; 7 | import android.os.Handler; 8 | import android.os.HandlerThread; 9 | import android.util.Log; 10 | 11 | import com.google.android.things.pio.PeripheralManagerService; 12 | import com.samgol.robot.Inputs.command.CommandSource; 13 | import com.samgol.robot.button.AlarmButton; 14 | import com.samgol.robot.camera.ServoCamera; 15 | import com.samgol.robot.chassis.DcMotorWithSpeed; 16 | import com.samgol.robot.chassis.RobotChassisMotorBased; 17 | import com.samgol.robot.chassis.RobotMotor; 18 | import com.samgol.robot.chassis.RobotСhassis; 19 | import com.samgol.robot.compass.RotationSensor; 20 | import com.samgol.robot.controller.FinalStateMachine; 21 | import com.samgol.robot.lcd.RobotLcd; 22 | import com.samgol.robot.ledrgb.LedRGB; 23 | import com.samgol.robot.obstacle.ObstacleSensor; 24 | import com.samgol.robot.remoteControl.Server; 25 | 26 | import java.io.IOException; 27 | import java.util.concurrent.TimeUnit; 28 | 29 | 30 | public class RobotActivity extends Activity { 31 | private static final String TAG = RobotActivity.class.getSimpleName(); 32 | //TODO check pins 33 | //Right motor 34 | private static final String GPIO_R_CW = "BCM27"; 35 | private static final String GPIO_R_CCW = "BCM23"; 36 | 37 | //Left motor 38 | private static final String GPIO_L_CW = "BCM17"; 39 | private static final String GPIO_L_CCW = "BCM25"; 40 | 41 | //HC-SR04 42 | private static final String GPIO_TRIG = "BCM26"; 43 | private static final String GPIO_ECHO = "BCM19"; 44 | 45 | //RGB Led 46 | private static final String GPIO_R = "BCM20"; 47 | private static final String GPIO_G = "BCM16"; 48 | private static final String GPIO_B = "BCM21"; 49 | 50 | //Alarm button 51 | private static final String GPIO_HALT = "BCM5"; 52 | private static final String GPIO_HALT_VCC = "BCM6"; 53 | 54 | //Servo camera 55 | private static final String GPIO_PWM_SERVO = "PWM0"; 56 | 57 | private static final String ROBOT_I2C = "I2C1"; 58 | 59 | private PeripheralManagerService service; 60 | private RobotСhassis robotСhassis; 61 | 62 | private ServoCamera servoCamera; 63 | private Server server; 64 | private ObstacleSensor obstacleDetector; 65 | private AlarmButton alarmButton; 66 | private LedRGB ledRGB; 67 | private RobotLcd mRobotLcd; 68 | 69 | private Handler mHandler; 70 | private HandlerThread mHandlerThread; 71 | 72 | private void initHandler() { 73 | mHandlerThread = new HandlerThread("test thread"); 74 | mHandlerThread.start(); 75 | mHandler = new Handler(mHandlerThread.getLooper()); 76 | } 77 | 78 | Runnable pause = () -> { 79 | try { 80 | TimeUnit.SECONDS.sleep(1); 81 | } catch (InterruptedException e) { 82 | e.printStackTrace(); 83 | } 84 | }; 85 | RotationSensor rotationSensor; 86 | 87 | @Override 88 | protected void onCreate(Bundle savedInstanceState) { 89 | 90 | super.onCreate(savedInstanceState); 91 | setContentView(R.layout.activity_robot); 92 | initHandler(); 93 | 94 | try { 95 | mRobotLcd = new RobotLcd(this, ROBOT_I2C); 96 | } catch (IOException e) { 97 | e.printStackTrace(); 98 | } 99 | 100 | service = new PeripheralManagerService(); 101 | // System.out.println(service.getGpioList()); 102 | try { 103 | RobotMotor leftMotor = new DcMotorWithSpeed(GPIO_L_CW, GPIO_L_CCW, service, 17); 104 | RobotMotor rightMotor = new DcMotorWithSpeed(GPIO_R_CW, GPIO_R_CCW, service); 105 | robotСhassis = new RobotChassisMotorBased(leftMotor, rightMotor); 106 | } catch (IOException e) { 107 | e.printStackTrace(); 108 | } 109 | 110 | try { 111 | ledRGB = new LedRGB(GPIO_R, GPIO_G, GPIO_B, service); 112 | } catch (IOException e) { 113 | e.printStackTrace(); 114 | ledRGB = null; 115 | } 116 | if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { 117 | Log.d(TAG, "No permission"); 118 | return; 119 | } 120 | 121 | try { 122 | servoCamera = new ServoCamera(GPIO_PWM_SERVO, this); 123 | 124 | } catch (IOException e) { 125 | e.printStackTrace(); 126 | } 127 | 128 | FinalStateMachine robotBrain = new FinalStateMachine(robotСhassis, servoCamera, ledRGB); 129 | 130 | CommandSource commandSource = new CommandSource(); 131 | commandSource.addObserver(robotBrain); 132 | server = new Server(8080, commandSource, getAssets()); 133 | 134 | if (servoCamera != null) { 135 | servoCamera.setImageConsumer(server); 136 | servoCamera.addObserver(robotBrain); 137 | } 138 | 139 | try { 140 | server.start(); 141 | Log.d(TAG, "onCreate: Http server started"); 142 | } catch (IOException e) { 143 | e.printStackTrace(); 144 | } 145 | 146 | try { 147 | obstacleDetector = new ObstacleSensor(service.openGpio(GPIO_ECHO), service.openGpio(GPIO_TRIG)); 148 | obstacleDetector.addObserver(robotBrain); 149 | } catch (IOException e) { 150 | e.printStackTrace(); 151 | } 152 | 153 | try { 154 | alarmButton = new AlarmButton(GPIO_HALT, GPIO_HALT_VCC, service); 155 | alarmButton.addObserver(robotBrain); 156 | } catch (IOException e) { 157 | e.printStackTrace(); 158 | } 159 | } 160 | 161 | @Override 162 | protected void onDestroy() { 163 | server.stop(); 164 | try { 165 | robotСhassis.close(); 166 | } catch (Exception e) { 167 | Log.w(TAG, "Exception: " + e.getMessage()); 168 | } 169 | 170 | try { 171 | ledRGB.close(); 172 | } catch (Exception e) { 173 | Log.w(TAG, "Exception: " + e.getMessage()); 174 | } 175 | try { 176 | servoCamera.close(); 177 | } catch (Exception e) { 178 | Log.w(TAG, "Exception: " + e.getMessage()); 179 | } 180 | try { 181 | obstacleDetector.close(); 182 | } catch (Exception e) { 183 | Log.w(TAG, "Exception: " + e.getMessage()); 184 | } 185 | 186 | try { 187 | alarmButton.close(); 188 | } catch (Exception e) { 189 | Log.w(TAG, "Exception: " + e.getMessage()); 190 | } 191 | try { 192 | mRobotLcd.close(); 193 | } catch (Exception e) { 194 | Log.w(TAG, "Exception: " + e.getMessage()); 195 | } 196 | 197 | mHandlerThread.quitSafely(); 198 | 199 | super.onDestroy(); 200 | } 201 | 202 | // private void setUpWifi(String ssid, String key){ 203 | // WifiConfiguration wifiConfig = new WifiConfiguration(); 204 | // wifiConfig.SSID = String.format("\"%s\"", ssid); 205 | // wifiConfig.preSharedKey = String.format("\"%s\"", key); 206 | // 207 | // WifiManager wifiManager = (WifiManager)getSystemService(WIFI_SERVICE); 208 | ////remember id 209 | // int netId = wifiManager.addNetwork(wifiConfig); 210 | // wifiManager.disconnect(); 211 | // wifiManager.enableNetwork(netId, true); 212 | // wifiManager.reconnect(); 213 | // } 214 | // private String getWifiAddress() { 215 | // WifiManager wifiMgr = (WifiManager) getSystemService(WIFI_SERVICE); 216 | // WifiInfo wifiInfo = wifiMgr.getConnectionInfo(); 217 | // int ip = wifiInfo.getIpAddress(); 218 | // String ipAddress = Formatter.formatIpAddress(ip); 219 | // return ipAddress; 220 | // } 221 | 222 | 223 | } 224 | // try { 225 | // rotationSensor = new RotationSensor(ROBOT_I2C); 226 | // mHandler.post(new Runnable() { 227 | // @Override 228 | // public void run() { 229 | // for (int i = 0; i < 1000; i++) { 230 | // try { 231 | // int[] vals = rotationSensor.getMagnitudeXY(); 232 | // Log.d(TAG, "run: " + Arrays.toString(vals)); 233 | // JSONObject object = new JSONObject(); 234 | // object.put("x", vals[0]); 235 | // object.put("y", vals[1]); 236 | // server.onMsg(object.toString()); 237 | // TimeUnit.SECONDS.sleep(1); 238 | // } catch (Exception e) { 239 | // Log.e(TAG, "Rotation: " + e.getMessage()); 240 | // } 241 | // } 242 | // } 243 | // }); 244 | // } catch (IOException e) { 245 | // e.printStackTrace(); 246 | // } 247 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/button/AlarmButton.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.button; 2 | 3 | import android.util.Log; 4 | 5 | import com.google.android.things.pio.Gpio; 6 | import com.google.android.things.pio.GpioCallback; 7 | import com.google.android.things.pio.PeripheralManagerService; 8 | import com.samgol.robot.Inputs.InputSource; 9 | 10 | import java.io.IOException; 11 | 12 | import static com.samgol.robot.Inputs.InputKb.HALT; 13 | 14 | /** 15 | * Created by x on 1/30/17. 16 | */ 17 | 18 | public class AlarmButton extends InputSource implements AutoCloseable { 19 | 20 | private static final String TAG = AlarmButton.class.getSimpleName(); 21 | private Gpio mButtonGpio; 22 | private Gpio mVccGpio; 23 | private PeripheralManagerService service; 24 | private long last_click; 25 | 26 | public AlarmButton(String btnGpio, String vccGpio, PeripheralManagerService service) throws IOException { 27 | this(btnGpio, service); 28 | mVccGpio = service.openGpio(vccGpio); 29 | mVccGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_HIGH); 30 | } 31 | 32 | public AlarmButton(String btnGpio, PeripheralManagerService service) throws IOException { 33 | this.service = service; 34 | mButtonGpio = service.openGpio(btnGpio); 35 | mButtonGpio.setDirection(Gpio.DIRECTION_IN); 36 | mButtonGpio.setEdgeTriggerType(Gpio.EDGE_RISING); 37 | mButtonGpio.registerGpioCallback(mCallback); 38 | } 39 | 40 | private void halt() { 41 | onInput(HALT); 42 | } 43 | 44 | private GpioCallback mCallback = new GpioCallback() { 45 | @Override 46 | public boolean onGpioEdge(Gpio gpio) { 47 | long click_time = System.currentTimeMillis(); 48 | if (click_time - last_click > 500) { 49 | Log.i(TAG, "GPIO changed, button pressed"); 50 | halt(); 51 | } 52 | last_click = click_time; 53 | return true; 54 | } 55 | }; 56 | 57 | @Override 58 | public void close() throws Exception { 59 | mButtonGpio.close(); 60 | mVccGpio.close(); 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/button/AlarmData.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.button; 2 | 3 | import com.samgol.robot.Inputs.InputData; 4 | 5 | import static com.samgol.robot.Inputs.InputType.HALT; 6 | 7 | /** 8 | * Created by x on 1/30/17. 9 | */ 10 | 11 | public class AlarmData extends InputData { 12 | public AlarmData() { 13 | super(HALT); 14 | defStringRep += "_" + HALT.name(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/camera/CamInputType.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.camera; 2 | 3 | /** 4 | * Created by x on 1/30/17. 5 | */ 6 | 7 | public enum CamInputType { 8 | SHOT_COMPLETED 9 | } 10 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/camera/CameraInputData.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.camera; 2 | 3 | import com.samgol.robot.Inputs.InputData; 4 | 5 | import static com.samgol.robot.Inputs.InputType.CAMERA; 6 | 7 | /** 8 | * Created by x on 1/30/17. 9 | */ 10 | 11 | public class CameraInputData extends InputData { 12 | public CameraInputData(CamInputType type) { 13 | super(CAMERA); 14 | defStringRep += "_" + type.name(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/camera/RobotCamera.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016, The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.samgol.robot.camera; 17 | 18 | import android.content.Context; 19 | import android.graphics.ImageFormat; 20 | import android.hardware.camera2.CameraAccessException; 21 | import android.hardware.camera2.CameraCaptureSession; 22 | import android.hardware.camera2.CameraCharacteristics; 23 | import android.hardware.camera2.CameraDevice; 24 | import android.hardware.camera2.CameraManager; 25 | import android.hardware.camera2.CaptureRequest; 26 | import android.hardware.camera2.CaptureResult; 27 | import android.hardware.camera2.TotalCaptureResult; 28 | import android.hardware.camera2.params.StreamConfigurationMap; 29 | import android.media.ImageReader; 30 | import android.os.Handler; 31 | import android.util.Log; 32 | import android.util.Size; 33 | 34 | import java.util.Collections; 35 | 36 | import static android.content.Context.CAMERA_SERVICE; 37 | 38 | public class RobotCamera { 39 | private static final String TAG = RobotCamera.class.getSimpleName(); 40 | 41 | private static final int IMAGE_WIDTH = 320; 42 | private static final int IMAGE_HEIGHT = 240; 43 | private static final int MAX_IMAGES = 1; 44 | 45 | private CameraDevice mCameraDevice; 46 | 47 | private CameraCaptureSession mCaptureSession; 48 | 49 | /** 50 | * An {@link ImageReader} that handles still image capture. 51 | */ 52 | private ImageReader mImageReader; 53 | 54 | // Lazy-loaded singleton, so only one instance of the camera is created. 55 | private RobotCamera() { 56 | } 57 | 58 | private static class InstanceHolder { 59 | private static RobotCamera mRobotCamera = new RobotCamera(); 60 | } 61 | 62 | public static RobotCamera getInstance() { 63 | return InstanceHolder.mRobotCamera; 64 | } 65 | 66 | /** 67 | * Initialize the camera device 68 | */ 69 | @SuppressWarnings("MissingPermission") 70 | public void initializeCamera(Context context, 71 | Handler backgroundHandler, 72 | ImageReader.OnImageAvailableListener imageAvailableListener) { 73 | // Discover the camera instance 74 | CameraManager manager = (CameraManager) context.getSystemService(CAMERA_SERVICE); 75 | String[] camIds = {}; 76 | try { 77 | camIds = manager.getCameraIdList(); 78 | } catch (CameraAccessException e) { 79 | Log.d(TAG, "Cam access exception getting IDs", e); 80 | } 81 | if (camIds.length < 1) { 82 | Log.d(TAG, "No cameras found"); 83 | return; 84 | } 85 | String id = camIds[0]; 86 | Log.d(TAG, "Using camera id " + id); 87 | 88 | // Initialize the image processor 89 | mImageReader = ImageReader.newInstance(IMAGE_WIDTH, IMAGE_HEIGHT, 90 | ImageFormat.JPEG, MAX_IMAGES); 91 | mImageReader.setOnImageAvailableListener( 92 | imageAvailableListener, backgroundHandler); 93 | 94 | // Open the camera resource 95 | try { 96 | manager.openCamera(id, mStateCallback, backgroundHandler); 97 | } catch (CameraAccessException cae) { 98 | Log.d(TAG, "RobotCamera access exception", cae); 99 | } 100 | } 101 | 102 | /** 103 | * Callback handling device state changes 104 | */ 105 | private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { 106 | @Override 107 | public void onOpened(CameraDevice cameraDevice) { 108 | Log.d(TAG, "Opened camera."); 109 | mCameraDevice = cameraDevice; 110 | } 111 | 112 | @Override 113 | public void onDisconnected(CameraDevice cameraDevice) { 114 | Log.d(TAG, "RobotCamera disconnected, closing."); 115 | cameraDevice.close(); 116 | } 117 | 118 | @Override 119 | public void onError(CameraDevice cameraDevice, int i) { 120 | Log.d(TAG, "RobotCamera device error, closing."); 121 | cameraDevice.close(); 122 | } 123 | 124 | @Override 125 | public void onClosed(CameraDevice cameraDevice) { 126 | Log.d(TAG, "Closed camera, releasing"); 127 | mCameraDevice = null; 128 | } 129 | }; 130 | 131 | /** 132 | * Begin a still image capture 133 | */ 134 | public void takePicture() { 135 | if (mCameraDevice == null) { 136 | Log.w(TAG, "Cannot capture image. RobotCamera not initialized."); 137 | return; 138 | } 139 | 140 | // Here, we create a CameraCaptureSession for capturing still images. 141 | try { 142 | mCameraDevice.createCaptureSession( 143 | Collections.singletonList(mImageReader.getSurface()), 144 | mSessionCallback, 145 | null); 146 | } catch (Exception cae) { 147 | 148 | Log.d(TAG, "access exception while preparing pic", cae); 149 | Log.e(TAG, "takePicture: ", cae); 150 | } 151 | } 152 | 153 | /** 154 | * Callback handling session state changes 155 | */ 156 | private CameraCaptureSession.StateCallback mSessionCallback = 157 | new CameraCaptureSession.StateCallback() { 158 | @Override 159 | public void onConfigured(CameraCaptureSession cameraCaptureSession) { 160 | // The camera is already closed 161 | if (mCameraDevice == null) { 162 | return; 163 | } 164 | 165 | // When the session is ready, we start capture. 166 | mCaptureSession = cameraCaptureSession; 167 | triggerImageCapture(); 168 | } 169 | 170 | @Override 171 | public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) { 172 | Log.w(TAG, "Failed to configure camera"); 173 | } 174 | }; 175 | 176 | /** 177 | * Execute a new capture request within the active session 178 | */ 179 | private void triggerImageCapture() { 180 | try { 181 | final CaptureRequest.Builder captureBuilder = 182 | mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 183 | captureBuilder.addTarget(mImageReader.getSurface()); 184 | captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON); 185 | Log.d(TAG, "Session initialized."); 186 | mCaptureSession.capture(captureBuilder.build(), mCaptureCallback, null); 187 | } catch (CameraAccessException cae) { 188 | Log.d(TAG, "camera capture exception"); 189 | } 190 | } 191 | 192 | /** 193 | * Callback handling capture session events 194 | */ 195 | private final CameraCaptureSession.CaptureCallback mCaptureCallback = 196 | new CameraCaptureSession.CaptureCallback() { 197 | 198 | @Override 199 | public void onCaptureProgressed(CameraCaptureSession session, 200 | CaptureRequest request, 201 | CaptureResult partialResult) { 202 | Log.d(TAG, "Partial result"); 203 | } 204 | 205 | @Override 206 | public void onCaptureCompleted(CameraCaptureSession session, 207 | CaptureRequest request, 208 | TotalCaptureResult result) { 209 | if (session != null) { 210 | session.close(); 211 | mCaptureSession = null; 212 | Log.d(TAG, "CaptureSession closed"); 213 | } 214 | } 215 | }; 216 | 217 | 218 | /** 219 | * Close the camera resources 220 | */ 221 | public void shutDown() { 222 | if (mCameraDevice != null) { 223 | mCameraDevice.close(); 224 | } 225 | } 226 | 227 | /** 228 | * Helpful debugging method: Dump all supported camera formats to log. You don't need to run 229 | * this for normal operation, but it's very helpful when porting this code to different 230 | * hardware. 231 | */ 232 | public static void dumpFormatInfo(Context context) { 233 | CameraManager manager = (CameraManager) context.getSystemService(CAMERA_SERVICE); 234 | String[] camIds = {}; 235 | try { 236 | camIds = manager.getCameraIdList(); 237 | } catch (CameraAccessException e) { 238 | Log.d(TAG, "Cam access exception getting IDs"); 239 | } 240 | if (camIds.length < 1) { 241 | Log.d(TAG, "No cameras found"); 242 | } 243 | String id = camIds[0]; 244 | Log.d(TAG, "Using camera id " + id); 245 | try { 246 | CameraCharacteristics characteristics = manager.getCameraCharacteristics(id); 247 | StreamConfigurationMap configs = characteristics.get( 248 | CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 249 | for (int format : configs.getOutputFormats()) { 250 | Log.d(TAG, "Getting sizes for format: " + format); 251 | for (Size s : configs.getOutputSizes(format)) { 252 | Log.d(TAG, "\t" + s.toString()); 253 | } 254 | } 255 | int[] effects = characteristics.get(CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS); 256 | for (int effect : effects) { 257 | Log.d(TAG, "Effect available: " + effect); 258 | } 259 | } catch (CameraAccessException e) { 260 | Log.d(TAG, "Cam access exception getting characteristics."); 261 | } 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/camera/ServoCamera.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.camera; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.media.Image; 7 | import android.media.ImageReader; 8 | import android.os.Handler; 9 | import android.os.HandlerThread; 10 | import android.util.Base64; 11 | import android.util.Log; 12 | 13 | import com.google.android.things.contrib.driver.pwmservo.Servo; 14 | import com.samgol.robot.Inputs.InputSource; 15 | import com.samgol.robot.remoteControl.ImageConsumer; 16 | 17 | import java.io.ByteArrayOutputStream; 18 | import java.io.IOException; 19 | import java.nio.ByteBuffer; 20 | 21 | import static com.samgol.robot.Inputs.InputKb.CAM_COMPLETED; 22 | 23 | /** 24 | * Created by x on 1/30/17. 25 | */ 26 | 27 | public class ServoCamera extends InputSource implements AutoCloseable { 28 | private static final String TAG = ServoCamera.class.getSimpleName(); 29 | private final String PWM_PIN; 30 | private String imageStr; 31 | 32 | private Servo mServo; 33 | private RobotCamera mCamera; 34 | private Handler mWebHandler; 35 | private HandlerThread mWebThread; 36 | private ImageConsumer imageConsumer; 37 | private Handler mCameraHandler; 38 | private HandlerThread mCameraThread; 39 | 40 | private static final int INC_ANGLE = 5; 41 | 42 | public ServoCamera(String PWM_PIN, Context context) throws IOException { 43 | this.PWM_PIN = PWM_PIN; 44 | mServo = new Servo("PWM0"); 45 | mServo.setPulseDurationRange(0.6, 2.5); // according to your servo's specifications 46 | mServo.setAngleRange(0, 180); // according to your servo's specifications 47 | mServo.setEnabled(true); 48 | mServo.setAngle(90); 49 | 50 | mWebThread = new HandlerThread("WebThread"); 51 | mWebThread.start(); 52 | mWebHandler = new Handler(mWebThread.getLooper()); 53 | 54 | mCameraThread = new HandlerThread("Camera Thread"); 55 | mCameraThread.start(); 56 | mCameraHandler = new Handler(mCameraThread.getLooper()); 57 | 58 | RobotCamera robotCamera = RobotCamera.getInstance(); 59 | robotCamera.initializeCamera(context, mCameraHandler, mOnImageAvailableListener); 60 | this.mCamera = robotCamera; 61 | } 62 | 63 | public void setImageConsumer(ImageConsumer imageConsumer) { 64 | this.imageConsumer = imageConsumer; 65 | } 66 | 67 | public void up() { 68 | try { 69 | mServo.setAngle(mServo.getAngle() >= 175 ? mServo.getAngle() : mServo.getAngle() + INC_ANGLE); 70 | } catch (IOException e) { 71 | e.printStackTrace(); 72 | } 73 | } 74 | 75 | public void center() { 76 | try { 77 | mServo.setAngle(90); 78 | } catch (IOException e) { 79 | e.printStackTrace(); 80 | } 81 | } 82 | 83 | public void down() { 84 | try { 85 | mServo.setAngle(mServo.getAngle() <= 5 ? mServo.getAngle() : mServo.getAngle() - INC_ANGLE); 86 | } catch (IOException e) { 87 | e.printStackTrace(); 88 | } 89 | } 90 | 91 | public void takeAshot() { 92 | mWebHandler.post(mCamera::takePicture); 93 | // mCamera.takePicture(); 94 | } 95 | 96 | private ImageReader.OnImageAvailableListener mOnImageAvailableListener = 97 | reader -> { 98 | Image image = reader.acquireLatestImage(); 99 | // get image bytes 100 | ByteBuffer imageBuf = image.getPlanes()[0].getBuffer(); 101 | final byte[] imageBytes = new byte[imageBuf.remaining()]; 102 | imageBuf.get(imageBytes); 103 | image.close(); 104 | 105 | onPictureTaken(imageBytes); 106 | }; 107 | 108 | 109 | private void onPictureTaken(final byte[] imageBytes) { 110 | Log.d(TAG, "onPictureTaken: imageBytes: " + imageBytes.length); 111 | if (imageBytes != null) { 112 | Bitmap shot = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); 113 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 114 | shot.compress(Bitmap.CompressFormat.JPEG, 70, bos); 115 | imageStr = Base64.encodeToString(bos.toByteArray(), Base64.NO_WRAP); 116 | 117 | mWebHandler.post(() -> { 118 | Log.d(TAG, "sending image " + imageStr.length() + " bytes "); 119 | // annotate image by uploading to Cloud Vision API 120 | try { 121 | Log.d(TAG, "run: " + imageStr); 122 | Log.d(TAG, "start_sending"); 123 | imageConsumer.onBase64Image(imageStr); 124 | } catch (Exception e) { 125 | } 126 | Log.d(TAG, "finish_sending"); 127 | onInput(CAM_COMPLETED); 128 | }); 129 | } 130 | } 131 | 132 | @Override 133 | public void close() throws Exception { 134 | mCamera.shutDown(); 135 | // mCameraThread.quitSafely(); 136 | mWebThread.quitSafely(); 137 | try { 138 | mServo.close(); 139 | } catch (IOException e) { 140 | Log.e(TAG, "button driver error", e); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/chassis/DcMotorMock.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.chassis; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * Created by x on 2/7/17. 7 | */ 8 | 9 | public class DcMotorMock implements RobotMotor { 10 | private final String TAG; 11 | private String name; 12 | 13 | public DcMotorMock(String name) { 14 | this.name = name; 15 | TAG = name + " " + DcMotorMock.class.getSimpleName(); 16 | } 17 | 18 | @Override 19 | public void cw(int speedPercentage) { 20 | Log.d(TAG, "cw() called with: speedPercentage = [" + speedPercentage + "]"); 21 | } 22 | 23 | @Override 24 | public void ccw(int speedPercentage) { 25 | Log.d(TAG, "ccw() called with: speedPercentage = [" + speedPercentage + "]"); 26 | } 27 | 28 | @Override 29 | public void halt() { 30 | Log.d(TAG, "halt() called"); 31 | } 32 | 33 | @Override 34 | public void close() throws Exception { 35 | Log.d(TAG, "close() called"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/chassis/DcMotorOnOff.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.chassis; 2 | 3 | import android.util.Log; 4 | 5 | import com.google.android.things.pio.Gpio; 6 | import com.google.android.things.pio.PeripheralManagerService; 7 | 8 | import java.io.IOException; 9 | 10 | public class DcMotorOnOff implements RobotMotor { 11 | 12 | private static final String TAG = DcMotorOnOff.class.getSimpleName(); 13 | private Gpio cwPin; 14 | private Gpio ccwPin; 15 | 16 | public DcMotorOnOff(Gpio gpioCw, Gpio gpioCcw) throws IOException { 17 | this.ccwPin = gpioCcw; 18 | this.cwPin = gpioCw; 19 | } 20 | 21 | public DcMotorOnOff(String gpioCw, String gpioCcw, PeripheralManagerService peripheralManagerService) throws IOException { 22 | cwPin = peripheralManagerService.openGpio(gpioCw); 23 | cwPin.setDirection(Gpio.DIRECTION_OUT_INITIALLY_HIGH); 24 | cwPin.setActiveType(Gpio.ACTIVE_HIGH); 25 | cwPin.setValue(true); 26 | ccwPin = peripheralManagerService.openGpio(gpioCcw); 27 | ccwPin.setDirection(Gpio.DIRECTION_OUT_INITIALLY_HIGH); 28 | ccwPin.setActiveType(Gpio.ACTIVE_HIGH); 29 | ccwPin.setValue(true); 30 | halt(); 31 | } 32 | 33 | @Override 34 | public void cw(int speedPercentage) { 35 | try { 36 | ccwPin.setValue(false); 37 | cwPin.setValue(true); 38 | Log.d(TAG, "cw cw: " + cwPin.getValue() + " ccw: " + ccwPin.getValue()); 39 | } catch (IOException e) { 40 | e.printStackTrace(); 41 | } 42 | } 43 | 44 | @Override 45 | public void ccw(int speedPercentage) { 46 | try { 47 | ccwPin.setValue(true); 48 | cwPin.setValue(false); 49 | Log.d(TAG, "cw: " + cwPin.getValue()); 50 | Log.d(TAG, "ccw cw: " + cwPin.getValue() + " ccw: " + ccwPin.getValue()); 51 | } catch (IOException e) { 52 | 53 | } 54 | } 55 | 56 | @Override 57 | public void halt() { 58 | try { 59 | cwPin.setValue(false); 60 | ccwPin.setValue(false); 61 | Log.d(TAG, "halt cw: " + cwPin.getValue() + " ccw: " + ccwPin.getValue()); 62 | } catch (IOException e) { 63 | } 64 | } 65 | 66 | @Override 67 | public void close() throws Exception { 68 | halt(); 69 | cwPin.close(); 70 | ccwPin.close(); 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/chassis/DcMotorWithSpeed.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.chassis; 2 | 3 | import android.support.annotation.StringDef; 4 | import android.util.Log; 5 | 6 | import com.google.android.things.pio.Gpio; 7 | import com.google.android.things.pio.PeripheralManagerService; 8 | 9 | import java.io.IOException; 10 | import java.lang.annotation.Retention; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | import static java.lang.annotation.RetentionPolicy.SOURCE; 14 | 15 | public class DcMotorWithSpeed implements RobotMotor, AutoCloseable { 16 | 17 | 18 | private static final String TAG = DcMotorWithSpeed.class.getSimpleName(); 19 | private Gpio cw; 20 | private Gpio ccw; 21 | private boolean run = true; 22 | private int speedInc; 23 | 24 | public DcMotorWithSpeed(String gpioCw, String gpioCcw, PeripheralManagerService service, int speedDec) throws IOException { 25 | this(gpioCw, gpioCcw, service); 26 | this.speedInc = speedDec; 27 | } 28 | 29 | public DcMotorWithSpeed(String gpioCw, String gpioCcw, PeripheralManagerService service) throws IOException { 30 | cw = service.openGpio(gpioCw); 31 | cw.setActiveType(Gpio.ACTIVE_HIGH); 32 | cw.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); 33 | 34 | ccw = service.openGpio(gpioCcw); 35 | ccw.setActiveType(Gpio.ACTIVE_HIGH); 36 | ccw.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); 37 | motorThread.start(); 38 | } 39 | 40 | @Retention(SOURCE) 41 | @StringDef({HALT, CW, CCW}) 42 | 43 | private @interface ICommand { 44 | } 45 | 46 | private static final String HALT = "HALT"; 47 | private static final String CW = "CW"; 48 | private static final String CCW = "CCW"; 49 | 50 | @ICommand 51 | private String cmd = HALT; 52 | 53 | private int speed; 54 | private static final int PERIOD = 10; 55 | 56 | private Thread motorThread = new Thread(new Runnable() { 57 | @Override 58 | public void run() { 59 | int sleepTime; 60 | @ICommand String curCmd; 61 | while (run) { 62 | sleepTime = (speed + speedInc) / 10; 63 | curCmd = cmd; 64 | try { 65 | if (sleepTime == 0 || curCmd.equalsIgnoreCase(HALT)) { 66 | ccw.setValue(false); 67 | cw.setValue(false); 68 | TimeUnit.MILLISECONDS.sleep(PERIOD); 69 | } else if (sleepTime == PERIOD) { 70 | switch (curCmd) { 71 | case CW: 72 | ccw.setValue(false); 73 | cw.setValue(true); 74 | break; 75 | case CCW: 76 | ccw.setValue(true); 77 | cw.setValue(false); 78 | break; 79 | default: 80 | break; 81 | } 82 | TimeUnit.MILLISECONDS.sleep(PERIOD); 83 | } else { 84 | switch (curCmd) { 85 | case CW: 86 | ccw.setValue(false); 87 | cw.setValue(true); 88 | break; 89 | case CCW: 90 | ccw.setValue(true); 91 | cw.setValue(false); 92 | break; 93 | default: 94 | break; 95 | } 96 | TimeUnit.MILLISECONDS.sleep(sleepTime); 97 | ccw.setValue(false); 98 | cw.setValue(false); 99 | TimeUnit.MILLISECONDS.sleep(PERIOD - sleepTime); 100 | } 101 | 102 | } catch (IOException | InterruptedException e) { 103 | Log.e(TAG, "motorThread " + e.getMessage()); 104 | } 105 | } 106 | } 107 | }); 108 | 109 | @Override 110 | public synchronized void cw(int speedPercentage) { 111 | cmd = CW; 112 | speed = speedPercentage; 113 | } 114 | 115 | @Override 116 | public synchronized void ccw(int speedPercentage) { 117 | cmd = CCW; 118 | speed = speedPercentage; 119 | } 120 | 121 | @Override 122 | public synchronized void halt() { 123 | cmd = HALT; 124 | speed = 0; 125 | } 126 | 127 | @Override 128 | public synchronized void close() throws Exception { 129 | halt(); 130 | run = false; 131 | TimeUnit.MILLISECONDS.sleep(PERIOD); 132 | cw.close(); 133 | ccw.close(); 134 | 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/chassis/RobotChassisMotorBased.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.chassis; 2 | 3 | import android.support.annotation.IntDef; 4 | 5 | import java.lang.annotation.Retention; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | import java.util.concurrent.TimeUnit; 9 | 10 | import static java.lang.annotation.RetentionPolicy.SOURCE; 11 | 12 | public class RobotChassisMotorBased implements RobotСhassis { 13 | private RobotMotor leftMotor, rightMotor; 14 | private ExecutorService cmdExec = Executors.newSingleThreadExecutor(); 15 | 16 | 17 | @Retention(SOURCE) 18 | @IntDef({FORWARD, BACKWARD, LEFT, RIGHT, STOP}) 19 | private @interface LastCommand { 20 | } 21 | 22 | private static final int STOP = 0; 23 | private static final int BACKWARD = 1; 24 | private static final int FORWARD = 2; 25 | private static final int LEFT = 3; 26 | private static final int RIGHT = 4; 27 | 28 | @LastCommand 29 | private int lastCommand = 0; 30 | 31 | private Runnable pause = () -> { 32 | try { 33 | TimeUnit.MILLISECONDS.sleep(500); 34 | } catch (InterruptedException e) { 35 | e.printStackTrace(); 36 | } 37 | }; 38 | 39 | public RobotChassisMotorBased(RobotMotor leftMotor, RobotMotor rightMotor) { 40 | this.leftMotor = leftMotor; 41 | this.rightMotor = rightMotor; 42 | stop(); 43 | } 44 | 45 | 46 | @Override 47 | public void forward(int speed) { 48 | lastCommand = FORWARD; 49 | cmdExec.execute(() -> { 50 | leftMotor.ccw(speed); 51 | rightMotor.cw(speed); 52 | }); 53 | } 54 | 55 | @Override 56 | public void backward(int speed) { 57 | lastCommand = BACKWARD; 58 | cmdExec.execute(() -> { 59 | leftMotor.cw(speed); 60 | rightMotor.ccw(speed); 61 | }); 62 | } 63 | 64 | @Override 65 | public void left(int speed) { 66 | switch (lastCommand) { 67 | case BACKWARD: 68 | simpleLeft(speed); 69 | cmdExec.execute(pause); 70 | backward(speed); 71 | break; 72 | case FORWARD: 73 | simpleLeft(speed); 74 | cmdExec.execute(pause); 75 | forward(speed); 76 | break; 77 | default: 78 | lastCommand = LEFT; 79 | simpleLeft(speed); 80 | break; 81 | } 82 | } 83 | 84 | private void simpleLeft(int speed) { 85 | cmdExec.execute(() -> { 86 | leftMotor.cw(speed); 87 | rightMotor.cw(speed); 88 | }); 89 | 90 | } 91 | 92 | @Override 93 | public void right(int speed) { 94 | switch (lastCommand) { 95 | case BACKWARD: 96 | simpleRight(speed); 97 | cmdExec.execute(pause); 98 | backward(speed); 99 | break; 100 | case FORWARD: 101 | simpleRight(speed); 102 | cmdExec.execute(pause); 103 | forward(speed); 104 | break; 105 | default: 106 | lastCommand = RIGHT; 107 | simpleRight(speed); 108 | break; 109 | } 110 | } 111 | 112 | private void simpleRight(int speed) { 113 | cmdExec.execute(() -> { 114 | leftMotor.ccw(speed); 115 | rightMotor.ccw(speed); 116 | }); 117 | } 118 | 119 | @Override 120 | public void stop() { 121 | lastCommand = STOP; 122 | cmdExec.execute(() -> { 123 | leftMotor.halt(); 124 | rightMotor.halt(); 125 | }); 126 | } 127 | 128 | @Override 129 | public void close() throws Exception { 130 | stop(); 131 | leftMotor.close(); 132 | rightMotor.close(); 133 | cmdExec.shutdown(); 134 | } 135 | 136 | } 137 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/chassis/RobotChassisPid.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.chassis; 2 | 3 | import android.support.annotation.IntDef; 4 | import android.support.annotation.IntRange; 5 | import android.util.Log; 6 | 7 | import com.samgol.robot.compass.RotationSensor; 8 | 9 | import java.io.IOException; 10 | import java.lang.annotation.Retention; 11 | import java.util.Arrays; 12 | 13 | import static java.lang.annotation.RetentionPolicy.SOURCE; 14 | 15 | 16 | public class RobotChassisPid implements RobotСhassis { 17 | 18 | private static final String TAG = RobotChassisPid.class.getSimpleName(); 19 | private RobotMotor leftMotor, rightMotor; 20 | private RotationSensor rotationSensor; 21 | 22 | @Retention(SOURCE) 23 | @IntDef({FORWARD, BACKWARD, LEFT, RIGHT, STOP}) 24 | private @interface Cmd { 25 | } 26 | 27 | private static final int STOP = 0; 28 | private static final int BACKWARD = 1; 29 | private static final int FORWARD = 2; 30 | private static final int LEFT = 3; 31 | private static final int RIGHT = 4; 32 | 33 | @Cmd 34 | private int mCmd = 0; 35 | private int mSpeed; 36 | 37 | public RobotChassisPid(RobotMotor leftMotor, RobotMotor rightMotor, RotationSensor rotationSensor) { 38 | this.leftMotor = leftMotor; 39 | this.rightMotor = rightMotor; 40 | this.rotationSensor = rotationSensor; 41 | stop(); 42 | } 43 | 44 | @Override 45 | public void forward(@IntRange(from = 0, to = 100) int speed) { 46 | mCmd = FORWARD; 47 | this.mSpeed = speed; 48 | execute(mCmd, mSpeed, 0); 49 | 50 | } 51 | 52 | @Override 53 | public void backward(@IntRange(from = 0, to = 100) int speed) { 54 | mCmd = BACKWARD; 55 | this.mSpeed = speed; 56 | execute(mCmd, mSpeed, 0); 57 | } 58 | 59 | @Override 60 | public void left(@IntRange(from = 0, to = 100) int speed) { 61 | mCmd = LEFT; 62 | this.mSpeed = speed; 63 | execute(mCmd, mSpeed, 45); 64 | 65 | } 66 | 67 | @Override 68 | public void right(@IntRange(from = 0, to = 100) int speed) { 69 | mCmd = RIGHT; 70 | this.mSpeed = speed; 71 | execute(mCmd, mSpeed, 45); 72 | } 73 | 74 | @Override 75 | public void stop() { 76 | mCmd = STOP; 77 | execute(mCmd, 0, -1); 78 | } 79 | 80 | public void left(@IntRange(from = 0, to = 100) int speed, int angle) { 81 | mCmd = LEFT; 82 | this.mSpeed = speed; 83 | 84 | } 85 | 86 | public void right(@IntRange(from = 0, to = 100) int speed, int angle) { 87 | mCmd = RIGHT; 88 | this.mSpeed = speed; 89 | 90 | } 91 | 92 | 93 | @Override 94 | public void close() throws Exception { 95 | 96 | 97 | } 98 | 99 | private void execute(@Cmd int command, int speed) { 100 | switch (command) { 101 | 102 | case BACKWARD: 103 | leftMotor.cw(speed); 104 | rightMotor.ccw(speed); 105 | break; 106 | case FORWARD: 107 | leftMotor.ccw(speed); 108 | rightMotor.cw(speed); 109 | break; 110 | case LEFT: 111 | leftMotor.cw(speed); 112 | rightMotor.cw(speed); 113 | break; 114 | case RIGHT: 115 | leftMotor.ccw(speed); 116 | rightMotor.ccw(speed); 117 | break; 118 | case STOP: 119 | leftMotor.halt(); 120 | rightMotor.halt(); 121 | break; 122 | } 123 | } 124 | 125 | private void execute(int[] motorsSpeed) { 126 | Log.d(TAG, "execute: " + Arrays.toString(motorsSpeed)); 127 | if (motorsSpeed[0] < 0) 128 | leftMotor.ccw(motorsSpeed[0] < -100 ? 100 : -motorsSpeed[0]); 129 | else leftMotor.cw(motorsSpeed[0] > 100 ? 100 : motorsSpeed[0]); 130 | if (motorsSpeed[1] < 0) 131 | rightMotor.ccw(motorsSpeed[1] < -100 ? 100 : -motorsSpeed[1]); 132 | else rightMotor.cw(motorsSpeed[1] > 100 ? 100 : motorsSpeed[1]); 133 | } 134 | 135 | private Thread executeControl; 136 | private final int P = 2, I = 1; 137 | private int curLSpeed, curRightSpeed; 138 | 139 | public void execute(@Cmd int cmd, int cSpeed, int cAngle) { 140 | if (executeControl != null) { 141 | executeControl.interrupt(); 142 | } 143 | if (cAngle >= 0 && rotationSensor != null) { 144 | executeControl = new Thread(new Runnable() { 145 | private int accomulutor = 0; 146 | 147 | @Override 148 | public void run() { 149 | int angle = cAngle; 150 | if (cmd == BACKWARD) { 151 | angle = (180 + angle) % 360; 152 | } 153 | int sensorAngle = 0; 154 | try { 155 | sensorAngle = rotationSensor.getYaw(); 156 | angle = (sensorAngle + angle) % 360; 157 | } catch (IOException e) { 158 | Log.e(TAG, "run: ", e); 159 | return; 160 | } 161 | 162 | int wheel_speed = cSpeed; 163 | if (cmd == BACKWARD) { 164 | wheel_speed = -wheel_speed; 165 | } else if (cmd != FORWARD) { 166 | wheel_speed = 0; 167 | } 168 | while (true) { 169 | int cur_angle = 0; 170 | try { 171 | cur_angle = rotationSensor.getYaw(); 172 | } catch (IOException e) { 173 | Log.e(TAG, "run: ", e); 174 | } 175 | int[] motorsSpeed = getPIDDifferentialDriveWheelsCommand(angle, cur_angle, wheel_speed, P, I); 176 | 177 | if (curLSpeed != motorsSpeed[0] || curRightSpeed != motorsSpeed[1]) { 178 | curLSpeed = motorsSpeed[0]; 179 | curRightSpeed = motorsSpeed[1]; 180 | execute(motorsSpeed); 181 | } 182 | try { 183 | Thread.sleep(20); 184 | } catch (InterruptedException e) { 185 | return; 186 | } 187 | } // while 188 | } 189 | 190 | private int[] getPIDDifferentialDriveWheelsCommand(int angle, int cur_angle, int wheel_speed, int P, int I) { 191 | int[] weelsSpeed = new int[]{0, 0}; 192 | // cur_angle = (cur_angle + angle) % 360; 193 | cur_angle = cur_angle < angle ? 360 + (cur_angle - angle) : (cur_angle - angle); 194 | if (cur_angle < 2 || cur_angle > 358) { 195 | weelsSpeed[0] = wheel_speed; 196 | weelsSpeed[1] = wheel_speed; 197 | accomulutor = 0; 198 | } else { 199 | // System.out.print("angle " + cur_angle + " "); 200 | 201 | if (wheel_speed < 0) { 202 | } 203 | int correction = ((cur_angle > 180 ? (360 - cur_angle) : cur_angle) * P); 204 | if (wheel_speed == 0) { 205 | // correction = (int) ((cur_angle > 180 ? (360 - cur_angle) : cur_angle) * P / 2); 206 | correction = ((cur_angle > 180 ? (360 - cur_angle) : cur_angle) * P); 207 | } 208 | 209 | accomulutor = (accomulutor / I) > 100 ? 100 : accomulutor + correction; 210 | // accomulutor += correction; 211 | int speed_prc; 212 | if (wheel_speed < 0) { 213 | speed_prc = wheel_speed + correction + accomulutor / I; 214 | cur_angle = (cur_angle + 180) % 360; 215 | } else { 216 | speed_prc = wheel_speed - correction - accomulutor / I; 217 | } 218 | // System.out.println(" I " + accomulutor + " \n"); 219 | if (cur_angle > 180) { 220 | weelsSpeed[0] = wheel_speed == 0 ? speed_prc / 2 : speed_prc; 221 | weelsSpeed[1] = wheel_speed == 0 ? -speed_prc / 2 : wheel_speed; 222 | // System.out.println("left correction " + speed_prc); 223 | } else { 224 | weelsSpeed[0] = wheel_speed == 0 ? -speed_prc / 2 : wheel_speed; 225 | weelsSpeed[1] = wheel_speed == 0 ? speed_prc / 2 : speed_prc; 226 | // System.out.println("right correction " + speed_prc); 227 | } 228 | } 229 | 230 | return weelsSpeed; 231 | } 232 | }); 233 | executeControl.start(); 234 | } else { 235 | execute(mCmd, mSpeed); 236 | Log.d(TAG, "execute: Normal command"); 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/chassis/RobotChassisSimple.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.chassis; 2 | 3 | import android.support.annotation.StringDef; 4 | 5 | import com.google.android.things.pio.Gpio; 6 | import com.google.android.things.pio.PeripheralManagerService; 7 | 8 | import java.io.IOException; 9 | import java.lang.annotation.Retention; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | import static java.lang.annotation.RetentionPolicy.SOURCE; 13 | 14 | /** 15 | * Created by x on 2/9/17. 16 | */ 17 | 18 | public class RobotChassisSimple implements RobotСhassis { 19 | 20 | private Gpio lCw; 21 | private Gpio lCcw; 22 | private Gpio rCw; 23 | private Gpio rCcw; 24 | private boolean run = true; 25 | 26 | public RobotChassisSimple(String gpioLCw, String gpioLCcw, String gpioRCw, String gpioRCcw, PeripheralManagerService service) throws IOException { 27 | 28 | lCw = service.openGpio(gpioLCw); 29 | lCw.setActiveType(Gpio.ACTIVE_HIGH); 30 | lCw.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); 31 | 32 | lCcw = service.openGpio(gpioLCcw); 33 | lCcw.setActiveType(Gpio.ACTIVE_HIGH); 34 | lCcw.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); 35 | 36 | rCw = service.openGpio(gpioRCw); 37 | rCw.setActiveType(Gpio.ACTIVE_HIGH); 38 | rCw.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); 39 | 40 | rCcw = service.openGpio(gpioRCcw); 41 | rCcw.setActiveType(Gpio.ACTIVE_HIGH); 42 | rCcw.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); 43 | 44 | chassisThread.start(); 45 | } 46 | 47 | @Retention(SOURCE) 48 | @StringDef({STOP, FORWARD, BACKWARD, LEFT, RIGHT}) 49 | 50 | private @interface ICommand { 51 | } 52 | 53 | private static final String STOP = "STOP"; 54 | private static final String FORWARD = "FORWARD"; 55 | private static final String BACKWARD = "BACKWARD"; 56 | private static final String LEFT = "LEFT"; 57 | private static final String RIGHT = "RIGHT"; 58 | 59 | @ICommand 60 | private String cmd = STOP; 61 | 62 | private int speed; 63 | private static final int PERIOD = 100; 64 | 65 | Thread chassisThread = new Thread(new Runnable() { 66 | @Override 67 | public void run() { 68 | int sleepTime; 69 | @ICommand String curCmd; 70 | while (run) { 71 | sleepTime = speed; 72 | curCmd = cmd; 73 | try { 74 | if (sleepTime == 0 || curCmd.equalsIgnoreCase(STOP)) { 75 | lCcw.setValue(false); 76 | lCw.setValue(false); 77 | rCcw.setValue(false); 78 | rCw.setValue(false); 79 | TimeUnit.MICROSECONDS.sleep(PERIOD); 80 | } else if (sleepTime == PERIOD) { 81 | switch (curCmd) { 82 | case FORWARD: 83 | lCcw.setValue(true); 84 | lCw.setValue(false); 85 | rCcw.setValue(false); 86 | rCw.setValue(true); 87 | break; 88 | case BACKWARD: 89 | lCcw.setValue(false); 90 | lCw.setValue(true); 91 | rCcw.setValue(true); 92 | rCw.setValue(false); 93 | break; 94 | case LEFT: 95 | lCcw.setValue(false); 96 | lCw.setValue(true); 97 | rCcw.setValue(false); 98 | rCw.setValue(true); 99 | break; 100 | case RIGHT: 101 | lCcw.setValue(true); 102 | lCw.setValue(false); 103 | rCcw.setValue(true); 104 | rCw.setValue(false); 105 | break; 106 | default: 107 | break; 108 | } 109 | TimeUnit.MICROSECONDS.sleep(PERIOD); 110 | } else { 111 | switch (curCmd) { 112 | case FORWARD: 113 | lCcw.setValue(true); 114 | lCw.setValue(false); 115 | rCcw.setValue(false); 116 | rCw.setValue(true); 117 | break; 118 | case BACKWARD: 119 | lCcw.setValue(false); 120 | lCw.setValue(true); 121 | rCcw.setValue(true); 122 | rCw.setValue(false); 123 | break; 124 | case LEFT: 125 | lCcw.setValue(false); 126 | lCw.setValue(true); 127 | rCcw.setValue(false); 128 | rCw.setValue(true); 129 | break; 130 | case RIGHT: 131 | lCcw.setValue(true); 132 | lCw.setValue(false); 133 | rCcw.setValue(true); 134 | rCw.setValue(false); 135 | break; 136 | default: 137 | break; 138 | } 139 | TimeUnit.MICROSECONDS.sleep(sleepTime); 140 | lCcw.setValue(false); 141 | lCw.setValue(false); 142 | rCcw.setValue(false); 143 | rCw.setValue(false); 144 | TimeUnit.MICROSECONDS.sleep(PERIOD - sleepTime); 145 | } 146 | 147 | } catch (IOException | InterruptedException e) { 148 | e.printStackTrace(); 149 | } 150 | } 151 | } 152 | }); 153 | 154 | @Override 155 | public synchronized void forward(int speed) { 156 | cmd = FORWARD; 157 | this.speed = speed; 158 | } 159 | 160 | @Override 161 | public synchronized void backward(int speed) { 162 | cmd = BACKWARD; 163 | this.speed = speed; 164 | } 165 | 166 | @Override 167 | public synchronized void left(int speed) { 168 | cmd = LEFT; 169 | this.speed = speed; 170 | 171 | } 172 | 173 | @Override 174 | public synchronized void right(int speed) { 175 | cmd = RIGHT; 176 | this.speed = speed; 177 | 178 | } 179 | 180 | @Override 181 | public synchronized void stop() { 182 | cmd = STOP; 183 | this.speed = 0; 184 | } 185 | 186 | @Override 187 | public void close() throws Exception { 188 | run = false; 189 | chassisThread.interrupt(); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/chassis/RobotMotor.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.chassis; 2 | 3 | public interface RobotMotor extends AutoCloseable { 4 | void cw(int speedPercentage); 5 | 6 | void ccw(int speedPercentage); 7 | 8 | void halt(); 9 | 10 | } -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/chassis/RobotСhassis.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.chassis; 2 | 3 | import android.support.annotation.IntRange; 4 | 5 | public interface RobotСhassis extends AutoCloseable { 6 | 7 | void forward(@IntRange(from = 0, to = 100) int speed); 8 | 9 | void backward(@IntRange(from = 0, to = 100) int speed); 10 | 11 | void left(@IntRange(from = 0, to = 100) int speed); 12 | 13 | void right(@IntRange(from = 0, to = 100) int speed); 14 | 15 | void stop(); 16 | 17 | } -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/compass/HMC5883L.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Cagdas Caglak 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.samgol.robot.compass; 18 | 19 | import com.google.android.things.pio.I2cDevice; 20 | import com.google.android.things.pio.PeripheralManagerService; 21 | 22 | import java.io.IOException; 23 | 24 | /** 25 | * Created by cagdas on 24.12.2016. 26 | */ 27 | 28 | public class HMC5883L implements AutoCloseable { 29 | private static final int HMC5883L_DEV_ADD = 0x1E; 30 | private static final int CONFIG_A = 0x00; 31 | private static final int CONFIG_B = 0x01; 32 | private static final int MODE_REG = 0x02; 33 | private static final int X_HIGH = 0x03; 34 | private static final int X_LOW = 0x04; 35 | private static final int Z_HIGH = 0x05; 36 | private static final int Z_LOW = 0x06; 37 | private static final int Y_HIGH = 0x07; 38 | private static final int Y_LOW = 0x08; 39 | private static final int STATUS_REG = 0x09; 40 | private static final int ID_REG_A = 0x0A; 41 | private static final int ID_REG_B = 0x0B; 42 | private static final int ID_REG_C = 0x0C; 43 | 44 | private static final int SAMPLES_AVARAGE_START = 0x05; 45 | private static final int SAMPLES_AVARAGE_LENGTH = 0x02; 46 | private static final int SAMPLES_AVARAGE_1 = 0x00; 47 | private static final int SAMPLES_AVARAGE_2 = 0x01; 48 | private static final int SAMPLES_AVARAGE_4 = 0x02; 49 | private static final int SAMPLES_AVARAGE_8 = 0x03; 50 | 51 | private static final int OUTPUT_RATE_START = 0x02; 52 | private static final int OUTPUT_RATE_LENGTH = 0x03; 53 | private static final int OUTPUT_RATE_0 = 0x00; 54 | private static final int OUTPUT_RATE_1 = 0x01; 55 | private static final int OUTPUT_RATE_2 = 0x02; 56 | private static final int OUTPUT_RATE_3 = 0x03; 57 | private static final int OUTPUT_RATE_4 = 0x04; 58 | private static final int OUTPUT_RATE_5 = 0x05; 59 | private static final int OUTPUT_RATE_6 = 0x06; 60 | private static final int OUTPUT_RATE_7 = 0x07; 61 | 62 | private static final int MEASUREMENT_START = 0x00; 63 | private static final int MEASUREMENT_LENGTH = 0x02; 64 | private static final int MEASUREMENT_NORMAL = 0x00; 65 | private static final int MEASUREMENT_POSITIVE = 0x01; 66 | private static final int MEASUREMENT_NEGATIVE = 0x02; 67 | 68 | private static final int GAIN_START = 0x05; 69 | private static final int GAIN_LENGTH = 0x03; 70 | private static final int GAIN_1370 = 0x00; 71 | private static final int GAIN_1090 = 0x01; 72 | private static final int GAIN_820 = 0x02; 73 | private static final int GAIN_660 = 0x03; 74 | private static final int GAIN_440 = 0x04; 75 | private static final int GAIN_390 = 0x05; 76 | private static final int GAIN_330 = 0x06; 77 | private static final int GAIN_230 = 0x07; 78 | 79 | private static final int OPERATION_MODE_START = 0x00; 80 | private static final int OPERATION_MODE_LENGTH = 0x02; 81 | private static final int OPERATION_MODE_CONT = 0x00; 82 | private static final int OPERATION_MODE_SINGLE = 0x01; 83 | private static final int OPERATION_MODE_IDLE = 0x02; 84 | 85 | private static final int RDY_BIT = 0x00; 86 | private static final int LOCK_BIT = 0x01; 87 | 88 | private I2cDevice mDevice; 89 | 90 | public HMC5883L(String bus) throws IOException { 91 | PeripheralManagerService peripheralManagerService = new PeripheralManagerService(); 92 | I2cDevice device = peripheralManagerService.openI2cDevice(bus, HMC5883L_DEV_ADD); 93 | try { 94 | connect(device); 95 | } catch (IOException | RuntimeException e) { 96 | try { 97 | close(); 98 | } catch (IOException | RuntimeException ignored) { 99 | } 100 | throw e; 101 | } 102 | } 103 | 104 | @Override 105 | public void close() throws IOException { 106 | if (this.mDevice != null) { 107 | this.mDevice.close(); 108 | this.mDevice = null; 109 | } 110 | } 111 | 112 | private void connect(I2cDevice device) throws IOException { 113 | this.mDevice = device; 114 | setSamplesAvarage(SAMPLES_AVARAGE_8); 115 | setOutputRate(OUTPUT_RATE_4); 116 | setMeasurementMode(MEASUREMENT_NORMAL); 117 | setMeasurementGain(GAIN_1090); 118 | setOperationMode(OPERATION_MODE_CONT); 119 | } 120 | 121 | public void setSamplesAvarage(int avarage) throws IOException { 122 | int value = this.mDevice.readRegByte(CONFIG_A) & 0xff; 123 | int bits = 1; 124 | int i = 0; 125 | while (i < SAMPLES_AVARAGE_LENGTH - 1) { 126 | bits = (bits << 1); 127 | ++bits; 128 | ++i; 129 | } 130 | value &= ~(bits << SAMPLES_AVARAGE_START); 131 | if (avarage == 0) { 132 | value |= (SAMPLES_AVARAGE_1 << SAMPLES_AVARAGE_START); 133 | } else if (avarage == 1) { 134 | value |= (SAMPLES_AVARAGE_2 << SAMPLES_AVARAGE_START); 135 | } else if (avarage == 2) { 136 | value |= (SAMPLES_AVARAGE_4 << SAMPLES_AVARAGE_START); 137 | } else if (avarage == 3) { 138 | value |= (SAMPLES_AVARAGE_8 << SAMPLES_AVARAGE_START); 139 | } 140 | this.mDevice.writeRegByte(CONFIG_A, (byte) value); 141 | } 142 | 143 | public int getSamplesAvarage() throws IOException { 144 | int value = this.mDevice.readRegByte(CONFIG_A) & 0xff; 145 | return (int) ((value >> SAMPLES_AVARAGE_START) % Math.pow(2, SAMPLES_AVARAGE_LENGTH)); 146 | } 147 | 148 | public void setOutputRate(int rate) throws IOException { 149 | int value = this.mDevice.readRegByte(CONFIG_A) & 0xff; 150 | int bits = 1; 151 | int i = 0; 152 | while (i < OUTPUT_RATE_LENGTH - 1) { 153 | bits = (bits << 1); 154 | ++bits; 155 | ++i; 156 | } 157 | value &= ~(bits << OUTPUT_RATE_START); 158 | if (rate == 0) { 159 | value |= (SAMPLES_AVARAGE_8 << SAMPLES_AVARAGE_START); 160 | } else if (rate == 1) { 161 | value |= (OUTPUT_RATE_1 << OUTPUT_RATE_START); 162 | } else if (rate == 2) { 163 | value |= (OUTPUT_RATE_2 << OUTPUT_RATE_START); 164 | } else if (rate == 3) { 165 | value |= (OUTPUT_RATE_3 << OUTPUT_RATE_START); 166 | } else if (rate == 4) { 167 | value |= (OUTPUT_RATE_4 << OUTPUT_RATE_START); 168 | } else if (rate == 5) { 169 | value |= (OUTPUT_RATE_5 << OUTPUT_RATE_START); 170 | } else if (rate == 6) { 171 | value |= (OUTPUT_RATE_6 << OUTPUT_RATE_START); 172 | } else if (rate == 7) { 173 | System.out.println("Reserved"); 174 | } 175 | this.mDevice.writeRegByte(CONFIG_A, (byte) value); 176 | } 177 | 178 | public int getOutputRate() throws IOException { 179 | int value = this.mDevice.readRegByte(CONFIG_A) & 0xff; 180 | return (int) ((value >> OUTPUT_RATE_START) % Math.pow(2, OUTPUT_RATE_LENGTH)); 181 | } 182 | 183 | public void setMeasurementMode(int mode) throws IOException { 184 | int value = this.mDevice.readRegByte(CONFIG_A) & 0xff; 185 | int bits = 1; 186 | int i = 0; 187 | while (i < MEASUREMENT_LENGTH - 1) { 188 | bits = (bits << 1); 189 | ++bits; 190 | ++i; 191 | } 192 | value &= ~(bits << MEASUREMENT_START); 193 | if (mode == 0) { 194 | value |= (MEASUREMENT_NORMAL << MEASUREMENT_START); 195 | } else if (mode == 2) { 196 | value |= (MEASUREMENT_POSITIVE << MEASUREMENT_START); 197 | } else if (mode == 3) { 198 | value |= (MEASUREMENT_NEGATIVE << MEASUREMENT_START); 199 | } 200 | this.mDevice.writeRegByte(CONFIG_A, (byte) value); 201 | } 202 | 203 | public int getMeasurementMode() throws IOException { 204 | int value = this.mDevice.readRegByte(CONFIG_A) & 0xff; 205 | return (int) ((value >> MEASUREMENT_START) % Math.pow(2, MEASUREMENT_LENGTH)); 206 | } 207 | 208 | public void setMeasurementGain(int gain) throws IOException { 209 | if (gain == 0) { 210 | this.mDevice.writeRegByte(CONFIG_B, (byte) (GAIN_1370 << 5)); 211 | } else if (gain == 1) { 212 | this.mDevice.writeRegByte(CONFIG_B, (byte) (GAIN_1090 << 5)); 213 | } else if (gain == 2) { 214 | this.mDevice.writeRegByte(CONFIG_B, (byte) (GAIN_820 << 5)); 215 | } else if (gain == 3) { 216 | this.mDevice.writeRegByte(CONFIG_B, (byte) (GAIN_660 << 5)); 217 | } else if (gain == 4) { 218 | this.mDevice.writeRegByte(CONFIG_B, (byte) (GAIN_440 << 5)); 219 | } else if (gain == 5) { 220 | this.mDevice.writeRegByte(CONFIG_B, (byte) (GAIN_390 << 5)); 221 | } else if (gain == 6) { 222 | this.mDevice.writeRegByte(CONFIG_B, (byte) (GAIN_330 << 5)); 223 | } else if (gain == 7) { 224 | this.mDevice.writeRegByte(CONFIG_B, (byte) (GAIN_230 << 5)); 225 | } 226 | } 227 | 228 | public int getMeasurementGain() throws IOException { 229 | int value = this.mDevice.readRegByte(CONFIG_B) & 0xff; 230 | return (int) ((value >> GAIN_START) % Math.pow(2, GAIN_LENGTH)); 231 | } 232 | 233 | public void setOperationMode(int mode) throws IOException { 234 | if (mode == 0) { 235 | this.mDevice.writeRegByte(MODE_REG, (byte) OPERATION_MODE_CONT); 236 | } else if (mode == 1) { 237 | this.mDevice.writeRegByte(MODE_REG, (byte) OPERATION_MODE_SINGLE); 238 | } else if (mode == 2) { 239 | this.mDevice.writeRegByte(MODE_REG, (byte) OPERATION_MODE_IDLE); 240 | } 241 | } 242 | 243 | public int getOperationMode() throws IOException { 244 | int value = this.mDevice.readRegByte(MODE_REG) & 0xff; 245 | return (int) ((value >> OPERATION_MODE_START) % Math.pow(2, OPERATION_MODE_LENGTH)); 246 | } 247 | 248 | 249 | public int getMagnitudeX() throws IOException { 250 | int lsb = this.mDevice.readRegByte(X_LOW) & 0xff; 251 | int msb = this.mDevice.readRegByte(X_HIGH); 252 | 253 | return (msb << 8 | lsb); 254 | } 255 | 256 | public int getMagnitudeY() throws IOException { 257 | int lsb = this.mDevice.readRegByte(Y_LOW) & 0xff; 258 | int msb = this.mDevice.readRegByte(Y_HIGH); 259 | 260 | return (msb << 8 | lsb); 261 | } 262 | 263 | public int getMagnitudeZ() throws IOException { 264 | int lsb = this.mDevice.readRegByte(Z_LOW) & 0xff; 265 | int msb = this.mDevice.readRegByte(Z_HIGH); 266 | 267 | return (msb << 8 | lsb); 268 | } 269 | 270 | public float[] getMagnitudes() throws IOException { 271 | float[] values = new float[3]; 272 | values[0] = getMagnitudeX(); 273 | values[1] = getMagnitudeY(); 274 | values[2] = getMagnitudeZ(); 275 | return values; 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/compass/RotationSensor.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.compass; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * Created by x on 2/11/17. 7 | */ 8 | 9 | public class RotationSensor { 10 | private HMC5883L hmc5883L; 11 | 12 | private String i2cBus; 13 | private int offsetX, offsetY; 14 | private static final double DEFAULT_SCALE = 0.92; 15 | 16 | private RotationSensor(String i2cBus, int offsetX, int getOffsetY) throws IOException { 17 | this.i2cBus = i2cBus; 18 | this.offsetX = offsetX; 19 | this.offsetY = getOffsetY; 20 | hmc5883L = new HMC5883L(this.i2cBus); 21 | } 22 | 23 | public RotationSensor(String i2cBus) throws IOException { 24 | this(i2cBus, 0, 0); 25 | } 26 | 27 | 28 | public int getYaw() throws IOException { 29 | double magnitudeX = hmc5883L.getMagnitudeX() * DEFAULT_SCALE + offsetX; 30 | double magnitudeY = hmc5883L.getMagnitudeY() * DEFAULT_SCALE + offsetY; 31 | double atan = Math.atan2(magnitudeX, magnitudeY); 32 | return (int) Math.toDegrees(atan < 0 ? atan + 2 * Math.PI : atan); 33 | } 34 | 35 | public int[] getMagnitudeXY() throws IOException { 36 | double magnitudeX = hmc5883L.getMagnitudeX() * DEFAULT_SCALE + offsetX; 37 | double magnitudeY = hmc5883L.getMagnitudeY() * DEFAULT_SCALE + offsetY; 38 | return new int[]{(int) magnitudeX, (int) magnitudeY}; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/controller/FinalStateMachine.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.controller; 2 | 3 | import android.support.annotation.StringDef; 4 | import android.util.Log; 5 | 6 | import com.samgol.robot.camera.ServoCamera; 7 | import com.samgol.robot.chassis.RobotСhassis; 8 | import com.samgol.robot.Inputs.InputData; 9 | import com.samgol.robot.Inputs.InputDataObserver; 10 | import com.samgol.robot.Inputs.InputType; 11 | import com.samgol.robot.ledrgb.LedRGB; 12 | 13 | import java.lang.annotation.Retention; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import java.util.concurrent.ArrayBlockingQueue; 17 | import java.util.concurrent.BlockingQueue; 18 | 19 | import static com.samgol.robot.Inputs.InputKb.CAM_COMPLETED; 20 | import static com.samgol.robot.Inputs.InputKb.CMD_BACKWARD; 21 | import static com.samgol.robot.Inputs.InputKb.CMD_CAM_DOWN; 22 | import static com.samgol.robot.Inputs.InputKb.CMD_CAM_SHOT; 23 | import static com.samgol.robot.Inputs.InputKb.CMD_CAM_UP; 24 | import static com.samgol.robot.Inputs.InputKb.CMD_FORWARD; 25 | import static com.samgol.robot.Inputs.InputKb.CMD_LEFT; 26 | import static com.samgol.robot.Inputs.InputKb.CMD_RIGHT; 27 | import static com.samgol.robot.Inputs.InputKb.CMD_STOP; 28 | import static com.samgol.robot.Inputs.InputKb.HALT; 29 | import static com.samgol.robot.Inputs.InputKb.OBS_CLOSE; 30 | import static com.samgol.robot.Inputs.InputKb.OBS_FAR; 31 | import static com.samgol.robot.Inputs.InputKb.OBS_NEAR; 32 | import static com.samgol.robot.Inputs.InputType.OBSTACLE; 33 | import static java.lang.annotation.RetentionPolicy.SOURCE; 34 | 35 | /** 36 | * Created by x on 1/8/17. 37 | */ 38 | 39 | public class FinalStateMachine implements InputDataObserver { 40 | 41 | private static final int spd = 30; 42 | private static final String TAG = FinalStateMachine.class.getSimpleName(); 43 | private RobotСhassis chassis; 44 | private ServoCamera camera; 45 | private LedRGB ledRGB; 46 | private BlockingQueue eventsQueue = new ArrayBlockingQueue<>(1000); 47 | private List eventLog = new ArrayList<>(); 48 | private boolean run = true; 49 | 50 | @Retention(SOURCE) 51 | @StringDef({OBSTACLE_FAR, OBSTACLE_CLOSE, SHOT_IN_PROGRESS}) 52 | 53 | private @interface RobotState { 54 | } 55 | 56 | private static final String OBSTACLE_FAR = "OBSTACLE_FAR"; 57 | private static final String OBSTACLE_CLOSE = "OBSTACLE_CLOSE"; 58 | private static final String SHOT_IN_PROGRESS = "SHOT_IN_PROGRESS"; 59 | 60 | @RobotState 61 | private String state = OBSTACLE_FAR; 62 | 63 | public FinalStateMachine(RobotСhassis сhassis, ServoCamera servoCamera, LedRGB ledRGB) { 64 | this.chassis = сhassis; 65 | this.camera = servoCamera; 66 | this.ledRGB = ledRGB; 67 | if (ledRGB != null) { 68 | ledRGB.turnAll(false); 69 | ledRGB.turnGreen(true); 70 | } 71 | сhassis.stop(); 72 | reactor.start(); 73 | } 74 | 75 | @Override 76 | public void onInput(InputData Input) { 77 | Log.d(TAG, "Event: " + Input.getDefStringRep()); 78 | try { 79 | eventsQueue.put(Input); 80 | } catch (InterruptedException e) { 81 | e.printStackTrace(); 82 | } 83 | } 84 | 85 | private Thread reactor = new Thread(() -> { 86 | while (run) { 87 | try { 88 | InputData evn = eventsQueue.take(); 89 | 90 | if (evn.getInputType() == OBSTACLE) { 91 | cleanLogByType(evn.getInputType()); 92 | eventLog.add(evn); 93 | } 94 | 95 | if (evn.eq(HALT)) 96 | chassis.stop(); 97 | 98 | switch (state) { 99 | case OBSTACLE_FAR: 100 | if (evn.eq(OBS_CLOSE)) { 101 | chassis.stop(); 102 | gotoS(OBSTACLE_CLOSE); 103 | } else if (evn.eq(CMD_STOP)) { 104 | chassis.stop(); 105 | } else if (evn.eq(CMD_FORWARD)) { 106 | chassis.forward(spd); 107 | } else if (evn.eq(CMD_BACKWARD)) { 108 | chassis.backward(spd); 109 | } else if (evn.eq(CMD_LEFT)) { 110 | chassis.left(spd); 111 | } else if (evn.eq(CMD_RIGHT)) { 112 | chassis.right(spd); 113 | } else if (evn.eq(CMD_CAM_SHOT)) { 114 | if (camera != null) { 115 | chassis.stop(); 116 | camera.takeAshot(); 117 | gotoS(SHOT_IN_PROGRESS); 118 | } 119 | } 120 | cameraPosition(evn); 121 | break; 122 | 123 | case OBSTACLE_CLOSE: 124 | cameraPosition(evn); 125 | if (evn.eq(CMD_BACKWARD)) 126 | chassis.backward(spd); 127 | else if (evn.eq(OBS_FAR) || evn.eq(OBS_NEAR)) 128 | gotoS(OBSTACLE_FAR); 129 | else 130 | chassis.stop(); 131 | break; 132 | 133 | case SHOT_IN_PROGRESS: 134 | if (evn.eq(CAM_COMPLETED)) { 135 | InputData inD = getLastByType(OBSTACLE); 136 | if (OBS_CLOSE.eq(inD)) { 137 | gotoS(OBSTACLE_CLOSE); 138 | } else { 139 | gotoS(OBSTACLE_FAR); 140 | } 141 | } 142 | break; 143 | default: 144 | break; 145 | } 146 | } catch (InterruptedException e) { 147 | 148 | } 149 | } 150 | }); 151 | 152 | private void cameraPosition(InputData evn) { 153 | if (camera != null) { 154 | 155 | if (evn.eq(CMD_CAM_DOWN)) { 156 | camera.down(); 157 | } else if (evn.eq(CMD_CAM_UP)) { 158 | camera.up(); 159 | } 160 | } else { 161 | if (evn.eq(CMD_CAM_DOWN)) { 162 | Log.d(TAG, "cameraPosition: camera is null " + evn.getDefStringRep()); 163 | } else if (evn.eq(CMD_CAM_UP)) { 164 | Log.d(TAG, "cameraPosition: camera is null " + evn.getDefStringRep()); 165 | } 166 | } 167 | } 168 | 169 | private void gotoS(@RobotState String state) { 170 | if (ledRGB != null) { 171 | ledRGB.turnAll(false); 172 | switch (state) { 173 | case OBSTACLE_CLOSE: 174 | ledRGB.turnRed(true); 175 | break; 176 | case OBSTACLE_FAR: 177 | ledRGB.turnGreen(true); 178 | break; 179 | default: 180 | ledRGB.turnBlue(true); 181 | break; 182 | } 183 | } 184 | this.state = state; 185 | Log.d(TAG, "GOTO State: " + state); 186 | } 187 | 188 | private void cleanLogByType(InputType type) { 189 | eventLog.removeIf(e -> e.getInputType() == type); 190 | } 191 | 192 | private InputData getLastByType(InputType type) { 193 | return eventLog.stream().filter(e -> e.getInputType() == type).findFirst().orElse(null); 194 | } 195 | 196 | } 197 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/lcd/Font.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.lcd; 2 | 3 | import com.google.android.things.contrib.driver.ssd1306.Ssd1306; 4 | 5 | public enum Font { 6 | 7 | FONT_5X5(0, 255, 5, 5, 9, 3, new byte[]{ 8 | 9 | 10 | }), 11 | FONT_5X8(0, 255, 5, 8, 9, 3, new byte[]{ 12 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 13 | (byte) 0x3E, (byte) 0x5B, (byte) 0x4F, (byte) 0x5B, (byte) 0x3E, 14 | (byte) 0x3E, (byte) 0x6B, (byte) 0x4F, (byte) 0x6B, (byte) 0x3E, 15 | (byte) 0x1C, (byte) 0x3E, (byte) 0x7C, (byte) 0x3E, (byte) 0x1C, 16 | (byte) 0x18, (byte) 0x3C, (byte) 0x7E, (byte) 0x3C, (byte) 0x18, 17 | (byte) 0x1C, (byte) 0x57, (byte) 0x7D, (byte) 0x57, (byte) 0x1C, 18 | (byte) 0x1C, (byte) 0x5E, (byte) 0x7F, (byte) 0x5E, (byte) 0x1C, 19 | (byte) 0x00, (byte) 0x18, (byte) 0x3C, (byte) 0x18, (byte) 0x00, 20 | (byte) 0xFF, (byte) 0xE7, (byte) 0xC3, (byte) 0xE7, (byte) 0xFF, 21 | (byte) 0x00, (byte) 0x18, (byte) 0x24, (byte) 0x18, (byte) 0x00, 22 | (byte) 0xFF, (byte) 0xE7, (byte) 0xDB, (byte) 0xE7, (byte) 0xFF, 23 | (byte) 0x30, (byte) 0x48, (byte) 0x3A, (byte) 0x06, (byte) 0x0E, 24 | (byte) 0x26, (byte) 0x29, (byte) 0x79, (byte) 0x29, (byte) 0x26, 25 | (byte) 0x40, (byte) 0x7F, (byte) 0x05, (byte) 0x05, (byte) 0x07, 26 | (byte) 0x40, (byte) 0x7F, (byte) 0x05, (byte) 0x25, (byte) 0x3F, 27 | (byte) 0x5A, (byte) 0x3C, (byte) 0xE7, (byte) 0x3C, (byte) 0x5A, 28 | (byte) 0x7F, (byte) 0x3E, (byte) 0x1C, (byte) 0x1C, (byte) 0x08, 29 | (byte) 0x08, (byte) 0x1C, (byte) 0x1C, (byte) 0x3E, (byte) 0x7F, 30 | (byte) 0x14, (byte) 0x22, (byte) 0x7F, (byte) 0x22, (byte) 0x14, 31 | (byte) 0x5F, (byte) 0x5F, (byte) 0x00, (byte) 0x5F, (byte) 0x5F, 32 | (byte) 0x06, (byte) 0x09, (byte) 0x7F, (byte) 0x01, (byte) 0x7F, 33 | (byte) 0x00, (byte) 0x66, (byte) 0x89, (byte) 0x95, (byte) 0x6A, 34 | (byte) 0x60, (byte) 0x60, (byte) 0x60, (byte) 0x60, (byte) 0x60, 35 | (byte) 0x94, (byte) 0xA2, (byte) 0xFF, (byte) 0xA2, (byte) 0x94, 36 | (byte) 0x08, (byte) 0x04, (byte) 0x7E, (byte) 0x04, (byte) 0x08, 37 | (byte) 0x10, (byte) 0x20, (byte) 0x7E, (byte) 0x20, (byte) 0x10, 38 | (byte) 0x08, (byte) 0x08, (byte) 0x2A, (byte) 0x1C, (byte) 0x08, 39 | (byte) 0x08, (byte) 0x1C, (byte) 0x2A, (byte) 0x08, (byte) 0x08, 40 | (byte) 0x1E, (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10, 41 | (byte) 0x0C, (byte) 0x1E, (byte) 0x0C, (byte) 0x1E, (byte) 0x0C, 42 | (byte) 0x30, (byte) 0x38, (byte) 0x3E, (byte) 0x38, (byte) 0x30, 43 | (byte) 0x06, (byte) 0x0E, (byte) 0x3E, (byte) 0x0E, (byte) 0x06, 44 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 45 | (byte) 0x00, (byte) 0x00, (byte) 0x5F, (byte) 0x00, (byte) 0x00, 46 | (byte) 0x00, (byte) 0x07, (byte) 0x00, (byte) 0x07, (byte) 0x00, 47 | (byte) 0x14, (byte) 0x7F, (byte) 0x14, (byte) 0x7F, (byte) 0x14, 48 | (byte) 0x24, (byte) 0x2A, (byte) 0x7F, (byte) 0x2A, (byte) 0x12, 49 | (byte) 0x23, (byte) 0x13, (byte) 0x08, (byte) 0x64, (byte) 0x62, 50 | (byte) 0x36, (byte) 0x49, (byte) 0x56, (byte) 0x20, (byte) 0x50, 51 | (byte) 0x00, (byte) 0x08, (byte) 0x07, (byte) 0x03, (byte) 0x00, 52 | (byte) 0x00, (byte) 0x1C, (byte) 0x22, (byte) 0x41, (byte) 0x00, 53 | (byte) 0x00, (byte) 0x41, (byte) 0x22, (byte) 0x1C, (byte) 0x00, 54 | (byte) 0x2A, (byte) 0x1C, (byte) 0x7F, (byte) 0x1C, (byte) 0x2A, 55 | (byte) 0x08, (byte) 0x08, (byte) 0x3E, (byte) 0x08, (byte) 0x08, 56 | (byte) 0x00, (byte) 0x80, (byte) 0x70, (byte) 0x30, (byte) 0x00, 57 | (byte) 0x08, (byte) 0x08, (byte) 0x08, (byte) 0x08, (byte) 0x08, 58 | (byte) 0x00, (byte) 0x00, (byte) 0x60, (byte) 0x60, (byte) 0x00, 59 | (byte) 0x20, (byte) 0x10, (byte) 0x08, (byte) 0x04, (byte) 0x02, 60 | (byte) 0x3E, (byte) 0x51, (byte) 0x49, (byte) 0x45, (byte) 0x3E, 61 | (byte) 0x00, (byte) 0x42, (byte) 0x7F, (byte) 0x40, (byte) 0x00, 62 | (byte) 0x72, (byte) 0x49, (byte) 0x49, (byte) 0x49, (byte) 0x46, 63 | (byte) 0x21, (byte) 0x41, (byte) 0x49, (byte) 0x4D, (byte) 0x33, 64 | (byte) 0x18, (byte) 0x14, (byte) 0x12, (byte) 0x7F, (byte) 0x10, 65 | (byte) 0x27, (byte) 0x45, (byte) 0x45, (byte) 0x45, (byte) 0x39, 66 | (byte) 0x3C, (byte) 0x4A, (byte) 0x49, (byte) 0x49, (byte) 0x31, 67 | (byte) 0x41, (byte) 0x21, (byte) 0x11, (byte) 0x09, (byte) 0x07, 68 | (byte) 0x36, (byte) 0x49, (byte) 0x49, (byte) 0x49, (byte) 0x36, 69 | (byte) 0x46, (byte) 0x49, (byte) 0x49, (byte) 0x29, (byte) 0x1E, 70 | (byte) 0x00, (byte) 0x00, (byte) 0x14, (byte) 0x00, (byte) 0x00, 71 | (byte) 0x00, (byte) 0x40, (byte) 0x34, (byte) 0x00, (byte) 0x00, 72 | (byte) 0x00, (byte) 0x08, (byte) 0x14, (byte) 0x22, (byte) 0x41, 73 | (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, 74 | (byte) 0x00, (byte) 0x41, (byte) 0x22, (byte) 0x14, (byte) 0x08, 75 | (byte) 0x02, (byte) 0x01, (byte) 0x59, (byte) 0x09, (byte) 0x06, 76 | (byte) 0x3E, (byte) 0x41, (byte) 0x5D, (byte) 0x59, (byte) 0x4E, 77 | (byte) 0x7C, (byte) 0x12, (byte) 0x11, (byte) 0x12, (byte) 0x7C, 78 | (byte) 0x7F, (byte) 0x49, (byte) 0x49, (byte) 0x49, (byte) 0x36, 79 | (byte) 0x3E, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x22, 80 | (byte) 0x7F, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x3E, 81 | (byte) 0x7F, (byte) 0x49, (byte) 0x49, (byte) 0x49, (byte) 0x41, 82 | (byte) 0x7F, (byte) 0x09, (byte) 0x09, (byte) 0x09, (byte) 0x01, 83 | (byte) 0x3E, (byte) 0x41, (byte) 0x41, (byte) 0x51, (byte) 0x73, 84 | (byte) 0x7F, (byte) 0x08, (byte) 0x08, (byte) 0x08, (byte) 0x7F, 85 | (byte) 0x00, (byte) 0x41, (byte) 0x7F, (byte) 0x41, (byte) 0x00, 86 | (byte) 0x20, (byte) 0x40, (byte) 0x41, (byte) 0x3F, (byte) 0x01, 87 | (byte) 0x7F, (byte) 0x08, (byte) 0x14, (byte) 0x22, (byte) 0x41, 88 | (byte) 0x7F, (byte) 0x40, (byte) 0x40, (byte) 0x40, (byte) 0x40, 89 | (byte) 0x7F, (byte) 0x02, (byte) 0x1C, (byte) 0x02, (byte) 0x7F, 90 | (byte) 0x7F, (byte) 0x04, (byte) 0x08, (byte) 0x10, (byte) 0x7F, 91 | (byte) 0x3E, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x3E, 92 | (byte) 0x7F, (byte) 0x09, (byte) 0x09, (byte) 0x09, (byte) 0x06, 93 | (byte) 0x3E, (byte) 0x41, (byte) 0x51, (byte) 0x21, (byte) 0x5E, 94 | (byte) 0x7F, (byte) 0x09, (byte) 0x19, (byte) 0x29, (byte) 0x46, 95 | (byte) 0x26, (byte) 0x49, (byte) 0x49, (byte) 0x49, (byte) 0x32, 96 | (byte) 0x03, (byte) 0x01, (byte) 0x7F, (byte) 0x01, (byte) 0x03, 97 | (byte) 0x3F, (byte) 0x40, (byte) 0x40, (byte) 0x40, (byte) 0x3F, 98 | (byte) 0x1F, (byte) 0x20, (byte) 0x40, (byte) 0x20, (byte) 0x1F, 99 | (byte) 0x3F, (byte) 0x40, (byte) 0x38, (byte) 0x40, (byte) 0x3F, 100 | (byte) 0x63, (byte) 0x14, (byte) 0x08, (byte) 0x14, (byte) 0x63, 101 | (byte) 0x03, (byte) 0x04, (byte) 0x78, (byte) 0x04, (byte) 0x03, 102 | (byte) 0x61, (byte) 0x59, (byte) 0x49, (byte) 0x4D, (byte) 0x43, 103 | (byte) 0x00, (byte) 0x7F, (byte) 0x41, (byte) 0x41, (byte) 0x41, 104 | (byte) 0x02, (byte) 0x04, (byte) 0x08, (byte) 0x10, (byte) 0x20, 105 | (byte) 0x00, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x7F, 106 | (byte) 0x04, (byte) 0x02, (byte) 0x01, (byte) 0x02, (byte) 0x04, 107 | (byte) 0x40, (byte) 0x40, (byte) 0x40, (byte) 0x40, (byte) 0x40, 108 | (byte) 0x00, (byte) 0x03, (byte) 0x07, (byte) 0x08, (byte) 0x00, 109 | (byte) 0x20, (byte) 0x54, (byte) 0x54, (byte) 0x78, (byte) 0x40, 110 | (byte) 0x7F, (byte) 0x28, (byte) 0x44, (byte) 0x44, (byte) 0x38, 111 | (byte) 0x38, (byte) 0x44, (byte) 0x44, (byte) 0x44, (byte) 0x28, 112 | (byte) 0x38, (byte) 0x44, (byte) 0x44, (byte) 0x28, (byte) 0x7F, 113 | (byte) 0x38, (byte) 0x54, (byte) 0x54, (byte) 0x54, (byte) 0x18, 114 | (byte) 0x00, (byte) 0x08, (byte) 0x7E, (byte) 0x09, (byte) 0x02, 115 | (byte) 0x18, (byte) 0xA4, (byte) 0xA4, (byte) 0x9C, (byte) 0x78, 116 | (byte) 0x7F, (byte) 0x08, (byte) 0x04, (byte) 0x04, (byte) 0x78, 117 | (byte) 0x00, (byte) 0x44, (byte) 0x7D, (byte) 0x40, (byte) 0x00, 118 | (byte) 0x20, (byte) 0x40, (byte) 0x40, (byte) 0x3D, (byte) 0x00, 119 | (byte) 0x7F, (byte) 0x10, (byte) 0x28, (byte) 0x44, (byte) 0x00, 120 | (byte) 0x00, (byte) 0x41, (byte) 0x7F, (byte) 0x40, (byte) 0x00, 121 | (byte) 0x7C, (byte) 0x04, (byte) 0x78, (byte) 0x04, (byte) 0x78, 122 | (byte) 0x7C, (byte) 0x08, (byte) 0x04, (byte) 0x04, (byte) 0x78, 123 | (byte) 0x38, (byte) 0x44, (byte) 0x44, (byte) 0x44, (byte) 0x38, 124 | (byte) 0xFC, (byte) 0x18, (byte) 0x24, (byte) 0x24, (byte) 0x18, 125 | (byte) 0x18, (byte) 0x24, (byte) 0x24, (byte) 0x18, (byte) 0xFC, 126 | (byte) 0x7C, (byte) 0x08, (byte) 0x04, (byte) 0x04, (byte) 0x08, 127 | (byte) 0x48, (byte) 0x54, (byte) 0x54, (byte) 0x54, (byte) 0x24, 128 | (byte) 0x04, (byte) 0x04, (byte) 0x3F, (byte) 0x44, (byte) 0x24, 129 | (byte) 0x3C, (byte) 0x40, (byte) 0x40, (byte) 0x20, (byte) 0x7C, 130 | (byte) 0x1C, (byte) 0x20, (byte) 0x40, (byte) 0x20, (byte) 0x1C, 131 | (byte) 0x3C, (byte) 0x40, (byte) 0x30, (byte) 0x40, (byte) 0x3C, 132 | (byte) 0x44, (byte) 0x28, (byte) 0x10, (byte) 0x28, (byte) 0x44, 133 | (byte) 0x4C, (byte) 0x90, (byte) 0x90, (byte) 0x90, (byte) 0x7C, 134 | (byte) 0x44, (byte) 0x64, (byte) 0x54, (byte) 0x4C, (byte) 0x44, 135 | (byte) 0x00, (byte) 0x08, (byte) 0x36, (byte) 0x41, (byte) 0x00, 136 | (byte) 0x00, (byte) 0x00, (byte) 0x77, (byte) 0x00, (byte) 0x00, 137 | (byte) 0x00, (byte) 0x41, (byte) 0x36, (byte) 0x08, (byte) 0x00, 138 | (byte) 0x02, (byte) 0x01, (byte) 0x02, (byte) 0x04, (byte) 0x02, 139 | (byte) 0x3C, (byte) 0x26, (byte) 0x23, (byte) 0x26, (byte) 0x3C, 140 | (byte) 0x1E, (byte) 0xA1, (byte) 0xA1, (byte) 0x61, (byte) 0x12, 141 | (byte) 0x3A, (byte) 0x40, (byte) 0x40, (byte) 0x20, (byte) 0x7A, 142 | (byte) 0x38, (byte) 0x54, (byte) 0x54, (byte) 0x55, (byte) 0x59, 143 | (byte) 0x21, (byte) 0x55, (byte) 0x55, (byte) 0x79, (byte) 0x41, 144 | (byte) 0x21, (byte) 0x54, (byte) 0x54, (byte) 0x78, (byte) 0x41, 145 | (byte) 0x21, (byte) 0x55, (byte) 0x54, (byte) 0x78, (byte) 0x40, 146 | (byte) 0x20, (byte) 0x54, (byte) 0x55, (byte) 0x79, (byte) 0x40, 147 | (byte) 0x0C, (byte) 0x1E, (byte) 0x52, (byte) 0x72, (byte) 0x12, 148 | (byte) 0x39, (byte) 0x55, (byte) 0x55, (byte) 0x55, (byte) 0x59, 149 | (byte) 0x39, (byte) 0x54, (byte) 0x54, (byte) 0x54, (byte) 0x59, 150 | (byte) 0x39, (byte) 0x55, (byte) 0x54, (byte) 0x54, (byte) 0x58, 151 | (byte) 0x00, (byte) 0x00, (byte) 0x45, (byte) 0x7C, (byte) 0x41, 152 | (byte) 0x00, (byte) 0x02, (byte) 0x45, (byte) 0x7D, (byte) 0x42, 153 | (byte) 0x00, (byte) 0x01, (byte) 0x45, (byte) 0x7C, (byte) 0x40, 154 | (byte) 0xF0, (byte) 0x29, (byte) 0x24, (byte) 0x29, (byte) 0xF0, 155 | (byte) 0xF0, (byte) 0x28, (byte) 0x25, (byte) 0x28, (byte) 0xF0, 156 | (byte) 0x7C, (byte) 0x54, (byte) 0x55, (byte) 0x45, (byte) 0x00, 157 | (byte) 0x20, (byte) 0x54, (byte) 0x54, (byte) 0x7C, (byte) 0x54, 158 | (byte) 0x7C, (byte) 0x0A, (byte) 0x09, (byte) 0x7F, (byte) 0x49, 159 | (byte) 0x32, (byte) 0x49, (byte) 0x49, (byte) 0x49, (byte) 0x32, 160 | (byte) 0x32, (byte) 0x48, (byte) 0x48, (byte) 0x48, (byte) 0x32, 161 | (byte) 0x32, (byte) 0x4A, (byte) 0x48, (byte) 0x48, (byte) 0x30, 162 | (byte) 0x3A, (byte) 0x41, (byte) 0x41, (byte) 0x21, (byte) 0x7A, 163 | (byte) 0x3A, (byte) 0x42, (byte) 0x40, (byte) 0x20, (byte) 0x78, 164 | (byte) 0x00, (byte) 0x9D, (byte) 0xA0, (byte) 0xA0, (byte) 0x7D, 165 | (byte) 0x39, (byte) 0x44, (byte) 0x44, (byte) 0x44, (byte) 0x39, 166 | (byte) 0x3D, (byte) 0x40, (byte) 0x40, (byte) 0x40, (byte) 0x3D, 167 | (byte) 0x3C, (byte) 0x24, (byte) 0xFF, (byte) 0x24, (byte) 0x24, 168 | (byte) 0x48, (byte) 0x7E, (byte) 0x49, (byte) 0x43, (byte) 0x66, 169 | (byte) 0x2B, (byte) 0x2F, (byte) 0xFC, (byte) 0x2F, (byte) 0x2B, 170 | (byte) 0xFF, (byte) 0x09, (byte) 0x29, (byte) 0xF6, (byte) 0x20, 171 | (byte) 0xC0, (byte) 0x88, (byte) 0x7E, (byte) 0x09, (byte) 0x03, 172 | (byte) 0x20, (byte) 0x54, (byte) 0x54, (byte) 0x79, (byte) 0x41, 173 | (byte) 0x00, (byte) 0x00, (byte) 0x44, (byte) 0x7D, (byte) 0x41, 174 | (byte) 0x30, (byte) 0x48, (byte) 0x48, (byte) 0x4A, (byte) 0x32, 175 | (byte) 0x38, (byte) 0x40, (byte) 0x40, (byte) 0x22, (byte) 0x7A, 176 | (byte) 0x00, (byte) 0x7A, (byte) 0x0A, (byte) 0x0A, (byte) 0x72, 177 | (byte) 0x7D, (byte) 0x0D, (byte) 0x19, (byte) 0x31, (byte) 0x7D, 178 | (byte) 0x26, (byte) 0x29, (byte) 0x29, (byte) 0x2F, (byte) 0x28, 179 | (byte) 0x26, (byte) 0x29, (byte) 0x29, (byte) 0x29, (byte) 0x26, 180 | (byte) 0x30, (byte) 0x48, (byte) 0x4D, (byte) 0x40, (byte) 0x20, 181 | (byte) 0x38, (byte) 0x08, (byte) 0x08, (byte) 0x08, (byte) 0x08, 182 | (byte) 0x08, (byte) 0x08, (byte) 0x08, (byte) 0x08, (byte) 0x38, 183 | (byte) 0x2F, (byte) 0x10, (byte) 0xC8, (byte) 0xAC, (byte) 0xBA, 184 | (byte) 0x2F, (byte) 0x10, (byte) 0x28, (byte) 0x34, (byte) 0xFA, 185 | (byte) 0x00, (byte) 0x00, (byte) 0x7B, (byte) 0x00, (byte) 0x00, 186 | (byte) 0x08, (byte) 0x14, (byte) 0x2A, (byte) 0x14, (byte) 0x22, 187 | (byte) 0x22, (byte) 0x14, (byte) 0x2A, (byte) 0x14, (byte) 0x08, 188 | (byte) 0xAA, (byte) 0x00, (byte) 0x55, (byte) 0x00, (byte) 0xAA, 189 | (byte) 0xAA, (byte) 0x55, (byte) 0xAA, (byte) 0x55, (byte) 0xAA, 190 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF, (byte) 0x00, 191 | (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0xFF, (byte) 0x00, 192 | (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0xFF, (byte) 0x00, 193 | (byte) 0x10, (byte) 0x10, (byte) 0xFF, (byte) 0x00, (byte) 0xFF, 194 | (byte) 0x10, (byte) 0x10, (byte) 0xF0, (byte) 0x10, (byte) 0xF0, 195 | (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0xFC, (byte) 0x00, 196 | (byte) 0x14, (byte) 0x14, (byte) 0xF7, (byte) 0x00, (byte) 0xFF, 197 | (byte) 0x00, (byte) 0x00, (byte) 0xFF, (byte) 0x00, (byte) 0xFF, 198 | (byte) 0x14, (byte) 0x14, (byte) 0xF4, (byte) 0x04, (byte) 0xFC, 199 | (byte) 0x14, (byte) 0x14, (byte) 0x17, (byte) 0x10, (byte) 0x1F, 200 | (byte) 0x10, (byte) 0x10, (byte) 0x1F, (byte) 0x10, (byte) 0x1F, 201 | (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x1F, (byte) 0x00, 202 | (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0xF0, (byte) 0x00, 203 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x1F, (byte) 0x10, 204 | (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x1F, (byte) 0x10, 205 | (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0xF0, (byte) 0x10, 206 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF, (byte) 0x10, 207 | (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10, 208 | (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0xFF, (byte) 0x10, 209 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF, (byte) 0x14, 210 | (byte) 0x00, (byte) 0x00, (byte) 0xFF, (byte) 0x00, (byte) 0xFF, 211 | (byte) 0x00, (byte) 0x00, (byte) 0x1F, (byte) 0x10, (byte) 0x17, 212 | (byte) 0x00, (byte) 0x00, (byte) 0xFC, (byte) 0x04, (byte) 0xF4, 213 | (byte) 0x14, (byte) 0x14, (byte) 0x17, (byte) 0x10, (byte) 0x17, 214 | (byte) 0x14, (byte) 0x14, (byte) 0xF4, (byte) 0x04, (byte) 0xF4, 215 | (byte) 0x00, (byte) 0x00, (byte) 0xFF, (byte) 0x00, (byte) 0xF7, 216 | (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, 217 | (byte) 0x14, (byte) 0x14, (byte) 0xF7, (byte) 0x00, (byte) 0xF7, 218 | (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x17, (byte) 0x14, 219 | (byte) 0x10, (byte) 0x10, (byte) 0x1F, (byte) 0x10, (byte) 0x1F, 220 | (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0xF4, (byte) 0x14, 221 | (byte) 0x10, (byte) 0x10, (byte) 0xF0, (byte) 0x10, (byte) 0xF0, 222 | (byte) 0x00, (byte) 0x00, (byte) 0x1F, (byte) 0x10, (byte) 0x1F, 223 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x1F, (byte) 0x14, 224 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFC, (byte) 0x14, 225 | (byte) 0x00, (byte) 0x00, (byte) 0xF0, (byte) 0x10, (byte) 0xF0, 226 | (byte) 0x10, (byte) 0x10, (byte) 0xFF, (byte) 0x10, (byte) 0xFF, 227 | (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0xFF, (byte) 0x14, 228 | (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x1F, (byte) 0x00, 229 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xF0, (byte) 0x10, 230 | (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 231 | (byte) 0xF0, (byte) 0xF0, (byte) 0xF0, (byte) 0xF0, (byte) 0xF0, 232 | (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x00, (byte) 0x00, 233 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF, (byte) 0xFF, 234 | (byte) 0x0F, (byte) 0x0F, (byte) 0x0F, (byte) 0x0F, (byte) 0x0F, 235 | (byte) 0x38, (byte) 0x44, (byte) 0x44, (byte) 0x38, (byte) 0x44, 236 | (byte) 0x7C, (byte) 0x2A, (byte) 0x2A, (byte) 0x3E, (byte) 0x14, 237 | (byte) 0x7E, (byte) 0x02, (byte) 0x02, (byte) 0x06, (byte) 0x06, 238 | (byte) 0x02, (byte) 0x7E, (byte) 0x02, (byte) 0x7E, (byte) 0x02, 239 | (byte) 0x63, (byte) 0x55, (byte) 0x49, (byte) 0x41, (byte) 0x63, 240 | (byte) 0x38, (byte) 0x44, (byte) 0x44, (byte) 0x3C, (byte) 0x04, 241 | (byte) 0x40, (byte) 0x7E, (byte) 0x20, (byte) 0x1E, (byte) 0x20, 242 | (byte) 0x06, (byte) 0x02, (byte) 0x7E, (byte) 0x02, (byte) 0x02, 243 | (byte) 0x99, (byte) 0xA5, (byte) 0xE7, (byte) 0xA5, (byte) 0x99, 244 | (byte) 0x1C, (byte) 0x2A, (byte) 0x49, (byte) 0x2A, (byte) 0x1C, 245 | (byte) 0x4C, (byte) 0x72, (byte) 0x01, (byte) 0x72, (byte) 0x4C, 246 | (byte) 0x30, (byte) 0x4A, (byte) 0x4D, (byte) 0x4D, (byte) 0x30, 247 | (byte) 0x30, (byte) 0x48, (byte) 0x78, (byte) 0x48, (byte) 0x30, 248 | (byte) 0xBC, (byte) 0x62, (byte) 0x5A, (byte) 0x46, (byte) 0x3D, 249 | (byte) 0x3E, (byte) 0x49, (byte) 0x49, (byte) 0x49, (byte) 0x00, 250 | (byte) 0x7E, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x7E, 251 | (byte) 0x2A, (byte) 0x2A, (byte) 0x2A, (byte) 0x2A, (byte) 0x2A, 252 | (byte) 0x44, (byte) 0x44, (byte) 0x5F, (byte) 0x44, (byte) 0x44, 253 | (byte) 0x40, (byte) 0x51, (byte) 0x4A, (byte) 0x44, (byte) 0x40, 254 | (byte) 0x40, (byte) 0x44, (byte) 0x4A, (byte) 0x51, (byte) 0x40, 255 | (byte) 0x00, (byte) 0x00, (byte) 0xFF, (byte) 0x01, (byte) 0x03, 256 | (byte) 0xE0, (byte) 0x80, (byte) 0xFF, (byte) 0x00, (byte) 0x00, 257 | (byte) 0x08, (byte) 0x08, (byte) 0x6B, (byte) 0x6B, (byte) 0x08, 258 | (byte) 0x36, (byte) 0x12, (byte) 0x36, (byte) 0x24, (byte) 0x36, 259 | (byte) 0x06, (byte) 0x0F, (byte) 0x09, (byte) 0x0F, (byte) 0x06, 260 | (byte) 0x00, (byte) 0x00, (byte) 0x18, (byte) 0x18, (byte) 0x00, 261 | (byte) 0x00, (byte) 0x00, (byte) 0x10, (byte) 0x10, (byte) 0x00, 262 | (byte) 0x30, (byte) 0x40, (byte) 0xFF, (byte) 0x01, (byte) 0x01, 263 | (byte) 0x00, (byte) 0x1F, (byte) 0x01, (byte) 0x01, (byte) 0x1E, 264 | (byte) 0x00, (byte) 0x19, (byte) 0x1D, (byte) 0x17, (byte) 0x12, 265 | (byte) 0x00, (byte) 0x3C, (byte) 0x3C, (byte) 0x3C, (byte) 0x3C, 266 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 267 | }), 268 | 269 | FONT_4X5(32, 95, 4, 5, 4, 7, new byte[]{ 270 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 271 | (byte) 0x00, (byte) 0x17, (byte) 0x00, (byte) 0x00, 272 | (byte) 0x03, (byte) 0x00, (byte) 0x03, (byte) 0x00, 273 | (byte) 0x1F, (byte) 0x0A, (byte) 0x1F, (byte) 0x0A, 274 | (byte) 0x17, (byte) 0x1F, (byte) 0x1D, (byte) 0x00, 275 | (byte) 0x09, (byte) 0x04, (byte) 0x12, (byte) 0x00, 276 | (byte) 0x0A, (byte) 0x15, (byte) 0x09, (byte) 0x14, 277 | (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x00, 278 | (byte) 0x00, (byte) 0x0E, (byte) 0x11, (byte) 0x00, 279 | (byte) 0x00, (byte) 0x11, (byte) 0x0E, (byte) 0x00, 280 | (byte) 0x05, (byte) 0x02, (byte) 0x05, (byte) 0x00, 281 | (byte) 0x04, (byte) 0x0E, (byte) 0x04, (byte) 0x00, 282 | (byte) 0x00, (byte) 0x18, (byte) 0x00, (byte) 0x00, 283 | (byte) 0x04, (byte) 0x04, (byte) 0x04, (byte) 0x00, 284 | (byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x00, 285 | (byte) 0x10, (byte) 0x0C, (byte) 0x03, (byte) 0x00, 286 | (byte) 0x1F, (byte) 0x11, (byte) 0x1F, (byte) 0x00, 287 | (byte) 0x12, (byte) 0x1F, (byte) 0x10, (byte) 0x00, 288 | (byte) 0x1D, (byte) 0x15, (byte) 0x17, (byte) 0x00, 289 | (byte) 0x15, (byte) 0x15, (byte) 0x1F, (byte) 0x00, 290 | (byte) 0x07, (byte) 0x04, (byte) 0x1F, (byte) 0x00, 291 | (byte) 0x17, (byte) 0x15, (byte) 0x1D, (byte) 0x00, 292 | (byte) 0x1F, (byte) 0x15, (byte) 0x1D, (byte) 0x00, 293 | (byte) 0x01, (byte) 0x01, (byte) 0x1F, (byte) 0x00, 294 | (byte) 0x1F, (byte) 0x15, (byte) 0x1F, (byte) 0x00, 295 | (byte) 0x17, (byte) 0x15, (byte) 0x1F, (byte) 0x00, 296 | (byte) 0x00, (byte) 0x0A, (byte) 0x00, (byte) 0x00, 297 | (byte) 0x00, (byte) 0x1A, (byte) 0x00, (byte) 0x00, 298 | (byte) 0x04, (byte) 0x0A, (byte) 0x11, (byte) 0x00, 299 | (byte) 0x0A, (byte) 0x0A, (byte) 0x0A, (byte) 0x00, 300 | (byte) 0x11, (byte) 0x0A, (byte) 0x04, (byte) 0x00, 301 | (byte) 0x01, (byte) 0x15, (byte) 0x07, (byte) 0x00, 302 | (byte) 0x1F, (byte) 0x15, (byte) 0x17, (byte) 0x00, 303 | (byte) 0x1F, (byte) 0x05, (byte) 0x1F, (byte) 0x00, 304 | (byte) 0x1F, (byte) 0x15, (byte) 0x0A, (byte) 0x00, 305 | (byte) 0x1F, (byte) 0x11, (byte) 0x11, (byte) 0x00, 306 | (byte) 0x1F, (byte) 0x11, (byte) 0x0E, (byte) 0x00, 307 | (byte) 0x1F, (byte) 0x15, (byte) 0x11, (byte) 0x00, 308 | (byte) 0x1F, (byte) 0x05, (byte) 0x01, (byte) 0x00, 309 | (byte) 0x1F, (byte) 0x11, (byte) 0x1D, (byte) 0x00, 310 | (byte) 0x1F, (byte) 0x04, (byte) 0x1F, (byte) 0x00, 311 | (byte) 0x00, (byte) 0x1F, (byte) 0x00, (byte) 0x00, 312 | (byte) 0x11, (byte) 0x11, (byte) 0x0F, (byte) 0x00, 313 | (byte) 0x1F, (byte) 0x0C, (byte) 0x13, (byte) 0x00, 314 | (byte) 0x1F, (byte) 0x10, (byte) 0x10, (byte) 0x00, 315 | (byte) 0x1F, (byte) 0x02, (byte) 0x1F, (byte) 0x00, 316 | (byte) 0x1F, (byte) 0x06, (byte) 0x1F, (byte) 0x00, 317 | (byte) 0x1F, (byte) 0x11, (byte) 0x1F, (byte) 0x00, 318 | (byte) 0x1F, (byte) 0x05, (byte) 0x07, (byte) 0x00, 319 | (byte) 0x1F, (byte) 0x15, (byte) 0x1F, (byte) 0x08, 320 | (byte) 0x1F, (byte) 0x0D, (byte) 0x17, (byte) 0x00, 321 | (byte) 0x17, (byte) 0x15, (byte) 0x1D, (byte) 0x00, 322 | (byte) 0x01, (byte) 0x1F, (byte) 0x01, (byte) 0x00, 323 | (byte) 0x1F, (byte) 0x10, (byte) 0x1F, (byte) 0x00, 324 | (byte) 0x0F, (byte) 0x10, (byte) 0x0F, (byte) 0x00, 325 | (byte) 0x1F, (byte) 0x08, (byte) 0x1F, (byte) 0x00, 326 | (byte) 0x1B, (byte) 0x04, (byte) 0x1B, (byte) 0x00, 327 | (byte) 0x03, (byte) 0x1C, (byte) 0x03, (byte) 0x00, 328 | (byte) 0x19, (byte) 0x15, (byte) 0x13, (byte) 0x00, 329 | (byte) 0x00, (byte) 0x1F, (byte) 0x11, (byte) 0x00, 330 | (byte) 0x03, (byte) 0x0C, (byte) 0x10, (byte) 0x00, 331 | (byte) 0x00, (byte) 0x11, (byte) 0x1F, (byte) 0x00, 332 | (byte) 0x02, (byte) 0x01, (byte) 0x02, (byte) 0x00, 333 | (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x00, 334 | }); 335 | 336 | private final int minChar, maxChar, width, height, outterWidth, outterHeight; 337 | private final byte[] data; 338 | 339 | Font(int minChar, int maxChar, int width, int height, int outterWidth, int outterHeight, byte[] data) { 340 | this.minChar = minChar; 341 | this.maxChar = maxChar; 342 | this.width = width; 343 | this.height = height; 344 | this.outterWidth = outterWidth; 345 | this.outterHeight = outterHeight; 346 | this.data = data; 347 | } 348 | 349 | public int getWidth() { 350 | return width; 351 | } 352 | 353 | public int getHeight() { 354 | return height; 355 | } 356 | 357 | public int getOutterWidth() { 358 | return outterWidth; 359 | } 360 | 361 | public int getOutterHeight() { 362 | return outterHeight; 363 | } 364 | 365 | public byte getData(int offset) { 366 | return this.data[offset]; 367 | } 368 | 369 | public int getMinChar() { 370 | return minChar; 371 | } 372 | 373 | public int getMaxChar() { 374 | return maxChar; 375 | } 376 | 377 | void drawChar(Ssd1306 display, char c, int x, int y, boolean on) { 378 | if (c > maxChar || c < minChar) { 379 | c = '?'; 380 | } 381 | 382 | c -= minChar; 383 | 384 | for (int i = 0; i < width; ++i) { 385 | int line = data[(c * width) + i]; 386 | 387 | for (int j = 0; j < height; ++j) { 388 | if ((line & 0x01) > 0) { 389 | display.setPixel(x + i, y + j, on); 390 | } 391 | line >>= 1; 392 | } 393 | } 394 | } 395 | 396 | } -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/lcd/Fonts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.samgol.robot.lcd; 18 | 19 | import com.google.android.things.contrib.driver.ssd1306.Ssd1306; 20 | 21 | /** 22 | * Contain Fonts hex values 23 | * 96 x 6 base 24 | *

25 | * http://jared.geek.nz/2014/jan/custom-fonts-for-microcontrollers 26 | * Author : Jared Sanson (jared@jared.geek.nz) 27 | */ 28 | public class Fonts { 29 | public static int CHAR_WIDTH = 6; 30 | public static int CHAR_HEIGHT = 8; 31 | 32 | public enum Type { 33 | font5x5, fontAcme5Outlines, fontAztech, fontCrackers, fontSuperDig, fontZxpix 34 | } 35 | 36 | public static char[][] font5x5 = { 37 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 38 | {0x5c, 0x00, 0x00, 0x00, 0x00, 0x00}, // ! 39 | {0x06, 0x00, 0x06, 0x00, 0x00, 0x00}, // " 40 | {0x28, 0x7c, 0x28, 0x7c, 0x28, 0x00}, // # 41 | {0x5c, 0x54, 0xfe, 0x54, 0x74, 0x00}, // $ 42 | {0x44, 0x20, 0x10, 0x08, 0x44, 0x00}, // % 43 | {0x28, 0x54, 0x54, 0x20, 0x50, 0x00}, // & 44 | {0x06, 0x00, 0x00, 0x00, 0x00, 0x00}, // ' 45 | {0x38, 0x44, 0x00, 0x00, 0x00, 0x00}, // ( 46 | {0x44, 0x38, 0x00, 0x00, 0x00, 0x00}, // ) 47 | {0x02, 0x07, 0x02, 0x00, 0x00, 0x00}, // * 48 | {0x10, 0x10, 0x7c, 0x10, 0x10, 0x00}, // + 49 | {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 50 | {0x10, 0x10, 0x10, 0x10, 0x10, 0x00}, // - 51 | {0x40, 0x00, 0x00, 0x00, 0x00, 0x00}, // . 52 | {0x60, 0x10, 0x0c, 0x00, 0x00, 0x00}, // / 53 | {0x7c, 0x64, 0x54, 0x4c, 0x7c, 0x00}, // 0 54 | {0x48, 0x7c, 0x40, 0x00, 0x00, 0x00}, // 1 55 | {0x64, 0x54, 0x54, 0x54, 0x48, 0x00}, // 2 56 | {0x44, 0x54, 0x54, 0x54, 0x6c, 0x00}, // 3 57 | {0x3c, 0x20, 0x70, 0x20, 0x20, 0x00}, // 4 58 | {0x5c, 0x54, 0x54, 0x54, 0x24, 0x00}, // 5 59 | {0x7c, 0x54, 0x54, 0x54, 0x74, 0x00}, // 6 60 | {0x04, 0x04, 0x64, 0x14, 0x0c, 0x00}, // 7 61 | {0x7c, 0x54, 0x54, 0x54, 0x7c, 0x00}, // 8 62 | {0x5c, 0x54, 0x54, 0x54, 0x7c, 0x00}, // 9 63 | {0x44, 0x00, 0x00, 0x00, 0x00, 0x00}, // : 64 | {0xc4, 0x00, 0x00, 0x00, 0x00, 0x00}, // ; 65 | {0x10, 0x28, 0x44, 0x00, 0x00, 0x00}, // < 66 | {0x28, 0x28, 0x28, 0x28, 0x28, 0x00}, // = 67 | {0x44, 0x28, 0x10, 0x00, 0x00, 0x00}, // > 68 | {0x08, 0x04, 0x54, 0x08, 0x00, 0x00}, // ? 69 | {0x7c, 0x44, 0x54, 0x54, 0x5c, 0x00}, // @ 70 | {0x7c, 0x24, 0x24, 0x24, 0x7c, 0x00}, // A 71 | {0x7c, 0x54, 0x54, 0x54, 0x6c, 0x00}, // B 72 | {0x7c, 0x44, 0x44, 0x44, 0x44, 0x00}, // C 73 | {0x7c, 0x44, 0x44, 0x44, 0x38, 0x00}, // D 74 | {0x7c, 0x54, 0x54, 0x54, 0x44, 0x00}, // E 75 | {0x7c, 0x14, 0x14, 0x14, 0x04, 0x00}, // F 76 | {0x7c, 0x44, 0x44, 0x54, 0x74, 0x00}, // G 77 | {0x7c, 0x10, 0x10, 0x10, 0x7c, 0x00}, // H 78 | {0x44, 0x44, 0x7c, 0x44, 0x44, 0x00}, // I 79 | {0x60, 0x40, 0x40, 0x44, 0x7c, 0x00}, // J 80 | {0x7c, 0x10, 0x10, 0x28, 0x44, 0x00}, // K 81 | {0x7c, 0x40, 0x40, 0x40, 0x40, 0x00}, // L 82 | {0x7c, 0x08, 0x10, 0x08, 0x7c, 0x00}, // M 83 | {0x7c, 0x08, 0x10, 0x20, 0x7c, 0x00}, // N 84 | {0x38, 0x44, 0x44, 0x44, 0x38, 0x00}, // O 85 | {0x7c, 0x14, 0x14, 0x14, 0x08, 0x00}, // P 86 | {0x3c, 0x24, 0x64, 0x24, 0x3c, 0x00}, // Q 87 | {0x7c, 0x14, 0x14, 0x14, 0x68, 0x00}, // R 88 | {0x5c, 0x54, 0x54, 0x54, 0x74, 0x00}, // S 89 | {0x04, 0x04, 0x7c, 0x04, 0x04, 0x00}, // T 90 | {0x7c, 0x40, 0x40, 0x40, 0x7c, 0x00}, // U 91 | {0x0c, 0x30, 0x40, 0x30, 0x0c, 0x00}, // V 92 | {0x3c, 0x40, 0x30, 0x40, 0x3c, 0x00}, // W 93 | {0x44, 0x28, 0x10, 0x28, 0x44, 0x00}, // X 94 | {0x0c, 0x10, 0x60, 0x10, 0x0c, 0x00}, // Y 95 | {0x44, 0x64, 0x54, 0x4c, 0x44, 0x00}, // Z 96 | {0x7c, 0x44, 0x00, 0x00, 0x00, 0x00}, // [ 97 | {0x0c, 0x10, 0x60, 0x00, 0x00, 0x00}, // "\" 98 | {0x44, 0x7c, 0x00, 0x00, 0x00, 0x00}, // ] 99 | {0x00, 0x01, 0x00, 0x01, 0x00, 0x00}, // ^ 100 | {0x40, 0x40, 0x40, 0x40, 0x40, 0x40}, // _ 101 | {0x00, 0x01, 0x00, 0x00, 0x00, 0x00}, // ` 102 | {0x7c, 0x24, 0x24, 0x24, 0x7c, 0x00}, // a 103 | {0x7c, 0x54, 0x54, 0x54, 0x6c, 0x00}, // b 104 | {0x7c, 0x44, 0x44, 0x44, 0x44, 0x00}, // c 105 | {0x7c, 0x44, 0x44, 0x44, 0x38, 0x00}, // d 106 | {0x7c, 0x54, 0x54, 0x54, 0x44, 0x00}, // e 107 | {0x7c, 0x14, 0x14, 0x14, 0x04, 0x00}, // f 108 | {0x7c, 0x44, 0x44, 0x54, 0x74, 0x00}, // g 109 | {0x7c, 0x10, 0x10, 0x10, 0x7c, 0x00}, // h 110 | {0x44, 0x44, 0x7c, 0x44, 0x44, 0x00}, // i 111 | {0x60, 0x40, 0x40, 0x44, 0x7c, 0x00}, // j 112 | {0x7c, 0x10, 0x10, 0x28, 0x44, 0x00}, // k 113 | {0x7c, 0x40, 0x40, 0x40, 0x40, 0x00}, // l 114 | {0x7c, 0x08, 0x10, 0x08, 0x7c, 0x00}, // m 115 | {0x7c, 0x08, 0x10, 0x20, 0x7c, 0x00}, // n 116 | {0x38, 0x44, 0x44, 0x44, 0x38, 0x00}, // o 117 | {0x7c, 0x14, 0x14, 0x14, 0x08, 0x00}, // p 118 | {0x3c, 0x24, 0x64, 0x24, 0x3c, 0x00}, // q 119 | {0x7c, 0x14, 0x14, 0x14, 0x68, 0x00}, // r 120 | {0x5c, 0x54, 0x54, 0x54, 0x74, 0x00}, // s 121 | {0x04, 0x04, 0x7c, 0x04, 0x04, 0x00}, // t 122 | {0x7c, 0x40, 0x40, 0x40, 0x7c, 0x00}, // u 123 | {0x0c, 0x30, 0x40, 0x30, 0x0c, 0x00}, // v 124 | {0x3c, 0x40, 0x30, 0x40, 0x3c, 0x00}, // w 125 | {0x44, 0x28, 0x10, 0x28, 0x44, 0x00}, // x 126 | {0x0c, 0x10, 0x60, 0x10, 0x0c, 0x00}, // y 127 | {0x44, 0x64, 0x54, 0x4c, 0x44, 0x00}, // z 128 | {0x10, 0x7c, 0x44, 0x00, 0x00, 0x00}, // { 129 | {0x6c, 0x00, 0x00, 0x00, 0x00, 0x00}, // | 130 | {0x44, 0x7c, 0x10, 0x00, 0x00, 0x00}, // } 131 | {0x02, 0x01, 0x02, 0x01, 0x00, 0x00}, // ~ 132 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 133 | }; 134 | 135 | public static char[][] fontAcme5Outlines = { 136 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 137 | {0x7f, 0x51, 0x7f, 0x00, 0x00, 0x00}, // ! 138 | {0x0f, 0x09, 0x0f, 0x09, 0x0f, 0x00}, // " 139 | {0x3e, 0x6b, 0x41, 0x6b, 0x41, 0x6b}, // # 140 | {0x7f, 0xd1, 0x94, 0xc5, 0x7f, 0x00}, // $ 141 | {0x77, 0x4d, 0x77, 0x59, 0x77, 0x00}, // % 142 | {0x7f, 0x49, 0x55, 0x49, 0x6f, 0x54}, // & 143 | {0x0f, 0x09, 0x0f, 0x00, 0x00, 0x00}, // ' 144 | {0x7f, 0xc1, 0xbe, 0xe3, 0x00, 0x00}, // ( 145 | {0xe3, 0xbe, 0xc1, 0x7f, 0x00, 0x00}, // ) 146 | {0x3e, 0x2a, 0x77, 0x41, 0x77, 0x2a}, // * 147 | {0x1c, 0x14, 0x77, 0x41, 0x77, 0x14}, // + 148 | {0xe0, 0xb0, 0xd0, 0x70, 0x00, 0x00}, // , 149 | {0x1c, 0x14, 0x14, 0x14, 0x1c, 0x00}, // - 150 | {0x70, 0x50, 0x70, 0x00, 0x00, 0x00}, // . 151 | {0x78, 0x4c, 0x77, 0x19, 0x0f, 0x00}, // / 152 | {0x7f, 0x41, 0x5d, 0x41, 0x7f, 0x00}, // 0 153 | {0x7f, 0x41, 0x7f, 0x00, 0x00, 0x00}, // 1 154 | {0x7f, 0x45, 0x55, 0x51, 0x7f, 0x00}, // 2 155 | {0x7f, 0x55, 0x55, 0x41, 0x7f, 0x00}, // 3 156 | {0x1f, 0x11, 0x77, 0x41, 0x7f, 0x00}, // 4 157 | {0x7f, 0x51, 0x55, 0x45, 0x7f, 0x00}, // 5 158 | {0x7f, 0x41, 0x55, 0x45, 0x7f, 0x00}, // 6 159 | {0x07, 0x7d, 0x45, 0x79, 0x0f, 0x00}, // 7 160 | {0x7f, 0x49, 0x55, 0x49, 0x7f, 0x00}, // 8 161 | {0x7f, 0x51, 0x55, 0x41, 0x7f, 0x00}, // 9 162 | {0x3e, 0x2a, 0x3e, 0x00, 0x00, 0x00}, // : 163 | {0xe0, 0xbe, 0xda, 0x7e, 0x00, 0x00}, // ; 164 | {0x1c, 0x36, 0x6b, 0x5d, 0x77, 0x00}, // < 165 | {0x3e, 0x2a, 0x2a, 0x2a, 0x2a, 0x3e}, // = 166 | {0x77, 0x5d, 0x6b, 0x36, 0x1c, 0x00}, // > 167 | {0x07, 0x7d, 0x55, 0x71, 0x1f, 0x00}, // ? 168 | {0x7f, 0x41, 0x5d, 0x55, 0x51, 0x7f}, // @ 169 | {0x7f, 0x41, 0x75, 0x41, 0x7f, 0x00}, // A 170 | {0x7f, 0x41, 0x55, 0x41, 0x7f, 0x00}, // B 171 | {0x7f, 0x41, 0x5d, 0x55, 0x77, 0x00}, // C 172 | {0x7f, 0x41, 0x5d, 0x63, 0x3e, 0x00}, // D 173 | {0x7f, 0x41, 0x55, 0x55, 0x7f, 0x00}, // E 174 | {0x7f, 0x41, 0x75, 0x15, 0x1f, 0x00}, // F 175 | {0x7f, 0x41, 0x5d, 0x45, 0x7f, 0x00}, // G 176 | {0x7f, 0x41, 0x77, 0x41, 0x7f, 0x00}, // H 177 | {0x7f, 0x41, 0x7f, 0x00, 0x00, 0x00}, // I 178 | {0x78, 0x48, 0x5f, 0x41, 0x7f, 0x00}, // J 179 | {0x7f, 0x41, 0x77, 0x49, 0x7f, 0x00}, // K 180 | {0x7f, 0x41, 0x5f, 0x50, 0x70, 0x00}, // L 181 | {0x7f, 0x41, 0x3b, 0x3b, 0x41, 0x7f}, // M 182 | {0x7f, 0x41, 0x3b, 0x76, 0x41, 0x7f}, // N 183 | {0x7f, 0x41, 0x5d, 0x41, 0x7f, 0x00}, // O 184 | {0x7f, 0x41, 0x75, 0x11, 0x1f, 0x00}, // P 185 | {0x7f, 0x41, 0x1d, 0x41, 0x7f, 0x00}, // Q 186 | {0x7f, 0x41, 0x6d, 0x51, 0x6f, 0x00}, // R 187 | {0x7f, 0x51, 0x55, 0x45, 0x7f, 0x00}, // S 188 | {0x07, 0x7d, 0x41, 0x7d, 0x07, 0x00}, // T 189 | {0x7f, 0x41, 0x5f, 0x41, 0x7f, 0x00}, // U 190 | {0x3f, 0x61, 0x5f, 0x61, 0x3f, 0x00}, // V 191 | {0x7f, 0x41, 0x6e, 0x6e, 0x41, 0x7f}, // W 192 | {0x7f, 0x49, 0x77, 0x49, 0x7f, 0x00}, // X 193 | {0x1f, 0x71, 0x47, 0x71, 0x1f, 0x00}, // Y 194 | {0x7b, 0x4d, 0x55, 0x59, 0x6f, 0x00}, // Z 195 | {0xff, 0x80, 0xbe, 0xe3, 0x00, 0x00}, // [ 196 | {0x0f, 0x19, 0x77, 0x4c, 0x78, 0x00}, // "\" 197 | {0xe3, 0xbe, 0x80, 0xff, 0x00, 0x00}, // ] 198 | {0x0e, 0x0b, 0x0d, 0x0b, 0x0e, 0x00}, // ^ 199 | {0xe0, 0xa0, 0xa0, 0xa0, 0xa0, 0xe0}, // _ 200 | {0x07, 0x0d, 0x0b, 0x0e, 0x00, 0x00}, // ` 201 | {0x7f, 0x41, 0x75, 0x41, 0x7f, 0x00}, // a 202 | {0x7f, 0x41, 0x55, 0x41, 0x7f, 0x00}, // b 203 | {0x7f, 0x41, 0x5d, 0x55, 0x77, 0x00}, // c 204 | {0x7f, 0x41, 0x5d, 0x63, 0x3e, 0x00}, // d 205 | {0x7f, 0x41, 0x55, 0x55, 0x7f, 0x00}, // e 206 | {0x7f, 0x41, 0x75, 0x15, 0x1f, 0x00}, // f 207 | {0x7f, 0x41, 0x5d, 0x45, 0x7f, 0x00}, // g 208 | {0x7f, 0x41, 0x77, 0x41, 0x7f, 0x00}, // h 209 | {0x7f, 0x41, 0x7f, 0x00, 0x00, 0x00}, // i 210 | {0x78, 0x48, 0x5f, 0x41, 0x7f, 0x00}, // j 211 | {0x7f, 0x41, 0x77, 0x49, 0x7f, 0x00}, // k 212 | {0x7f, 0x41, 0x5f, 0x50, 0x70, 0x00}, // l 213 | {0x7f, 0x41, 0x3b, 0x3b, 0x41, 0x7f}, // m 214 | {0x7f, 0x41, 0x3b, 0x76, 0x41, 0x7f}, // n 215 | {0x7f, 0x41, 0x5d, 0x41, 0x7f, 0x00}, // o 216 | {0x7f, 0x41, 0x75, 0x11, 0x1f, 0x00}, // p 217 | {0x7f, 0x41, 0x1d, 0x41, 0x7f, 0x00}, // q 218 | {0x7f, 0x41, 0x6d, 0x51, 0x6f, 0x00}, // r 219 | {0x7f, 0x51, 0x55, 0x45, 0x7f, 0x00}, // s 220 | {0x07, 0x7d, 0x41, 0x7d, 0x07, 0x00}, // t 221 | {0x7f, 0x41, 0x5f, 0x41, 0x7f, 0x00}, // u 222 | {0x3f, 0x61, 0x5f, 0x61, 0x3f, 0x00}, // v 223 | {0x7f, 0x41, 0x6e, 0x6e, 0x41, 0x7f}, // w 224 | {0x7f, 0x49, 0x77, 0x49, 0x7f, 0x00}, // x 225 | {0x1f, 0x71, 0x47, 0x71, 0x1f, 0x00}, // y 226 | {0x7b, 0x4d, 0x55, 0x59, 0x6f, 0x00}, // z 227 | {0x1c, 0xf7, 0x88, 0xbe, 0xe3, 0x00}, // { 228 | {0xff, 0x80, 0xff, 0x00, 0x00, 0x00}, // | 229 | {0xe3, 0xbe, 0x88, 0xf7, 0x1c, 0x00}, // } 230 | {0x0f, 0x09, 0x0d, 0x09, 0x0b, 0x09}, // ~ 231 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 232 | }; 233 | 234 | public static char[][] fontAztech = { 235 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 236 | {0x00, 0x2e, 0x00, 0x00, 0x00, 0x00}, // ! 237 | {0x00, 0x02, 0x00, 0x02, 0x00, 0x00}, // " 238 | {0x00, 0x0a, 0x1e, 0x0a, 0x1e, 0x00}, // # 239 | {0x00, 0x0e, 0x2a, 0x6b, 0x2a, 0x3a}, // $ 240 | {0x00, 0x06, 0x06, 0x26, 0x18, 0x06}, // % 241 | {0x38, 0x3e, 0x2a, 0x2a, 0x28, 0x38}, // & 242 | {0x18, 0x02, 0x00, 0x00, 0x00, 0x00}, // ' 243 | {0x00, 0x3e, 0x22, 0x00, 0x00, 0x00}, // ( 244 | {0x00, 0x22, 0x3e, 0x00, 0x00, 0x00}, // ) 245 | {0x00, 0x0e, 0x0e, 0x0e, 0x04, 0x00}, // * 246 | {0x00, 0x08, 0x1c, 0x08, 0x00, 0x00}, // + 247 | {0x00, 0x20, 0x00, 0x00, 0x00, 0x00}, // , 248 | {0x00, 0x08, 0x08, 0x08, 0x00, 0x00}, // - 249 | {0x00, 0x20, 0x00, 0x00, 0x00, 0x00}, // . 250 | {0x00, 0x20, 0x18, 0x06, 0x00, 0x00}, // / 251 | {0x00, 0x3e, 0x22, 0x2a, 0x22, 0x3e}, // 0 252 | {0x02, 0x3e, 0x00, 0x00, 0x00, 0x00}, // 1 253 | {0x00, 0x38, 0x28, 0x2a, 0x2a, 0x2e}, // 2 254 | {0x00, 0x22, 0x2a, 0x2e, 0x38, 0x00}, // 3 255 | {0x00, 0x0e, 0x08, 0x08, 0x3e, 0x08}, // 4 256 | {0x00, 0x2e, 0x2a, 0x2a, 0x28, 0x38}, // 5 257 | {0x00, 0x3e, 0x2a, 0x2a, 0x28, 0x38}, // 6 258 | {0x00, 0x06, 0x02, 0x02, 0x0a, 0x3e}, // 7 259 | {0x00, 0x38, 0x2e, 0x2a, 0x2e, 0x38}, // 8 260 | {0x00, 0x0e, 0x0a, 0x2a, 0x2a, 0x3e}, // 9 261 | {0x00, 0x28, 0x00, 0x00, 0x00, 0x00}, // : 262 | {0x00, 0x28, 0x00, 0x00, 0x00, 0x00}, // ; 263 | {0x00, 0x08, 0x14, 0x22, 0x00, 0x00}, // < 264 | {0x00, 0x14, 0x14, 0x14, 0x14, 0x00}, // = 265 | {0x00, 0x22, 0x14, 0x08, 0x00, 0x00}, // > 266 | {0x00, 0x06, 0x02, 0x2a, 0x0a, 0x06}, // ? 267 | {0x00, 0x3e, 0x02, 0x3a, 0x2a, 0x0a}, // @ 268 | {0x22, 0x3e, 0x02, 0x0a, 0x0a, 0x3e}, // A 269 | {0x00, 0x3e, 0x22, 0x2a, 0x2e, 0x38}, // B 270 | {0x00, 0x3e, 0x22, 0x22, 0x20, 0x30}, // C 271 | {0x00, 0x3e, 0x22, 0x22, 0x22, 0x3c}, // D 272 | {0x00, 0x3e, 0x2a, 0x22, 0x20, 0x30}, // E 273 | {0x00, 0x3e, 0x0a, 0x0a, 0x06, 0x02}, // F 274 | {0x00, 0x3e, 0x22, 0x2a, 0x28, 0x38}, // G 275 | {0x00, 0x3e, 0x08, 0x08, 0x08, 0x3e}, // H 276 | {0x00, 0x22, 0x3e, 0x22, 0x00, 0x00}, // I 277 | {0x00, 0x30, 0x20, 0x20, 0x22, 0x3e}, // J 278 | {0x00, 0x3e, 0x08, 0x08, 0x0e, 0x38}, // K 279 | {0x00, 0x3e, 0x20, 0x20, 0x20, 0x30}, // L 280 | {0x00, 0x3e, 0x02, 0x3e, 0x20, 0x3e}, // M 281 | {0x3e, 0x3e, 0x02, 0x3e, 0x20, 0x3e}, // N 282 | {0x00, 0x3e, 0x22, 0x22, 0x22, 0x3e}, // O 283 | {0x00, 0x3e, 0x02, 0x0a, 0x0a, 0x0e}, // P 284 | {0x00, 0x3e, 0x22, 0x22, 0x22, 0x3e}, // Q 285 | {0x00, 0x3e, 0x02, 0x0a, 0x0e, 0x38}, // R 286 | {0x00, 0x0e, 0x0a, 0x2a, 0x2a, 0x3a}, // S 287 | {0x00, 0x06, 0x02, 0x3e, 0x02, 0x06}, // T 288 | {0x00, 0x3e, 0x20, 0x20, 0x20, 0x3e}, // U 289 | {0x00, 0x3e, 0x20, 0x20, 0x3e, 0x00}, // V 290 | {0x00, 0x3e, 0x20, 0x3e, 0x02, 0x3e}, // W 291 | {0x3e, 0x3a, 0x0e, 0x08, 0x0e, 0x3a}, // X 292 | {0x00, 0x0e, 0x08, 0x08, 0x28, 0x3e}, // Y 293 | {0x00, 0x3a, 0x2a, 0x2a, 0x0a, 0x0e}, // Z 294 | {0x00, 0x3e, 0x22, 0x00, 0x00, 0x00}, // [ 295 | {0x00, 0x02, 0x0c, 0x30, 0x00, 0x00}, // "\" 296 | {0x22, 0x3e, 0x00, 0x00, 0x00, 0x00}, // ] 297 | {0x00, 0x01, 0x00, 0x01, 0x00, 0x00}, // ^ 298 | {0x00, 0x20, 0x20, 0x20, 0x00, 0x00}, // _ 299 | {0x00, 0x01, 0x00, 0x00, 0x00, 0x00}, // ` 300 | {0x00, 0x38, 0x28, 0x28, 0x08, 0x38}, // a 301 | {0x00, 0x3e, 0x20, 0x28, 0x28, 0x38}, // b 302 | {0x00, 0x38, 0x28, 0x28, 0x20, 0x30}, // c 303 | {0x00, 0x38, 0x28, 0x28, 0x20, 0x3e}, // d 304 | {0x00, 0xf8, 0x88, 0x28, 0x28, 0x38}, // e 305 | {0x00, 0xf8, 0x28, 0x28, 0x18, 0x08}, // f 306 | {0x00, 0x38, 0x28, 0xa8, 0x88, 0xf8}, // g 307 | {0x00, 0x3c, 0x08, 0x08, 0x08, 0x38}, // h 308 | {0x00, 0x3a, 0x00, 0x00, 0x00, 0x00}, // i 309 | {0x80, 0xfa, 0x00, 0x00, 0x00, 0x00}, // j 310 | {0x00, 0x3e, 0x08, 0x08, 0x38, 0x2c}, // k 311 | {0x00, 0x3e, 0x20, 0x00, 0x00, 0x00}, // l 312 | {0x00, 0x38, 0x08, 0x38, 0x20, 0x38}, // m 313 | {0x38, 0x38, 0x08, 0x38, 0x20, 0x38}, // n 314 | {0x00, 0x38, 0x28, 0x28, 0x28, 0x38}, // o 315 | {0x00, 0xf8, 0x08, 0x28, 0x28, 0x38}, // p 316 | {0x00, 0x38, 0x28, 0x28, 0x08, 0xf8}, // q 317 | {0x00, 0x38, 0x08, 0x08, 0x18, 0x08}, // r 318 | {0x00, 0x38, 0x28, 0xa8, 0xa8, 0xe8}, // s 319 | {0x00, 0x3e, 0x28, 0x28, 0x20, 0x30}, // t 320 | {0x00, 0x38, 0x20, 0x20, 0x20, 0x38}, // u 321 | {0x00, 0x38, 0x20, 0x38, 0x00, 0x00}, // v 322 | {0x00, 0x38, 0x20, 0x38, 0x08, 0x38}, // w 323 | {0x38, 0x28, 0x38, 0x10, 0x38, 0x28}, // x 324 | {0x00, 0x38, 0x20, 0xa0, 0xa0, 0xf8}, // y 325 | {0x00, 0xe8, 0xa8, 0xa8, 0x28, 0x38}, // z 326 | {0x08, 0x3e, 0x22, 0x00, 0x00, 0x00}, // { 327 | {0x00, 0x3f, 0x00, 0x00, 0x00, 0x00}, // | 328 | {0x22, 0x3e, 0x08, 0x00, 0x00, 0x00}, // } 329 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ~ 330 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 331 | }; 332 | 333 | public static char[][] fontBlokus = { 334 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 335 | {0x00, 0x00, 0x5e, 0x00, 0x00, 0x00}, // ! 336 | {0x00, 0x0e, 0x00, 0x0e, 0x00, 0x00}, // " 337 | {0xd0, 0x70, 0xdc, 0x70, 0x58, 0x00}, // # 338 | {0x26, 0x4a, 0xff, 0x52, 0x22, 0x00}, // $ 339 | {0x00, 0x46, 0x2a, 0x1a, 0x0e, 0x04}, // % 340 | {0x7e, 0x76, 0x42, 0x45, 0x6b, 0x51}, // & 341 | {0x00, 0x00, 0x0e, 0x02, 0x00, 0x00}, // ' 342 | {0x00, 0x7e, 0x81, 0x00, 0x00, 0x00}, // ( 343 | {0x00, 0x81, 0x7e, 0x00, 0x00, 0x00}, // ) 344 | {0x00, 0x1c, 0x00, 0x00, 0x00, 0x00}, // * 345 | {0x00, 0x20, 0x7c, 0x20, 0x00, 0x00}, // + 346 | {0x00, 0x00, 0x80, 0x60, 0x00, 0x00}, // , 347 | {0x00, 0x10, 0x10, 0x10, 0x00, 0x00}, // - 348 | {0x00, 0x40, 0x00, 0x00, 0x00, 0x00}, // . 349 | {0x00, 0xfe, 0x00, 0x00, 0x00, 0x00}, // / 350 | {0x00, 0x30, 0x48, 0x48, 0x30, 0x00}, // 0 351 | {0x10, 0x48, 0x78, 0x40, 0x00, 0x00}, // 1 352 | {0x00, 0x42, 0x62, 0x52, 0x4a, 0x46}, // 2 353 | {0x00, 0x88, 0x28, 0x38, 0xc0, 0x00}, // 3 354 | {0x00, 0x20, 0x50, 0x48, 0x48, 0xe0}, // 4 355 | {0xf0, 0x28, 0x28, 0xc8, 0x48, 0x00}, // 5 356 | {0x00, 0x38, 0x4c, 0x46, 0x26, 0x1a}, // 6 357 | {0x08, 0x88, 0x48, 0x28, 0x18, 0x08}, // 7 358 | {0x14, 0x2a, 0x46, 0x2a, 0x14, 0x00}, // 8 359 | {0x00, 0x30, 0x48, 0x48, 0xa8, 0x78}, // 9 360 | {0x00, 0x00, 0x48, 0x00, 0x00, 0x00}, // : 361 | {0x00, 0x00, 0x80, 0x68, 0x00, 0x00}, // ; 362 | {0x08, 0x14, 0x22, 0x41, 0x00, 0x00}, // < 363 | {0x00, 0x30, 0x30, 0x30, 0x30, 0x00}, // = 364 | {0x41, 0x22, 0x14, 0x08, 0x00, 0x00}, // > 365 | {0x00, 0x02, 0x52, 0x0a, 0x06, 0x00}, // ? 366 | {0x00, 0x38, 0x44, 0x42, 0xa2, 0xbc}, // @ 367 | {0x20, 0x40, 0x62, 0x14, 0x12, 0x14}, // A 368 | {0x62, 0x7e, 0x4a, 0x4a, 0x34, 0x00}, // B 369 | {0x1c, 0x22, 0x42, 0x42, 0x42, 0x24}, // C 370 | {0x42, 0x7e, 0x42, 0x42, 0x24, 0x18}, // D 371 | {0x42, 0x7e, 0x4a, 0x4a, 0x42, 0x00}, // E 372 | {0x00, 0x42, 0x7e, 0x0a, 0x02, 0x00}, // F 373 | {0x1c, 0x22, 0x42, 0x52, 0xe4, 0x00}, // G 374 | {0x00, 0x42, 0x7e, 0x08, 0x7e, 0x42}, // H 375 | {0x00, 0x42, 0x7e, 0x42, 0x00, 0x00}, // I 376 | {0x02, 0x82, 0x7e, 0x02, 0x00, 0x00}, // J 377 | {0x00, 0x42, 0x7e, 0x08, 0x08, 0x16}, // K 378 | {0x00, 0x42, 0x7e, 0x40, 0x60, 0x00}, // L 379 | {0x00, 0x7e, 0x44, 0x08, 0x10, 0x08}, // M 380 | {0x00, 0x7e, 0x42, 0x04, 0x08, 0x08}, // N 381 | {0x7e, 0x24, 0x42, 0x42, 0x24, 0x18}, // O 382 | {0x02, 0x7e, 0x52, 0x12, 0x0c, 0x00}, // P 383 | {0x18, 0x24, 0x42, 0x42, 0xa4, 0x18}, // Q 384 | {0x42, 0x7e, 0x46, 0x0e, 0x16, 0x20}, // R 385 | {0xf3, 0xc6, 0x46, 0x4a, 0x37, 0x00}, // S 386 | {0x02, 0x02, 0x7e, 0x02, 0x02, 0x00}, // T 387 | {0x00, 0x02, 0x3e, 0x40, 0x3e, 0x02}, // U 388 | {0x02, 0x1e, 0x20, 0x40, 0x20, 0x12}, // V 389 | {0x02, 0x0e, 0x20, 0x40, 0x22, 0x1e}, // W 390 | {0x42, 0x66, 0x1a, 0x1e, 0x66, 0x42}, // X 391 | {0x02, 0x0a, 0x50, 0x60, 0x50, 0x0a}, // Y 392 | {0x02, 0x42, 0x62, 0x4a, 0x42, 0x20}, // Z 393 | {0x00, 0x00, 0xfe, 0x82, 0x00, 0x00}, // [ 394 | {0x00, 0xfe, 0x00, 0x00, 0x00, 0x00}, // "\" 395 | {0x00, 0x82, 0xfe, 0x00, 0x00, 0x00}, // ] 396 | {0x00, 0x1c, 0x06, 0x18, 0x00, 0x00}, // ^ 397 | {0x80, 0x80, 0x80, 0x80, 0x80, 0x00}, // _ 398 | {0x00, 0x00, 0x02, 0x00, 0x00, 0x00}, // ` 399 | {0x28, 0x58, 0x58, 0x78, 0x40, 0x00}, // a 400 | {0x40, 0x3f, 0x48, 0x48, 0x38, 0x00}, // b 401 | {0x30, 0x48, 0x48, 0x30, 0x00, 0x00}, // c 402 | {0x38, 0x48, 0x48, 0x3f, 0x40, 0x00}, // d 403 | {0x30, 0x68, 0x68, 0x30, 0x00, 0x00}, // e 404 | {0x48, 0x7f, 0x09, 0x02, 0x00, 0x00}, // f 405 | {0x98, 0x68, 0x68, 0x58, 0x84, 0x00}, // g 406 | {0x40, 0x7f, 0x08, 0x48, 0x78, 0x40}, // h 407 | {0x00, 0x78, 0x40, 0x00, 0x00, 0x00}, // i 408 | {0x08, 0xfa, 0x08, 0x00, 0x00, 0x00}, // j 409 | {0x40, 0x7f, 0x08, 0x14, 0x28, 0x48}, // k 410 | {0x7e, 0x40, 0x00, 0x00, 0x00, 0x00}, // l 411 | {0x48, 0x78, 0x48, 0x78, 0x48, 0x78}, // m 412 | {0x48, 0x78, 0x08, 0x48, 0x78, 0x40}, // n 413 | {0x30, 0x48, 0x48, 0x30, 0x00, 0x00}, // o 414 | {0x08, 0xf0, 0x48, 0x48, 0x30, 0x00}, // p 415 | {0x30, 0x48, 0x48, 0xf0, 0x08, 0x00}, // q 416 | {0x40, 0x78, 0x00, 0x08, 0x00, 0x00}, // r 417 | {0x30, 0x68, 0x68, 0x10, 0x00, 0x00}, // s 418 | {0x08, 0x3e, 0x48, 0x48, 0x20, 0x00}, // t 419 | {0x08, 0x78, 0x38, 0x48, 0x00, 0x00}, // u 420 | {0x18, 0x40, 0x20, 0x18, 0x08, 0x00}, // v 421 | {0x38, 0x40, 0x38, 0x40, 0x38, 0x40}, // w 422 | {0x48, 0x28, 0x10, 0x28, 0x48, 0x00}, // x 423 | {0x08, 0x38, 0x48, 0xf8, 0x00, 0x00}, // y 424 | {0x48, 0x68, 0x58, 0x48, 0x00, 0x00}, // z 425 | {0x00, 0x00, 0x10, 0x6c, 0x82, 0x00}, // { 426 | {0x00, 0x00, 0x7e, 0x00, 0x00, 0x00}, // | 427 | {0x00, 0x00, 0x82, 0x6c, 0x10, 0x00}, // } 428 | {0x00, 0x20, 0x10, 0x20, 0x10, 0x00}, // ~ 429 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 430 | }; 431 | 432 | public static char[][] fontBMplain = { 433 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 434 | {0x2e, 0x00, 0x00, 0x00, 0x00, 0x00}, // ! 435 | {0x03, 0x00, 0x03, 0x00, 0x00, 0x00}, // " 436 | {0x0a, 0x1f, 0x0a, 0x1f, 0x0a, 0x00}, // # 437 | {0x2e, 0x2a, 0x6b, 0x2a, 0x3a, 0x00}, // $ 438 | {0x0e, 0x2a, 0x1e, 0x08, 0x3c, 0x2a}, // % 439 | {0x3e, 0x2a, 0x2a, 0x22, 0x38, 0x08}, // & 440 | {0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // ' 441 | {0x1c, 0x22, 0x00, 0x00, 0x00, 0x00}, // ( 442 | {0x22, 0x1c, 0x00, 0x00, 0x00, 0x00}, // ) 443 | {0x15, 0x0e, 0x04, 0x0e, 0x15, 0x00}, // * 444 | {0x08, 0x08, 0x3e, 0x08, 0x08, 0x00}, // + 445 | {0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 446 | {0x08, 0x08, 0x08, 0x08, 0x08, 0x00}, // - 447 | {0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, // . 448 | {0x20, 0x10, 0x08, 0x04, 0x02, 0x00}, // / 449 | {0x3e, 0x22, 0x2a, 0x22, 0x3e, 0x00}, // 0 450 | {0x04, 0x3e, 0x00, 0x00, 0x00, 0x00}, // 1 451 | {0x3a, 0x2a, 0x2a, 0x2a, 0x2e, 0x00}, // 2 452 | {0x2a, 0x2a, 0x2a, 0x2a, 0x3e, 0x00}, // 3 453 | {0x0e, 0x08, 0x08, 0x08, 0x3e, 0x00}, // 4 454 | {0x2e, 0x2a, 0x2a, 0x2a, 0x3a, 0x00}, // 5 455 | {0x3e, 0x2a, 0x2a, 0x2a, 0x3a, 0x00}, // 6 456 | {0x02, 0x02, 0x02, 0x02, 0x3e, 0x00}, // 7 457 | {0x3e, 0x2a, 0x2a, 0x2a, 0x3e, 0x00}, // 8 458 | {0x2e, 0x2a, 0x2a, 0x2a, 0x3e, 0x00}, // 9 459 | {0x14, 0x00, 0x00, 0x00, 0x00, 0x00}, // : 460 | {0x34, 0x00, 0x00, 0x00, 0x00, 0x00}, // ; 461 | {0x08, 0x14, 0x22, 0x00, 0x00, 0x00}, // < 462 | {0x14, 0x14, 0x14, 0x14, 0x14, 0x00}, // = 463 | {0x22, 0x14, 0x08, 0x00, 0x00, 0x00}, // > 464 | {0x06, 0x02, 0x2a, 0x0a, 0x0e, 0x00}, // ? 465 | {0x3e, 0x02, 0x3a, 0x2a, 0x3e, 0x00}, // @ 466 | {0x3e, 0x12, 0x12, 0x12, 0x3e, 0x00}, // A 467 | {0x3e, 0x2a, 0x2a, 0x2a, 0x36, 0x00}, // B 468 | {0x3e, 0x22, 0x22, 0x22, 0x22, 0x00}, // C 469 | {0x3e, 0x22, 0x22, 0x22, 0x1c, 0x00}, // D 470 | {0x3e, 0x2a, 0x2a, 0x2a, 0x22, 0x00}, // E 471 | {0x3e, 0x0a, 0x0a, 0x0a, 0x02, 0x00}, // F 472 | {0x3e, 0x22, 0x2a, 0x2a, 0x3a, 0x00}, // G 473 | {0x3e, 0x08, 0x08, 0x08, 0x3e, 0x00}, // H 474 | {0x22, 0x3e, 0x22, 0x00, 0x00, 0x00}, // I 475 | {0x38, 0x20, 0x20, 0x20, 0x3e, 0x00}, // J 476 | {0x3e, 0x08, 0x08, 0x14, 0x22, 0x00}, // K 477 | {0x3e, 0x20, 0x20, 0x20, 0x20, 0x00}, // L 478 | {0x3e, 0x04, 0x38, 0x04, 0x3e, 0x00}, // M 479 | {0x3e, 0x04, 0x08, 0x10, 0x3e, 0x00}, // N 480 | {0x3e, 0x22, 0x22, 0x22, 0x3e, 0x00}, // O 481 | {0x3e, 0x0a, 0x0a, 0x0a, 0x0e, 0x00}, // P 482 | {0x3e, 0x22, 0x72, 0x22, 0x3e, 0x00}, // Q 483 | {0x3e, 0x0a, 0x0a, 0x1a, 0x2e, 0x00}, // R 484 | {0x2e, 0x2a, 0x2a, 0x2a, 0x3a, 0x00}, // S 485 | {0x02, 0x02, 0x3e, 0x02, 0x02, 0x00}, // T 486 | {0x1e, 0x20, 0x20, 0x20, 0x1e, 0x00}, // U 487 | {0x0e, 0x10, 0x20, 0x10, 0x0e, 0x00}, // V 488 | {0x3e, 0x10, 0x0e, 0x10, 0x3e, 0x00}, // W 489 | {0x22, 0x14, 0x08, 0x14, 0x22, 0x00}, // X 490 | {0x02, 0x04, 0x38, 0x04, 0x02, 0x00}, // Y 491 | {0x3a, 0x2a, 0x2a, 0x2a, 0x2e, 0x00}, // Z 492 | {0x3e, 0x22, 0x00, 0x00, 0x00, 0x00}, // [ 493 | {0x3f, 0x21, 0x3f, 0x00, 0x00, 0x00}, // "\" 494 | {0x22, 0x3e, 0x00, 0x00, 0x00, 0x00}, // ] 495 | {0x0c, 0x1e, 0x3c, 0x1e, 0x0c, 0x00}, // ^ 496 | {0x20, 0x20, 0x20, 0x20, 0x20, 0x00}, // _ 497 | {0x1c, 0x3e, 0x3e, 0x3e, 0x1c, 0x00}, // ` 498 | {0x3c, 0x24, 0x24, 0x24, 0x3c, 0x20}, // a 499 | {0x3e, 0x24, 0x24, 0x24, 0x3c, 0x00}, // b 500 | {0x3c, 0x24, 0x24, 0x24, 0x24, 0x00}, // c 501 | {0x3c, 0x24, 0x24, 0x24, 0x3e, 0x00}, // d 502 | {0x3c, 0x24, 0x34, 0x2c, 0x24, 0x00}, // e 503 | {0x08, 0x3e, 0x0a, 0x0a, 0x00, 0x00}, // f 504 | {0x1c, 0x54, 0x54, 0x54, 0x7c, 0x00}, // g 505 | {0x3e, 0x04, 0x04, 0x04, 0x3c, 0x00}, // h 506 | {0x3a, 0x00, 0x00, 0x00, 0x00, 0x00}, // i 507 | {0x7a, 0x00, 0x00, 0x00, 0x00, 0x00}, // j 508 | {0x3e, 0x08, 0x14, 0x22, 0x00, 0x00}, // k 509 | {0x02, 0x3e, 0x00, 0x00, 0x00, 0x00}, // l 510 | {0x3c, 0x04, 0x3c, 0x04, 0x3c, 0x00}, // m 511 | {0x3c, 0x04, 0x04, 0x04, 0x3c, 0x00}, // n 512 | {0x3c, 0x24, 0x24, 0x24, 0x3c, 0x00}, // o 513 | {0x7c, 0x24, 0x24, 0x24, 0x3c, 0x00}, // p 514 | {0x3c, 0x24, 0x24, 0x24, 0x7c, 0x00}, // q 515 | {0x3c, 0x04, 0x04, 0x04, 0x00, 0x00}, // r 516 | {0x24, 0x2c, 0x34, 0x24, 0x00, 0x00}, // s 517 | {0x04, 0x3e, 0x24, 0x24, 0x00, 0x00}, // t 518 | {0x3c, 0x20, 0x20, 0x20, 0x3c, 0x00}, // u 519 | {0x0c, 0x10, 0x20, 0x10, 0x0c, 0x00}, // v 520 | {0x3c, 0x20, 0x3c, 0x20, 0x3c, 0x00}, // w 521 | {0x24, 0x24, 0x18, 0x24, 0x24, 0x00}, // x 522 | {0x1c, 0x50, 0x50, 0x50, 0x7c, 0x00}, // y 523 | {0x24, 0x34, 0x2c, 0x24, 0x00, 0x00}, // z 524 | {0x08, 0x3e, 0x22, 0x00, 0x00, 0x00}, // { 525 | {0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00}, // | 526 | {0x22, 0x3e, 0x08, 0x00, 0x00, 0x00}, // } 527 | {0x01, 0x01, 0x01, 0x00, 0x00, 0x00}, // ~ 528 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 529 | }; 530 | 531 | public static char[][] fontCrackers = { 532 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 533 | {0x5e, 0x06, 0x06, 0x00, 0x00, 0x00}, // ! 534 | {0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00}, // " 535 | {0x20, 0x7c, 0x38, 0x38, 0x7c, 0x08}, // # 536 | {0x48, 0xfe, 0x64, 0x64, 0x00, 0x00}, // $ 537 | {0x64, 0x60, 0x60, 0x18, 0x0c, 0x0c}, // % 538 | {0x74, 0x4a, 0x4a, 0x7e, 0x48, 0x00}, // & 539 | {0x1e, 0x00, 0x00, 0x00, 0x00, 0x00}, // ' 540 | {0x3c, 0x7e, 0x7e, 0x42, 0x00, 0x00}, // ( 541 | {0x42, 0x7e, 0x7e, 0x3c, 0x00, 0x00}, // ) 542 | {0x04, 0x0c, 0x04, 0x06, 0x0c, 0x04}, // * 543 | {0x10, 0x3c, 0x3c, 0x3c, 0x10, 0x00}, // + 544 | {0x00, 0x60, 0xe0, 0x00, 0x00, 0x00}, // , 545 | {0x08, 0x08, 0x08, 0x00, 0x00, 0x00}, // - 546 | {0x60, 0x60, 0x60, 0x00, 0x00, 0x00}, // . 547 | {0x60, 0x78, 0x78, 0x1e, 0x06, 0x00}, // / 548 | {0x3c, 0x3c, 0x7e, 0x42, 0x7e, 0x7e}, // 0 549 | {0x04, 0x7e, 0x7e, 0x7e, 0x00, 0x00}, // 1 550 | {0x76, 0x7a, 0x7e, 0x7e, 0x4c, 0x00}, // 2 551 | {0x4a, 0x7e, 0x7e, 0x7c, 0x00, 0x00}, // 3 552 | {0x0e, 0x08, 0x7e, 0x7e, 0x7e, 0x00}, // 4 553 | {0x4e, 0x4e, 0x4e, 0x7a, 0x1a, 0x00}, // 5 554 | {0x3c, 0x7e, 0x7e, 0x4a, 0x7a, 0x00}, // 6 555 | {0x02, 0x02, 0x0a, 0x7e, 0x7e, 0x7e}, // 7 556 | {0x7e, 0x7e, 0x7e, 0x4a, 0x7e, 0x00}, // 8 557 | {0x0c, 0x4a, 0x7e, 0x7e, 0x3c, 0x00}, // 9 558 | {0x66, 0x66, 0x66, 0x00, 0x00, 0x00}, // : 559 | {0x66, 0xe6, 0x00, 0x00, 0x00, 0x00}, // ; 560 | {0x08, 0x3c, 0x7e, 0x7e, 0x62, 0x00}, // < 561 | {0x14, 0x14, 0x14, 0x00, 0x00, 0x00}, // = 562 | {0x62, 0x7e, 0x7e, 0x3c, 0x08, 0x00}, // > 563 | {0x02, 0x4a, 0x0e, 0x0e, 0x0c, 0x00}, // ? 564 | {0x3c, 0x7e, 0x7e, 0x4a, 0x72, 0x30}, // @ 565 | {0x7a, 0x4a, 0x7e, 0x7e, 0x7c, 0x00}, // A 566 | {0x7e, 0x7e, 0x7e, 0x4a, 0x24, 0x00}, // B 567 | {0x3c, 0x7e, 0x7e, 0x7e, 0x46, 0x00}, // C 568 | {0x7e, 0x7e, 0x7e, 0x62, 0x3c, 0x00}, // D 569 | {0x7e, 0x7e, 0x7e, 0x4a, 0x00, 0x00}, // E 570 | {0x7e, 0x7e, 0x7e, 0x0a, 0x00, 0x00}, // F 571 | {0x3c, 0x7e, 0x7e, 0x42, 0x62, 0x00}, // G 572 | {0x7e, 0x7e, 0x7e, 0x18, 0x7e, 0x00}, // H 573 | {0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00}, // I 574 | {0x40, 0x7e, 0x7e, 0x7e, 0x00, 0x00}, // J 575 | {0x7e, 0x7e, 0x7e, 0x3c, 0x66, 0x00}, // K 576 | {0x7e, 0x7e, 0x7e, 0x40, 0x00, 0x00}, // L 577 | {0x7e, 0x3e, 0x3e, 0x7c, 0x3e, 0x3e}, // M 578 | {0x7e, 0x3e, 0x7e, 0x7c, 0x7e, 0x00}, // N 579 | {0x3c, 0x3c, 0x7e, 0x62, 0x7e, 0x7e}, // O 580 | {0x7e, 0x7e, 0x7e, 0x22, 0x0c, 0x00}, // P 581 | {0x3c, 0x7e, 0x7e, 0x62, 0x7e, 0x7c}, // Q 582 | {0x7e, 0x7e, 0x7e, 0x0a, 0x64, 0x00}, // R 583 | {0x4c, 0x4e, 0x4e, 0x7a, 0x1a, 0x00}, // S 584 | {0x02, 0x7e, 0x7e, 0x7e, 0x02, 0x00}, // T 585 | {0x7e, 0x60, 0x7e, 0x7e, 0x7e, 0x00}, // U 586 | {0x3e, 0x60, 0x7e, 0x7e, 0x3e, 0x00}, // V 587 | {0x7e, 0x7c, 0x7c, 0x3e, 0x7c, 0x7c}, // W 588 | {0x46, 0x7e, 0x08, 0x7e, 0x62, 0x62}, // X 589 | {0x5e, 0x5e, 0x5e, 0x70, 0x3e, 0x00}, // Y 590 | {0x66, 0x7a, 0x7a, 0x5e, 0x66, 0x00}, // Z 591 | {0x7e, 0x7e, 0x7e, 0x42, 0x00, 0x00}, // [ 592 | {0x06, 0x1e, 0x1e, 0x78, 0x60, 0x00}, // "\" 593 | {0x42, 0x7e, 0x7e, 0x7e, 0x00, 0x00}, // ] 594 | {0x0c, 0x06, 0x0c, 0x00, 0x00, 0x00}, // ^ 595 | {0x40, 0x40, 0x40, 0x40, 0x40, 0x00}, // _ 596 | {0x02, 0x06, 0x06, 0x04, 0x00, 0x00}, // ` 597 | {0x78, 0x24, 0x7c, 0x7c, 0x78, 0x00}, // a 598 | {0x7c, 0x7c, 0x7c, 0x48, 0x20, 0x00}, // b 599 | {0x18, 0x7c, 0x7c, 0x7c, 0x4c, 0x00}, // c 600 | {0x20, 0x48, 0x7c, 0x7c, 0x7c, 0x00}, // d 601 | {0x18, 0x7c, 0x7c, 0x74, 0x4c, 0x00}, // e 602 | {0x78, 0x7c, 0x7c, 0x24, 0x00, 0x00}, // f 603 | {0x18, 0x7c, 0x7c, 0x44, 0x74, 0x00}, // g 604 | {0x7c, 0x7c, 0x7c, 0x08, 0x60, 0x00}, // h 605 | {0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00}, // i 606 | {0x40, 0x7c, 0x7c, 0x7c, 0x00, 0x00}, // j 607 | {0x7c, 0x7c, 0x7c, 0x20, 0x48, 0x00}, // k 608 | {0x7c, 0x7c, 0x7c, 0x40, 0x00, 0x00}, // l 609 | {0x7c, 0x3c, 0x3c, 0x78, 0x3c, 0x3c}, // m 610 | {0x7c, 0x7c, 0x7c, 0x04, 0x78, 0x00}, // n 611 | {0x18, 0x18, 0x7c, 0x44, 0x7c, 0x7c}, // o 612 | {0x7c, 0x7c, 0x7c, 0x24, 0x08, 0x00}, // p 613 | {0x18, 0x18, 0x7c, 0x44, 0x7c, 0x7c}, // q 614 | {0x7c, 0x7c, 0x7c, 0x04, 0x00, 0x00}, // r 615 | {0x5c, 0x7c, 0x7c, 0x74, 0x00, 0x00}, // s 616 | {0x08, 0x7c, 0x7c, 0x7c, 0x48, 0x00}, // t 617 | {0x7c, 0x60, 0x7c, 0x7c, 0x7c, 0x00}, // u 618 | {0x3c, 0x60, 0x7c, 0x7c, 0x3c, 0x00}, // v 619 | {0x7c, 0x78, 0x78, 0x3c, 0x78, 0x78}, // w 620 | {0x4c, 0x3c, 0x3c, 0x78, 0x64, 0x00}, // x 621 | {0x4c, 0x4c, 0x4c, 0x78, 0x3c, 0x00}, // y 622 | {0x5c, 0x74, 0x44, 0x5c, 0x74, 0x00}, // z 623 | {0x24, 0x7e, 0x42, 0x42, 0x00, 0x00}, // { 624 | {0x7e, 0x00, 0x00, 0x00, 0x00, 0x00}, // | 625 | {0x42, 0x7e, 0x24, 0x00, 0x00, 0x00}, // } 626 | {0x04, 0x06, 0x06, 0x02, 0x04, 0x06}, // ~ 627 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 628 | }; 629 | 630 | public static char[][] fontSuperDig = { 631 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 632 | {0x58, 0x5c, 0x00, 0x00, 0x00, 0x00}, // ! 633 | {0x00, 0x01, 0x00, 0x00, 0x01, 0x00}, // " 634 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // # 635 | {0x5c, 0xfe, 0x54, 0xfe, 0x74, 0x00}, // $ 636 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // % 637 | {0x70, 0x5c, 0x54, 0x74, 0x7c, 0x50}, // & 638 | {0x00, 0x01, 0x00, 0x00, 0x00, 0x00}, // ' 639 | {0x70, 0x7c, 0x44, 0x00, 0x00, 0x00}, // ( 640 | {0x44, 0x7c, 0x70, 0x00, 0x00, 0x00}, // ) 641 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // * 642 | {0x10, 0x10, 0x70, 0x7c, 0x10, 0x00}, // + 643 | {0x40, 0xc0, 0x00, 0x00, 0x00, 0x00}, // , 644 | {0x10, 0x10, 0x10, 0x10, 0x00, 0x00}, // - 645 | {0x40, 0x40, 0x00, 0x00, 0x00, 0x00}, // . 646 | {0x70, 0x7c, 0x03, 0x00, 0x00, 0x00}, // / 647 | {0x7c, 0x44, 0x44, 0x44, 0x7c, 0x1c}, // 0 648 | {0x04, 0x04, 0x7c, 0x1c, 0x00, 0x00}, // 1 649 | {0x74, 0x74, 0x54, 0x54, 0x5c, 0x00}, // 2 650 | {0x44, 0x54, 0x54, 0x54, 0x7c, 0x70}, // 3 651 | {0x1c, 0x10, 0x10, 0x7c, 0x7c, 0x00}, // 4 652 | {0x5c, 0x5c, 0x54, 0x54, 0x74, 0x00}, // 5 653 | {0x70, 0x7c, 0x54, 0x54, 0x74, 0x00}, // 6 654 | {0x04, 0x14, 0x14, 0x14, 0x7c, 0x70}, // 7 655 | {0x70, 0x5c, 0x54, 0x74, 0x7c, 0x00}, // 8 656 | {0x5c, 0x54, 0x54, 0x54, 0x7c, 0x1c}, // 9 657 | {0x50, 0x50, 0x00, 0x00, 0x00, 0x00}, // : 658 | {0x50, 0xd0, 0x00, 0x00, 0x00, 0x00}, // ; 659 | {0x18, 0x18, 0x24, 0x42, 0x00, 0x00}, // < 660 | {0x28, 0x28, 0x28, 0x28, 0x00, 0x00}, // = 661 | {0x42, 0x24, 0x18, 0x18, 0x00, 0x00}, // > 662 | {0x04, 0x14, 0x54, 0x54, 0x1c, 0x1c}, // ? 663 | {0xf8, 0x04, 0x74, 0x74, 0x54, 0x54}, // @ 664 | {0x70, 0x7c, 0x14, 0x14, 0x3c, 0x00}, // A 665 | {0x7c, 0x74, 0x54, 0x54, 0x7c, 0x00}, // B 666 | {0x70, 0x7c, 0x44, 0x44, 0x44, 0x44}, // C 667 | {0x70, 0x7c, 0x44, 0x44, 0x48, 0x70}, // D 668 | {0x70, 0x7c, 0x54, 0x54, 0x54, 0x44}, // E 669 | {0x70, 0x7c, 0x14, 0x14, 0x14, 0x04}, // F 670 | {0x70, 0x7c, 0x44, 0x44, 0x54, 0x74}, // G 671 | {0x70, 0x7c, 0x10, 0x10, 0x7c, 0x00}, // H 672 | {0x70, 0x7c, 0x00, 0x00, 0x00, 0x00}, // I 673 | {0x60, 0x40, 0x40, 0x40, 0x7c, 0x70}, // J 674 | {0x7c, 0x70, 0x10, 0x1c, 0x70, 0x00}, // K 675 | {0x70, 0x7c, 0x40, 0x40, 0x40, 0x60}, // L 676 | {0x70, 0x7c, 0x04, 0x04, 0x7c, 0x04}, // M 677 | {0x70, 0x7c, 0x04, 0x04, 0x04, 0x7c}, // N 678 | {0x70, 0x7c, 0x44, 0x44, 0x44, 0x7c}, // O 679 | {0x70, 0x7c, 0x24, 0x24, 0x3c, 0x00}, // P 680 | {0x7c, 0x44, 0x44, 0x44, 0x7c, 0x00}, // Q 681 | {0x7c, 0x74, 0x14, 0x14, 0x3c, 0x00}, // R 682 | {0x5c, 0x5c, 0x54, 0x54, 0x74, 0x00}, // S 683 | {0x04, 0x04, 0x7c, 0x74, 0x04, 0x00}, // T 684 | {0x70, 0x7c, 0x40, 0x40, 0x40, 0x7c}, // U 685 | {0x70, 0x7c, 0x40, 0x40, 0x20, 0x1c}, // V 686 | {0x70, 0x7c, 0x40, 0x40, 0x7c, 0x40}, // W 687 | {0x70, 0x7c, 0x10, 0x10, 0x3c, 0x00}, // X 688 | {0x1c, 0x10, 0x70, 0x70, 0x1c, 0x00}, // Y 689 | {0x74, 0x74, 0x54, 0x54, 0x5c, 0x00}, // Z 690 | {0xf0, 0xfe, 0x82, 0x00, 0x00, 0x00}, // [ 691 | {0x03, 0x7c, 0x70, 0x00, 0x00, 0x00}, // "\" 692 | {0x82, 0xfe, 0xf0, 0x00, 0x00, 0x00}, // ] 693 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ^ 694 | {0x40, 0x40, 0x40, 0x40, 0x00, 0x00}, // _ 695 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ` 696 | {0x70, 0x7c, 0x14, 0x14, 0x3c, 0x00}, // a 697 | {0x7c, 0x74, 0x54, 0x54, 0x7c, 0x00}, // b 698 | {0x70, 0x7c, 0x44, 0x44, 0x44, 0x44}, // c 699 | {0x70, 0x7c, 0x44, 0x44, 0x48, 0x70}, // d 700 | {0x70, 0x7c, 0x54, 0x54, 0x54, 0x44}, // e 701 | {0x70, 0x7c, 0x14, 0x14, 0x14, 0x04}, // f 702 | {0x70, 0x7c, 0x44, 0x44, 0x54, 0x74}, // g 703 | {0x70, 0x7c, 0x10, 0x10, 0x7c, 0x00}, // h 704 | {0x70, 0x7c, 0x00, 0x00, 0x00, 0x00}, // i 705 | {0x60, 0x40, 0x40, 0x40, 0x7c, 0x70}, // j 706 | {0x7c, 0x70, 0x10, 0x1c, 0x70, 0x00}, // k 707 | {0x70, 0x7c, 0x40, 0x40, 0x40, 0x60}, // l 708 | {0x70, 0x7c, 0x04, 0x04, 0x7c, 0x04}, // m 709 | {0x70, 0x7c, 0x04, 0x04, 0x04, 0x7c}, // n 710 | {0x70, 0x7c, 0x44, 0x44, 0x44, 0x7c}, // o 711 | {0x70, 0x7c, 0x24, 0x24, 0x3c, 0x00}, // p 712 | {0x7c, 0x44, 0x44, 0x44, 0x7c, 0x00}, // q 713 | {0x7c, 0x74, 0x14, 0x14, 0x3c, 0x00}, // r 714 | {0x5c, 0x5c, 0x54, 0x54, 0x74, 0x00}, // s 715 | {0x04, 0x04, 0x7c, 0x74, 0x04, 0x00}, // t 716 | {0x70, 0x7c, 0x40, 0x40, 0x40, 0x7c}, // u 717 | {0x70, 0x7c, 0x40, 0x40, 0x20, 0x1c}, // v 718 | {0x70, 0x7c, 0x40, 0x40, 0x7c, 0x40}, // w 719 | {0x70, 0x7c, 0x10, 0x10, 0x3c, 0x00}, // x 720 | {0x1c, 0x10, 0x70, 0x70, 0x1c, 0x00}, // y 721 | {0x74, 0x74, 0x54, 0x54, 0x5c, 0x00}, // z 722 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // { 723 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // | 724 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // } 725 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ~ 726 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 727 | }; 728 | 729 | public static char[][] fontZxpix = { 730 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 731 | {0x2f, 0x00, 0x00, 0x00, 0x00, 0x00}, // ! 732 | {0x03, 0x00, 0x03, 0x00, 0x00, 0x00}, // " 733 | {0x12, 0x3f, 0x12, 0x12, 0x3f, 0x12}, // # 734 | {0x2e, 0x2a, 0x7f, 0x2a, 0x3a, 0x00}, // $ 735 | {0x23, 0x13, 0x08, 0x04, 0x32, 0x31}, // % 736 | {0x10, 0x2a, 0x25, 0x2a, 0x10, 0x20}, // & 737 | {0x02, 0x01, 0x00, 0x00, 0x00, 0x00}, // ' 738 | {0x1e, 0x21, 0x00, 0x00, 0x00, 0x00}, // ( 739 | {0x21, 0x1e, 0x00, 0x00, 0x00, 0x00}, // ) 740 | {0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x08}, // * 741 | {0x08, 0x08, 0x3e, 0x08, 0x08, 0x08}, // + 742 | {0x80, 0x60, 0x00, 0x00, 0x00, 0x00}, // , 743 | {0x08, 0x08, 0x08, 0x08, 0x08, 0x00}, // - 744 | {0x30, 0x30, 0x00, 0x00, 0x00, 0x00}, // . 745 | {0x20, 0x10, 0x08, 0x04, 0x02, 0x00}, // / 746 | {0x1e, 0x31, 0x29, 0x25, 0x23, 0x1e}, // 0 747 | {0x22, 0x21, 0x3f, 0x20, 0x20, 0x20}, // 1 748 | {0x32, 0x29, 0x29, 0x29, 0x29, 0x26}, // 2 749 | {0x12, 0x21, 0x21, 0x25, 0x25, 0x1a}, // 3 750 | {0x18, 0x14, 0x12, 0x3f, 0x10, 0x10}, // 4 751 | {0x17, 0x25, 0x25, 0x25, 0x25, 0x19}, // 5 752 | {0x1e, 0x25, 0x25, 0x25, 0x25, 0x18}, // 6 753 | {0x01, 0x01, 0x31, 0x09, 0x05, 0x03}, // 7 754 | {0x1a, 0x25, 0x25, 0x25, 0x25, 0x1a}, // 8 755 | {0x06, 0x29, 0x29, 0x29, 0x29, 0x1e}, // 9 756 | {0x24, 0x00, 0x00, 0x00, 0x00, 0x00}, // : 757 | {0x80, 0x64, 0x00, 0x00, 0x00, 0x00}, // ; 758 | {0x08, 0x14, 0x22, 0x00, 0x00, 0x00}, // < 759 | {0x14, 0x14, 0x14, 0x14, 0x14, 0x00}, // = 760 | {0x22, 0x14, 0x08, 0x00, 0x00, 0x00}, // > 761 | {0x02, 0x01, 0x01, 0x29, 0x05, 0x02}, // ? 762 | {0x1e, 0x21, 0x2d, 0x2b, 0x2d, 0x0e}, // @ 763 | {0x3e, 0x09, 0x09, 0x09, 0x09, 0x3e}, // A 764 | {0x3f, 0x25, 0x25, 0x25, 0x25, 0x1a}, // B 765 | {0x1e, 0x21, 0x21, 0x21, 0x21, 0x12}, // C 766 | {0x3f, 0x21, 0x21, 0x21, 0x12, 0x0c}, // D 767 | {0x3f, 0x25, 0x25, 0x25, 0x25, 0x21}, // E 768 | {0x3f, 0x05, 0x05, 0x05, 0x05, 0x01}, // F 769 | {0x1e, 0x21, 0x21, 0x21, 0x29, 0x1a}, // G 770 | {0x3f, 0x04, 0x04, 0x04, 0x04, 0x3f}, // H 771 | {0x21, 0x21, 0x3f, 0x21, 0x21, 0x21}, // I 772 | {0x10, 0x20, 0x20, 0x20, 0x20, 0x1f}, // J 773 | {0x3f, 0x04, 0x0c, 0x0a, 0x11, 0x20}, // K 774 | {0x3f, 0x20, 0x20, 0x20, 0x20, 0x20}, // L 775 | {0x3f, 0x02, 0x04, 0x04, 0x02, 0x3f}, // M 776 | {0x3f, 0x02, 0x04, 0x08, 0x10, 0x3f}, // N 777 | {0x1e, 0x21, 0x21, 0x21, 0x21, 0x1e}, // O 778 | {0x3f, 0x09, 0x09, 0x09, 0x09, 0x06}, // P 779 | {0x1e, 0x21, 0x29, 0x31, 0x21, 0x1e}, // Q 780 | {0x3f, 0x09, 0x09, 0x09, 0x19, 0x26}, // R 781 | {0x12, 0x25, 0x25, 0x25, 0x25, 0x18}, // S 782 | {0x01, 0x01, 0x01, 0x3f, 0x01, 0x01}, // T 783 | {0x1f, 0x20, 0x20, 0x20, 0x20, 0x1f}, // U 784 | {0x0f, 0x10, 0x20, 0x20, 0x10, 0x0f}, // V 785 | {0x1f, 0x20, 0x10, 0x10, 0x20, 0x1f}, // W 786 | {0x21, 0x12, 0x0c, 0x0c, 0x12, 0x21}, // X 787 | {0x01, 0x02, 0x0c, 0x38, 0x04, 0x02}, // Y 788 | {0x21, 0x31, 0x29, 0x25, 0x23, 0x21}, // Z 789 | {0x3f, 0x21, 0x00, 0x00, 0x00, 0x00}, // [ 790 | {0x02, 0x04, 0x08, 0x10, 0x20, 0x00}, // "\" 791 | {0x21, 0x3f, 0x00, 0x00, 0x00, 0x00}, // ] 792 | {0x04, 0x02, 0x3f, 0x02, 0x04, 0x00}, // ^ 793 | {0x40, 0x40, 0x40, 0x40, 0x40, 0x40}, // _ 794 | {0x01, 0x02, 0x00, 0x00, 0x00, 0x00}, // ` 795 | {0x10, 0x30, 0x2a, 0x2a, 0x3c, 0x00}, // a 796 | {0x3f, 0x24, 0x24, 0x24, 0x18, 0x00}, // b 797 | {0x0c, 0x14, 0x22, 0x22, 0x00, 0x00}, // c 798 | {0x18, 0x24, 0x24, 0x24, 0x3f, 0x00}, // d 799 | {0x1c, 0x2c, 0x2a, 0x2a, 0x24, 0x00}, // e 800 | {0x3e, 0x05, 0x01, 0x00, 0x00, 0x00}, // f 801 | {0x18, 0x28, 0xa4, 0xa4, 0x7c, 0x00}, // g 802 | {0x3f, 0x04, 0x04, 0x0c, 0x30, 0x00}, // h 803 | {0x24, 0x3d, 0x20, 0x00, 0x00, 0x00}, // i 804 | {0x20, 0x40, 0x40, 0x3d, 0x00, 0x00}, // j 805 | {0x3f, 0x0c, 0x12, 0x20, 0x00, 0x00}, // k 806 | {0x1f, 0x20, 0x20, 0x00, 0x00, 0x00}, // l 807 | {0x3e, 0x02, 0x3c, 0x02, 0x3c, 0x00}, // m 808 | {0x3e, 0x02, 0x02, 0x02, 0x3c, 0x00}, // n 809 | {0x0c, 0x14, 0x22, 0x32, 0x0c, 0x00}, // o 810 | {0xfc, 0x24, 0x24, 0x24, 0x18, 0x00}, // p 811 | {0x18, 0x24, 0x24, 0x24, 0xfc, 0x80}, // q 812 | {0x3c, 0x04, 0x02, 0x02, 0x00, 0x00}, // r 813 | {0x24, 0x2c, 0x2a, 0x2a, 0x10, 0x00}, // s 814 | {0x02, 0x1f, 0x22, 0x20, 0x00, 0x00}, // t 815 | {0x1e, 0x20, 0x20, 0x20, 0x1e, 0x00}, // u 816 | {0x06, 0x18, 0x20, 0x18, 0x06, 0x00}, // v 817 | {0x1e, 0x30, 0x1c, 0x30, 0x0e, 0x00}, // w 818 | {0x22, 0x14, 0x08, 0x14, 0x22, 0x00}, // x 819 | {0x0c, 0x10, 0xa0, 0xa0, 0x7c, 0x00}, // y 820 | {0x22, 0x32, 0x2a, 0x26, 0x22, 0x22}, // z 821 | {0x0c, 0x3f, 0x21, 0x00, 0x00, 0x00}, // { 822 | {0x3f, 0x00, 0x00, 0x00, 0x00, 0x00}, // | 823 | {0x21, 0x3f, 0x0c, 0x00, 0x00, 0x00}, // } 824 | {0x02, 0x01, 0x02, 0x01, 0x00, 0x00}, // ~ 825 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} 826 | }; 827 | 828 | private static void setPexel(Ssd1306 ssd1306, int x, int y, boolean on) { 829 | if (x < 0 || y < 0 || x >= ssd1306.getLcdWidth() || y >= ssd1306.getLcdHeight()) { 830 | // Ignore the out of bound at this point 831 | return; 832 | } 833 | ssd1306.setPixel(x, y, on); 834 | } 835 | 836 | static void drawString(Ssd1306 ssd1306, int x, int y, String text, Fonts.Type type) { 837 | byte[] characters = text.getBytes(); 838 | 839 | for (byte character : characters) { 840 | int code = (int) character; 841 | int index = code - 32; 842 | 843 | if (index >= 0 && index < 96) { 844 | char[] pixel = Fonts.font5x5[index]; 845 | 846 | if (type == Fonts.Type.font5x5) 847 | pixel = Fonts.font5x5[index]; 848 | else if (type == Fonts.Type.fontAcme5Outlines) 849 | pixel = Fonts.fontAcme5Outlines[index]; 850 | else if (type == Fonts.Type.fontAztech) 851 | pixel = Fonts.fontAztech[index]; 852 | else if (type == Fonts.Type.fontCrackers) 853 | pixel = Fonts.fontCrackers[index]; 854 | else if (type == Fonts.Type.fontSuperDig) 855 | pixel = Fonts.fontSuperDig[index]; 856 | else if (type == Fonts.Type.fontZxpix) 857 | pixel = Fonts.fontZxpix[index]; 858 | 859 | // Draw pixels 860 | for (int j = 0; j < Fonts.CHAR_WIDTH; j++) { 861 | String binary = Integer.toBinaryString(pixel[j]); 862 | while (binary.length() < Fonts.CHAR_HEIGHT) { 863 | binary = "0" + binary; 864 | } 865 | 866 | // Reverse it 867 | binary = new StringBuilder(binary).reverse().toString(); 868 | 869 | for (int i = 0; i < Fonts.CHAR_HEIGHT; i++) { 870 | if (binary.substring(i, i + 1).equals("1")) 871 | setPexel(ssd1306,(x + j), (y + i), true); 872 | else 873 | setPexel(ssd1306,(x + j), (y + i), false); 874 | } 875 | } 876 | 877 | x = x + Fonts.CHAR_WIDTH; 878 | } 879 | } 880 | } 881 | } -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/lcd/RobotLcd.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.lcd; 2 | 3 | import android.content.Context; 4 | import android.net.wifi.WifiManager; 5 | import android.os.Handler; 6 | import android.os.HandlerThread; 7 | import android.util.Log; 8 | 9 | import com.google.android.things.contrib.driver.ssd1306.Ssd1306; 10 | 11 | import java.io.IOException; 12 | import java.math.BigInteger; 13 | import java.net.InetAddress; 14 | import java.net.UnknownHostException; 15 | import java.nio.ByteOrder; 16 | 17 | import static android.content.Context.WIFI_SERVICE; 18 | 19 | /** 20 | * Created by x on 1/31/17. 21 | */ 22 | 23 | public class RobotLcd implements AutoCloseable { 24 | private static final String TAG = RobotLcd.class.getSimpleName(); 25 | private Handler mLcdHandler; 26 | private HandlerThread mLcdHandlerThread; 27 | private Ssd1306 mScreen; 28 | private Context context; 29 | private String cur_ip = " "; 30 | 31 | public RobotLcd(Context context, String i2cBusAddress) throws IOException { 32 | Log.d(TAG, "RobotLcd() called with: context, i2cBusAddress = [" + i2cBusAddress + "]"); 33 | mLcdHandlerThread = new HandlerThread("Lcd thread"); 34 | mLcdHandlerThread.start(); 35 | mLcdHandler = new Handler(mLcdHandlerThread.getLooper()); 36 | mScreen = new Ssd1306(i2cBusAddress); 37 | this.context = context.getApplicationContext(); 38 | 39 | drawStringCentered("STARTED", Font.FONT_5X8, 10, true); 40 | try { 41 | mScreen.show(); 42 | } catch (IOException e) { 43 | e.printStackTrace(); 44 | } 45 | showWifiInfo(); 46 | } 47 | 48 | 49 | @Override 50 | public void close() throws Exception { 51 | mLcdHandlerThread.quitSafely(); 52 | mScreen.close(); 53 | } 54 | 55 | private void showWifiInfo() { 56 | mLcdHandler.post( 57 | new Runnable() { 58 | @Override 59 | public void run() { 60 | String ip = wifiIpAddress(context); 61 | 62 | if (ip != null && !cur_ip.equalsIgnoreCase(ip)) { 63 | cur_ip = ip; 64 | Log.d(TAG, "run() called ip: " + ip); 65 | mScreen.clearPixels(); 66 | drawStringCentered("ANDROID THINGS", Font.FONT_5X8, 0, true); 67 | drawStringCentered("ROBOT", Font.FONT_5X8, 10, true); 68 | // Fonts.drawString(mScreen, 0, 0, "Android Things", Fonts.Type.fontAcme5Outlines); 69 | // Fonts.drawString(mScreen, 0, 20, "ROBOT " + ip, Fonts.Type.fontAcme5Outlines); 70 | // drawString("ip: ", Font.FONT_5X8, 10, 30, true); 71 | // drawString(ip, Font.FONT_4X5, 35, 32, true); 72 | Fonts.drawString(mScreen, 10, 30, "IP: " + ip, Fonts.Type.font5x5); 73 | Fonts.drawString(mScreen, 25, 50, " :(){ :|:& };:", Fonts.Type.font5x5); 74 | // drawStringCentered(ip, Font.FONT_5X8, 40, true); 75 | try { 76 | mScreen.show(); 77 | // mScreen.startScroll(0, 50, Ssd1306.ScrollMode.RightHorizontal); 78 | } catch (IOException e) { 79 | e.printStackTrace(); 80 | } 81 | } else if (ip == null) { 82 | Log.d(TAG, "run() called ip is null"); 83 | mScreen.clearPixels(); 84 | 85 | drawStringCentered("ANDROID THINGS", Font.FONT_5X8, 0, true); 86 | drawStringCentered("ROBOT", Font.FONT_5X8, 10, true); 87 | drawStringCentered("no ip address", Font.FONT_5X8, 30, true); 88 | try { 89 | mScreen.show(); 90 | } catch (IOException e) { 91 | e.printStackTrace(); 92 | } 93 | } 94 | mLcdHandler.postDelayed(this, 10000); 95 | } 96 | }); 97 | } 98 | 99 | 100 | private String wifiIpAddress(Context context) { 101 | WifiManager wifiManager = (WifiManager) context.getSystemService(WIFI_SERVICE); 102 | int ipAddress = wifiManager.getConnectionInfo().getIpAddress(); 103 | 104 | if (ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN)) { 105 | ipAddress = Integer.reverseBytes(ipAddress); 106 | } 107 | 108 | byte[] ipByteArray = BigInteger.valueOf(ipAddress).toByteArray(); 109 | 110 | String ipAddressString; 111 | try { 112 | ipAddressString = InetAddress.getByAddress(ipByteArray).getHostAddress(); 113 | } catch (UnknownHostException ex) { 114 | Log.e(TAG, "Unable to get host address."); 115 | ipAddressString = null; 116 | } 117 | 118 | return ipAddressString; 119 | } 120 | 121 | private synchronized void drawString(String string, Font font, int x, int y, boolean on) { 122 | int posX = x; 123 | int posY = y; 124 | for (char c : string.toCharArray()) { 125 | if (c == '\n') { 126 | posY += font.getOutterHeight(); 127 | posX = x; 128 | } else { 129 | if (posX >= 0 && posX + font.getWidth() < mScreen.getLcdWidth() 130 | && posY >= 0 && posY + font.getHeight() < mScreen.getLcdHeight()) { 131 | font.drawChar(mScreen, c, posX, posY, on); 132 | } 133 | posX += font.getOutterWidth(); 134 | } 135 | } 136 | } 137 | 138 | private synchronized void drawStringCentered(String string, Font font, int y, boolean on) { 139 | final int strSizeX = string.length() * font.getOutterWidth(); 140 | final int x = (mScreen.getLcdWidth() - strSizeX) / 2; 141 | drawString(string, font, x, y, on); 142 | 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/ledrgb/LedRGB.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.ledrgb; 2 | 3 | import android.util.Log; 4 | 5 | import com.google.android.things.pio.Gpio; 6 | import com.google.android.things.pio.PeripheralManagerService; 7 | 8 | import java.io.IOException; 9 | 10 | import static com.google.android.things.pio.Gpio.DIRECTION_OUT_INITIALLY_LOW; 11 | 12 | /** 13 | * Created by x on 1/31/17. 14 | */ 15 | 16 | public class LedRGB implements AutoCloseable { 17 | private static final String TAG = LedRGB.class.getSimpleName(); 18 | private Gpio mLedRed; 19 | private Gpio mLedGreen; 20 | private Gpio mLedBlue; 21 | private PeripheralManagerService service; 22 | 23 | public LedRGB(String gpioR, String gpioG, String gpioB, PeripheralManagerService service) throws IOException { 24 | this.service = service; 25 | 26 | mLedRed = service.openGpio(gpioR); 27 | mLedRed.setDirection(DIRECTION_OUT_INITIALLY_LOW); 28 | mLedGreen = service.openGpio(gpioG); 29 | mLedGreen.setDirection(DIRECTION_OUT_INITIALLY_LOW); 30 | mLedBlue = service.openGpio(gpioB); 31 | mLedBlue.setDirection(DIRECTION_OUT_INITIALLY_LOW); 32 | } 33 | 34 | public void turnRed(boolean on) { 35 | try { 36 | mLedRed.setValue(on); 37 | } catch (IOException e) { 38 | Log.e(TAG, "turnRed: ", e); 39 | } 40 | } 41 | 42 | public void turnBlue(boolean on) { 43 | try { 44 | mLedBlue.setValue(on); 45 | } catch (IOException e) { 46 | Log.e(TAG, "turnBlue: ", e); 47 | } 48 | } 49 | 50 | public void turnGreen(boolean on) { 51 | try { 52 | mLedGreen.setValue(on); 53 | } catch (IOException e) { 54 | Log.e(TAG, "turnGreen: ", e); 55 | } 56 | } 57 | 58 | public void turnAll(boolean on) { 59 | try { 60 | mLedRed.setValue(on); 61 | mLedGreen.setValue(on); 62 | mLedBlue.setValue(on); 63 | } catch (IOException e) { 64 | Log.e(TAG, "turnAll: ", e); 65 | } 66 | } 67 | 68 | @Override 69 | public void close() throws Exception { 70 | mLedRed.close(); 71 | mLedBlue.close(); 72 | mLedGreen.close(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/obstacle/Hcsr04.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.obstacle; 2 | 3 | 4 | import com.google.android.things.pio.Gpio; 5 | 6 | import java.io.IOException; 7 | 8 | /** 9 | * DistanceMonitor class to monitor distance measured by sensor 10 | * 11 | * @author Rutger Claes 12 | */ 13 | public class Hcsr04 { 14 | 15 | private final static float SOUND_SPEED = 340.29f; // speed of sound in m/s 16 | private final static int TRIG_DURATION_IN_MICROS = 10; // trigger duration 17 | private final static int TIMEOUT = 2100; 18 | 19 | private final Gpio echoPin; 20 | private final Gpio trigPin; 21 | 22 | public Hcsr04(Gpio echoPin, Gpio trigPin) throws IOException { 23 | this.echoPin = echoPin; 24 | this.trigPin = trigPin; 25 | trigPin.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); 26 | echoPin.setDirection(Gpio.DIRECTION_IN); 27 | } 28 | 29 | /* 30 | * This method returns the distance measured by the sensor in cm 31 | * 32 | * @throws TimeoutException if a timeout occurs 33 | */ 34 | public synchronized float measureDistance() throws Exception { 35 | triggerSensor(); 36 | waitForSignal(); 37 | long duration = measureSignal(); 38 | return duration * SOUND_SPEED / 20000F; 39 | } 40 | 41 | /** 42 | * Put a high on the trig pin for TRIG_DURATION_IN_MICROS 43 | */ 44 | private void triggerSensor() { 45 | try { 46 | trigPin.setValue(true); 47 | Thread.sleep(0, TRIG_DURATION_IN_MICROS * 1000); 48 | trigPin.setValue(false); 49 | } catch (InterruptedException | IOException ex) { 50 | 51 | } 52 | } 53 | 54 | /** 55 | * Wait for a high on the echo pin 56 | */ 57 | private void waitForSignal() throws Exception { 58 | int countdown = 10; 59 | 60 | while (!echoPin.getValue() && countdown > 0) { 61 | countdown--; 62 | } 63 | 64 | if (countdown <= 0) { 65 | throw new Exception("Timeout waiting for signal start"); 66 | } 67 | } 68 | 69 | /** 70 | * @return the duration of the signal in micro seconds 71 | * @throws Exception 72 | */ 73 | private long measureSignal() throws Exception { 74 | int countdown = TIMEOUT*10; 75 | long start = System.nanoTime(); 76 | while (echoPin.getValue() && countdown > 0) { 77 | countdown--; 78 | } 79 | long end = System.nanoTime(); 80 | 81 | if (countdown <= 0) { 82 | throw new Exception("Timeout waiting for signal end"); 83 | } 84 | 85 | return (long) Math.ceil((end - start) / 1000.0); // Return micro seconds 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/obstacle/ObstacleInput.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.obstacle; 2 | 3 | import com.samgol.robot.Inputs.InputType; 4 | import com.samgol.robot.Inputs.InputData; 5 | 6 | /** 7 | * Created by x on 1/8/17. 8 | */ 9 | 10 | public class ObstacleInput extends InputData { 11 | public ObstacleInput(ObstacleInputDataType type) { 12 | super(InputType.OBSTACLE); 13 | defStringRep += "_" + type.name(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/obstacle/ObstacleInputDataType.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.obstacle; 2 | 3 | /** 4 | * Created by x on 1/8/17. 5 | */ 6 | 7 | public enum ObstacleInputDataType { 8 | CLOSE, FAR, NEAR 9 | } 10 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/obstacle/ObstacleSensor.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.obstacle; 2 | 3 | import android.os.Handler; 4 | import android.os.HandlerThread; 5 | import android.util.Log; 6 | 7 | import com.google.android.things.pio.Gpio; 8 | import com.samgol.robot.Inputs.InputSource; 9 | 10 | import java.io.IOException; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | import static android.content.ContentValues.TAG; 14 | import static com.samgol.robot.Inputs.InputKb.OBS_CLOSE; 15 | import static com.samgol.robot.Inputs.InputKb.OBS_FAR; 16 | import static com.samgol.robot.Inputs.InputKb.OBS_NEAR; 17 | import static com.samgol.robot.obstacle.ObstacleInputDataType.FAR; 18 | 19 | /** 20 | * Created by x on 1/8/17. 21 | */ 22 | 23 | public class ObstacleSensor extends InputSource implements AutoCloseable { 24 | private ObstacleInputDataType state; 25 | private static final int CLOSE = 10; 26 | private static final int NEAR = 20; 27 | private Gpio trig; 28 | private Gpio echo; 29 | private Hcsr04 hcsr04; 30 | 31 | private HandlerThread mHandlerThread; 32 | private Handler mHandler; 33 | private Runnable pollDist; 34 | 35 | public ObstacleSensor(Gpio trig, Gpio echo) throws IOException { 36 | state = FAR; 37 | this.trig = trig; 38 | this.echo = echo; 39 | 40 | hcsr04 = new Hcsr04(echo, trig); 41 | mHandlerThread = new HandlerThread("Distance Sensor"); 42 | mHandlerThread.start(); 43 | mHandler = new Handler(mHandlerThread.getLooper()); 44 | 45 | pollDist = () -> { 46 | int count = 3; 47 | float d = -1; 48 | while (count > 0) { 49 | try { 50 | d = hcsr04.measureDistance(); 51 | // Log.d(TAG, "Distance: " + d); 52 | break; 53 | } catch (Exception e) { 54 | count--; 55 | Log.w(TAG, "Distance warning: " + e.getMessage()); 56 | } 57 | try { 58 | TimeUnit.MILLISECONDS.sleep(50); 59 | } catch (InterruptedException e) { 60 | } 61 | } 62 | onDistance((int) d); 63 | try { 64 | TimeUnit.MILLISECONDS.sleep(200); 65 | } catch (InterruptedException e) { 66 | 67 | } 68 | mHandler.post(pollDist); 69 | }; 70 | mHandler.post(pollDist); 71 | } 72 | 73 | private void onDistance(int distance) { 74 | switch (state) { 75 | case CLOSE: 76 | if (distance > CLOSE) { 77 | if (distance > NEAR) { 78 | state = FAR; 79 | onInput(OBS_FAR); 80 | } else { 81 | state = ObstacleInputDataType.NEAR; 82 | onInput(OBS_NEAR); 83 | } 84 | } 85 | break; 86 | case FAR: 87 | if (distance < CLOSE) { 88 | state = ObstacleInputDataType.CLOSE; 89 | onInput(OBS_CLOSE); 90 | } else if (distance < NEAR) { 91 | state = ObstacleInputDataType.NEAR; 92 | onInput(OBS_NEAR); 93 | } 94 | break; 95 | case NEAR: 96 | if (distance < CLOSE) { 97 | state = ObstacleInputDataType.CLOSE; 98 | onInput(OBS_CLOSE); 99 | } 100 | if (distance > NEAR) { 101 | state = ObstacleInputDataType.FAR; 102 | onInput(OBS_FAR); 103 | } 104 | break; 105 | default: 106 | break; 107 | } 108 | } 109 | 110 | @Override 111 | public void close() throws Exception { 112 | mHandlerThread.quitSafely(); 113 | 114 | trig.close(); 115 | echo.close(); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/remoteControl/CommandListener.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.remoteControl; 2 | 3 | /** 4 | * Created by x on 1/7/17. 5 | */ 6 | 7 | public interface CommandListener { 8 | void onCommand(String command); 9 | } 10 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/remoteControl/ImageConsumer.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.remoteControl; 2 | 3 | /** 4 | * Created by x on 1/31/17. 5 | */ 6 | 7 | public interface ImageConsumer { 8 | void onBase64Image(String msg); 9 | 10 | void onMsg(String msg); 11 | } 12 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/remoteControl/Server.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.remoteControl; 2 | 3 | 4 | import android.content.res.AssetManager; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | 9 | import fi.iki.elonen.IWebSocketFactory; 10 | import fi.iki.elonen.NanoHTTPD; 11 | import fi.iki.elonen.WebSocket; 12 | import fi.iki.elonen.WebSocketResponseHandler; 13 | 14 | public class Server extends NanoHTTPD implements ImageConsumer { 15 | private WebSocketResponseHandler responseHandler; 16 | private AssetManager assetManager; 17 | private Ws mWs; 18 | 19 | private IWebSocketFactory webSocketFactory = new IWebSocketFactory() { 20 | @Override 21 | public WebSocket openWebSocket(IHTTPSession handshake) { 22 | mWs = new Ws(handshake, commandListener); 23 | return mWs; 24 | } 25 | }; 26 | 27 | private CommandListener commandListener; 28 | 29 | public Server(int port, CommandListener commandListener, AssetManager assetManager) { 30 | super(port); 31 | this.commandListener = commandListener; 32 | this.assetManager = assetManager; 33 | 34 | responseHandler = new WebSocketResponseHandler(webSocketFactory); 35 | } 36 | 37 | @Override 38 | public Response serve(IHTTPSession session) { 39 | NanoHTTPD.Response ws = responseHandler.serve(session); 40 | if (ws == null) { 41 | String uri = session.getUri(); 42 | try { 43 | if (uri.equals("/")) { 44 | // InputStream inputStream = assetManager.open("magc.html"); 45 | InputStream inputStream = assetManager.open("wscontrol.html"); 46 | return new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, "text/html", inputStream); 47 | } 48 | // if (uri.equals("/iotRobot.js")) { 49 | // File file = new File("website/iotRobot.js"); 50 | // return new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, "text/javascript", new FileInputStream(file)); 51 | // } 52 | } catch (Exception e) { 53 | System.out.println("Somthing wrong"); 54 | e.printStackTrace(); 55 | new NanoHTTPD.Response("hello, i am runing...."); 56 | } 57 | } 58 | return ws; 59 | } 60 | 61 | @Override 62 | public void onBase64Image(String msg) { 63 | try { 64 | mWs.send("data:image/png;base64," + msg); 65 | } catch (IOException e) { 66 | e.printStackTrace(); 67 | } 68 | } 69 | 70 | @Override 71 | public void onMsg(String msg) { 72 | try { 73 | if (mWs != null) 74 | mWs.send(msg); 75 | } catch (IOException e) { 76 | e.printStackTrace(); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Robot/src/main/java/com/samgol/robot/remoteControl/Ws.java: -------------------------------------------------------------------------------- 1 | package com.samgol.robot.remoteControl; 2 | 3 | import java.io.IOException; 4 | 5 | import fi.iki.elonen.NanoHTTPD.IHTTPSession; 6 | import fi.iki.elonen.WebSocket; 7 | import fi.iki.elonen.WebSocketFrame; 8 | import fi.iki.elonen.WebSocketFrame.CloseCode; 9 | 10 | class Ws extends WebSocket { 11 | 12 | private CommandListener commandListener; 13 | 14 | public Ws(IHTTPSession handshakeRequest, CommandListener commandListener) { 15 | super(handshakeRequest); 16 | this.commandListener = commandListener; 17 | System.out.println("user connected......"); 18 | } 19 | 20 | @Override 21 | protected void onPong(WebSocketFrame pongFrame) { 22 | System.out.println("user pong......."); 23 | } 24 | 25 | @Override 26 | protected void onMessage(WebSocketFrame messageFrame) { 27 | // System.out.println("User message : " + messageFrame.getTextPayload().trim()); 28 | commandListener.onCommand(messageFrame.getTextPayload().trim()); 29 | } 30 | 31 | @Override 32 | protected void onClose(CloseCode code, String reason, boolean initiatedByRemote) { 33 | System.out.println("user disconnected....."); 34 | } 35 | 36 | @Override 37 | protected void onException(IOException e) { 38 | System.out.println(e.getMessage()); 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /Robot/src/main/res/layout/activity_robot.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 17 | 18 | -------------------------------------------------------------------------------- /Robot/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /Robot/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /Robot/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /Robot/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AndroidThingsRobot 3 | 4 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.2.3' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euler2dot7/android_things_robot/6bbdf767f5a61e0893942e7be248d95765a72702/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Dec 28 10:00:20 PST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /img/btn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euler2dot7/android_things_robot/6bbdf767f5a61e0893942e7be248d95765a72702/img/btn.jpg -------------------------------------------------------------------------------- /img/h-bridge.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euler2dot7/android_things_robot/6bbdf767f5a61e0893942e7be248d95765a72702/img/h-bridge.jpg -------------------------------------------------------------------------------- /img/hc-sr04-02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euler2dot7/android_things_robot/6bbdf767f5a61e0893942e7be248d95765a72702/img/hc-sr04-02.jpg -------------------------------------------------------------------------------- /img/motor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euler2dot7/android_things_robot/6bbdf767f5a61e0893942e7be248d95765a72702/img/motor.jpg -------------------------------------------------------------------------------- /img/raspberry_pi_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euler2dot7/android_things_robot/6bbdf767f5a61e0893942e7be248d95765a72702/img/raspberry_pi_3.jpg -------------------------------------------------------------------------------- /img/rgb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euler2dot7/android_things_robot/6bbdf767f5a61e0893942e7be248d95765a72702/img/rgb.jpg -------------------------------------------------------------------------------- /img/robot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euler2dot7/android_things_robot/6bbdf767f5a61e0893942e7be248d95765a72702/img/robot.jpg -------------------------------------------------------------------------------- /img/servo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euler2dot7/android_things_robot/6bbdf767f5a61e0893942e7be248d95765a72702/img/servo.jpg -------------------------------------------------------------------------------- /img/ssd1306.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/euler2dot7/android_things_robot/6bbdf767f5a61e0893942e7be248d95765a72702/img/ssd1306.jpg -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':Robot' 2 | --------------------------------------------------------------------------------