Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
pca9685_i2c.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2013-2020 Chris Efstathiou hendrixgr@gmail.com
3 *
4 * This file is part of paparazzi.
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
29//###################################################################################################
30// I N C L U D E D H E A D E R F I L E S
31//###################################################################################################
34#include "mcu_periph/i2c.h"
35#include "mcu_periph/sys_time.h"
36
37#include "math/pprz_isa.h"
38#include "mcu_periph/sys_time.h"
39#include "modules/core/abi.h"
40#include "mcu_periph/uart.h"
41
42#if DOWNLINK
44#endif
45
46
47
48
49
50//###################################################################################################
51// P R E P R O C E S S O R D I R E C T I V E S A N D D E F I N I T I O N S
52//###################################################################################################
53// BIG ENDIAN DEFINITIONS
54//#define BUF2INT(_buf,_idx) ((int16_t)((_buf[_idx]<<8) | _buf[_idx+1]))
55//#define INT2BUF(_int,_buf,_idx) { _buf[_idx] = (_int>>8); _buf[_idx+1] = _int; }
56
57// LITTLE ENDIAN DEFINITIONS USED FOR AvR CPU DUE TO MORE EFFICIENT DATA TRANSFERS
58#define BUF2INT(_buf,_idx) ((int16_t)((_buf[_idx+1]<<8) | _buf[_idx]))
59#define INT2BUF(_int,_buf,_idx) { _buf[_idx] = _int; _buf[_idx+1] = (_int>>8); }
60
61#ifndef PCA9685_I2C_DEV
62#define PCA9685_I2C_DEV i2c2
63#endif
65
66#ifndef PCA9865_SRV_RESOLUTION
67#define PCA9865_SRV_RESOLUTION 1. // in microseconds
68#endif
69
70#ifndef PCA9865_SRV_DEFAULT_VAL_US
71#define PCA9865_SRV_DEFAULT_VAL_US 1000. // in microseconds
72#endif
73
74#ifndef PCA9865_SRV_NUMBER
75#define PCA9865_SRV_NUMBER 16 // in microseconds
76#endif
77
78// I2C Addreses
79#ifndef PCA9685_I2C_SLAVE_ADDR
80#define PCA9685_I2C_SLAVE_ADDR 0xE0
81#endif
83
84#ifndef PCA9685_I2C_ALLCALL_ADDR
85#define PCA9685_I2C_ALLCALL_ADDR 0xE0
86#endif
87#ifndef PCA9685_I2C_RESET_ADDR
88#define PCA9685_I2C_RESET_ADDR 0x06
89#endif
90#ifndef PCA9685_I2C_GEN_CALL_ADDR
91#define PCA9685_I2C_GEN_CALL_ADDR 0x00
92#endif
93
94// Register addresses
95#define PCA9685_MODE1_REG_ADDR 0x00
96#define PCA9685_MODE2_REG_ADDR 0x01
97#define PCA9685_ALLCALL_ADDR 0x05
98
99#define PCA9685_LED0_ON_L_REG_ADDR 0X06
100#define PCA9685_LED0_ON_H_REG_ADDR 0X07
101#define PCA9685_LED0_OFF_L_REG_ADDR 0X08
102#define PCA9685_LED0_OFF_H_REG_ADDR 0X09
103
104#define PCA9685_LED1_ON_L_REG_ADDR 0X0A
105#define PCA9685_LED1_ON_H_REG_ADDR 0X0B
106#define PCA9685_LED1_OFF_L_REG_ADDR 0X0C
107#define PCA9685_LED1_OFF_H_REG_ADDR 0X0D
108
109#define PCA9685_LED2_ON_L_REG_ADDR 0X0E
110#define PCA9685_LED2_ON_H_REG_ADDR 0X0F
111#define PCA9685_LED2_OFF_L_REG_ADDR 0X10
112#define PCA9685_LED2_OFF_H_REG_ADDR 0X11
113
114#define PCA9685_LED3_ON_L_REG_ADDR 0X12
115#define PCA9685_LED3_ON_H_REG_ADDR 0X13
116#define PCA9685_LED3_OFF_L_REG_ADDR 0X14
117#define PCA9685_LED3_OFF_H_REG_ADDR 0X15
118
119#define PCA9685_LED4_ON_L_REG_ADDR 0X16
120#define PCA9685_LED4_ON_H_REG_ADDR 0X17
121#define PCA9685_LED4_OFF_L_REG_ADDR 0X18
122#define PCA9685_LED4_OFF_H_REG_ADDR 0X19
123
124#define PCA9685_LED5_ON_L_REG_ADDR 0X1A
125#define PCA9685_LED5_ON_H_REG_ADDR 0X1B
126#define PCA9685_LED5_OFF_L_REG_ADDR 0X1C
127#define PCA9685_LED5_OFF_H_REG_ADDR 0X1D
128
129#define PCA9685_LED6_ON_L_REG_ADDR 0X1E
130#define PCA9685_LED6_ON_H_REG_ADDR 0X1F
131#define PCA9685_LED6_OFF_L_REG_ADDR 0X20
132#define PCA9685_LED6_OFF_H_REG_ADDR 0X21
133
134#define PCA9685_LED7_ON_L_REG_ADDR 0X22
135#define PCA9685_LED7_ON_H_REG_ADDR 0X23
136#define PCA9685_LED7_OFF_L_REG_ADDR 0X24
137#define PCA9685_LED7_OFF_H_REG_ADDR 0X25
138
139
140#define PCA9685_LED8_ON_L_REG_ADDR 0X26
141#define PCA9685_LED8_ON_H_REG_ADDR 0X27
142#define PCA9685_LED8_OFF_L_REG_ADDR 0X28
143#define PCA9685_LED8_OFF_H_REG_ADDR 0X29
144
145#define PCA9685_LED9_ON_L_REG_ADDR 0X2A
146#define PCA9685_LED9_ON_H_REG_ADDR 0X2B
147#define PCA9685_LED9_OFF_L_REG_ADDR 0X2C
148#define PCA9685_LED9_OFF_H_REG_ADDR 0X2D
149
150#define PCA9685_LED10_ON_L_REG_ADDR 0X2E
151#define PCA9685_LED10_ON_H_REG_ADDR 0X2F
152#define PCA9685_LED10_OFF_L_REG_ADDR 0X30
153#define PCA9685_LED10_OFF_H_REG_ADDR 0X31
154
155#define PCA9685_LED11_ON_L_REG_ADDR 0X32
156#define PCA9685_LED11_ON_H_REG_ADDR 0X33
157#define PCA9685_LED11_OFF_L_REG_ADDR 0X34
158#define PCA9685_LED11_OFF_H_REG_ADDR 0X35
159
160#define PCA9685_LED12_ON_L_REG_ADDR 0X36
161#define PCA9685_LED12_ON_H_REG_ADDR 0X37
162#define PCA9685_LED12_OFF_L_REG_ADDR 0X38
163#define PCA9685_LED12_OFF_H_REG_ADDR 0X39
164
165#define PCA9685_LED13_ON_L_REG_ADDR 0X3A
166#define PCA9685_LED13_ON_H_REG_ADDR 0X3B
167#define PCA9685_LED13_OFF_L_REG_ADDR 0X3C
168#define PCA9685_LED13_OFF_H_REG_ADDR 0X3D
169
170#define PCA9685_LED14_ON_L_REG_ADDR 0X3E
171#define PCA9685_LED14_ON_H_REG_ADDR 0X3F
172#define PCA9685_LED14_OFF_L_REG_ADDR 0X40
173#define PCA9685_LED14_OFF_H_REG_ADDR 0X41
174
175#define PCA9685_LED15_ON_L_REG_ADDR 0X42
176#define PCA9685_LED15_ON_H_REG_ADDR 0X43
177#define PCA9685_LED15_OFF_L_REG_ADDR 0X44
178#define PCA9685_LED15_OFF_H_REG_ADDR 0X45
179
180#define PCA9685_ALL_LED_ON_L_REG_ADDR 0XFA
181#define PCA9685_ALL_LED_ON_H_REG_ADDR 0XFB
182#define PCA9685_ALL_LED_OFF_L_REG_ADDR 0XFC
183#define PCA9685_ALL_LED_OFF_H_REG_ADDR 0XFD
184
185#define PCA9685_PRESCALER_REG_ADDR 0XFE
186
187//Bit positions
188//MODE 0 REGISTER
189#define PCA9865_RESTART_BIT 7 // 1= RESTART ENABLE, DEFAULT = 0
190#define PCA9865_AUTO_INCREMENT_BIT 5 // 1 = AUTO INCREMENT, DEFAULT = 0
191#define PCA9865_SLEEP_BIT 4 // 1 = LOW POWER MODE (OSC OFF), 0=NORMAL MODE, DEFAULT=0
192#define PCA9865_ALLCALL_BIT 0 // 1 = ALL LED ENABLE, DEFAULT = 1
193//MODE 1 REGISTER
194#define PCA9865_OUTDRV_BIT 2 // 1 = TOTEM POLE, 0 = OPEN DRAIN, DEFAULT = 1
195
196
197
198
199#if !defined(SITL)
200//###################################################################################################
201// P R I V A T E F U N C T I O N P R O T O T Y P E S
202//###################################################################################################
203#if defined(PCA9685_SEND_SERVO_VALUES) && PCA9685_SEND_SERVO_VALUES == 1
204static void pca9685_send_servo_values(struct transport_tx *trans, struct link_device *dev);
205#endif
206
207
208
209
210//###################################################################################################
211// G L O B A L V A R I A B L E S
212//###################################################################################################
213
214enum {
222
227#if defined(PCA9685_SEND_SERVO_VALUES) && PCA9685_SEND_SERVO_VALUES == 1
228PRINT_CONFIG_MSG("PCA9685 servo values can be found in the ""BARO_WORDS"" message")
230#endif
232
233
234//###################################################################################################
235// P R I V A T E F U N C T I O N D E F I N I T I O N S
236//###################################################################################################
237
238//111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
239#if defined(PCA9685_SEND_SERVO_VALUES) && PCA9685_SEND_SERVO_VALUES == 1
240static void pca9685_send_servo_values(struct transport_tx *trans, struct link_device *dev)
241{
242
243// For debugging purposes we send anly the first 4 servo values using the BARO_WORDS message.
244// Those values are read back from PCA9865 so they indicate if the module is working as intended.
246 trans, dev, AC_ID,
249 );
250
251
252 return;
253}
254#endif
255
256
257//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
258// P U B L I C F U N C T I O N D E F I N I T I O N S
259//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
260
261//111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
263{
265
266 if (srv_nb < 16) {
269 pca9865_reg_nb[srv_nb] = (srv_nb * 4) + 8;
270
271 }
272
273 return (FALSE);
274}
275
276
277
278//222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
280{
281
283 uint32_t timer0 = 0;
284
285// clear all arrays to zero.
286 for (srv_cnt = 0; srv_cnt < PCA9865_SRV_NUMBER; srv_cnt++) {
288#if defined(PCA9685_SEND_SERVO_VALUES) && PCA9685_SEND_SERVO_VALUES == 1
290#endif
292 }
293 srv_cnt = 0;
296
301 if (sys_time.nb_tick > timer0) { break; }
302 }
303
304// Internal Oscillator Off, the oscillator is off by default on power up.
306 pca9685_i2c_trans.buf[1] = (1 << PCA9865_SLEEP_BIT) | (1 << PCA9865_ALLCALL_BIT); // OSC off
310 if (sys_time.nb_tick > timer0) { break; }
311 }
312
313 reg_value = (uint16_t)((float)PCA9865_SRV_RESOLUTION / 0.04); //0.04 = 1/25 Mhz
314 if (reg_value > 0xFF) { reg_value = 0xFF; } // Sanity check.
320 if (sys_time.nb_tick > timer0) { break; }
321 }
322
323// Internal Oscillator On, Auto Increment on, AllCall enabled, 500 microseconds needed.
329 if (sys_time.nb_tick > timer0) { break; }
330 }
331
332 do {
337 if (sys_time.nb_tick > timer0) { break; }
338 }
339
340 } while ((pca9685_i2c_trans.buf[0] & (1 << PCA9865_RESTART_BIT)) != 0);
341
343 pca9685_i2c_trans.buf[1] = 0;
344 pca9685_i2c_trans.buf[2] = 0;
347 pca9685_i2c_trans.buf[4] = (uint8_t)((reg_value >> 8) & 0x000F);
351 if (sys_time.nb_tick > timer0) { break; }
352 }
353
354
357
358#if DOWNLINK
359#if defined(PCA9685_SEND_SERVO_VALUES) && PCA9685_SEND_SERVO_VALUES == 1
361#endif
362#endif
363
364// Initialize all 16 servo with the default values
365 pca9865_set_servo(0, 1500);
366 pca9865_set_servo(1, 1500);
367 pca9865_set_servo(2, 1000);
368 pca9865_set_servo(3, 1500);
369 for (srv_cnt = 4; srv_cnt < PCA9865_SRV_NUMBER; srv_cnt++) {
371 }
372 srv_cnt = 0;
373
374 return;
375}
376
377
378
379//333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
381{
382// If a servo change was requested write the appropriate pca9685 registers.
383// Since those servos are not intented for flight surface control they can be updated slower
384// at about one servo each module cycle. This way i2c load is minimized.
385//
386// Start searching for a servo change request either after intialization or after all
387// servo channels have been searched (looping).
388// This loop will be executed always until a servo value change is requested.
389// Then it will break with "srv_cnt" having the servo number to be changed.
390
391// DELAY IN ORDER TO GIVE TIME TO THE INTERNAL PCA9865 OSCILLATOR TO STABILIZE.
392//if (sys_time.nb_sec > 3){
394 for (srv_cnt = 0; srv_cnt < 16; srv_cnt++) {
395 if (pca9865_reg_nb[srv_cnt] > 0) {
397 break;
398 }
399 }
400 }
401
402 // Change the above found register in order to update the servo pwm value.
403 // The search for another servo to change is completed in the "event" function.
404 if (srv_cnt < 16) {
411 }
412 }
413//}
414
415 return;
416}
417
418
419
420//444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444
422{
423
424//--------------------------------------------------------------------------------------------------
425// IF SUCCESFULL
426//--------------------------------------------------------------------------------------------------
428
430 // Read back the changed value just to be sure...
434
436#if defined(PCA9685_SEND_SERVO_VALUES) && PCA9685_SEND_SERVO_VALUES == 1
438#endif
440 //pca9685_i2c_init();
441 return;
442 }
444 // Delete this request.
446 // Search for the next changed servo value.
447 // If a value > 0 is detected x will contain the new servo number to be changed.
448 srv_cnt++;
449 for (; srv_cnt < 16; srv_cnt++) { if (pca9865_reg_nb[srv_cnt] > 0) { break; } }
450 }
451//-------------------------------------------------------------------------------------------------
452// ELSE IF NOT SUCCESFULL
453//-------------------------------------------------------------------------------------------------
454 }//else{ pca9685_i2c_init(); }
455
456 return;
457}
458
459#else
460// just to stop the compiler complaining i manipulte srv_nb and srv_val a little.
462void pca9685_i2c_init(void) { return; }
463void pca9685_i2c_periodic(void) { return; }
464void pca9685_i2c_event(void) { return; }
465
466#endif // #if !defined(SITL)
467
468/************************************************************************************************/
469// T H E E N D
470/************************************************************************************************/
471
Main include for ABI (AirBorneInterface).
volatile uint8_t buf[I2C_BUF_LEN]
Transaction buffer With I2C_BUF_LEN number of bytes.
Definition i2c.h:122
enum I2CTransactionStatus status
Transaction status.
Definition i2c.h:126
bool i2c_transmit(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len)
Submit a write only transaction.
Definition i2c.c:202
bool i2c_transceive(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len_w, uint16_t len_r)
Submit a write/read transaction.
Definition i2c.c:222
@ I2CTransSuccess
transaction successfully finished by I2C driver
Definition i2c.h:57
@ I2CTransDone
transaction set to done by user level
Definition i2c.h:59
@ I2CTransPending
transaction is pending in queue
Definition i2c.h:55
I2C transaction structure.
Definition i2c.h:93
Architecture independent I2C (Inter-Integrated Circuit Bus) API.
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
uint16_t foo
Definition main_demo5.c:58
PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF)
uint8_t pca9685_i2c_status
#define PCA9685_MODE1_REG_ADDR
Definition pca9685_i2c.c:95
uint8_t pca9865_reg_nb[16]
#define PCA9685_I2C_DEV
Definition pca9685_i2c.c:62
void pca9685_i2c_periodic(void)
#define PCA9865_SRV_RESOLUTION
Definition pca9685_i2c.c:67
void pca9685_i2c_init(void)
@ PCA9865_I2C_STATUS_CHANGE_LED_REG_FINISHED
@ PCA9685_I2C_STATUS_INITIALIZED
@ PCA9865_I2C_STATUS_READ_LED_REG_BUSY
@ PCA9865_I2C_STATUS_WRITE_LED_REG_READY
@ PCA9685_I2C_STATUS_UNINIT
@ PCA9865_I2C_STATUS_WRITE_LED_REG_BUSY
void pca9685_i2c_event(void)
bool pca9865_set_servo(uint8_t srv_nb, uint16_t srv_val)
#define PCA9865_ALLCALL_BIT
#define PCA9685_ALL_LED_ON_L_REG_ADDR
uint8_t srv_cnt
#define PCA9865_SLEEP_BIT
#define PCA9865_RESTART_BIT
#define PCA9685_I2C_GEN_CALL_ADDR
Definition pca9685_i2c.c:91
uint16_t pca9865_write_servo_vals[PCA9865_SRV_NUMBER]
struct i2c_transaction pca9685_i2c_trans
#define PCA9685_I2C_RESET_ADDR
Definition pca9685_i2c.c:88
#define PCA9865_SRV_NUMBER
Definition pca9685_i2c.c:75
#define PCA9685_I2C_ALLCALL_ADDR
Definition pca9685_i2c.c:85
#define PCA9865_SRV_DEFAULT_VAL_US
Definition pca9685_i2c.c:71
#define PCA9685_I2C_SLAVE_ADDR
Definition pca9685_i2c.c:80
#define BUF2INT(_buf, _idx)
Definition pca9685_i2c.c:58
#define PCA9685_PRESCALER_REG_ADDR
#define PCA9865_AUTO_INCREMENT_BIT
Paparazzi fixed point algebra.
Paparazzi atmospheric pressure conversion utilities.
#define FALSE
Definition std.h:5
static const struct usb_device_descriptor dev
Definition usb_ser_hw.c:74
Architecture independent timing functions.
volatile uint32_t nb_tick
SYS_TIME_TICKS since startup.
Definition sys_time.h:74
#define SYS_TIME_FREQUENCY
(Default) sys_time timer frequency in Hz.
Definition sys_time.h:56
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition telemetry.c:51
Periodic telemetry system header (includes downlink utility and generated code).
#define DefaultPeriodic
Set default periodic telemetry.
Definition telemetry.h:66
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.