I have a bunch of labeled servos, each one has its own calibrated min, mid and max pulse-width value.
// repository of calibrated servo pulse width values:
#define SERVO_0x01_MIN 165
#define SERVO_0x01_MID 347
#define SERVO_0x01_MAX 550
#define SERVO_0x02_MIN 165
#define SERVO_0x02_MID 347
#define SERVO_0x02_MAX 550
...
To simplify maintenance of the code, swapping a servo should only require changing a single macro definition value.
// maps certain positions on robot to the servo that is installed there
#define JOINT_0 0x02
#define JOINT_1 0x05
#define JOINT_2 0x0A
...
// function-like macros to resolve values from mapping
#define GET_MIN(servo) SERVO_##servo##_MIN
#define GET_MID(servo) SERVO_##servo##_MID
#define GET_MAX(servo) SERVO_##servo##_MAX
The problem I'm having is that calling a function-like macro with an argument that itself is a macro does not resolve to its terminal value:
// main
int main(void) {
// this works
int max_0x01 = GET_MAX(0x01); // int max_0x01 = 550;
// this doesn't
int max_joint_0 = GET_MAX(JOINT_0); // int max_joint_0 = SERVO_JOINT_0_MAX;
}
What can I do to make GET_MAX(JOINT_0) turn into 550 ?
#define GET_MAX(servo) GET_MAX2(servo)
#define GET_MAX2(servo) SERVO_##servo##_MAX
The preprocessor will perform expansion (textual replacement) upon a variadic macro until it can expand no further. So passing in JOINT_0, such as GET_MAX(JOINT_0) will expand to
GET_MAX2(0x02)
This gets further expanded to
SERVO_0x02_MAX
And finally replaced with the #define value 550
Related
I am in C++ defining blocks that go in a special area of memory. I want to define a block, then define the address of the next block in a variable that gets redefined for each block.
#include <iostream>
using namespace std;
#define BASE_ADDRESS 0X1000
// type a gets 100 bytes
#define TYPE_A BASE_ADDRESS
#define NEXT_FREE_BLOCK (BASE_ADDRESS + 100)
// type b gets 200 bytes, starting at the next free address
#define TYPE_B NEXT_FREE_BLOCK
#undef NEXT_FREE_BLOCK
#define NEXT_FREE_BLOCK (TYPE_B + 200)
// ---end of RWW memory map---
int main()
{
cout<<"Hello free block " << NEXT_FREE_BLOCK << endl;
return 0;
}
Example code that I've looked up looks like this. But when I try to compile this, I get "compilation failed due to the following errors":
main.cpp:12:16: error: ‘NEXT_FREE_BLOCK’ was not declared in this scope
#define TYPE_B NEXT_FREE_BLOCK
^
main.cpp:14:26: note: in expansion of macro ‘TYPE_B’
#define NEXT_FREE_BLOCK (TYPE_B + 200)
^~~~~~
main.cpp:20:34: note: in expansion of macro ‘NEXT_FREE_BLOCK’
cout<<"Hello free block " << NEXT_FREE_BLOCK << endl;
^~~~~~~~~~~~~~~
If I comment out the 'type b' lines, it runs as expected. If I comment out the #undef line, it tells me I've redefined the macro. I would like to redefine the macro without getting an error or warning; is there a way to do that?
Lets take a look at this example:
#define MYMACRO 0 //MYMACRO = 0
#define ANOTHERMACRO MYMACRO //ANOTHERMACRO = MYMACRO = 0
int main() {
return ANOTHERMACRO;
}
All good right?
But if we do this:
#define MYRECURSIVEMACRO 0 //MYRECURSIVEMACRO = 0
#define MYMACRO MYRECURSIVEMACRO //MYMACRO = MYRECURSIVEMACRO
#undef MYRECURSIVEMACRO // MYRECURSIVEMACRO does not exist
#define MYRECURSIVEMACRO (MYMACRO+10) //What was MYMACRO again? It was MYRECURSIVEMACRO, but now we are setting MYRECURSIVEMACRO, which right now is being defined, to itself plus 10, and now I am 100% confused
#define ANOTHERMACRO MYRECURSIVEMACRO //Now what?
int main() {
return ANOTHERMACRO;
}
We get this:
1>C:\dev\Stack Overflow\Source.cpp(520,9): error C2065: 'MYMACRO': undeclared identifier
(At least for MSVC++)
Now if we look at this:
#define BASE_ADDRESS 0X1000 //BASE_ADDRESS = 0x1000
// type a gets 100 bytes
#define TYPE_A BASE_ADDRESS //TYPE_A = BASE_ADDRESS = 0x1000
#define NEXT_FREE_BLOCK (BASE_ADDRESS + 100) //NEXT_FREE_BLOCK = 0x1000 + 100
// type b gets 200 bytes, starting at the next free address
#define TYPE_B NEXT_FREE_BLOCK //TYPE_B = NEXT_FREE_BLOCK
#undef NEXT_FREE_BLOCK //NEXT_FREE_BLOCK is gone
#define NEXT_FREE_BLOCK (TYPE_B + 200) //Now what? Same problem as before!
// ---end of RWW memory map---
This is why it isn't working.
#ifndef _CXS_H
#define _CXS_H
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#ifdef MATLAB_MEX_FILE
#include "mex.h"
#endif
#ifdef __cplusplus
#ifndef NCOMPLEX
#include <complex>
typedef std::complex<double> cs_complex_t ;
#endif
extern "C" {
#else
#ifndef NCOMPLEX
#include <complex.h>
#define cs_complex_t double _Complex
#endif
#endif
#define CS_VER 2 /* CXSparse Version */
#define CS_SUBVER 3
#define CS_SUBSUB 0
#define CS_DATE "Jun 1, 2012" /* CXSparse release date */
#define CS_COPYRIGHT "Copyright (c) Timothy A. Davis, 2006-2012"
#define CXSPARSE
#include "SuiteSparse_config.h"
#define cs_long_t SuiteSparse_long
#define cs_long_t_id SuiteSparse_long_id
#define cs_long_t_max SuiteSparse_long_max
........................
typedef struct cs_ci_sparse /* matrix in compressed-column or triplet form */
{
int nzmax ; /* maximum number of entries */
int m ; /* number of rows */
int n ; /* number of columns */
int *p ; /* column pointers (size n+1) or col indices (size nzmax) */
int *i ; /* row indices, size nzmax */
cs_complex_t *x ; /* numerical values, size nzmax */
int nz ; /* # of entries in triplet matrix, -1 for compressed-col */
} cs_ci ;
....................
#ifdef __cplusplus
}
#endif
#endif
I am getting a compilation error:
Error 1 error C2143: syntax error : missing ';' before '*'
for the line:
cs_complex_t *x ; /* numerical values, size nzmax */
Due to the size of the file some irrelevant parts are missing. Is there something that could explain this error given this code segment? This project is a simulator like Spice.
The code you've posted will lead to exactly this error if the macro NCOMPLEX is defined. Both definitions of cs_complex_t are enclosed in #ifndef NCOMPLEX. So if the macro NCOMPLEX is defined, cs_complex_t will not be defined and will thus be an unresolvable identifier when the compiler encounters it in the definition of cs_ci_sparse.
I'd say that's a logical bug in the file. If the definition of cs_complex_t depends on the absence of NCOMPLEX, all uses of cs_complex_t should depend on it too.
I have a quick question regarding printing the evaluated values of #defines using #pragma message. I'm using msvc++ in Visual Studio 2008.
Below is a simplified example:
#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
#define WIDTH 10
#define HEIGHT 10
#define AREA (WIDTH * HEIGHT)
#pragma message("Area is: " __STR1__(AREA))
Now when I compile I get the following output:
>Area is: (10 * 10)
This is not exactly what I want. Is there any way to print out the evaluation of a #define expression so that I get:
>Area is: 100
during compilation. Perhaps this is not possible. Eventually I want to be able to cause a compiler error if the evaluated value is too large. i.e.
#if(AREA > 1000)
#pragma message(__ERROR__)
#endif
Some of my #defines use sizeof() which I believe causes issues in itself when evaluating conditionals - but that's a problem for the future!
I looked at the following post How do I show the value of a #define at compile time in gcc which is fine as long as the #define is defined as a value, and not a concatenation of other #defines.
The preprocessor won't do math for you, it can only substitute tokens and expand macros in a textual way.
If you want to calculate that value during compilation you should go for constexpr (http://en.cppreference.com/w/cpp/language/constexpr, more precisely this will hint the compiler to calculate it at compile-time)
#include <iostream>
#define WIDTH 10
#define HEIGHT 10
template<int a, int b>
constexpr int getArea() {
static_assert(a*b < 1000, "Area is too big");
return a*b;
}
const int area = getArea<WIDTH, HEIGHT>();
int main(void) {
std::cout << area;
}
Example
static_assert will do the check for the area if it is too large.
The precompiler can do limited math in #if statements. This may be sufficient for your needs:
#define WIDTH 10
#define HEIGHT 10
#define AREA (WIDTH * HEIGHT)
#if AREA > 1000
#error Oh bad, oh bad, oh bad
#endif
For more complex mathematics I would second what Marco A. said but you don't need that in a template or anything.
You can just put it up with all your #defines, for example:
#define WIDTH 10
#define HEIGHT 10
#define AREA (WIDTH * HEIGHT)
#define __ERROR__ "Oh bad, oh bad, oh bad"
static_assert(AREA < 1000, __ERROR__);
Or even simpler: static_assert(WIDTH * HEIGHT < 1000, "Oh bad, oh bad, oh bad");
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I am new in here, posting because I have read several posts that have help me.I know you may regard this post as another duplicate, while it's not. It's not a duplicate because my code is different than others. Here is my code as:
#include "bcm2835.h"
#include <cmath>
#include <iostream>
using namespace std;
// COMMANDS
#define WAKEUP 0x02
#define SLEEP 0x04
#define RESET 0x06
#define START 0x09
#define STOP 0x0a
#define RDATAC 0x10
#define SDATAC 0x11
#define RDATA 0x12
#define OFSCAL 0x18
#define GANCAL 0x19
#define RREG1 0x20
#define WREG1 0x40
#define RREG2 0x08
#define WREG2 0x08
// REGISTERS
#define CONFIG0 0x85
#define CONFIG1 0x10 // checksum is kept off
#define CONFIG2 0x15 //10SPS data rate and Gate control mode
#define OFC0 0x00
#define OFC1 0x00
#define OFC2 0x00
#define FSC0 0x00
#define FSC1 0x00
#define FSC2 0x40
#define NUM 1024
int nobytes;
int S = 50;
int i,flag = 1;
int j, k, factor, converged, count = 0;
char status = LOW;
char txbuffer[11], rxbuffer[4], dummy;
float xhat, xhat_m, P_m, L , K, last_xhat_converged, xhat_converged = 0.0;
float P = 1.0;
float R = 0.01;
float Q, mean, variance = 0;
float current, lastreading, current_test[50];
double key, startkey;
float X1[4096];
float X2[4096];
float Xf1[4096];
float Xf2[4096];
float v[4096];
float xf[4096];
float c[65536];
float ys[65536];
spi_start();
initialise();
void spi_start()
{
bcm2835_init();
//cout << "The SPI mode is starting";
// INITIAL SETUP OF THE SPI DEVICE
bcm2835_spi_begin(); // Setup the SPI0 port on the RaspberryPi
bcm2835_spi_chipSelect(BCM2835_SPI_CS0); // Assert the chip select
bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST); // Set the Bit order
bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW); // Set the the chip select to be active low
bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_64); // Set the clock divider, SPI speed is 3.90625MHz
bcm2835_spi_setDataMode(BCM2835_SPI_MODE1); // Set the Data mode
//cout << "The SPI mode has been started";
}
void initialise()
{
// INITIAL RESET OF THE CHIP
nobytes = 1;
txbuffer[0] = RESET;
bcm2835_spi_writenb(txbuffer, nobytes);
bcm2835_delay(100); //no accurate timing required
// WRITING OF THE CONTROL AND THE CALIBRATION REGISTERS
nobytes = 11;
txbuffer[0] = WREG1;
txbuffer[1] = WREG2;
txbuffer[2] = CONFIG0;
txbuffer[3] = CONFIG1;
txbuffer[4] = CONFIG2;
txbuffer[5] = OFC0;
txbuffer[6] = OFC1;
txbuffer[7] = OFC2;
txbuffer[8] = FSC0;
txbuffer[9] = FSC1;
txbuffer[10]= FSC2;
bcm2835_spi_writenb(txbuffer, nobytes);
bcm2835_delay(100); //no accurate timing required
}
suggestions will be appreciated.
Your issue is that you are confusing the compiler:
spi_start();
initialize();
Are function calls and not function declarations.
Please include the return types:
void spi_start();
void initialise();
How to convert this to use VC++ and MASM
static __inline__ void io_wait(void)
{
asm volatile("jmp 1f;1:jmp 1f;1:");
}
I know asm changes to __asm and we remove the volatile but whats next?
I am trying to create the function to place in the code below
#define PIC1 0x20
#define PIC2 0xA0
#define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1)
#define PIC_EOI 0x20
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
#define ICW1_INIT 0x10 /* Initialization - required! */
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
void remap_pics(int pic1, int pic2)
{
UCHAR a1, a2;
a1=ReadPort8(PIC1_DATA);
a2=ReadPort8(PIC2_DATA);
WritePort8(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4);
io_wait();
WritePort8(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);
io_wait();
WritePort8(PIC1_DATA, pic1);
io_wait();
WritePort8(PIC2_DATA, pic2);
io_wait();
WritePort8(PIC1_DATA, 4);
io_wait();
WritePort8(PIC2_DATA, 2);
io_wait();
WritePort8(PIC1_DATA, ICW4_8086);
io_wait();
WritePort8(PIC2_DATA, ICW4_8086);
io_wait();
WritePort8(PIC1_DATA, a1);
WritePort8(PIC2_DATA, a2);
}
I think you'll have better luck by telling us what you're trying to do with this code. Neither of the platforms supported by VC++ will wait for IO completion by executing an unconditional jump.
Nevertheless, given your example, I see several problems you need to address first:
"1f" needs to have a suffix indicating that it's hexadecimal. In VC++ you can use either C-style (0x1f) or assembly style (1fh) suffixes in inline assembly
it seems that you've got two "1" labels. Besides the fact that two labels of the same name are going to collide, I believe VC++ doesn't support label names containing only digits
1fh is a strange address to jump to. In Real mode it's IRQ area, in Protected mode it's inside the first page, which most of the OSes keep not-present to catch NULL dereference.
Barring that, your code can be translated to VC++ should look like this:
__asm {
jmp 1fh
a1:
jmp 1fh
b1:
}
But this will not get you anything useful. So please state what you're trying to accomplish
Seems GNU gas syntax, jmp 1f means jump to label 1 forward.
static __inline__ void io_wait(void)
{
#ifdef __GNUC__
asm volatile("jmp 1f;1:jmp 1f;1:");
#else
/* MSVC x86 supports inline asm */
__asm {
jmp a1
a1:
jmp b1
b1:
}
#endif
}