Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BeagleBone AI support #203

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion library/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ BUILDDIR := build
INCLUDEDIR := include
SHORTNAME := librobotcontrol.so
SONAME := librobotcontrol.so.1
FULLNAME := librobotcontrol.so.1.0.4
FULLNAME := librobotcontrol.so.1.0.5
TARGET := $(LIBDIR)/$(FULLNAME)
RC_VAR_DIR := var/lib/robotcontrol

Expand Down
26 changes: 20 additions & 6 deletions library/include/rc/adc.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,31 @@
* follows:
*
* - 1 - Ground
* - 2 - VDD_ADC (1.8V)
* - 3 - AIN0
* - 4 - AIN1
* - 5 - AIN2
* - 6 - AIN3
* - 2 - VDD_ADC (1.8V) (optional 3.3V on BeagleBone AI)
* - 3 - AIN0 (4 on BeagleBone AI)
* - 4 - AIN1 (6 on BeagleBone AI)
* - 5 - AIN2 (7 on BeagleBone AI)
* - 6 - AIN3 (5 on BeagleBone AI)
*
* All 8 ADC channels on the Sitara including the 4 listed above can be read
* with rc_adc_read_raw(int ch) which returns the raw integer output of the
* 12-bit ADC. rc_adc_read_volt(int ch) additionally converts this raw value to
* a voltage.
*
* On BeagleBone AI, the on-board ADC is replaced with an SMTPE811. The pin
* mapping was done in a way to support touch screens and the channels are
* all swiveled around. The ADC2AI() macro will swivel using this table:
*
* AM3358 - AI
* 0 - 0 (X+)
* 1 - 1 (X-)
* 2 - 3 (Y-)
* 3 - 2 (Y+)
* 4 - 7 (IN3)
* 5 - 6 (IN2)
* 6 - 4 (IN0)
* 7 - 5 (IN1 - grounded on BeagleBone AI)
*
* See the rc_test_adc example for sample use case.
*
* @addtogroup ADC
Expand Down Expand Up @@ -94,4 +108,4 @@ double rc_adc_dc_jack(void);

#endif // RC_ADC_H

/** @} end group ADC*/
/** @} end group ADC*/
6 changes: 4 additions & 2 deletions library/include/rc/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ typedef enum rc_model_t{
MODEL_RPI0_W,
MODEL_RPI_CM,
MODEL_RPI_CM3,
MODEL_PC
MODEL_PC,
MODEL_BB_AI,
MODEL_BB_AI_RC
} rc_model_t;


Expand Down Expand Up @@ -101,4 +103,4 @@ void rc_model_category_print(void);

#endif // RC_MODEL_H

