1 /*
2   OrangutanX2.h - Library of functions for controlling the auxiliary
3 	processor on the Orangutan X2.
4 */
5 
6 /*
7  * Written by Ben Schmidel, Mar 2, 2010.
8  * Copyright (c) 2010-2012 Pololu Corporation. For more information, see
9  *
10  *   http://www.pololu.com
11  *   http://forum.pololu.com
12  *   http://www.pololu.com/docs/0J18
13  *
14  * You may freely modify and share this code, as long as you keep this
15  * notice intact (including the three links above).  Licensed under the
16  * Creative Commons BY-SA 3.0 license:
17  *
18  *   http://creativecommons.org/licenses/by-sa/3.0/
19  *
20  * Disclaimer: To the extent permitted by law, Pololu provides this work
21  * without any warranty.  It might be defective, in which case you agree
22  * to be responsible for all resulting costs and damages.
23  */
24 
25 #ifndef OrangutanX2_h
26 #define OrangutanX2_h
27 
28 #include "../OrangutanResources/include/OrangutanModel.h"
29 
30 #ifdef _ORANGUTAN_X2
31 
32 #include "../OrangutanBuzzer/OrangutanBuzzer.h"		// for note macros
33 
34 
35 // COMMANDS
36 #define CMD_MOTOR1_BRAKE_LOW			128
37 #define CMD_MOTOR1_BRAKE_HIGH			130
38 #define CMD_MOTOR2_BRAKE_LOW			132
39 #define CMD_MOTOR2_BRAKE_HIGH			134
40 #define CMD_MOTOR1_FORWARD				136
41 #define CMD_MOTOR1_REVERSE				138
42 #define CMD_MOTOR2_FORWARD				140
43 #define CMD_MOTOR2_REVERSE				142
44 #define CMD_JOINT_BRAKE					144	// 150 will also joint-brake low
45 #define CMD_JOINT_FORWARD				146
46 #define CMD_JOINT_REVERSE				148
47 #define CMD_JOINT_ACCEL_FORWARD			228
48 #define CMD_JOINT_ACCEL_REVERSE			230
49 #define CMD_MOTOR1_ACCEL_FORWARD		232
50 #define CMD_MOTOR1_ACCEL_REVERSE		234
51 #define CMD_MOTOR2_ACCEL_FORWARD		236
52 #define CMD_MOTOR2_ACCEL_REVERSE		238
53 
54 #define CMD_DISABLE_JOINT_MOTOR_MODE	214
55 #define CMD_ENABLE_JOINT_MOTOR_MODE		215
56 #define CMD_SET_M1_ACCELERATION			208
57 #define CMD_SET_M2_ACCELERATION			209
58 #define CMD_SET_M1_BRAKE_DURATION		188
59 #define CMD_SET_M2_BRAKE_DURATION		190
60 #define CMD_SET_PWM_FREQUENCIES			210
61 #define CMD_SET_NUM_CURRENT_SAMPLES		212
62 #define CMD_SET_M1_CURRENT_LIMIT		192
63 #define CMD_SET_M2_CURRENT_LIMIT		194
64 
65 #define CMD_GET_M1_CURRENT				216
66 #define CMD_GET_M2_CURRENT				217
67 
68 
69 #define CMD_BUZZER_OFF					225
70 #define CMD_PLAY_NOTE					152
71 #define CMD_PLAY_FREQUENCY				160
72 
73 #define CMD_PLAY_MELODY					176
74 #define CMD_STORE_NOTE					168
75 #define CMD_END_MELODY					224
76 #define CMD_ERASE_MELODIES				186
77 
78 #define CMD_SET_VOLUME					226
79 #define CMD_SET_NOTE_GAP				187
80 
81 
82 #define CMD_SEND_SERIAL					220
83 #define CMD_READ_SERIAL					219
84 
85 #define CMD_SET_SERIAL					200
86 #define CMD_SET_AND_SAVE_SERIAL			201
87 #define CMD_SET_READ_READY_SIZE			227
88 
89 #define CMD_GET_SEND_BUFF_FREE_SPACE	222
90 #define CMD_GET_READ_BUFF_NUM_BYTES		223
91 #define CMD_GET_UART_ERROR				252
92 
93 
94 #define CMD_WRITE_EEPROM				240
95 #define CMD_READ_EEPROM					248
96 #define CMD_GET_EEPROM_BUSY				254
97 
98 
99 #define CMD_GET_STATUS					218
100 #define CMD_GET_FIRMWARE_VERSION		253
101 
102 
103 // Arguments for the setMotor() method
104 #define MOTOR1		0
105 #define MOTOR2		1
106 #define JOINT_MOTOR	0xFF
107 
108 #define IMMEDIATE_DRIVE	0
109 #define ACCEL_DRIVE	1
110 #define BRAKE_LOW		0xFF
111 
112 // argument options for setMotorPWM() function
113 //  PWM frequency = 20MHz / prescaler / 2^(bit-resolution)
114 //  e.g. PRESCALER_8 with RESOLUTION_7BIT = freq. of 19.5 kHz
115 #define	RESOLUTION_7BIT				0		// pwm ranges from 0 - 127
116 #define RESOLUTION_8BIT				1		// pwm ranges from 0 - 255
117 #define PRESCALER_8					0		// 20MHz / 8
118 #define PRESCALER_64				1		// 20MHz / 64
119 #define PRESCALER_256				2		// 20MHz / 256
120 #define PRESCALER_1024				3		// 20MHz / 1024
121 
122 // argument options for the setSerial() function
123 #define UART_READ_BUFF_SZ			32	// UART read buffer can hold 32 bytes
124 #define UART_SEND_BUFF_SZ			32	// UART send buffer can hold 32 bytes
125 
126 #define UART_NO_PARITY				0
127 #define UART_EVEN_PARITY			2
128 #define UART_ODD_PARITY				3
129 
130 #define UART_ONE_STOP_BIT			0
131 #define UART_TWO_STOP_BITS			1
132 
133 #define UART_NORMAL_SPEED			0
134 #define UART_DOUBLE_SPEED			1
135 
136 // UBRR values that achieve various bauds at normal speed
137 #define UBRR_115200_BAUD			10	// -1.4% error
138 #define UBRR_76800_BAUD				15	// 1.7% error
139 #define UBRR_57600_BAUD				21	// -1.4% error
140 #define UBRR_38400_BAUD				32	// -1.4% error
141 #define UBRR_28800_BAUD				42	// .9% error
142 #define UBRR_19200_BAUD				64	// .2% error
143 #define UBRR_14400_BAUD				86	// -.2% error
144 #define UBRR_9600_BAUD				129	// .2% error
145 #define UBRR_4800_BAUD				259	// .2% error
146 #define UBRR_2400_BAUD				520	// 0% error
147 
148 // UART error byte bits
149 #define UART_SEND_BUFF_OVERRUN		1		// UART send buffer overflow
150 #define UART_READ_BUFF_OVERRUN		2		// UART read buffer overflow
151 #define UART_FRAME_ERROR			4
152 #define UART_DATA_OVERRUN			8
153 #define UART_PARITY_ERROR			16
154 #define UART_READ_BUFF_UNDERRUN		32		// tried reading from empty buffer
155 
156 // status byte bits
157 #define STATUS_UART_ERROR			1	// cleared only on status byte read
158 #define STATUS_UART_READ_READY		2	// value always reflects current state
159 #define STATUS_UART_SEND_FULL		4	// value always reflects current state
160 #define STATUS_BUZZER_FINISHED		8	// value always reflects current state
161 #define STATUS_M1_FAULT				16	// cleared only on status byte read
162 #define STATUS_M1_CURRENT_HIGH		32	// cleared only on status byte read
163 #define STATUS_M2_FAULT				64	// cleared only on status byte read
164 #define STATUS_M2_CURRENT_HIGH		128	// cleared only on status byte read
165 
166 
167 // mega168's EEPROM addresses for settings
168 #define ADDR_INIT_CHECK				0	// check to see if EEPROM initialized
169 #define ADDR_M1_PWM_FREQUENCY		1	// freq + resolution of PWM1 (timer0)
170 #define ADDR_M2_PWM_FREQUENCY		2	// freq + resolution of PWM2 (timer2)
171 #define ADDR_M1_CURRENT_SAMPLES		3	// number of M1 ADC samples to avg
172 										//   must be a power of 2 <= 128
173 #define ADDR_M2_CURRENT_SAMPLES		4	// number of M2 ADC samples to avg
174 										//   must be a power of 2 <= 128
175 #define ADDR_M1_CURRENT_LIMIT		5	// 0 = no limit
176 #define ADDR_M1_CL_P_CONST			6	// 7-bit P val: pwm += P * (CL - cur)
177 										//   0 = shutdown motor on overlimit
178 #define ADDR_M2_CURRENT_LIMIT		7	// 0 = no limit
179 #define ADDR_M2_CL_P_CONST			8	// 7-bit P val: pwm += P * (CL - cur)
180 										//   0 = shutdowm motor on overlimit
181 #define ADDR_M1_ACCELERATION		9	// M1 acceleration; 0 = instantaneous
182 #define ADDR_M2_ACCELERATION		10	// M2 acceleration; 0 = instantaneous
183 #define ADDR_M1_BRAKE_DURATION		11	// M1 time to spend hard braking (ms)
184 #define ADDR_M2_BRAKE_DURATION		12	// M2 time to spend hard braking (ms)
185 #define ADDR_SERIAL_SETTINGS		13	// parity, stop bits, 2x speed, p. mode
186 #define ADDR_SERIAL_UBRRH			14	// UBRRH register (determines baud)
187 #define ADDR_SERIAL_UBRRL			15	// UBRRL register (determines baud)
188 #define ADDR_SERIAL_READ_READY		16	// UART read buffer ready for reading
189 #define ADDR_BUZZER_VOLUME			17	// buzzer volume
190 #define ADDR_STARTUP_MELODY			18	// melody that plays on startup
191 										//  0 - 7 = melody, 8 = silence
192 										//  else chirp
193 #define ADDR_NOTE_GAP				19	// default duration in ms of silent
194 										//   pause inserted after each note
195 #define ADDR_SCK_DURATION			20	// programmer SPI SCK setting
196 #define ADDR_ISP_STATE				21  // 168 ISP state (in progmode or not)
197 #define ADDR_ISP_SW_MINOR			22	// ISP version major byte
198 #define ADDR_ISP_SW_MAJOR			23	// ISP version minor byte
199 
200 
201 // no pointer to the start of melody0 is needed as location never changes
202 #define ADDR_MELODY_START_PTR_MSBS	24	// bit i is MSB of melody i+1 pointer
203 #define ADDR_MELODY1_START_PTR		25	// address of pointer to melody1 start
204 #define ADDR_MELODY2_START_PTR		26	// melody 2
205 #define ADDR_MELODY3_START_PTR		27	// melody 3
206 #define ADDR_MELODY4_START_PTR		28	// melody 4
207 #define ADDR_MELODY5_START_PTR		29	// melody 5
208 #define ADDR_MELODY6_START_PTR		30	// melody 6
209 #define ADDR_MELODY7_START_PTR		31	// melody 7
210 #define ADDR_MELODY7_END_PTR		32	// ptr to end of melody 7
211 
212 // address of 1st note of melody 0
213 #define ADDR_MELODY0_START			33
214 
215 // there is room in EEPROM for 159 notes, distributed in any way amongst the
216 // eight melodies.  The mega168's EEPROM is 512 bytes in size.
217 
218 #ifdef __cplusplus
219 
220 // C++ Function Declarations
221 
222 class OrangutanX2
223 {
224   private:
225 	static void writeToEEPROM(unsigned int address, unsigned char data);
226 	static unsigned char isEEPROMBusy();
227 
228 	// Delays execution until the EEPROM on the auxiliary MCU is available for
229 	// writing or reading.  This is a PRIVATE method.
waitForEEPROM()230 	static inline void waitForEEPROM()
231 	{
232 		while (isEEPROMBusy());
233 	}
234 
235 
236   public:
237 	static unsigned char getStatus();
238 	static void getFirmwareVersion(unsigned char &majorVersion, unsigned char &minorVersion);
239 
240 	// After this function is called, the mega168 must be manually reset for the
241 	// changes to take effect.  After the reset the settings will all be restored
242 	//  to their factory default values.
restoreDefaultSettings()243 	static inline void restoreDefaultSettings()
244 	{
245 		writeToEEPROM(ADDR_INIT_CHECK, 0xFF);
246 	}
247 
248 	static void saveAVRISPVersion(unsigned char vMajor, unsigned char vMinor);
249 
250 	// This method writes a byte to EEPROM if the specified address is outside
251 	// the parameter address space.  It can be safely used for general non-volatile
252 	// data storage using the auxiliary MCU's EEPROM.  If the specified address is
253 	// inside the parameter address space (i.e. address <= 23), the method
254 	// does nothing and the data is not stored.
saveEEPROMByte(unsigned int address,unsigned char data)255 	static inline void saveEEPROMByte(unsigned int address, unsigned char data)
256 	{
257 		if (address > 23)
258 			writeToEEPROM(address, data);
259 	}
260 
261 	// This method provides public access to the private writeToEEPROM() method.
262 	// It is intended to be used for saving X2 parameters, but it can be used to write
263 	// bytes to any address in the auxiliary MCU's EEPROM (0 - 511).  For saving bytes
264 	// that are not parameters, the saveEEPROMByte() method should be used so that
265 	// parameter data cannot be accidentally corrupted.  Parameter addresses are defined
266 	// in OrangutanX2.h.
saveParameter(unsigned int paramAddress,unsigned char paramValue)267 	static inline void saveParameter(unsigned int paramAddress, unsigned char paramValue)
268 	{
269 		writeToEEPROM(paramAddress, paramValue);
270 	}
271 
272 	static unsigned char readEEPROMByte(unsigned int address);
273 
readParameter(unsigned int paramAddress)274 	static inline unsigned char readParameter(unsigned int paramAddress)
275 	{
276 		return readEEPROMByte(paramAddress);
277 	}
278 
279 	static void setMotor(unsigned char motor, unsigned char operationMode, int speed);
280 	static void setPWMFrequencies(unsigned char M1Resolution, unsigned char M1Prescaler,
281 		unsigned char M2Resolution, unsigned char M2Prescaler, unsigned char save);
282 	static void setAcceleration(unsigned char motor, unsigned char accel,
283 		unsigned char save);
284 	static void setBrakeDuration(unsigned char motor, unsigned char brakeDur,
285 		unsigned char save);
286 	static void setNumCurrentSamples( unsigned char M1Exponent, unsigned char M2Exponent,
287 		unsigned char save);
288 	static void setCurrentLimit(unsigned char motor, unsigned char limit,
289 		unsigned char P, unsigned char save);
290 	static unsigned char getMotorCurrent(unsigned char motor);
291 
292 	static void playNote(unsigned char note, unsigned int duration);
293 	static void playFrequency(unsigned int frequency, unsigned int duration);
294 	static void buzzerOff();
295 	static void setVolume(unsigned char volume, unsigned char save = 0);
296 	static void setNoteGap(unsigned char noteGap, unsigned char save = 0);
297 
298 	static void setSerial(unsigned char parity, unsigned char stopBits,
299 		unsigned char speedMode, unsigned int baud_UBRR, unsigned char save);
300 	static void enablePermanentProgMode(unsigned char save);
301 	static void setReadReadySize(unsigned char rrSize, unsigned char save);
302 	static unsigned char getTXBufferSpace();
303 	static unsigned char getNumRXBytes();
304 	static unsigned char getSerialError();
305 	static unsigned char sendSerialByteIfReady(unsigned char data);
306 	static unsigned char readSerialByte();
307 };
308 
309 extern "C" {
310 #endif // __cplusplus
311 
312 // C Function Declarations
313 
314 void x2_get_firmware_version(unsigned char *vmajor, unsigned char *vminor);
315 unsigned char x2_get_status(void);
316 void x2_restore_default_settings(void);
317 void x2_save_avrisp_version(unsigned char vmajor, unsigned char vminor);
318 void x2_save_eeprom_byte(unsigned int address, unsigned char data);
319 void x2_save_parameter(unsigned int param_address, unsigned char param_value);
320 unsigned char x2_read_eeprom_byte(unsigned int address);
321 unsigned char x2_read_parameter(unsigned int param_address);
322 
323 void x2_set_motor(unsigned char motor, unsigned char operation_mode, int speed);
324 void x2_set_pwm_frequencies(unsigned char m1_resolution, unsigned char m1_prescaler,
325 	unsigned char m2_resolution, unsigned char m2_prescaler, unsigned char save);
326 void x2_set_acceleration(unsigned char motor, unsigned char accel, unsigned char save);
327 void x2_set_brake_duration(unsigned char motor, unsigned char brake_dur, unsigned char save);
328 void x2_set_num_current_samples(unsigned char m1_exp, unsigned char m2_exp, unsigned char save);
329 void x2_set_current_limit(unsigned char motor, unsigned char limit, unsigned char p,
330 	unsigned char save);
331 unsigned char x2_get_motor_current(unsigned char motor);
332 
333 void x2_play_note(unsigned char note, unsigned int duration);
334 void x2_play_frequency(unsigned int frequency, unsigned int duration);
335 void x2_buzzer_off(void);
336 void x2_set_volume(unsigned char volume, unsigned char save);
337 void x2_set_note_gap(unsigned char note_gap, unsigned char save);
338 
339 void x2_set_serial(unsigned char parity, unsigned char stop_bits, unsigned char speed_mode,
340 	unsigned int baud_ubrr, unsigned char save);
341 void x2_enable_permanent_programming_mode(unsigned char save);
342 void x2_set_read_ready_size(unsigned char rrsize, unsigned char save);
343 unsigned char x2_get_tx_buffer_space(void);
344 unsigned char x2_get_num_rx_bytes(void);
345 unsigned char x2_get_serial_error(void);
346 unsigned char x2_send_serial_byte_if_ready(unsigned char data);
347 unsigned char x2_read_serial_byte(void);
348 
349 #ifdef __cplusplus
350 }
351 #endif
352 
353 #endif // _ORANGUTAN_X2
354 
355 #endif // OrangutanX2_h
356