MMDVMHost on a Le Potato

Several years ago I supported a Kickstarter campaign for a single-board computer called Le Potato. Strange name aside it looked pretty good. It had 2GB of ram, an optional eMMC module, and an Amologic S905X processor. When it arrived in 2017 I powered it up messed around with it a bit, and promptly stuck it in a drawer.

Fast forward five years and here I am with an STM32-DVM board from Repeater Builder setting it up on a Raspberry Pi I happened to buy before they became rare.

I had it all set up with Pi-Star running on it and was using it as a DMR repeater. Then I started to think. The ease of use of Pi-Star was great and it worked very well. But maybe I wanted to see what I could do on my own, without relying on Pi-Star. And, while I’m at it, seeing as how the Raspberry Pi had gotten so rare and expensive, maybe I can find something else to set it up on. Then I thought about the Le Potato sitting in a drawer in my shop.

So I head over to the Libre Computer page and see that there are several options for distributions for the board. So I decide on Raspbian Bullseye thinking that it might make following instructions easier for tutorials written with the Raspberry Pi in mind. I also decided to look it up and, yes, the Le Potato is still available for $35 from Amazon or Loverpi. I am not affiliated with either site and I make no money from links you click.

Looking at the map for the 40-pin header, it looked like the STM32-DVM board could be plugged right in as is. So I put their Raspbian Buster on an SD card and booted the board. There are ways around this but I decided it would be easiest for me to connect a keyboard and monitor for the first boot. Then ran raspi-config to set up SSH access and a user and password.

Next, I followed these instructions for enabling hardware on the Le Potato, namely the serial port on the 40-pin header and I2C. By the way, the serial port on the 40-pin header on the Le Potato is /dev/ttyAML6. I then followed these instructions for building MMDVMHost. I also set up a 100MB ram drive for MMDVMHost to log to.

DG9VH has two dashboards available for MMDVMHost. An older one just called MMDVMHost-Dashboard and a newer one called MMDVMHost-Websocketboard. I had installed the older dashboard first and then later installed the Websocketboard. I have them both running and can choose which one I want to see by the port number I use. The newer Websocketboard is set up to use port 8000.

And that’s about it. Everything mostly works. For some reason, I have to set the baud rate in the MMDVM.ini file to 115200. I’m pretty sure on the Raspberry Pi this was working at 460800 but that wouldn’t work on the Le Potato. The OS will report that the baud rate is set to 460800 but it won’t talk to the STM32-DVM card. Also 230400 would not work either. Again, I could set the port to that speed but it wouldn’t talk to the board. Also, my OLED display will not work. In looking at the source code for the OLED displays, it seems that some Broadcom-specific code is used for accessing the I2C port.

So, my next steps will be to see if I can figure out what’s up with the baud rate, re-write the OLED display part of the code to work with the I2C on the Le Potato, and eventually, see what I can do to customize the dashboard.

Well, that’s about it. Thank you. Questions?

UPDATES:

Update #1: Looking at the MMDVM firmware repository I noticed there was a recent commit to allow a serial port speed of 500000 for Allwinner CPUs. I decided to go ahead and get set up to build the modem firmware. Tried configuring the firmware for a serial speed of 500000 but MMDVMHost complained that it was an unsupported serial port speed. Decided not to mess with it right now so I went back and recompiled the firmware for 460800 and it works now at 460800. Apparently, the firmware I had in the modem was not set up for 460800 originally.

Update #2: OLED display is now working. There is a one-line readme file in the ArduiPi_OLED source that says to run autogen.sh to build for a BananaPi. Doing so removed some of the bcm2835-specific code but not all of it. Most of the remaining code dealt with using GPIO for a reset on the I2C display or for chip select on the SPI version of the display. Since I was using I2C with no reset connected I was able to comment out those lines.

Update #3: As requested here are the changes I made to get the OLED working. Again, this will only work on an I2C OLED. It should be possible to get an SPI OLED working. It would just require adding code for the GPIO on the Le Potato for SPI select line.

Below are the changes as a diff against the ArduiPi_OLED source code. Mostly it is just commenting out the Broadcom-specific code.

diff --git a/ArduiPi_OLED.cpp b/ArduiPi_OLED.cpp
index b13c3d9..405ba57 100644
--- a/ArduiPi_OLED.cpp
+++ b/ArduiPi_OLED.cpp
@@ -295,6 +295,7 @@ boolean ArduiPi_OLED::select_oled(uint8_t OLED_TYPE)
 
     case OLED_ADAFRUIT_I2C_128x64:
       _i2c_addr = ADAFRUIT_I2C_ADDRESS;
+	fprintf(stderr,"Arduipi: Adafruit display selected\n");
     break;
     
     case OLED_SEEED_I2C_128x64:
@@ -338,8 +339,8 @@ boolean ArduiPi_OLED::select_oled(uint8_t OLED_TYPE)
     return false;
 
   // Init Raspberry PI GPIO
-  if (!bcm2835_init())
-    return false;
+//  if (!bcm2835_init())
+//    return false;
     
   return true;
   
@@ -395,7 +396,7 @@ boolean ArduiPi_OLED::init(int8_t RST, uint8_t OLED_TYPE)
   // bcm2835_i2c_set_baudrate(400000);
 
   // Setup reset pin direction as output
-  bcm2835_gpio_fsel(rst, BCM2835_GPIO_FSEL_OUTP);
+//  bcm2835_gpio_fsel(rst, BCM2835_GPIO_FSEL_OUTP);
   
   return ( true);
 }
@@ -430,22 +431,23 @@ void ArduiPi_OLED::begin( void )
   uint8_t precharge;
   
   constructor(oled_width, oled_height);