/** @} end group Model*/
/** @} end group Model*/
10 changes: 6 additions & 4 deletions library/include/rc/pru.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ extern "C" {
* and "am335x-pru1-fw", please don't overwrite these if they exist. Name your
* firmware image something like "am335x-pru0-mycustom-fw".
*
* @param[in] ch pru core to start (0 or 1)
* @param[in] ch pru core to start (0 or 1 on AM3, 2-5 on AM5)
* @param[in] fw_name The firmware image name, e.g. "am335x-pru0-fw", do not
* include '/lib/firmware' in the path, only the file name.
*
Expand All @@ -42,15 +42,17 @@ int rc_pru_start(int ch, const char* fw_name);
* This is done by mapping to /dev/mem and therefore requires root privileges
* but provides extremely low-latency memory access to communicate with the PRU.
*
* @param[in] ch pru core to reference (0 or 1 on AM3, 2-5 on AM5)
*
* @return memory pointer on success, NULL on failure
*/
volatile uint32_t* rc_pru_shared_mem_ptr(void);
volatile uint32_t* rc_pru_shared_mem_ptr(int ch);


/**
* Unloads pru binaries
*
* @param[in] ch pru core to stop (0 or 1)
* @param[in] ch pru core to stop (0 or 1 on AM3, 2-5 on AM5)
*
* @return 0 on success, -1 on failure.
*/
Expand All @@ -63,4 +65,4 @@ int rc_pru_stop(int ch);

#endif // RC_PRU_H

/** @} end group PRU */
/** @} end group PRU */
4 changes: 2 additions & 2 deletions library/include/rc/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extern "C" {

#define RC_LIB_VERSION_MAJOR 1
#define RC_LIB_VERSION_MINOR 0
#define RC_LIB_VERSION_PATCH 4
#define RC_LIB_VERSION_PATCH 5
#define RC_LIB_VERSION_HEX ((RC_LIB_VERSION_MAJOR << 16) | \
(RC_LIB_VERSION_MINOR << 8) | \
(RC_LIB_VERSION_PATCH))
Expand Down Expand Up @@ -58,4 +58,4 @@ void rc_version_print(void);

#endif //RC_VERSION_H

/** @} end group version*/
/** @} end group version*/
12 changes: 10 additions & 2 deletions library/src/io/adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <fcntl.h> // for open
#include <unistd.h> // for close
#include <rc/adc.h>
#include <rc/model.h>

// preposessor macros
#define unlikely(x) __builtin_expect (!!(x), 0)
Expand All @@ -24,6 +25,7 @@
#define V_DIV_RATIO 11.0
#define BATT_DEADZONE 1.0

#define ADC2AI(x) (x==0?0:(x==1?1:(x==2?3:(x==3?2:(x==4?7:(x==5?6:(x==6?4:(x==7?5:-1))))))))
Copy link
Sponsor Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an ugly hack. Not the desired approach. I need to figure out how to do a better job remapping the channels in a more portable way.

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a series of symlink entries into the device tree to create something like /dev/bone/adc/Px_y? I'd think that would be a better way to handle GPIOs than with the LED drivers like Deepak Khatri did for now.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an ugly hack. Not the desired approach. I need to figure out how to do a better job remapping the channels in a more portable way.

can we make ADC2AI(x) an inline function


#define CHANNELS 8
#define IIO_DIR "/sys/bus/iio/devices/iio:device0"
Expand All @@ -42,7 +44,10 @@ int rc_adc_init(void)
if(init_flag) return 0;

for(i=0;i<CHANNELS;i++){
snprintf(buf, sizeof(buf), IIO_DIR "/in_voltage%d_raw", i);
if(rc_model()==MODEL_BB_AI || rc_model()==MODEL_BB_AI_RC)
snprintf(buf, sizeof(buf), IIO_DIR "/in_voltage%d_raw", ADC2AI(i));
else
snprintf(buf, sizeof(buf), IIO_DIR "/in_voltage%d_raw", i);
temp_fd = open(buf, O_RDONLY);
if(temp_fd<0){
perror("ERROR in rc_adc_init, failed to open iio adc interface\n");
Expand Down Expand Up @@ -100,7 +105,10 @@ double rc_adc_read_volt(int ch)
{
int raw = rc_adc_read_raw(ch);
if(raw<0) return -1;
return raw * 1.8 / 4095.0;
if(rc_model()==MODEL_BB_AI || rc_model()==MODEL_BB_AI_RC)
return raw * 0.805664062 / 1000.0; // * in_voltage_scale = mV
else
return raw * 1.8 / 4095.0;
}


Expand Down
2 changes: 1 addition & 1 deletion library/src/io/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#define likely(x) __builtin_expect (!!(x), 1)

#define DEVICE_BASE "/dev/gpiochip"
#define CHIPS_MAX 6 // up to 6 chip chips, make larger if you want
#define CHIPS_MAX 10 // up to 10 chip chips, make larger if you want
#define MAX_BUF 64


Expand Down
2 changes: 1 addition & 1 deletion library/src/led.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#define unlikely(x) __builtin_expect (!!(x), 0)


#define SYSFS_LED_DIR "/sys/devices/platform/leds/leds/"
#define SYSFS_LED_DIR "/sys/class/leds/"
#define BRIGHTNESS_FILE "/brightness"
#define MAX_BUF 128
#define NUM_LEDS 11
Expand Down
12 changes: 11 additions & 1 deletion library/src/model.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ static void __check_model(void)

current_category = CATEGORY_BEAGLEBONE;

if(strcmp(c, "BeagleBoard.org BeagleBone AI")==0){
current_model = MODEL_BB_AI;
return;
}
if(strcmp(c, "BeagleBoard.org BeagleBone AI RoboticsCape")==0){
current_model = MODEL_BB_AI_RC;
return;
}
if(strcmp(c, "TI AM335x BeagleBone Black")==0){
current_model = MODEL_BB_BLACK;
return;
Expand Down Expand Up @@ -178,6 +186,8 @@ void rc_model_print(void)
switch(model){

caseprint(MODEL_UNKNOWN)
caseprint(MODEL_BB_AI)
caseprint(MODEL_BB_AI_RC)
caseprint(MODEL_BB_BLACK)
caseprint(MODEL_BB_BLACK_RC)
caseprint(MODEL_BB_BLACK_W)
Expand Down Expand Up @@ -222,4 +232,4 @@ void rc_model_category_print(void)
return;
}

#undef caseprint
#undef caseprint
45 changes: 34 additions & 11 deletions library/src/pru/encoder_pru.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,27 @@
#include <rc/pru.h>
#include <rc/time.h>
#include <rc/encoder_pru.h>
#include <rc/model.h>

#define ENCODER_PRU_CH 0 // PRU0
#define ENCODER_PRU_FW "am335x-pru0-rc-encoder-fw"
#define ENCODER_MEM_OFFSET 16
#define AM335X_ENCODER_PRU_CH 0 // PRU0
#define AM335X_ENCODER_PRU_FW "am335x-pru0-rc-encoder-fw"
#define AM57XX_ENCODER_PRU_CH 3 // PRU1_1
#define AM57XX_ENCODER_PRU_FW "am57xx-pru1_1-rc-encoder-fw"
#define ENCODER_MEM_OFFSET 16

// pru shared memory pointer
static volatile unsigned int* shared_mem_32bit_ptr = NULL;
static int init_flag=0;

int rc_encoder_pru_init(void)
{
return 0; // until we fix for AM5
int i;
// map memory
shared_mem_32bit_ptr = rc_pru_shared_mem_ptr();
if(rc_model()==MODEL_BB_AI || rc_model()==MODEL_BB_AI_RC)
shared_mem_32bit_ptr = rc_pru_shared_mem_ptr(AM57XX_ENCODER_PRU_CH);
else
shared_mem_32bit_ptr = rc_pru_shared_mem_ptr(AM335X_ENCODER_PRU_CH);
if(shared_mem_32bit_ptr==NULL){
fprintf(stderr, "ERROR in rc_encoder_pru_init, failed to map shared memory pointer\n");
init_flag=0;
Expand All @@ -34,9 +41,16 @@ int rc_encoder_pru_init(void)
shared_mem_32bit_ptr[ENCODER_MEM_OFFSET]=42;

// start pru
if(rc_pru_start(ENCODER_PRU_CH, ENCODER_PRU_FW)){
fprintf(stderr,"ERROR in rc_encoder_pru_init, failed to start PRU%d\n", ENCODER_PRU_CH);
return -1;
if(rc_model()==MODEL_BB_AI || rc_model()==MODEL_BB_AI_RC){
if(rc_pru_start(AM57XX_ENCODER_PRU_CH, AM57XX_ENCODER_PRU_FW)){
fprintf(stderr,"ERROR in rc_encoder_pru_init, failed to start PRU%d\n", AM57XX_ENCODER_PRU_CH);
return -1;
}
} else {
if(rc_pru_start(AM335X_ENCODER_PRU_CH, AM335X_ENCODER_PRU_FW)){
fprintf(stderr,"ERROR in rc_encoder_pru_init, failed to start PRU%d\n", AM335X_ENCODER_PRU_CH);
return -1;
}
}

// make sure memory actually got zero'd out
Expand All @@ -48,9 +62,15 @@ int rc_encoder_pru_init(void)
rc_usleep(100000);
}

fprintf(stderr, "ERROR in rc_encoder_pru_init, %s failed to load\n", ENCODER_PRU_FW);
fprintf(stderr, "attempting to stop PRU%d\n", ENCODER_PRU_CH);
rc_pru_stop(ENCODER_PRU_CH);
if(rc_model()==MODEL_BB_AI || rc_model()==MODEL_BB_AI_RC){
fprintf(stderr, "ERROR in rc_encoder_pru_init, %s failed to load\n", AM57XX_ENCODER_PRU_FW);
fprintf(stderr, "attempting to stop PRU%d\n", AM57XX_ENCODER_PRU_CH);
rc_pru_stop(AM57XX_ENCODER_PRU_CH);
} else {
fprintf(stderr, "ERROR in rc_encoder_pru_init, %s failed to load\n", AM335X_ENCODER_PRU_FW);
fprintf(stderr, "attempting to stop PRU%d\n", AM335X_ENCODER_PRU_CH);
rc_pru_stop(AM335X_ENCODER_PRU_CH);
}
init_flag=0;
return -1;
}
Expand All @@ -62,7 +82,10 @@ void rc_encoder_pru_cleanup(void)
if(shared_mem_32bit_ptr != NULL){
shared_mem_32bit_ptr[ENCODER_MEM_OFFSET]=0;
}
rc_pru_stop(ENCODER_PRU_CH);
if(rc_model()==MODEL_BB_AI || rc_model()==MODEL_BB_AI_RC)
rc_pru_stop(AM57XX_ENCODER_PRU_CH);
else
rc_pru_stop(AM335X_ENCODER_PRU_CH);
shared_mem_32bit_ptr = NULL;
init_flag=0;
return;
Expand Down
Loading