For YRL Robot Arm

Committer:
jah128
Date:
Fri Mar 03 13:28:54 2017 +0000
Revision:
0:b14dfd8816da
Updated

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jah128 0:b14dfd8816da 1 /* University of York Robotics Laboratory Robot Arm Controller Board
jah128 0:b14dfd8816da 2 *
jah128 0:b14dfd8816da 3 * Dynamixel Servo Library for AX-12 and MX-28
jah128 0:b14dfd8816da 4 *
jah128 0:b14dfd8816da 5 * Based on library by Chris Styles (see copyright notice at end of file)
jah128 0:b14dfd8816da 6 *
jah128 0:b14dfd8816da 7 * File: servo.cpp
jah128 0:b14dfd8816da 8 *
jah128 0:b14dfd8816da 9 * (C) Dept. Electronics & Computer Science, University of York
jah128 0:b14dfd8816da 10 * James Hilder, Alan Millard, Shuhei Miyashita, Homero Elizondo, Jon Timmis
jah128 0:b14dfd8816da 11 *
jah128 0:b14dfd8816da 12 * February 2017, Version 1.0
jah128 0:b14dfd8816da 13 */
jah128 0:b14dfd8816da 14
jah128 0:b14dfd8816da 15 // NOTE:
jah128 0:b14dfd8816da 16 // When communicating with 'new' servos the are defaulted to ID 1
jah128 0:b14dfd8816da 17 // Make sure only one such servo is connected at one time
jah128 0:b14dfd8816da 18 // Also note that this library defaults to 57600 serial comms
jah128 0:b14dfd8816da 19 // The MX-28s are defaulted to communicate at this speed but the AX-12s are not (1Mbaud)
jah128 0:b14dfd8816da 20 // Use SetInitBaud(57600) to override the default and then change baud rate when setting up MX-28s
jah128 0:b14dfd8816da 21
jah128 0:b14dfd8816da 22 #ifndef SERVO_H
jah128 0:b14dfd8816da 23 #define SERVO_H
jah128 0:b14dfd8816da 24
jah128 0:b14dfd8816da 25 #include "mbed.h"
jah128 0:b14dfd8816da 26 #include "SerialHalfDuplex.h"
jah128 0:b14dfd8816da 27
jah128 0:b14dfd8816da 28 #define WRITE_DEBUG 0
jah128 0:b14dfd8816da 29 #define READ_DEBUG 0
jah128 0:b14dfd8816da 30 #define TRIGGER_DEBUG 0
jah128 0:b14dfd8816da 31 #define DEBUG 0
jah128 0:b14dfd8816da 32
jah128 0:b14dfd8816da 33 // Number of times to retry a read\write operation if read times out
jah128 0:b14dfd8816da 34 #define READ_TIMEOUT_LIMIT 3
jah128 0:b14dfd8816da 35
jah128 0:b14dfd8816da 36 #define LOW_VOLTAGE_LIMIT 90
jah128 0:b14dfd8816da 37 #define HIGH_VOLTAGE_LIMIT 140
jah128 0:b14dfd8816da 38 #define HIGH_TEMPERATURE_LIMIT 70
jah128 0:b14dfd8816da 39
jah128 0:b14dfd8816da 40 #define AX12_MODEL 0x0C
jah128 0:b14dfd8816da 41 #define MX28_MODEL 0x1D
jah128 0:b14dfd8816da 42
jah128 0:b14dfd8816da 43 #define RETURN_DELAY 250
jah128 0:b14dfd8816da 44
jah128 0:b14dfd8816da 45 #define REG_MODEL_NUMBER 0x00
jah128 0:b14dfd8816da 46 #define REG_FIRMWARE_VERSION 0x02
jah128 0:b14dfd8816da 47 #define REG_ID 0x03
jah128 0:b14dfd8816da 48 #define REG_BAUDRATE 0x04
jah128 0:b14dfd8816da 49 #define REG_RETURN_DELAY 0x05
jah128 0:b14dfd8816da 50 #define REG_CW_LIMIT 0x06
jah128 0:b14dfd8816da 51 #define REG_CCW_LIMIT 0x08
jah128 0:b14dfd8816da 52 #define REG_HIGHTEMP_LIMIT 0x0B
jah128 0:b14dfd8816da 53 #define REG_LOW_VOLTAGE_LIMIT 0x0C
jah128 0:b14dfd8816da 54 #define REG_HIGH_VOLTAGE_LIMIT 0x0D
jah128 0:b14dfd8816da 55 #define REG_MAX_TORQUE 0x0E
jah128 0:b14dfd8816da 56 #define REG_TORQUE_ENABLE 0x18
jah128 0:b14dfd8816da 57 #define REG_GOAL_POSITION 0x1E
jah128 0:b14dfd8816da 58 #define REG_MOVING_SPEED 0x20
jah128 0:b14dfd8816da 59 #define REG_VOLTS 0x2A
jah128 0:b14dfd8816da 60 #define REG_TEMP 0x2B
jah128 0:b14dfd8816da 61 #define REG_SPEED 0x26
jah128 0:b14dfd8816da 62 #define REG_LOAD 0x28
jah128 0:b14dfd8816da 63 #define REG_MOVING 0x2E
jah128 0:b14dfd8816da 64 #define REG_POSITION 0x24
jah128 0:b14dfd8816da 65 #define REG_EEPROM_LOCK 0x2F
jah128 0:b14dfd8816da 66
jah128 0:b14dfd8816da 67 #define MODE_POSITION 0
jah128 0:b14dfd8816da 68 #define MODE_ROTATION 1
jah128 0:b14dfd8816da 69
jah128 0:b14dfd8816da 70 #define CW 1
jah128 0:b14dfd8816da 71 #define CCW 0
jah128 0:b14dfd8816da 72
jah128 0:b14dfd8816da 73 extern Serial data;
jah128 0:b14dfd8816da 74
jah128 0:b14dfd8816da 75 /** Servo Class
jah128 0:b14dfd8816da 76 * Class with functions to control a Dynamixel single-wire TTL Serial Servo
jah128 0:b14dfd8816da 77 *
jah128 0:b14dfd8816da 78 * Example code for main.cpp:
jah128 0:b14dfd8816da 79 * @code
jah128 0:b14dfd8816da 80 * #include "servo.h"
jah128 0:b14dfd8816da 81 * Servo servo(p9,p10)
jah128 0:b14dfd8816da 82 * int main(){
jah128 0:b14dfd8816da 83 * arm.init();
jah128 0:b14dfd8816da 84 * while(1) { //Do something!
jah128 0:b14dfd8816da 85 * }
jah128 0:b14dfd8816da 86 * }
jah128 0:b14dfd8816da 87 * @endcode
jah128 0:b14dfd8816da 88 */
jah128 0:b14dfd8816da 89 class Servo {
jah128 0:b14dfd8816da 90
jah128 0:b14dfd8816da 91 public:
jah128 0:b14dfd8816da 92
jah128 0:b14dfd8816da 93 /** Create a Dynamixel servo controller object connected to the specified serial port, with the specified ID
jah128 0:b14dfd8816da 94 *
jah128 0:b14dfd8816da 95 * @param pin tx pin
jah128 0:b14dfd8816da 96 * @param pin rx pin
jah128 0:b14dfd8816da 97 */
jah128 0:b14dfd8816da 98 Servo(PinName tx, PinName rx);
jah128 0:b14dfd8816da 99
jah128 0:b14dfd8816da 100 void ClearBuffer(void);
jah128 0:b14dfd8816da 101
jah128 0:b14dfd8816da 102 void ScanForServos(void);
jah128 0:b14dfd8816da 103
jah128 0:b14dfd8816da 104
jah128 0:b14dfd8816da 105 /** Prints (over PC serial) a detailed set of data for the servo
jah128 0:b14dfd8816da 106 *
jah128 0:b14dfd8816da 107 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 108 */
jah128 0:b14dfd8816da 109 void DebugData(int ID);
jah128 0:b14dfd8816da 110
jah128 0:b14dfd8816da 111 /** Set the mode of the servo
jah128 0:b14dfd8816da 112 *
jah128 0:b14dfd8816da 113 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 114 * @param mode
jah128 0:b14dfd8816da 115 * 0 = Positional, default
jah128 0:b14dfd8816da 116 * 1 = Continuous rotation
jah128 0:b14dfd8816da 117 */
jah128 0:b14dfd8816da 118 int SetMode(int ID, int mode);
jah128 0:b14dfd8816da 119
jah128 0:b14dfd8816da 120 /** Set goal angle, in positional mode
jah128 0:b14dfd8816da 121 *
jah128 0:b14dfd8816da 122 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 123 * @param goal 0-4095
jah128 0:b14dfd8816da 124 * @param flags, defaults to 0
jah128 0:b14dfd8816da 125 * flags[0] = blocking, return when goal position reached
jah128 0:b14dfd8816da 126 * flags[1] = register, activate with a broadcast trigger
jah128 0:b14dfd8816da 127 *
jah128 0:b14dfd8816da 128 */
jah128 0:b14dfd8816da 129 int SetGoal(int ID, short goal, int flags = 0);
jah128 0:b14dfd8816da 130
jah128 0:b14dfd8816da 131 /** Set goal angle in integer degrees, in positional mode
jah128 0:b14dfd8816da 132 *
jah128 0:b14dfd8816da 133 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 134 * @param degrees 0-300
jah128 0:b14dfd8816da 135 * @param flags, defaults to 0
jah128 0:b14dfd8816da 136 * flags[0] = blocking, return when goal position reached
jah128 0:b14dfd8816da 137 * flags[1] = register, activate with a broadcast trigger
jah128 0:b14dfd8816da 138 *
jah128 0:b14dfd8816da 139 */
jah128 0:b14dfd8816da 140 int SetGoalDegrees(int ID, int degrees, int flags = 0);
jah128 0:b14dfd8816da 141
jah128 0:b14dfd8816da 142
jah128 0:b14dfd8816da 143 /** Set the speed of the servo in continuous rotation mode
jah128 0:b14dfd8816da 144 *
jah128 0:b14dfd8816da 145 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 146 * @param speed, -1.0 to 1.0
jah128 0:b14dfd8816da 147 * -1.0 = full speed counter clock wise
jah128 0:b14dfd8816da 148 * 1.0 = full speed clock wise
jah128 0:b14dfd8816da 149 */
jah128 0:b14dfd8816da 150 int SetCRSpeed(int ID, float speed);
jah128 0:b14dfd8816da 151
jah128 0:b14dfd8816da 152
jah128 0:b14dfd8816da 153 /** Set the clockwise limit of the servo
jah128 0:b14dfd8816da 154 *
jah128 0:b14dfd8816da 155 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 156 * @param degrees, 0-300
jah128 0:b14dfd8816da 157 */
jah128 0:b14dfd8816da 158 int SetCWLimit(int ID, int degrees);
jah128 0:b14dfd8816da 159
jah128 0:b14dfd8816da 160 /** Set the counter-clockwise limit of the servo
jah128 0:b14dfd8816da 161 *
jah128 0:b14dfd8816da 162 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 163 * @param degrees, 0-300
jah128 0:b14dfd8816da 164 */
jah128 0:b14dfd8816da 165 int SetCCWLimit(int ID, int degrees);
jah128 0:b14dfd8816da 166
jah128 0:b14dfd8816da 167 /** Enable or disable the torque hold of the servo
jah128 0:b14dfd8816da 168 *
jah128 0:b14dfd8816da 169 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 170 * @param enable, 0=disable (floppy) 1=enable (hold)
jah128 0:b14dfd8816da 171 */
jah128 0:b14dfd8816da 172 int SetTorqueEnable (int ID, int enable);
jah128 0:b14dfd8816da 173
jah128 0:b14dfd8816da 174
jah128 0:b14dfd8816da 175 /** Change the low voltage limit of a servo
jah128 0:b14dfd8816da 176 *
jah128 0:b14dfd8816da 177 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 178 * @param lv_limit, 0-254
jah128 0:b14dfd8816da 179 *
jah128 0:b14dfd8816da 180 * voltage = lv_limit / 10
jah128 0:b14dfd8816da 181 */
jah128 0:b14dfd8816da 182 int SetLowVoltageLimit (int ID, char lv_limit);
jah128 0:b14dfd8816da 183
jah128 0:b14dfd8816da 184 /** Lock the EEPROM area of a servo
jah128 0:b14dfd8816da 185 *
jah128 0:b14dfd8816da 186 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 187 */
jah128 0:b14dfd8816da 188 int LockEeprom(int ID);
jah128 0:b14dfd8816da 189
jah128 0:b14dfd8816da 190 /** Change the high voltage limit of a servo
jah128 0:b14dfd8816da 191 *
jah128 0:b14dfd8816da 192 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 193 * @param hv_limit, 0-254
jah128 0:b14dfd8816da 194 *
jah128 0:b14dfd8816da 195 * voltage = hv_limit / 10
jah128 0:b14dfd8816da 196 */
jah128 0:b14dfd8816da 197 int SetHighVoltageLimit (int ID, char hv_limit);
jah128 0:b14dfd8816da 198
jah128 0:b14dfd8816da 199 /** Change the delay time of a servo
jah128 0:b14dfd8816da 200 *
jah128 0:b14dfd8816da 201 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 202 * @param delay, 0-254 C
jah128 0:b14dfd8816da 203 *
jah128 0:b14dfd8816da 204 */
jah128 0:b14dfd8816da 205 int SetDelayTime (int ID, char delay);
jah128 0:b14dfd8816da 206
jah128 0:b14dfd8816da 207 /** Change the high temperature limit of a servo
jah128 0:b14dfd8816da 208 *
jah128 0:b14dfd8816da 209 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 210 * @param temp_limit, 0-254 C
jah128 0:b14dfd8816da 211 *
jah128 0:b14dfd8816da 212 */
jah128 0:b14dfd8816da 213 int SetTemperatureLimit (int ID, char temp_limit);
jah128 0:b14dfd8816da 214
jah128 0:b14dfd8816da 215 /** Change the ID of a servo
jah128 0:b14dfd8816da 216 *
jah128 0:b14dfd8816da 217 * @param CurentID 1-255
jah128 0:b14dfd8816da 218 * @param NewID 1-255
jah128 0:b14dfd8816da 219 *
jah128 0:b14dfd8816da 220 * If a servo ID is not know, the broadcast address of 0 can be used for CurrentID.
jah128 0:b14dfd8816da 221 * In this situation, only one servo should be connected to the bus
jah128 0:b14dfd8816da 222 */
jah128 0:b14dfd8816da 223 int SetID(int CurrentID, int NewID);
jah128 0:b14dfd8816da 224
jah128 0:b14dfd8816da 225 /** Change the baud of a servo
jah128 0:b14dfd8816da 226 *
jah128 0:b14dfd8816da 227 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 228 * @param baud, 0-252
jah128 0:b14dfd8816da 229 *
jah128 0:b14dfd8816da 230 * baudrate = 2000000/baud (with special cases 250=2.25Mbps, 251=2.5Mbps and 252=3Mbps on MX-28 only)
jah128 0:b14dfd8816da 231 */
jah128 0:b14dfd8816da 232 int SetBaud (int ID, int baud);
jah128 0:b14dfd8816da 233
jah128 0:b14dfd8816da 234 /** Poll to see if the servo is moving
jah128 0:b14dfd8816da 235 *
jah128 0:b14dfd8816da 236 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 237 * @returns true is the servo is moving
jah128 0:b14dfd8816da 238 */
jah128 0:b14dfd8816da 239 int isMoving(int ID);
jah128 0:b14dfd8816da 240
jah128 0:b14dfd8816da 241 /** Send the broadcast "trigger" command, to activate any outstanding registered commands
jah128 0:b14dfd8816da 242 */
jah128 0:b14dfd8816da 243 void trigger(void);
jah128 0:b14dfd8816da 244
jah128 0:b14dfd8816da 245 /** Read the model number of the servo
jah128 0:b14dfd8816da 246 *
jah128 0:b14dfd8816da 247 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 248 * @returns int matching defined model number
jah128 0:b14dfd8816da 249 */
jah128 0:b14dfd8816da 250 int GetModelNumber(int ID);
jah128 0:b14dfd8816da 251
jah128 0:b14dfd8816da 252 /** Read the current angle of the servo
jah128 0:b14dfd8816da 253 *
jah128 0:b14dfd8816da 254 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 255 * @returns float in the range 0.0-300.0
jah128 0:b14dfd8816da 256 */
jah128 0:b14dfd8816da 257 float GetPositionDegrees(int ID);
jah128 0:b14dfd8816da 258
jah128 0:b14dfd8816da 259
jah128 0:b14dfd8816da 260 /** Read the raw angle reading of the servo
jah128 0:b14dfd8816da 261 *
jah128 0:b14dfd8816da 262 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 263 * @returns short in the range 0 - 4095 for MX-28
jah128 0:b14dfd8816da 264 */
jah128 0:b14dfd8816da 265 short GetPosition(int ID);
jah128 0:b14dfd8816da 266
jah128 0:b14dfd8816da 267
jah128 0:b14dfd8816da 268 /** Read the temperature of the servo
jah128 0:b14dfd8816da 269 *
jah128 0:b14dfd8816da 270 * @returns float temperature
jah128 0:b14dfd8816da 271 */
jah128 0:b14dfd8816da 272 float GetTemp(int ID);
jah128 0:b14dfd8816da 273
jah128 0:b14dfd8816da 274 /** Read the supply voltage of the servo
jah128 0:b14dfd8816da 275 *
jah128 0:b14dfd8816da 276 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 277 * @returns short voltage * 10
jah128 0:b14dfd8816da 278 */
jah128 0:b14dfd8816da 279 short GetVoltage(int ID) ;
jah128 0:b14dfd8816da 280
jah128 0:b14dfd8816da 281 /** Read the supply voltage of the servo
jah128 0:b14dfd8816da 282 *
jah128 0:b14dfd8816da 283 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 284 * @returns float voltage
jah128 0:b14dfd8816da 285 */
jah128 0:b14dfd8816da 286 float GetVolts(int ID);
jah128 0:b14dfd8816da 287
jah128 0:b14dfd8816da 288 /** Read the temperature of the servo
jah128 0:b14dfd8816da 289 *
jah128 0:b14dfd8816da 290 * @returns short temperature
jah128 0:b14dfd8816da 291 */
jah128 0:b14dfd8816da 292 short GetTemperature(int ID);
jah128 0:b14dfd8816da 293
jah128 0:b14dfd8816da 294 /** Read the torque load of the servo
jah128 0:b14dfd8816da 295 *
jah128 0:b14dfd8816da 296 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 297 * @returns short load, range 0-2048, 0 is 100% CCW, 1024 is zero and 2048 is 100% CW
jah128 0:b14dfd8816da 298 */
jah128 0:b14dfd8816da 299 short GetLoad(int ID) ;
jah128 0:b14dfd8816da 300
jah128 0:b14dfd8816da 301 /** Read the speed of the servo
jah128 0:b14dfd8816da 302 *
jah128 0:b14dfd8816da 303 * @param ID, the Bus ID of the servo 1-255
jah128 0:b14dfd8816da 304 * @returns short speed
jah128 0:b14dfd8816da 305 */
jah128 0:b14dfd8816da 306 short GetSpeed(int ID) ;
jah128 0:b14dfd8816da 307
jah128 0:b14dfd8816da 308 /** Change the internal baud rate to something other than 1000000 (note MX-28s default to 57600)
jah128 0:b14dfd8816da 309 *
jah128 0:b14dfd8816da 310 * @param baud, the baud rate to set
jah128 0:b14dfd8816da 311 * @param delaytime, the delay time to set (x2 us)
jah128 0:b14dfd8816da 312 */
jah128 0:b14dfd8816da 313 void SetInitBaud(int baud, int delaytime);
jah128 0:b14dfd8816da 314
jah128 0:b14dfd8816da 315 /** Returns the software lower limit for the given servo
jah128 0:b14dfd8816da 316 *
jah128 0:b14dfd8816da 317 * @param ID, the servo ID to return the limit for
jah128 0:b14dfd8816da 318 * @returns short limit (either preset value or 0)
jah128 0:b14dfd8816da 319 */
jah128 0:b14dfd8816da 320 short GetLowerLimit(int ID);
jah128 0:b14dfd8816da 321
jah128 0:b14dfd8816da 322 /** Returns the software upper limit for the given servo
jah128 0:b14dfd8816da 323 *
jah128 0:b14dfd8816da 324 * @param ID, the servo ID to return the limit for
jah128 0:b14dfd8816da 325 * @returns short limit (either preset value or 4095)
jah128 0:b14dfd8816da 326 */
jah128 0:b14dfd8816da 327 short GetUpperLimit(int ID);
jah128 0:b14dfd8816da 328
jah128 0:b14dfd8816da 329
jah128 0:b14dfd8816da 330 private :
jah128 0:b14dfd8816da 331 SerialHalfDuplex _servo;
jah128 0:b14dfd8816da 332 int read(int ID, int start, int length, char* data);
jah128 0:b14dfd8816da 333 int write(int ID, int start, int length, char* data, int flag=0);
jah128 0:b14dfd8816da 334
jah128 0:b14dfd8816da 335 };
jah128 0:b14dfd8816da 336
jah128 0:b14dfd8816da 337
jah128 0:b14dfd8816da 338
jah128 0:b14dfd8816da 339 #endif
jah128 0:b14dfd8816da 340
jah128 0:b14dfd8816da 341 /*
jah128 0:b14dfd8816da 342 * Copyright 2017 University of York
jah128 0:b14dfd8816da 343 *
jah128 0:b14dfd8816da 344 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
jah128 0:b14dfd8816da 345 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
jah128 0:b14dfd8816da 346 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS
jah128 0:b14dfd8816da 347 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
jah128 0:b14dfd8816da 348 * See the License for the specific language governing permissions and limitations under the License.
jah128 0:b14dfd8816da 349 *
jah128 0:b14dfd8816da 350 */
jah128 0:b14dfd8816da 351
jah128 0:b14dfd8816da 352 /*
jah128 0:b14dfd8816da 353 * Copyright (c) 2010, Chris Styles (http://mbed.org)
jah128 0:b14dfd8816da 354 *
jah128 0:b14dfd8816da 355 * Permission is hereby granted, free of charge, to any person obtaining a copy
jah128 0:b14dfd8816da 356 * of this software and associated documentation files (the "Software"), to deal
jah128 0:b14dfd8816da 357 * in the Software without restriction, including without limitation the rights
jah128 0:b14dfd8816da 358 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
jah128 0:b14dfd8816da 359 * copies of the Software, and to permit persons to whom the Software is
jah128 0:b14dfd8816da 360 * furnished to do so, subject to the following conditions:
jah128 0:b14dfd8816da 361 *
jah128 0:b14dfd8816da 362 * The above copyright notice and this permission notice shall be included in
jah128 0:b14dfd8816da 363 * all copies or substantial portions of the Software.
jah128 0:b14dfd8816da 364 *
jah128 0:b14dfd8816da 365 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
jah128 0:b14dfd8816da 366 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
jah128 0:b14dfd8816da 367 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
jah128 0:b14dfd8816da 368 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
jah128 0:b14dfd8816da 369 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
jah128 0:b14dfd8816da 370 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
jah128 0:b14dfd8816da 371 * THE SOFTWARE.
jah128 0:b14dfd8816da 372 */