Metadata-Version: 2.4
Name: opencplc
Version: 0.1.2
Summary: Project configuration and build tool for OpenCPLC
Author: Xaeian
License: MIT
Project-URL: Repository, https://github.com/OpenCPLC/Forge
Keywords: embedded,stm32,opencplc,build,forge
Requires-Python: >=3.12
Description-Content-Type: text/markdown
Requires-Dist: xaeian

## OpenCPLC ⚒️ Forge

**Forge** is a console app that makes working with **OpenCPLC** easier. Its job is to set up your environment so you 👨‍💻developer can focus on building apps instead of fighting with configs and compilation. Available as a **Python [`pip`](https://pypi.org/project/opencplc)** package or standalone **`opencplc.exe`** from 🚀[Releases](https://github.com/OpenCPLC/Forge/releases) _(in that case add its location to system **PATH** manually)_

```bash
pip install opencplc
```

Just pick a folder _(your workspace)_ open [CMD](#-console) and type:

```bash
opencplc -n <project_name> -b <board>
opencplc -n myapp -b Uno
```

This creates a directory _(or directory tree)_ in [projects location](#️-config) `${projects}` matching the name `<project_name>`. Two files are created inside: `main.c` and `main.h`: the minimal project setup. Don't delete them or move to subfolders.

When you have more projects, you can switch between them freely:

```bash
opencplc <project_name>
opencplc myapp
```

You can also pick projects by number from list:

```bash
opencplc -l  # show project list
opencplc 3   # load project #3 from list
```

When creating new project or switching to existing one, all files needed for compilation _(`makefile`, `flash.ld`, ...)_ are regenerated. These transform everything _(project and framework files: `.c`, `.h`, `.s`)_ into binary files `.bin`/`.hex` that can be flashed to the PLC.

If you change `PRO_x` config values in **`main.h`** or modify **project structure**:

- adding new files,
- moving files,
- deleting files,
- renaming files,

you need to reload the project. If project is already active, no need to type its name `-r --reload`:

```bash
opencplc <project_name>
opencplc -r
```

Here _(roughly)_ ends **Forge** job, and further work goes like typical **embedded systems** project using [**✨Make**](#-make).

## ✨ Make

If you have proper project config and `makefile` generated by ⚒️**Forge**, to build and flash program to PLC just open console in workspace and type:

```bash
make build  # build C project to binary
make flash  # upload binary to PLC memory
# or
make run    # run = build + flash
```

`makefile` has few more functions. Full list:

- **`make build`** or just **`make`**: Builds C project to `.bin`, `.hex`, `.elf` files
- **`make flash`**: Uploads program to PLC _(microcontroller)_ memory
- **`make run`**: Does `make build`, then `make flash`
- **`make clean`** or `make clr`: Removes built files for active project
- `make clean_all` or `make clr_all`: Removes built files for all projects
- `make dist`: Copies `.bin` and `.hex` files to the project folder
- **`make erase`**: Completely wipes microcontroller memory _(**erase** full chip)_

## ⚙️ Config

On first run ⚒️Forge creates config file **`opencplc.json`**. It contains:

- **`version`**: Default OpenCPLC framework version. This version gets installed. Replaces unspecified `-f --framework`. Value `latest` means newest stable version.
- `paths`: List of _(relative)_ paths
  - `projects`: Main projects directory. New projects go here. You can also copy projects manually. All projects are detected automatically. Project name is the path after this location.
  - `examples`: Directory with demo examples downloaded from [Demo](https://github.com/OpenCPLC/Demo) repository.
  - `framework`: Directory with all OpenCPLC framework versions. Subdirectories are created for versions like `major.minor.patch`, `develop` or `main`. Each contains files for that framework version. Only needed versions are downloaded.
  - `build`: Directory with built applications
- `default`: Default values _(`chip`, `flash`, `ram`, `optLevel`)_ for params not passed when creating new project
- **`pwsh`**: Setting this to `true` makes `makefile` for **PowerShell**. For `false` it's **Bash** version.
- `available-versions`: List of all available framework versions. Set automatically.

## 🤔 How works?

First **Forge** installs **GNU Arm Embedded Toolchain**, **OpenOCD**, **Make**, **Git** client and sets system variables if these apps aren't visible from console. For HOST platform, **MinGW** (GCC for Windows) is installed instead of ARM toolchain. If you don't want anyone messing with your system, you can [set it up manually](self-install.md). When ⚒️**Forge** installs missing apps, it asks to reset console because system variables load on startup and new ones were added.

Then if needed, it clones OpenCPLC framework from [repository](https://github.com/OpenCPLC/Core) to `${framework}` folder from `opencplc.json`. Version from config or specified with `-f --framework` gets cloned:

```bash
opencplc <project_name> --new -f 1.0.2
opencplc <project_name> --new -f develop
```

### 📌 Project versioning

Each project stores in `main.h` the framework version it was created with _(definition `PRO_VERSION`)_. When switching to existing project:

- If project version differs from current framework, **Forge** tries to download matching version
- If download fails, warning about potential incompatibility shows up
- Demo examples `-e --example` always use version saved in project

This way old projects can compile even after framework update to newer version.

Main **Forge** function is preparing files needed for project:

- `flash.ld`: defines RAM and FLASH memory layout _(overwrites, STM32 only)_
- `makefile`: Contains build, clean and flash rules _(overwrites)_
- `c_cpp_properties.json`: sets header paths and IntelliSense config in VS Code _(overwrites)_
- `launch.json`: configures debugging in VSCode _(overwrites)_
- `tasks.json`: describes tasks like compile or flash _(overwrites)_
- `settings.json`: sets local editor preferences _(creates once, not overwritten)_
- `extensions.json`: suggests useful VSCode extensions _(creates once, not overwritten)_

There's also bunch of helper functions accessible through smart use of [**🚩flags**](#-flags).

### 🗂️ Workspace structure

```
workspace/
├─ opencplc.json  # workspace config
├─ makefile       # active project (generated by Forge)
├─ flash.ld       # linker script (generated by Forge, STM32 only)
├─ .vscode/       # VSCode config (generated by Forge)
├─ opencplc/      # framework (downloaded automatically)
│  ├─ 1.0.3/
│  ├─ 1.2.0/
│  └─ develop/
├─ projects/      # user projects
│  ├─ myapp/
│  │  ├─ main.c
│  │  └─ main.h
│  └─ firm/app/   # projects can be nested
│     ├─ main.c
│     └─ main.h
├─ examples/      # demo examples
└─ build/         # compiled binary files
```

If IntelliSense stops working, use `F1` → _C/C++: Reset IntelliSense Database_.

## 🖥️ Host

Forge supports **Host** platform for developing and testing code on PC (Windows/Linux) without embedded hardware:

```bash
opencplc -n myapp -c Host  # desktop project
```

This creates project that compiles with native GCC (MinGW on Windows) instead of ARM toolchain. Useful for:

- Testing algorithms and logic without hardware
- Developing protocol parsers and data processing
- Unit testing framework components
- Quick prototyping before deploying to PLC

Host platform provides stub implementations for hardware-dependent modules (GPIO, timers, etc.) so code structure remains compatible with STM32 targets.

## 🚩 Flags

Beyond the basic flags described above, there are a few more worth knowing. Full list:

#### Basic

- **`name`**: Project name. Default first argument. Also defines the project path: `${projects}/name`, and output files (`.bin`, `.hex`, `.elf`) are tied to it. Can also be a project number from the `-l` list.
- `-n --new`: Creates a new project with the given name.
- `-e --example`: Loads a demo example by name from the [Demo](https://github.com/OpenCPLC/Demo) repository.
- `-r --reload`: Reads the project name and example flag from an existing `makefile`, then regenerates project files. **`name`** is not required.
- `-d --delete`: Deletes the project with the given **`name`**.
- `-g --get`: Downloads a project from Git (**GitHub**, **GitLab**, ...) or a remote ZIP and adds it as a new project. The second argument (first is the link) can be a reference (`branch`, `tag`). If **`name`** is not specified, it tries to read it from the `@name` field in `main.h`.

#### Hardware config

- `-b --board`: PLC board for the new project: `Uno`, `Dio`, `Aio`, `Eco`, `Custom` for a custom design, or `None` for a bare microcontroller. `Custom` provides the PLC layer without peripheral mapping — fill it in manually.
- `-c --chip`: Microcontroller or platform: `STM32G081`, `STM32G0C1`, `STM32WB55`, `HOST` (compile for PC). Without `-b --board`, the project runs without the PLC layer — only HAL and standard framework libraries. Useful for Nucleo boards or custom hardware.
- `-m --memory`: Memory in kB: `FLASH RAM [RESERVED]`. `RESERVED` is the memory allocated for config and EEPROM, subtracted from FLASH in the linker file `flash.ld`. _(STM32 only)_

#### Build config

- `-f --framework`: Framework version: `latest`, `develop`, `1.0.0`. If not provided, read from the `version` field in `opencplc.json`.
- `-o --opt-level`: Compiler optimization level: `O0` _(debug)_, `Og` _(default)_, `O1`, `O2`, `O3`. Levels `O2` and `O3` show a warning for STM32 _(timing/debugging issues)_ but are allowed for `HOST`.

#### Info

- `-l --list`: Lists existing projects, or examples when `-e --example` is active.
- `-i --info`: Returns basic info about the specified or active project, including project and framework versions.
- `-F --framework-versions`: Lists all available OpenCPLC framework versions.
- `-v --version`: Shows the ⚒️Forge version and repository link.

#### Tools

- `-a --assets`: Downloads helper materials for design _(docs, diagrams)_. Optionally accepts a folder name as destination.
- `-u --update`: Checks for and installs ⚒️Forge updates. Accepts a specific version or `latest`.
- `-y --yes`: Auto-confirms all prompts _(non-interactive mode)_.

#### Hash utilities

- `-hl --hash-list`: Generates an enum with DJB2 hashes from a tag list.
- `-ht --hash-title`: Enum type name for the hash generator.
- `-hd --hash-define`: Uses `#define` instead of `enum` for hash output.

🗑️ Deleting and 💾 copying projects can be done directly from the OS.
Each project stores all the information it needs in `main.h`, and its presence is auto-detected on startup.

## 📟 Console

⚒️Forge and ✨Make are console programs. Essential for working with OpenCPLC.

System console is available in many apps like **Command Prompt**, **PowerShell**, [**GIT Bash**](https://git-scm.com/downloads), even terminal in [**VSCode**](https://code.visualstudio.com/). If console call returns error, it probably wasn't opened in workspace. Close console and open it in right folder or navigate manually with `cd` command.

## 📋 Usage examples

```bash
# Creating new project
opencplc -n myapp -b Uno                  # project for OpenCPLC Uno board
opencplc -n myapp -b Eco -m 128 36        # project for Eco with 128kB/36kB memory
opencplc -n myapp -b Custom -c STM32G081  # custom hardware with PLC layer (no peripheral mapping)
opencplc -n myapp -c STM32G081            # bare-metal project for STM32G081 (e.g. Nucleo)
opencplc -n myapp -c Host                 # desktop project (Windows/Linux)

# Managing projects
opencplc myapp      # load project 'myapp'
opencplc 3          # load project #3 from list
opencplc -r         # reload active project
opencplc -l         # list all projects
opencplc -i         # info about active project

# Demo examples
opencplc -e blinky  # load example 'blinky'
opencplc -e -l      # list available examples

# Downloading projects
opencplc -g https://github.com/user/repo
opencplc -g https://github.com/user/repo v1.0.0

# Updates
opencplc -u         # update Forge to latest version
opencplc -F         # show available Core versions
```
