Community-PIO-CH32V / platform-ch32v

PlatformIO platform for CH32V RISC-V chips (CH32V003, CH32V103, CH32V20x, CH32V30x, CH32X035) and CH56x, CH57x, CH58x, CH59x
Apache License 2.0
203 stars 33 forks source link

Create a quick user guide for pin definitions and framework's methods. Helper macros idea. #61

Open dzalf opened 3 months ago

dzalf commented 3 months ago

Dear @maxgerhardt

DISCLAIMER: I originally wrote this wall of text while still experimenting with the framework. I figured at the end of my "presentation" that some of the ideas I propose here might be redundant or even nonsensical and I could be proposing stuff that might break things. This is simply a reflection of my poor understanding of this somewhat new platform for the CH32V RISC-V processors. Please take everything I say here with a grain of salt

First of all, I would like to thank you for the amazing work and effort you have put into creating this gargantuan project.

I recently started experimenting with these RISC-V chips and, like many others, I got my DevKits from Aliexpress at an incredibly low price.

While working with the CH32V0003F4P6-R0-1v1 dev board I faced some issues, like the WCH-LinkE not detecting the chip through the WCH-LinkUtility app. I managed to finally read the chip by preselecting the chip family CH32V00X on the drop-down menu. This hasn't worked, however, with the bigger devKit CH32Vx03C-R0-1v0. It is impossible to read it the same way but that's a topic for another forum.

After this, I decided to run a mundane blinky code to understand this implementation of the Arduino framework a bit better, however, this is where I got stuck for a while.

I noticed that if I declare the pin PC_3, as one would normally do: pinMode(PC_3, OUTPUT); and use digitalWrite(PC_3, HIGH) // or LOW nothing happens. The code simply doesn't run AT ALL. Granted that I bridged this pin to one of the pin headers from LEDs 1/2. No life. In this regard, I struggled to find any references to the available configuration settings to include in the platformio.ini file. I serendipitously figured that flashing using the line:

; Upload via WCH-LINK
upload_protocol = wch-link

worked just fine.

After some experimenting and reading through the custom headers that you include in the framework, I found the function called: pinNametoDigitalPin inside pins_arduino.cpp. I then redeclared the pin as: pinMode(pinNametoDigitalPin(PC_3), OUTPUT) then in the main loop used: digitalToggle(pinNametoDigitalPin(PC_3)). Surprise! Works great.

This left me thinking. While I understand that the documentation is under active development, it might be worth creating a simple file describing the functionalities of the framework and explaining the specific bindings to declare the pins.

Finally, it occurred to me that the pins could be declared using some nice helper macros in the following form:

#include <Arduino.h>

#define CAT(X,Y) CAT2(X,Y)
#define CAT2(X,Y) X##Y

//Here, the D fromGPIOD stands for "Digital" since there is another function for analog pins
#define GPIOD(Port,n) (pinNametoDigitalPin(CAT(CAT(CAT(P,Port),_),n))) 

#define LED1 GPIOD(C,1)
#define LED2 GPIOD(C,2)

unsigned long elapsed;

void sayHi(int);

void setup()
{
  Serial.begin(115200);  // this expands to Serial1 --> Tx is PD5

  delay(1000);  // wait catch the message during bootup

  Serial.println(F("Initial steps with CH32V..."));

  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);

  //pinMode(PD_6, OUTPUT);  // system hangs

  digitalWrite(LED1, LOW);
  digitalWrite(LED2, HIGH);

  //digitalWrite(PD_6, HIGH);

  elapsed = micros();
}

void loop()
{

  unsigned long now = micros();

  if (now - elapsed >= 10)
  {
    elapsed = now;
    digitalToggle(LED1);
    digitalToggle(LED2);

    //digitalToggle(PD_6);
  }

  sayHi(5);

}

void sayHi(int del)
{
  Serial.print("Hi there!");
  delayMicroseconds(del);
}

this code works as expected. Here is the output from my dirt-cheap logic analyser:

image

where the LED pins toggle, as expected:

image

then, if I use the GPIOD macro, I can make the pin PD_6 work as intended:

Here, I modified the function to create a burst effect and to blink one of the leads separately:

#include <Arduino.h>

#define CAT(X, Y) CAT2(X, Y)
#define CAT2(X, Y) X##Y

#define GPIOD(Port, n) (pinNametoDigitalPin(CAT(CAT(CAT(P, Port), _), n)))
#define GPIOA(Port, n) (pinNametoAnalogPin(CAT(CAT(CAT(P, Port), _), n)))

#define LED1 GPIOD(C, 1)
#define LED2 GPIOD(C, 2)
#define blink GPIOD(C, 3)
#define Pulse GPIOD(D, 6)

bool enableBurst = false;
unsigned long elapsed;

void sayHi(int);

void setup()
{

  Serial.begin(115200);

  delay(1000);

  Serial.println(F("Initial steps with CH32V..."));

  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(Pulse, OUTPUT);
  pinMode(blink, OUTPUT);

  digitalWrite(LED1, LOW);
  digitalWrite(LED2, HIGH);
  digitalWrite(Pulse, LOW);
  digitalWrite(blink, HIGH);

  elapsed = millis();
}

void loop()
{

  unsigned long now = millis();

  if (now - elapsed >= 250)
  {
    elapsed = now;

    digitalToggle(LED1);
    digitalToggle(LED2);
    digitalToggle(blink);

    if (digitalRead(LED1))
    {
      enableBurst = true;
    }
    else
    {
      enableBurst = false;
    }

    sayHi(0); // I am being silly, I know ¬¬
  }

  if (enableBurst)
    digitalToggle(Pulse);
}

void sayHi(int del)
{
  Serial.print("Hi there!");
  delayMicroseconds(del);
}

obtaining the following output:

image image

https://github.com/Community-PIO-CH32V/platform-ch32v/assets/3759916/a2fa17f0-ebbe-4fcd-a232-ea6fc35284af

maxgerhardt commented 1 month ago

Not really understanding the thing about digitalWrite(PC_3);. The variant header is exposing the macros for the pin numbers correctly as e.g. PA1, PC3, PD4, etc.

https://github.com/openwch/arduino_core_ch32/blob/273620c809ba4cc3c6928543c6929634de8e50ba/variants/CH32V00x/CH32V003F4/variant_CH32V003F4.h#L22-L40

So example code, that is also already contained in this repo (blinky-arduino) should work perfectly fine.