Help needed: converting STM-code to STM Arduino framework

Working libraries, libraries being ported and related hardware
Post Reply
ZaphodB
Posts: 1
Joined: Mon Sep 11, 2023 9:32 am

Help needed: converting STM-code to STM Arduino framework

Post by ZaphodB »

Hi, I'm trying to reuse some open source code that was written for a eurorack module in a project I'm working on. Specifically I'd like to use the DAC code of that project (BRAIDS by Mutable Instruments). I'm using the STMF103x BluePill in my project and have been programming it using platformio and VCS using the following config:
[env:bluepill_f103c8]
platform = ststm32
board = bluepill_f103c8
build_flags = -Wall
framework = arduino
monitor_speed = 230400
lib_deps =
embeddedartistry/LibPrintf@^1.2.13
powerbroker2/SafeString@^4.1.27
adafruit/Adafruit NeoPixel@^1.11.0
ruiseixasm/Versatile_RotaryEncoder@^1.2.1
fortyseveneffects/MIDI Library@^5.0.2
This worked out fine so far. Now I'm trying to add the DAC-code from the BRAIDS project, so I need to convert it to the 'arduino' framework. So far I've adapted the code thus:

Code: Select all

// Copyright 2012 Emilie Gillet.
//
// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
// Rewritten and modified for Soundforce Throughhole Braids by Martin Timms.
// Implementing a 16bit DAC using two channels of the MCP4822 dual 12bit DAC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 
// See http://creativecommons.org/licenses/MIT/ for more information.
//
// -----------------------------------------------------------------------------
//
// Driver for DAC.

#ifndef BRAIDS_DRIVERS_DAC_H_
#define BRAIDS_DRIVERS_DAC_H_

#include <stm32f1xx.h>

#define NOP1 __asm__ volatile ("nop");
#define NOP2 NOP1 NOP1
#define NOP4 NOP2 NOP2
#define NOP8 NOP4 NOP4
#define NOP16 NOP8 NOP8
#define NOP32 NOP16 NOP16
#define NOP64 NOP32 NOP32
#define NOP128 NOP64 NOP64

#define NOP96 NOP64 NOP32
#define NOP7 NOP4 NOP2 NOP1
#define NOP13 NOP8 NOP4 NOP1

#define NOP_N(N) for(register unsigned i=0; i<(N); i++) __asm__ volatile ("nop");

// For defines and structs have a look at:
// .platformio/packages/framework-arduinoststm32/system/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_spi.h

class Dac {

 public:
  Dac() { }
  ~Dac() { }
  
  void Init() {
    // Initialize SS pin.
    GPIO_InitTypeDef gpio_init;
    gpio_init.Pin = PB12; //GPIO_Pin_12;
    gpio_init.Speed = GPIO_SPEED_HIGH; // GPIO_Speed_50MHz;
    gpio_init.Mode = GPIO_MODE_AF_PP; // GPIO_Mode_Out_PP;
    HAL_GPIO_Init(GPIOB, &gpio_init);
    
    // Initialize MOSI and SCK pins.
    gpio_init.Pin = PB13 | PB15; // GPIO_Pin_13 | GPIO_Pin_15;
    gpio_init.Speed = GPIO_SPEED_HIGH; // GPIO_Speed_50MHz;
    gpio_init.Mode = GPIO_MODE_AF_PP; //  GPIO_Mode_AF_PP;
    HAL_GPIO_Init(GPIOB, &gpio_init);
    
    // Initialize SPI
    SPI_InitTypeDef spi_init;
    spi_init.Direction = SPI_DIRECTION_1LINE; // /SPI_Direction_1Line_Tx; 
    spi_init.Mode = SPI_MODE_MASTER; // SPI_Mode_Master;
    spi_init.DataSize = SPI_DATASIZE_16BIT; // SPI_DataSize_16b;
    spi_init.CLKPolarity = SPI_POLARITY_HIGH; // SPI_CPOL_High;
    spi_init.CLKPhase = SPI_PHASE_1EDGE; // SPI_CPHA_1Edge;
    spi_init.NSS = SPI_NSS_SOFT; // SPI_NSS_Soft;
    spi_init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; // SPI_BaudRatePrescaler_2;
    spi_init.FirstBit = SPI_FIRSTBIT_MSB; // SPI_FirstBit_MSB;
    spi_init.CRCPolynomial = 7;
    HAL_SPI_Init(SPI2, &spi_init); // SPI_Init(SPI2, &spi_init);
    HAL_SPI_ENABLE(SPI2); // SPI_Cmd(SPI2, ENABLE);
  }

  inline void Write(uint16_t value) {
    uint16_t val2;
 
    GPIOB->BSRR = PB12;
    NOP7 //14ns * 7

    GPIOB->BRR = PB12;
    NOP13 //14ns * 13

    //step 1 convert 16 bits data to 11 bits
    val2 = value >> 5;
    val2+=1024;
    //step 2 add the configuration bit_mask
    val2 &= 0x0FFF;
    //val2 |= 0x3000;
    val2 |= 0x1000; //2x gain
    SPI2->DR = val2;

    NOP128 //14ns * 128

    //calculate first 5 bits
    val2 = value & 0x001F;
    val2 =val2 << 3;
    val2+=1920; //1024; Value to add to 8 bit to get to centre

    val2 &= 0x0FFF;
    val2 |= 0x9000; //2x gain

    GPIOB->BSRR = PB12;
    NOP7 //14ns * 7

    GPIOB->BRR = PB12;
    NOP13 //14ns * 13

    //Write to second DAC channel
    SPI2->DR = val2;
  }
 
