I am using C to program a microcontroller (NHS3152) to calculate resistance using this formula:
RES = (V1-V2)/I
I want to write a program that:
Updates the values of 3 Floats and 1 integer (V1, V2, I, RES)
Update uint8_t text[] = "Char to store values of V_1, V_2, I, Res"; with a string with the values of these 3 floats and 1 integer
Commits text to memory using the function: "Example1_Creating_an_NDEF..." (provided below)
The issue I am having is with Updating text with the values of the 3 floats and 1 integer. I am able to do it with sprintf, however I cannot use this function with my microcontroller (I dont know why it stops me from flashing it to memory)
The code bellow is an example of what i want to achieve in from point 2 above, in the real code the float and integer values are updated by getting values from sensors on the mircocontroller:
#include <stdio.h>
#include <stdint.h>
static volatile float V_1 = 5.0; // store value of Voltage 1
static volatile float V_2 = 2.0; // store value of voltage 2
static volatile int I = 5; // store current value
static volatile float RES; // calcualte resitance
int i=1;
uint8_t text[] = "Char to store values of V_1, V_2, I, Res";
int main(void)
{
printf( text);
printf("\n");
//updates values for ADC_1, ADC_2, I, Res,
while(i<=2){ // real while loop is infinite
V_1 ++ ; // Usually value updates from microcontroller sensor
V_2 ++ ;
I ++;
RES = (V_1-V_2)/I; // calculating resistance
sprintf((char *)text, "Updated Text V1: %6.2f V2: %6.2f I: %8.d resistance: %e", V_1, V_2,I, RES ); // what i want to do but without sprintf
printf( text);
printf("\n");
i++;
}
printf("END");
}
OUT:
Char to store values of V_1, V_2, I, Res
Updated Text V1: 6.00 V2: 3.00 I: 6 resistance: 5.000000e-01
Updated Text V1: 7.00 V2: 4.00 I: 7 resistance: 4.285714e-01
END
Here is the Code including the function Example1_Creating_an_NDEF.. from point 3. This working code manages to Commit the text to memory (it works). All i need is to be able to update the text without sprintf as i believe these functions aren't allowed when i'm not in debug mode.
#include "board.h"
// From ndeft2t
#include "ndeft2t/ndeft2t.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
uint8_t instance[NDEFT2T_INSTANCE_SIZE] __attribute__((aligned (4)));
uint8_t buffer[NFC_SHARED_MEM_BYTE_SIZE ] __attribute__((aligned (4)));
uint8_t locale[] = "en";
uint8_t text[] = "Char to store values of V_1, V_2, I, Res";
// I want to add these to the text message
static volatile float V_1 = 5.0;
static volatile float V_2 = 2.0;
static volatile int I = 5;
static volatile float Res = ;
static void Example1_Creating_an_NDEF_Message_with_a_single_record_of_type_TEXT (void)
{
Chip_NFC_Init(NSS_NFC); /* Is normally already called during board initialization. */
NDEFT2T_Init();
NDEFT2T_CreateMessage(instance, buffer, NFC_SHARED_MEM_BYTE_SIZE, true);
NDEFT2T_CREATE_RECORD_INFO_T recordInfo = {.shortRecord = true, .pString = locale};
if (NDEFT2T_CreateTextRecord(instance, &recordInfo)) {
/* The payload length to pass excludes the NUL terminator. */
if (NDEFT2T_WriteRecordPayload(instance, text, sizeof(text) - 1)) {
NDEFT2T_CommitRecord(instance);
}
}
NDEFT2T_CommitMessage(instance);
/* The return value of the commit function is ignored here. */
}
int main(void)
{
Board_Init();
//NDEFT2T_Init();
/* Optional feature: send the ARM clock to PIO0_1 */
Chip_IOCON_SetPinConfig(NSS_IOCON, IOCON_PIO0_1, IOCON_FUNC_1);
Chip_Clock_Clkout_SetClockSource(CLOCK_CLKOUTSOURCE_SYSTEM);
/* Blink & attach a message to Memory */
while (1) {
//updates values for V_1, V_2, I, Res,
V_1++;
V_2++;
I++;
RES = (V_1 - V_2)/RES;
// Update the text message to contain "(V_1, V_2, I, RES)"
LED_Toggle(LED_RED);
Example1_Creating_an_NDEF_Message_with_a_single_record_of_type_TEXT();
Chip_Clock_System_BusyWait_ms(500);
}
return 0;
}
EDIT: responding to KamilCuk's comment : Do you really need float? Does your mcu has floating point support? Consider using integers only.
The fucntions i use to get V1,V2 & I, all return an Integer (eg: V1=2931 12 bit converter so between 0 and 4096 ) however to convert the integer value to the real value i need to use the following conversion:
V1_real= (V1* 1.2) / 2825 + 0.09; // CONVERSION added line
Without conversion i Cannot calculate Res.
An acceptable compromise is to commit to memory the values V1, V2, I without converstion to real values. I can then calculate RES in a second momemnt, once i retrieve the data from the MCU ( i am using my phone as an NFC reader, the chip is an NFC tag)
So the question is:
How do i convert the message in text to a message containing the integers (V_1,V_2,I)? :
Something like:
uint8_t text[] = "Char to store values of V_1, V_2, I";
text = "Message with V_1: V_1value, V_2: V_2value, I: IValue
Below is the code i use to extract the value of V_1 & V_2:
void adc (void)
{
Chip_IOCON_SetPinConfig(NSS_IOCON, IOCON_ANA0_1, IOCON_FUNC_1);
Chip_ADCDAC_SetMuxADC(NSS_ADCDAC0, ADCDAC_IO_ANA0_1);
Chip_ADCDAC_SetInputRangeADC(NSS_ADCDAC0, ADCDAC_INPUTRANGE_WIDE);
Chip_ADCDAC_SetModeADC(NSS_ADCDAC0, ADCDAC_SINGLE_SHOT);
Chip_ADCDAC_StartADC(NSS_ADCDAC0);
//Getting the data
while (!(Chip_ADCDAC_ReadStatus(NSS_ADCDAC0) & ADCDAC_STATUS_ADC_DONE)) {
; /* Wait until measurement completes. For single-shot mode only! */
}
//Data V1 stored here
adcInput_1 = Chip_ADCDAC_GetValueADC(NSS_ADCDAC0);
// Usually i use this line to then conver it to the real value of V1
//adcInput_1= (adcInput_1 * 1.2) / 2825 + 0.09; // CONVERSION added line
//! [adcdac_nss_example_3]
}
Maybe someone has a better solution that allows me to actually arrive at having also RES calculated, knowing that:
RES= V1_real-V1_real/I_real
V1_real= (V1* 1.2) / 2825 + 0.09 and 0< V1 < 4000 (12 bit converter for V1)
V2_real= (V2* 1.2) / 2825 + 0.09 and 0< V2 < 4000
I_real = I*1e-12 0<I<4000
#include <gb/gb.h>
#include <stdio.h>
#include "racecars.h"
/*
RACECARS.C
Tile Source File.
Info:
Form : All tiles as one unit.
Format : Gameboy 4 color.
Compression : None.
Counter : None.
Tile size : 8 x 8
Tiles : 0 to 16
Palette colors : None.
SGB Palette : None.
CGB Palette : None.
Convert to metatiles : No.
This file was generated by GBTD v2.2
*/
/* Start of tile array. */
unsigned char Racecars[] =
{
0x7E,0x7E,0x42,0x5E,0xC3,0xD7,0xC3,0xDF,
0x42,0x52,0x7E,0x7E,0xC3,0xC3,0xC3,0xC3,
0x1C,0x1C,0x36,0x3E,0x62,0x7A,0x43,0x4B,
0x41,0x5D,0x7F,0x7F,0x55,0x55,0x77,0x77,
0x38,0x38,0x44,0xC6,0xAA,0xAA,0xAA,0xAA,
0xAA,0xAA,0x82,0x82,0x44,0xC6,0x38,0x38,
0x18,0x18,0x18,0x18,0x24,0x24,0x42,0x42,
0xFF,0xFF,0x00,0xC6,0x00,0xC6,0x00,0x00,
0x3C,0x3C,0x24,0xE7,0x24,0xE7,0x24,0x24,
0x24,0xE7,0x3C,0xFF,0x24,0x24,0x3C,0x3C,
0x18,0x18,0x24,0xE7,0x42,0xC3,0x42,0x42,
0x42,0x42,0x24,0x66,0x18,0x7E,0x00,0x00,
0xF2,0xF2,0x96,0x96,0xF2,0xF2,0x82,0x82,
0x8F,0x8F,0x00,0x00,0x00,0x00,0x00,0x00,
0xEE,0xEE,0x82,0x82,0x8E,0x8E,0x8B,0x8B,
0xEE,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,
0xEE,0xEE,0x82,0x82,0x8E,0x8E,0x82,0x82,
0xEE,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,
0xE2,0xE2,0x86,0x86,0x82,0x82,0x82,0x82,
0xE7,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,
0xEA,0xEA,0x8A,0x8A,0x8E,0x8E,0x82,0x82,
0xE2,0xE2,0x00,0x00,0x00,0x00,0x00,0x00,
0xE7,0xE7,0x84,0x84,0x87,0x87,0x81,0x81,
0xE7,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,
0xF7,0xF7,0x85,0x85,0x85,0x85,0xB5,0xB5,
0x95,0x95,0xF7,0xF7,0x00,0x00,0x00,0x00,
0x82,0x82,0x82,0x82,0x92,0x92,0x92,0x92,
0x92,0x92,0x92,0x92,0xFE,0xFE,0x00,0x00,
0xFF,0xFF,0x10,0x10,0x10,0x10,0x10,0x10,
0x10,0x10,0xFF,0xFF,0x00,0x00,0x00,0x00,
0x82,0x82,0xC2,0xC2,0xA2,0xA2,0x92,0x92,
0x8A,0x8A,0x86,0x86,0x82,0x82,0x00,0x00,
0x20,0x20,0x30,0x30,0x38,0x38,0x3C,0x3C,
0x20,0x20,0x20,0x20,0x20,0x20,0xFF,0xFF
};
/* End of RACECARS.C */
int main(void){ //starts the main function
int x,y,st,key,z; //define the integers x and y wich will be used to define the hero position, key will be used later
int x1,y1,st1;
int x2,y2,st2;
int x3,y3,st3;
x=20; //set x as 20
y=20; //set y as 20
st=0; //sprite type(1=closed 0=open)
z=0; //set z=0, z will be used for testing if its time to change sprite or not
set_sprite_data(0,76,Racecars); //set our sprite data
wait_vbl_done(); //wait for the visual blank to be done
set_sprite_tile(0,0); //set our tile 0 as the tile 0 of our tile data-pacman open
set_sprite_tile(1,1); //set our tile 1 as the 1st tile of our tile data-pacman closed
set_sprite_tile(2,2);
set_sprite_tile(3,3);
set_sprite_tile(4,4);
set_sprite_tile(5,5);
set_sprite_tile(6,6);
set_sprite_tile(7,7);
set_sprite_tile(8,8);
set_sprite_tile(9,9);
set_sprite_tile(10,10);
set_sprite_tile(11,11);
set_sprite_tile(12,12);
set_sprite_tile(13,13);
set_sprite_tile(14,14);
set_sprite_tile(15,15);
set_sprite_tile(16,16);
move_sprite(st,x,y);
#define MapSizeX 256;
#define MapSizeY 256;
UBYTE ScrollXCnt;
UBYTE ScrollYCnt;
BYTE SCXCnt;
BYTE SCYCnt;
UBYTE tempa, tempb;
UWORD Cnt;
Cnt = 0;
wait_vbl_done();
for(tempa = 0; tempa != 32; tempa++) {
set_bkg_tiles(0,tempa,32,tempa+1,TileMap[Cnt]);
Cnt = Cnt + MapSizeX;
}
if(joypad() & J_UP) ScrollUp();
if(joypad() & J_DOWN) ScrollDown();
if(joypad() & J_LEFT) ScrollLeft();
if(joypad() & J_RIGHT) ScrollRight();
wait_vbl_done();
scroll_bkg(x,y);
ScrollX++; or ScrollX--;
ScrollY++; or ScrollY--;
SCXCnt++; or SCXCnt++;
SCYCnt++; or SCYCnt--;
if(SCXCnt == 8) {
SCXCnt = 0;
Cnt = ScrollX / 8;
Cnt = Cnt + 20;
for(tempa = 0; tempa != 224; tempa++) {
set_bkg_tiles(0,tempa,1,tempa+1,TileMap[Cnt]);
Cnt = Cnt + MapSizeX;
}
}
if(SCXCnt == -8) {
SCXCnt = 0;
SCXCnt = 0;
Cnt = ScrollX / 8;
Cnt--;
for(tempa = 0; tempa != 224; tempa++) {
set_bkg_tiles(0,tempa,1,tempa+1,TileMap[Cnt]);
Cnt = Cnt + MapSizeX;
}
}
.
.
.
That is the c code
I ran the prompt and the following errors popped up.
Parse error before ubyte line 108
Parse error before scroll x
Parse error before scroll y
Parse error before scxCnt
Parse error before ScyCnt
Parse error before 32
Your issue is that you are tying to define new variables in the middle of the function. The GBDK compiler does not allow that, for whatever reason. (This is apparently part of the ANSI C / C89 standard)
You can fix this by changing the top of your main() from
int main(void){ //starts the main function
int x,y,st,key,z; //define the integers x and y wich will be used to define the hero position, key will be used later
int x1,y1,st1;
int x2,y2,st2;
int x3,y3,st3;
to this:
int main(void){ //starts the main function
int x,y,st,key,z; //define the integers x and y wich will be used to define the hero position, key will be used later
int x1,y1,st1;
int x2,y2,st2;
int x3,y3,st3;
//These variables are used later on.
UBYTE ScrollXCnt;
UBYTE ScrollYCnt;
BYTE SCXCnt;
BYTE SCYCnt;
UBYTE tempa, tempb;
UWORD Cnt;
Alternatively, you could move all of the code starting at those variables to another function, and then those variables will be declared with the function and all will be fine.
You might be missing an include file which defines UBYTE.
That UBYTE error shouldn't occur with current sdcc 4.1.0 and therefore gbdk-2020 4.0.3
GBDK's last update was 2001 or so...
Though the other errors are coming from your code being invalid.
That's no valid C code:
ScrollX++; or ScrollX--;
ScrollY++; or ScrollY--;
SCXCnt++; or SCXCnt++;
SCYCnt++; or SCYCnt--;
And I don't think this is doing what you want:
#define MapSizeX 256;
#define MapSizeY 256;
Defines are always unscoped since they are handled by the preprocessor and not the compiler. And you rather want #define MapSizeX 256U
What you wrote will work with your code.
Cnt = Cnt + MapSizeX; turning into Cnt = Cnt + 256;; isn't a big deal, but it would likely break later.
I have a program that compares variables from two structs and sets a bit accordingly for a bitmap variable. I have to compare each variables of the struct. No. of variables in reality are more for each struct but for simplicity I took 3. I wanted to know if i can create a macro for comparing the variables and setting the bit in the bitmap accordingly.
#include<stdio.h>
struct num
{
int a;
int b;
int c;
};
struct num1
{
int d;
int e;
int f;
};
enum type
{
val1 = 0,
val2 = 1,
val3 = 2,
};
int main()
{
struct num obj1;
struct num1 obj2;
int bitmap = 0;
if( obj1.a != obj2.d)
{
bitmap = bitmap | val1;
}
if (obj1.b != obj2.e)
bitmap = bitmap | val2;
printf("bitmap - %d",bitmap);
return 1;
}
can i declare a macro like...
#define CHECK(cond)
if (!(cond))
printf(" failed check at %x: %s",__LINE__, #cond);
//set the bit accordingly
#undef CHECK
With a modicum of care, you can do it fairly easily. You just need to identify what you're comparing and setting carefully, and pass them as macro parameters. Example usage:
CHECK(obj1.a, obj2.d, bitmap, val1);
CHECK(obj1.b, obj2.e, bitmap, val2);
This assumes that CHECK is defined something like:
#define STRINGIFY(expr) #expr
#define CHECK(v1, v2, bitmap, bit) do \
{ if ((v1) != (v2)) \
{ printf("failed check at %d: %s\n", __LINE__, STRINGIFY(v1 != v2)); \
(bitmap) |= (1 << (bit)); \
} \
} while (0)
You can lay the macro out however you like, of course; I'm not entirely happy with that, but it isn't too awful.
Demo Code
Compilation and test run:
$ gcc -Wall -Wextra -g -O3 -std=c99 xx.c -o xx && ./xx
failed check at 40: obj1.a != obj2.d
failed check at 42: obj1.c != obj2.f
bitmap - 5
$
Actual code:
#include <stdio.h>
struct num
{
int a;
int b;
int c;
};
struct num1
{
int d;
int e;
int f;
};
enum type
{
val1 = 0,
val2 = 1,
val3 = 2,
};
#define STRINGIFY(expr) #expr
#define CHECK(v1, v2, bitmap, bit) do \
{ if ((v1) != (v2)) \
{ printf("failed check at %d: %s\n", __LINE__, STRINGIFY(v1 != v2)); \
(bitmap) |= (1 << (bit)); \
} \
} while (0)
int main(void)
{
struct num obj1 = { 1, 2, 3 };
struct num1 obj2 = { 2, 2, 4 };
int bitmap = 0;
CHECK(obj1.a, obj2.d, bitmap, val1);
CHECK(obj1.b, obj2.e, bitmap, val2);
CHECK(obj1.c, obj2.f, bitmap, val3);
printf("bitmap - %X\n", bitmap);
return 0;
}
Clearly, this code relies on you matching the right elements and bit numbers in the invocations of the CHECK macro.
It's possible to devise more complex schemes using offsetof() etc and initialized arrays describing the data structures, etc, but you'd end up with a more complex system and little benefit. In particular, the invocations can't reduce the parameter count much. You could assume 'bitmap' is the variable. You need to identify the two objects, so you'll specify 'obj1' and 'obj2'. Somewhere along the line, you need to identify which fields are being compared and the bit to set. That could be some single value (maybe the bit number), but you've still got 3 arguments (CHECK(obj1, obj2, valN) and the assumption about bitmap) or 4 arguments (CHECK(obj1, obj2, bitmap, valN) without the assumption about bitmap), but a lot of background complexity and probably a greater chance of getting it wrong. If you can tinker with the code so that you have a single type instead of two types, etc, then you can make life easier with the hypothetical system, but it is still simpler to handle things the way shown in the working code, I think.
I concur with gbulmer that I probably wouldn't do things this way, but you did state that you had reduced the sizes of the structures dramatically (for which, thanks!) and it would become more enticing as the number of fields increases (but I'd only write out the comparisons for one pair of structure types once, in a single function).
You could also revise the macro to:
#define CHECK(cond, bitmap, bit) do \
{ if (cond) \
{ printf("failed check at %d: %s\n", __LINE__, STRINGIFY(cond)); \
(bitmap) |= (1 << (bit)); \
} \
} while (0)
CHECK(obj1.a != obj2.d, bitmap, val1);
...
CHECK((strcmp(obj3.str1, obj4.str) != 0), bitmap, val6);
where the last line shows that this would allow you to choose arbitrary comparisons, even if they contain commas. Note the extra set of parentheses surrounding the call to strcmp()!
You should be able to do that except you need to use backslash for multi-line macros
#ifndef CHECK
#define CHECK(cond) \
if (!(cond)) { \
printf(" failed check at %x: %s",__LINE__, #cond); \
//set the bit accordingly
}
#endif /* CHECK */
If you want to get really fancy (and terse), you can use the concatenation operator. I also recommend changing your structures around a little bit to have different naming conventions, though without knowing what you're trying to do with it, it's hard to say. I also noticed in your bit field that you have one value that's 0; that won't tell you much when you try to look at that bit value. If you OR 0 into anything, it remains unchanged. Anyway, here's your program slightly re-written:
struct num {
int x1; // formerly a/d
int x2; // formerly b/e
int x3; // formerly c/f
};
enum type {
val1 = 1, // formerly 0
val2 = 2, // formerly 1
val3 = 4, // formerly 2
};
// CHECK uses the catenation operator (##) to construct obj1.x1, obj1.x2, etc.
#define CHECK(__num) {\
if( obj1.x##__num != obj2.x##__num )\
bitmap |= val##__num;\
}
void main( int argc, char** argv ) {
struct num obj1;
struct num obj2;
int bitmap = 0;
CHECK(1);
CHECK(2);
CHECK(3);
}
As a reasonable rule of thumb, when trying to do bit-arrays is C, there needs to be a number that can be used to index the bit.
You can either pass that bit number into the macro, or try to derive it.
Pretty much the only thing available at compile time or run time is the address of a field.
So you could use that.
There are a few questions to understand if it might work.
For your structs:
Are all the fields in the same order? I.e. you can compare c with f, and not c with e?
Do all of the corresponding fields have the same type
Is the condition just equality? Each macro will have the condition wired in, so each condition needs a new macro.
If the answer to all is yes, then you could use the address:
#define CHECK(s1, f1, s2, f2) do \
{ if ((&s1.f1-&s1 != &s2.f2-&s2) || (sizeof(s1.f1)!=sizeof(s2.f2)) \
|| (s1.f1) != (s2.f2) \
{ printf("failed check at %d: ", #s1 "." #f1 "!=" #s1 "." #f1 "\n", \
__LINE__); \
(shared_bitmap) |= (1 << (&s1.f1-&s1)); // test failed \
} \
} while (0)
I'm not too clear on whether it is a bitmap for all comparisons, or one per struct pair. I've assumed it is a bit map for all.
There is quite a lot of checking to ensure you haven't broken 'the two rules':
(&s1.f1-&s1 != &s2.f2-&s2) || (sizeof(s1.f1)!=sizeof(s2.f2))
If you are confident that the tests will be correct, without those constraints, just throw that part of the test away.
WARNING I have not compiled that code.
This becomes much simpler if the values are an array.
I probably wouldn't use it. It seems a bit too tricky to me :-)