+  fprintf(stderr,"ArduiPi is beginning\n");
 
   // Setup reset pin direction (used by both SPI and I2C)  
-  bcm2835_gpio_fsel(rst, BCM2835_GPIO_FSEL_OUTP);
-  bcm2835_gpio_write(rst, HIGH);
+//  bcm2835_gpio_fsel(rst, BCM2835_GPIO_FSEL_OUTP);
+//  bcm2835_gpio_write(rst, HIGH);
   
   // VDD (3.3V) goes high at start, lets just chill for a ms
   usleep(1000);
   
   // bring reset low
-  bcm2835_gpio_write(rst, LOW);
+//  bcm2835_gpio_write(rst, LOW);
   
   // wait 10ms
   usleep(10000);
   
   // bring out of reset
-  bcm2835_gpio_write(rst, HIGH);
+//  bcm2835_gpio_write(rst, HIGH);
   
   // depends on OLED type configuration
   if (oled_height == 32)
diff --git a/Makefile b/Makefile
index f974fa7..0d5069c 100644
--- a/Makefile
+++ b/Makefile
@@ -24,10 +24,10 @@ HWPLAT:=$(shell cat $(ROOT_DIR)/hwplatform)
 
 # sets CCFLAGS hw platform dependant
 ifeq ($(HWPLAT),BananaPI)
-	CCFLAGS=-Wall -Ofast -mfpu=vfpv4 -mfloat-abi=hard -march=armv7 -mtune=cortex-a7 -DBANANAPI
+	CCFLAGS=-Wall -Ofast -DBANANAPI
 else # fallback to raspberry
 	# The recommended compiler flags for the Raspberry Pi
-	CCFLAGS=-Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s
+	CCFLAGS=-Wall -Ofast 
 endif
 
 # Where you want it installed when you do 'make install'
diff --git a/bcm2835.c b/bcm2835.c
index 75954d7..5524c4e 100644
--- a/bcm2835.c
+++ b/bcm2835.c
@@ -817,7 +817,7 @@ int bcm2835_i2c_begin(void)
 	int fd ;
 
 #if BANANAPI
-	if ((fd = open ("/dev/i2c-2", O_RDWR)) < 0)
+	if ((fd = open ("/dev/i2c-0", O_RDWR)) < 0)
 #else
 	if ((fd = open (bcm2835_get_pi_version() == 1 ? "/dev/i2c-0":"/dev/i2c-1" , O_RDWR)) < 0)
 #endif
@@ -1020,12 +1020,12 @@ exit:
 int bcm2835_close(void)
 {
     if (debug) return 1; // Success
-    unmapmem((void**) &bcm2835_gpio, BCM2835_BLOCK_SIZE);
-    unmapmem((void**) &bcm2835_pwm,  BCM2835_BLOCK_SIZE);
-    unmapmem((void**) &bcm2835_clk,  BCM2835_BLOCK_SIZE);
-    unmapmem((void**) &bcm2835_spi0, BCM2835_BLOCK_SIZE);
-    unmapmem((void**) &bcm2835_bsc0, BCM2835_BLOCK_SIZE);
-    unmapmem((void**) &bcm2835_bsc1, BCM2835_BLOCK_SIZE);
-    unmapmem((void**) &bcm2835_st,   BCM2835_BLOCK_SIZE);
+//    unmapmem((void**) &bcm2835_gpio, BCM2835_BLOCK_SIZE);
+//    unmapmem((void**) &bcm2835_pwm,  BCM2835_BLOCK_SIZE);
+//    unmapmem((void**) &bcm2835_clk,  BCM2835_BLOCK_SIZE);
+//    unmapmem((void**) &bcm2835_spi0, BCM2835_BLOCK_SIZE);
+//    unmapmem((void**) &bcm2835_bsc0, BCM2835_BLOCK_SIZE);
+//    unmapmem((void**) &bcm2835_bsc1, BCM2835_BLOCK_SIZE);
+//    unmapmem((void**) &bcm2835_st,   BCM2835_BLOCK_SIZE);
     return 1; // Success
 }    
diff --git a/examples/Makefile b/examples/Makefile
index 98c3334..587ecf0 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -20,10 +20,10 @@ HWPLAT:=$(shell cat $(ROOT_DIR)/../hwplatform)
 
 # sets CCFLAGS hw platform dependant
 ifeq ($(HWPLAT),BananaPI)
-        CCFLAGS=-Wall -Ofast -mfpu=vfpv4 -mfloat-abi=hard -march=armv7 -mtune=cortex-a7 -DBANANAPI
+        CCFLAGS=-Wall -Ofast -DBANANAPI -L/usr/local/lib/
 else # fallback to raspberry
         # The recommended compiler flags for the Raspberry Pi
-        CCFLAGS=-Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s
+        CCFLAGS=-Ofast 
 endif
 
 prefix := /usr/local
diff --git a/hwplatform b/hwplatform
index b20bbc3..8ded141 100644
--- a/hwplatform
+++ b/hwplatform
@@ -1 +1 @@
-RaspberryPI
+BananaPI

2 thoughts on “MMDVMHost on a Le Potato”

  1. Hi,

    I followed much the same path of building MMDVMHost, ircDDBGateway, YSFgateway, on a Le Potato board but I have not been able to get the OLED display to work. Can you share more about how you accomplished that?

    Vy 73 de Brian, NJ6N

    1. I can. I’ll post the details in a couple of days. I’ll say now that all the changes I made were in the ArduiPi-OLED library which is dynamically linked. So I just needed to recompile the library after my changes, not the MMDVMHost program.

Leave a Reply

Your email address will not be published. Required fields are marked *