  private:
  
 // DISALLOW_COPY_AND_ASSIGN(Dac);
};

#endif  // BRAIDS_DRIVERS_DAC_H_
As you can see in the Init() method I've changed the statements to comply with the new syntax and left the old code as a comment behind slashes for reference. Only the last statement "HAL_SPI_ENABLE(SPI2); // SPI_Cmd(SPI2, ENABLE);" is not accepted by the compiler and it appears to have a problem with SPI2:

Code: Select all

Building in release mode
Compiling .pio/build/bluepill_f103c8/src/main.cpp.o
Compiling .pio/build/bluepill_f103c8/FrameworkArduino/USBSerial.cpp.o
Compiling .pio/build/bluepill_f103c8/FrameworkArduino/VirtIOSerial.cpp.o
Compiling .pio/build/bluepill_f103c8/FrameworkArduino/WInterrupts.cpp.o
In file included from /home/jos/.platformio/packages/framework-arduinoststm32/system/Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f1xx.h:131,
                 from /home/jos/.platformio/packages/framework-arduinoststm32/cores/arduino/stm32/stm32_def.h:28,
                 from /home/jos/.platformio/packages/framework-arduinoststm32/cores/arduino/stm32/clock.h:19,
                 from /home/jos/.platformio/packages/framework-arduinoststm32/cores/arduino/wiring_time.h:23,
                 from /home/jos/.platformio/packages/framework-arduinoststm32/cores/arduino/wiring.h:38,
                 from /home/jos/.platformio/packages/framework-arduinoststm32/cores/arduino/Arduino.h:36,
                 from src/main.cpp:1:
src/dac.hpp: In member function 'void Dac::Init()':
/home/jos/.platformio/packages/framework-arduinoststm32/system/Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xb.h:654:30: error: cannot convert 'SPI_TypeDef*' to 'SPI_HandleTypeDef*' {aka '__SPI_HandleTypeDef*'}
  654 | #define SPI2                ((SPI_TypeDef *)SPI2_BASE)
      |                             ~^~~~~~~~~~~~~~~~~~~~~~~~~
      |                              |
      |                              SPI_TypeDef*
src/dac.hpp:85:18: note: in expansion of macro 'SPI2'
   85 |     HAL_SPI_Init(SPI2, &spi_init); // SPI_Init(SPI2, &spi_init);
      |                  ^~~~
In file included from /home/jos/.platformio/packages/framework-arduinoststm32/system/STM32F1xx/stm32f1xx_hal_conf_default.h:348,
                 from /home/jos/.platformio/packages/framework-arduinoststm32/system/STM32F1xx/stm32f1xx_hal_conf.h:13,
                 from /home/jos/.platformio/packages/framework-arduinoststm32/system/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal.h:30,
                 from /home/jos/.platformio/packages/framework-arduinoststm32/system/Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f1xx.h:255,
                 from /home/jos/.platformio/packages/framework-arduinoststm32/cores/arduino/stm32/stm32_def.h:28,
                 from /home/jos/.platformio/packages/framework-arduinoststm32/cores/arduino/stm32/clock.h:19,
                 from /home/jos/.platformio/packages/framework-arduinoststm32/cores/arduino/wiring_time.h:23,
                 from /home/jos/.platformio/packages/framework-arduinoststm32/cores/arduino/wiring.h:38,
                 from /home/jos/.platformio/packages/framework-arduinoststm32/cores/arduino/Arduino.h:36,
                 from src/main.cpp:1:
/home/jos/.platformio/packages/framework-arduinoststm32/system/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_spi.h:653:51: note:   initializing argument 1 of 'HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef*)'
  653 | HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi);
      |                                ~~~~~~~~~~~~~~~~~~~^~~~
In file included from src/main.cpp:335:
src/dac.hpp:86:5: error: 'HAL_SPI_ENABLE' was not declared in this scope; did you mean 'AFIO_SPI1_ENABLE'?
   86 |     HAL_SPI_ENABLE(SPI2); // SPI_Cmd(SPI2, ENABLE);
      |     ^~~~~~~~~~~~~~
      |     AFIO_SPI1_ENABLE
Compiling .pio/build/bluepill_f103c8/FrameworkArduino/WMath.cpp.o
Compiling .pio/build/bluepill_f103c8/FrameworkArduino/WSerial.cpp.o
*** [.pio/build/bluepill_f103c8/src/main.cpp.o] Error 1
I've searched in '.platformio/packages/framework-arduinoststm32/system/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_spi.h' but do not seem to be able find an equivalent or replacement statement for 'SPI_Cmd(SPI2, ENABLE)', nor do I understand what the conversion error is all about. Does anybody have any suggestions?
Post Reply

Return to “Libraries & Hardware”