Initiate APM32F40X MCU Support in Betaflight (#13709)
[betaflight.git] / src / utils / def_generated.pl
blob22329d2973f1cde3a9f2e705bfc9adca9011d726
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
5 # This sript will generate templated files for peripherals
7 # io_def_generated.h
9 my @ports = ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I');
10 my @pins = 0 .. 15;
11 my @timers = (1,2,3,4,6,7,8,15,16,17);
12 my $drivers_dir = "src/main/drivers";
14 # change list separator to newline - we use @{} interpolation to merge multiline strings
15 $" = "\n";
17 chomp(my $license = <<"END");
19 * This file is part of Cleanflight and Betaflight.
21 * Cleanflight and Betaflight are free software. You can redistribute
22 * this software and/or modify this software under the terms of the
23 * GNU General Public License as published by the Free Software
24 * Foundation, either version 3 of the License, or (at your option)
25 * any later version.
27 * Cleanflight and Betaflight are distributed in the hope that they
28 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
29 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
30 * See the GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this software.
35 * If not, see <http://www.gnu.org/licenses/>.
37 END
39 chomp(my $disclaimer_generated = <<"END");
40 // this file is automatically generated by src/utils/def_generated.pl script
41 // do not modify this file directly, your changes will be lost
42 END
44 my $io_def_file="$drivers_dir/io_def_generated.h";
45 my $fh;
46 open $fh, '>', $io_def_file or die "Cannot open $io_def_file: $!";
47 print { $fh} <<"END" or die "Cannot write into $io_def_file: $!"; close $fh;
48 ${license}
50 #pragma once
52 ${disclaimer_generated}
54 // DEFIO_PORT_<port>_USED_MASK is bitmask of used pins on target
55 // DEFIO_PORT_<port>_USED_COUNT is count of used pins on target
57 @{[do {
58 my @prev_ports = ();
59 map { my $port = $_; my $ret = << "END2"; push @prev_ports, $port; $ret } @ports; }]}
60 #if defined(TARGET_IO_PORT${port})
61 # define DEFIO_PORT_${port}_USED_MASK TARGET_IO_PORT${port}
62 # define DEFIO_PORT_${port}_USED_COUNT BITCOUNT(DEFIO_PORT_${port}_USED_MASK)
63 #else
64 # define DEFIO_PORT_${port}_USED_MASK 0
65 # define DEFIO_PORT_${port}_USED_COUNT 0
66 #endif
67 #define DEFIO_PORT_${port}_OFFSET (@{[join('+', map { "DEFIO_PORT_${_}_USED_COUNT" } @prev_ports) || '0']})
68 END2
71 // DEFIO_GPIOID__<port> maps to port index
72 @{[ map { my $port = $_; chomp(my $ret = << "END2"); $ret } @ports ]}
73 #define DEFIO_GPIOID__${port} @{[ord($port)-ord('A')]}
74 END2
76 // DEFIO_TAG__P<port><pin> will expand to TAG if defined for target, error is triggered otherwise
77 // DEFIO_TAG_E__P<port><pin> will expand to TAG if defined, to NONE otherwise (usefull for tables that are CPU-specific)
78 // DEFIO_REC__P<port><pin> will expand to ioRec* (using DEFIO_REC_INDEX(idx))
80 @{[do {
81 my @prev_ports = ();
82 map { my $port = $_; my @ret = map { my $pin = $_; chomp(my $ret = << "END2"); $ret } @pins ; push @prev_ports, $port; @ret } @ports; }]}
83 #if DEFIO_PORT_${port}_USED_MASK & BIT(${pin})
84 # define DEFIO_TAG__P${port}${pin} DEFIO_TAG_MAKE(DEFIO_GPIOID__${port}, ${pin})
85 # define DEFIO_TAG_E__P${port}${pin} DEFIO_TAG_MAKE(DEFIO_GPIOID__${port}, ${pin})
86 # define DEFIO_REC__P${port}${pin} DEFIO_REC_INDEXED(BITCOUNT(DEFIO_PORT_${port}_USED_MASK & (BIT(${pin}) - 1)) + @{[join('+', map { "DEFIO_PORT_${_}_USED_COUNT" } @prev_ports) || '0']})
87 #else
88 # define DEFIO_TAG__P${port}${pin} defio_error_P${port}${pin}_is_not_supported_on_TARGET
89 # define DEFIO_TAG_E__P${port}${pin} DEFIO_TAG_E__NONE
90 # define DEFIO_REC__P${port}${pin} defio_error_P${port}${pin}_is_not_supported_on_TARGET
91 #endif
92 END2
94 // DEFIO_IO_USED_COUNT is number of io pins supported on target
95 #define DEFIO_IO_USED_COUNT (@{[join('+', map { "DEFIO_PORT_${_}_USED_COUNT" } @ports) || '0']})
97 // DEFIO_PORT_USED_LIST - comma separated list of bitmask for all used ports.
98 // DEFIO_PORT_OFFSET_LIST - comma separated list of port offsets (count of pins before this port)
99 // unused ports on end of list are skipped
100 @{[do {
101 my @used_ports = @ports;
102 map { my $port = $_; chomp(my $ret = << "END2"); @used_ports = grep {$_ ne $port} @used_ports; $ret } reverse(@ports) }]}
103 #if !defined DEFIO_PORT_USED_LIST && DEFIO_PORT_${port}_USED_COUNT > 0
104 # define DEFIO_PORT_USED_COUNT @{[scalar @used_ports]}
105 # define DEFIO_PORT_USED_LIST @{[join(',', map { "DEFIO_PORT_${_}_USED_MASK" } @used_ports)]}
106 # define DEFIO_PORT_OFFSET_LIST @{[join(',', map { "DEFIO_PORT_${_}_OFFSET" } @used_ports)]}
107 #endif
108 END2
110 #if !defined(DEFIO_PORT_USED_LIST)
111 # if !defined DEFIO_NO_PORTS // supress warnings if we really don't want any pins
112 # warning "No pins are defined. Maybe you forgot to define TARGET_IO_PORTx in target.h"
113 # endif
114 # define DEFIO_PORT_USED_COUNT 0
115 # define DEFIO_PORT_USED_LIST /* empty */
116 # define DEFIO_PORT_OFFSET_LIST /* empty */
117 #endif
120 exit; # only IO code is merged now
122 my $timer_def_file="$drivers_dir/timer_def_generated.h";
123 open $fh, '>', $timer_def_file or die "Cannot open $timer_def_file: $!";
124 print { $fh} <<"END" or die "Cannot write into $timer_def_file: $!"; close $fh;
125 #pragma once
126 ${disclaimer_generated}
128 // make sure macros for all timers are defined
129 @{[ map { my $timer = $_; chomp(my $ret = << "END2"); $ret } @timers ]}
130 #ifndef TARGET_TIMER_TIM${timer}
131 # define TARGET_TIMER_TIM${timer} -1
132 #endif
133 END2
135 // generate mask with used timers
136 @{[do {
137 my @prev_timers = ();
138 map { my $timer = $_; chomp(my $ret = << "END2"); push @prev_timers, $timer; $ret } @timers }]}
139 #if TARGET_TIMER_TIM${timer} > 0
140 # define TARGET_TIMER_TIM${timer}_BIT BIT(${timer})
141 # define TARGET_TIMER_TIM${timer}_INDEX ( @{[ join("+", map("(TARGET_TIMER_TIM${_} >= 0)", @prev_timers)) || 0 ]} )
142 #else
143 # define TARGET_TIMER_TIM${timer}_BIT 0
144 # define TARGET_TIMER_TIM${timer}_INDEX deftimer_error_TIMER${timer}_is_not_enabled_on_target
145 #endif
146 END2
147 #define TIMER_USED_BITS ( @{[ join "|", map("TARGET_TIMER_TIM${_}_BIT", @timers) ]} )
148 #define TIMER_USED_COUNT ( @{[ join "+", map("(TARGET_TIMER_TIM${_} >= 0)", @timers) ]} )
150 // structure to hold all timerRec_t.
151 // Number of channels per timer is user specifed, structure will ensure correct packing
152 struct timerRec_all {
153 @{[ map { my $timer = $_; chomp(my $ret = << "END2"); $ret } @timers ]}
154 #if TARGET_TIMER_TIM${timer} >= 0
155 timerRec_t rec_TIM${timer};
156 # if TARGET_TIMER_TIM${timer} > 0
157 timerChRec_t rec_TIM${timer}_ch[TARGET_TIMER_TIM${timer}];
158 # endif
159 #endif
160 END2
164 my $timer_inc_file="$drivers_dir/timer_c_generated.inc";
165 open $fh, '>', $timer_inc_file or die "Cannot open $timer_inc_file: $!";
166 print { $fh} <<"END" or die "Cannot write into $timer_inc_file: $!"; close $fh;
167 ${disclaimer_generated}
169 // this code is included into timer.c file
171 const timerDef_t timerDefs[] = {
172 @{[ map { my $timer = $_; chomp(my $ret = << "END2"); $ret } @timers ]}
173 #if TARGET_TIMER_TIM${timer} >= 0
174 DEF_TIMER_DEFINE(${timer}),
175 #endif
176 END2
179 timerRec_t* const timerRecPtrs[] = {
180 @{[ map { my $timer = $_; chomp(my $ret = << "END2"); $ret } @timers ]}
181 #if TARGET_TIMER_TIM${timer} >= 0
182 &timerRecs.rec_TIM${timer},
183 #endif
184 END2
185 NULL // terminate the list