So after a day of struggling I managed to get Debian 11 on a IMX7D, 5.4.129 kernel to recognize the MAX14830 and talk to it via the MAX310X driver. But when I try to send data with echo a > /dev/ttyMAX0 nothing happens. Well except the Tx count going up.
Looking at the SPI traffic this seems to be going correctly and the chip is sending the expected responses (Tx FIFO count returns three if three characters are being send) but nothing seems to happen to the buffer. The driver keeps interrogating the max but the FIFO stays at 3. Then the driver reaches a timeout I guess. Because it then sends 0x81,0x00 which clears the IRQen register, followed by 0x9B 0x40 which sets the baudrate register... which makes it all the more confusing.
So far I've gone through all the stty settings and used -ixon to disable XON/XOFF but that didn't make a difference.
Is there a way/place/file that holds the settings for the driver? Or am I forgetting something? RX doesn't seem to work either but not sure if the max isn't receiving it or just not informing the driver.
The relevant portion of the DTS
&ecspi3 {
max14830: max14830#3 {
compatible = "maxim,max14830";
spi-max-frequency = <15000000>;
reg = <0>; // SPI chip select number
clocks = <&clk16m0>;
clock-names = "osc";
interrupt-parent = <&gpio5>;
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
gpio-controller; // Marks the device node as a GPIO controller
#gpio-cells = <2>;
clk16m0: clk16m0 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <3686400>; // freq of external xtal
clock-accuracy = <100>;
};
};
};
And the comms during startup
OUT IN MEANING
0x9F 0xCE -> Write globalCmd = Enable Extend register map acces
0x05 0x00 -> 0x0F 0xB4 -> Clear SpclChrIntEn= RevID is B4
0x9F 0xCD -> Write globalCmd = Disable Extend register map access
0x8A 0x01 -> Write UART0 Mode2 = Set RST
0x8A 0x00 -> Write UART0 Mode2 = Clear RST
0x1C 0x00 -> 0x0F 0x01 -> Read UART0 DivLSB = Div0 set
0x89 0x80 -> Set UART0 MODE1 = ~RTS0 is three state
0xAA 0x01 -> Write UART1 Mode2 = Set RST
0xAA 0x00 -> Write UART1 Mode2 = Clear RST
0x3C 0x00 -> 0x0F 0x01 -> Read UART1 DivLSB = Div0 set
0xA9 0x80 -> Set UART1 MODE1 = ~RTS1 is three state
0xCA 0x01 -> Write UART2 Mode2 = Set RST
0xCA 0x00 -> Write UART2 Mode2 = Clear RST
0x5C 0x00 -> 0xF 0x01 -> Read UART2 DivLSB = Div0 set
0xC9 0x80 -> Set UART2 MODE1 = ~RTS2 is three state
0xEA 0x01 -> Write UART3 Mode2 = Set RST
0xEA 0x00 -> Write UART3 Mode2 = Clear RST
0x7C 0x00 -> 0x0F 0x01 -> Read UART3 DivLSB = Div0 set
0xE9 0x80 -> Set UART3 MODE1 = ~RTS3 is three state
0x9A 0x44 -> Write PLLConfig = Set PreDiv5 and PreDiv2
0x9E 0x14 -> Write ClockSource = 0001 0100 -> first 1 at dont care, second PLLen
0x81 0x00 -> Clear IRQen UART0
0x02 0x00 -> 0x0F 0x60 -> Read ISR UART0 = both fifo empty
0x1B 0x00 -> 0x0F 0x00 -> Read BRConfig UART0 -> all clear
0x9B 0x40 -> Write BRConfig UART0 -> FRACT2 Set
0xA1 0x00 -> Clear IRQen UART1
0x22 0x00 -> 0x0F 0x60 -> Read ISR UART1 = both fifo empty
0x3B 0x00 -> 0x0F 0x00 -> Read BRConfig UART1 -> all clear
0xBB 0x40 -> Write BRConfig UART1 -> FRACT2 Set
0xC1 0x00 -> Clear IRQen UART2
0x42 0x00 -> 0x0F 0x60 -> Read ISR UART2 = both fifo empty
0x58 0x00 -> 0x0F 0x00 -> Read BRConfig UART2 -> all clear
0xDB 0x40 -> Write BRConfig UART2 -> FRACT2 Set
0xE1 0x00 -> Clear IRQen UART3
0x62 0x00 -> 0x0F 0x60 -> Read ISR UART3 = both fifo empty
0x7B 0x00 -> 0x0F 0x00 -> Read BRConfig UART3 -> all clear
0xFB 0x40 -> Write BRConfig UART3 -> FRACT2 Set
ttyMAX0 setup according to stty
Result of stty -F /dev/ttyMAX0
-parenb -> don't generate parity
-parodd -> Even parity?
-cmspar -> No stick parity
cs8 -> character size 8 bits
hupcl -> don't send hangup signal
-cstopb -> use one bit per character
cread -> allow input to be received
clocal -> disable modem control signals
-crtscts -> dont enable rts/cts handschaking
-ignbr -> don't ignore break characters
-brkint -> breaks don't cause an interrupt signal
-ignpar -> don't ignore characters with parity errors
-parmrk -> don't mark parity errors
-inpck -> don't enable parity checking
-istrip -> don't clear high (8th) bit of input characters
-inlcr -> dont translate newline to carriage return
-igncr -> don't ignore carriage return
icrnl -> don't translate carriage return to newline
-ixon -> disable XON/XOFF flow control
-ixoff -> disable sending of start/stop characters
-iuclc -> don't translate uppercase to lowercase
-ixany -> Don't let any character restart output
-imaxbel -> don't beep and flush
-iutf8 -> don't assume characters are utf8 encoded
OUTPUT SETTINGS
opost -> post process output
-olcuc -> don't translate lower to upper
-ocrnl -> don't translate carriage return to newline
onlcr -> translate newline to carriage return newline
-onocr -> print carriage return in the first column
-onlret -> newline doesn't perform a carriage return
-ofill -> don't use fill characters instead of timing for delays
-ofdel -> don't use delete character for fill instead of null
nl0
cr0
tab0 -> horizontal tab delay style 0
bs0
vt0
ff0 -> form feed delay style
isig -> enable interrpt,
icanon -> enable special characters: erase, kill, werase, rprnt
iexten -> enable non-POSIX special characters
echo -> echo input characters
echoe -> echo erase characters as backspace-space-backspace
echok -> echo a newline after a kill character
-echonl
-noflsh -> don't disable flushing after interrupt & quit special
chars
-xcase
-tostop
-echoprt
echoctl -> echo control characters in hat notation ('^c')
echoke -> kill all line by obeying the echoprt and echoe settings
-flusho
-extproc
TX wasn't working because clock-names should have been xtal
RX wasn't working because i never opened the port but checked /proc/tty/driver/max310x for received data and the driver disables rx if a port isn't open.
Working node.
&ecspi3 {
/delete-node/spidev#0;
max14830: max14830#3 {
compatible = "maxim,max14830";
spi-max-frequency = <15000000>;
reg = <0>; // SPI chip select number
clocks = <&clk16m0>;
clock-names = "xtal"; /* because using external xtal */
interrupt-parent = <&gpio5>;
interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
gpio-controller; /* Marks the device node as a GPIO controller */
#gpio-cells = <2>;
clk16m0: clk16m0 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <3686400>; /* external xtal frequency */
clock-accuracy = <100>;
};
};
};
```
I am developing a project where I have to read the holding registers data. I check everything using this http://www.freemodbus.com/ and it is working and get a proper response. While trying with the developed program I am not getting the proper response.
Software Response: 0x01 0x03 0x04 0x1a 0xa0 0x42 0x48 0xcd 0x9f
Arduino response: 0x01 0x04 0x83 0x43 0xff 0xff 0xff 0xff 0xff
note that in Arduino response there is no 0x03 after 0x01 I don't know why it is happening can anyone please help me with this.
please find attached Arduino code below.
static union
{
unsigned long a;
byte b[4];
float f;
}vr;
void readregister(unsigned int address)
{
byte rxbuf[]={0,0,0,0,0,0,0,0,0,0,0};
byte data[] = {0x01,0x03,0x00,0xab,0x00,0x02,0xb5,0xeb};
Serial3.flush();
for(int i=0;i<8;i++)
{
Serial3.write(data[i]);
}
delay(250);
while(Serial3.available()>0)
{
for(int v=0; v<=10;v++)
{
rxbuf[v]=Serial3.read();
Serial.println(rxbuf[v],HEX);
}
}
Serial3.flush();
vr.b[3]=rxbuf[3];
vr.b[2]=rxbuf[2];
vr.b[1]=rxbuf[5];
vr.b[0]=rxbuf[4];
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial3.begin(9600,SERIAL_8E1);
}
void loop() {
// put your main code here, to run repeatedly:
readregister(99);
Serial.print("\n");
delay(3000);
}
Yes, I think you're getting an Error code 4 back from the device. See http://www.simplymodbus.ca/exceptions.htm
On this line, where you prep your request:
byte data[] = {0x01,0x03,0x00,0xab,0x00,0x02,0xb5,0xeb};
You're saying, device 1, function 3, 0x00 is space, then register address 0xAB. Not sure about the extra zero then, then length 2, and then CRC. So I vote that either the CRC is wrong, or the extra zero is wrong.
Also, note that modbus fails on ocassion for no reason, even when you do everything right, so retry after a few seconds and see what happens
I've been reading a lot of questions and answers regarding nrf24l01 and Arduinos while I was trying to figure out my problem. I'm fairly sure no one had this issue yet but I might be wrong. Here is my problem:
If I upload the sending code to the UNO and the receiving code to the NANO I keep getting errors. And nothing gets transmitted. However, if I do the opposite and I upload the sending code to the NANO and the receiving code to the UNO, everything is fine... I've been scratching my head for a couple days without any idea and I would like to get input from other people because I ran out of ideas...
I tried different nrf24l01 modules (I got about 20) to see if one was fried. Still the same thing. Tried changing to different pins... still the same thing. Changed the code to get it simpler and simpler to narrow down.. still the same thing. Maybe it requires more power to scan than send a package and the 3.3v from the Nano is not enough? I highly doubt..
I'm really curious if you guys can figure this one out. I think I provided a lot of info. If you need more feel free to ask.
Here is my set-up:
Arduino Nano:
And here is the log from the printDetails() function:
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xb01dfacece 0xb01dfacece
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xb01dfacece
RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x02
RF_CH = 0x73
RF_SETUP = 0x07
CONFIG = 0x0e
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_MAX
Arduino Uno:
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xb01dfacece 0xb01dfacece
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xb01dfacece
RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x02
RF_CH = 0x73
RF_SETUP = 0x07
CONFIG = 0x0e
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_MAX
Here is the Receiver code:
#include <SPI.h>
#include "RF24.h"
#include "nRF24L01.h"
#include "printf.h"
RF24 myRadio (7,8);
const uint64_t pipe = 0xB01DFACECEL;
struct package
{
int id=0;
int code = 0;
char text[100] = "";
};
typedef struct package Package;
Package data;
void setup() {
Serial.begin(115200);
printf_begin();
delay(1000);
myRadio.begin();
myRadio.setChannel(115);
myRadio.openReadingPipe(1,pipe);
myRadio.printDetails();
myRadio.startListening();
Serial.println("Set-Up Done");
delay(1000);
}
void loop() {
if(myRadio.available())
{
while(myRadio.available())
{
myRadio.read(&data, sizeof(data));
Serial.print("\nPackage");
Serial.println(data.id);
Serial.println(data.code);
Serial.println(data.text);
}
}
delay(500);
}
Here is the Sending code:
#include <SPI.h>
#include "RF24.h"
#include "nRF24L01.h"
#include "printf.h"
RF24 myRadio (7,8);
const uint64_t pipe = 0xB01DFACECEL;
struct package
{
int id=1;
int code = 2;
char text[100] = "text";
};
typedef struct package Package;
Package data;
void setup() {
Serial.begin(9600);
printf_begin();
delay(1000);
myRadio.begin();
myRadio.setChannel(115);
myRadio.openWritingPipe(pipe);
myRadio.setRetries(15,15);
myRadio.printDetails();
myRadio.stopListening();
Serial.println("Set-Up Done");
delay(1000);
}
void loop() {
if(!myRadio.write(&data, sizeof(data)))
{
Serial.println("error!!");
myRadio.printDetails();
}
Serial.print("\nPackage");
Serial.println(data.id);
Serial.println(data.code);
Serial.println(data.text);
data.id += 1;
data.code += 1;
delay(3000);
}
Try putting a 10uf capacitor across the +3.3v and gnd of each of the nRF24L01 module.
These modules need a lot of sending power which the capacitor helps with. I hope it works for you.
Try putting a 10uf capacitor across the +3.3v and gnd of each of the nRF24L01 module.
If that dosen't work, run the nrf24l01 off its own supply, 3.3v but have seen these peak at 1A! sending bursts. and the poor Nano's 3.3V comes from the FT232 chip, only 50mA is available.
At present, I am trying audio decoding for the first time using avcodec_decode_audio4(), which is always returning error.
Note: My overall intention is to merge multiple AMR_NB encoded files into one audio file, and eventually mux this final audio file with another video file into .mp4 container.
Here's the code:
if(avformat_open_input(&sound, "/tmp/aud0", NULL, NULL)!=0) {
printf("Error in opening input file aud0\n");
exit(1);
} else {
printf("Opened aud0 into FormatContext\n");
}
if(avformat_find_stream_info(sound, NULL)<0){
printf("Error in finding stream info\n");
avformat_close_input(&sound);
exit(1);
}
int aud_stream_idx=-1;
for(int count=0; count<sound->nb_streams; count++) {
if(sound->streams[count]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
aud_stream_idx = count;
printf("Audio stream index %d found\n", count);
break;
}
}
if(aud_stream_idx==-1) {
printf("Audio stream not found in the aud0 file\n");
avformat_close_input(&sound);
exit(1);
}
AVCodecContext *audioCC = sound->streams[aud_stream_idx]->codec;
printf("Audio codec_id=%d, codec_name=%s\n", audioCC->codec_id, audioCC->codec_name);
AVCodec *audioC = avcodec_find_decoder(audioCC->codec_id);
if (audioC == NULL) { printf("Couldn't find decoder\n");
avformat_close_input(&sound);
exit(1);
} else {
printf("Found decoder name %s\n", audioCC->codec_name);
}
if(avcodec_open2(audioCC, audioC, NULL)<0) {
printf("Couldn't open decoder\n");
avformat_close_input(&sound);
exit(1);
} else {
printf("Found decoder name %s\n", audioCC->codec_name);
printf("Found bitrate %d\n", audioCC->bit_rate);
printf("Found sample_rate %d\n", audioCC->sample_rate);
printf("Found sample_fmt %d\n", audioCC->sample_fmt); }
/* decode until eof */
av_init_packet(&avpkt);
avpkt.data=NULL;
avpkt.size=0;
if(av_read_frame(sound, &avpkt)<0) {
printf("Couldn't read encoded audio packet\n");
av_free_packet(&avpkt);
avformat_close_input(&sound);
exit(1);
} else {
printf("Read encoded audio packet\n");
printf("avpkt.pts = %d\n", avpkt.pts);
printf("avpkt.dts = %d\n", avpkt.dts);
printf("avpkt.duration = %d\n", avpkt.duration);
printf("avpkt.stream_index = %d\n", avpkt.stream_index);
printf("avpkt.data = %x\n", avpkt.data);
printf("avpkt.data[0] = %02x\n", avpkt.data[0]);
printf("avpkt.data[0]>>>3&0x0f = %02x\n", avpkt.data[0]>>3 & 0x0f);
}
fprintf(stderr, "avpkt.size=%d\n", avpkt.size);
while (avpkt.size > 0) {
int got_frame = 0;
if (!decoded_frame) {
if (!(decoded_frame = avcodec_alloc_frame())) {
fprintf(stderr, "out of memory\n");
exit(1);
} } else
avcodec_get_frame_defaults(decoded_frame);
len = avcodec_decode_audio4(audioCC, decoded_frame, &got_frame, &avpkt);
if (len < 0) {
fprintf(stderr, "Error %d while decoding\n", len);
exit(1);
}
Here is the output I see (I think demuxing is working fine):
Opened aud0 into FormatContext
Audio stream index 0 found
Audio codec_id=73728, codec_name=
Found decoder name
Found decoder name
Found bitrate 5200
Found sample_rate 8000
Found sample_fmt 3
Read encoded audio packet
avpkt.pts = 0
avpkt.dts = 0
avpkt.duration = 160
avpkt.stream_index = 0
avpkt.data = 91e00680
avpkt.data[0] = 04
avpkt.data[0]>>>3&0x0f = 00
avpkt.size=13
[amrnb # 0x7fce9300bc00] Corrupt bitstream
Error -1094995529 while decoding
This audio was created by recording voice on an Android device.
I also tried a .m4a generated by QuickTime, but no luck.
I feel I am missing some crucial step (like not initializing some CodecContext field, or not reading into AVPacket properly). In any case, if someone has any input or similar example, please let me know.
To help others understand ffmpeg error codes, this may be helpful. Error codes from ffmpeg (error.h from avutil) :
http://ffmpeg.org/doxygen/trunk/error_8h_source.html
It turns out the value you specified is :
#define AVERROR_INVALIDDATA FFERRTAG( 'I','N','D','A')
The -1094995529 becomes -0x41444E49 and when you look at those letters, in ACSII, 0x41 = 'A', 0x44 = 'D', 0x4E = 'N, and 0x49 = 'I'. Due to the macro/etc things are reversed, so ADNI becomes INDA, which you can see from the #define snippet, is the AVERROR_INVALIDDATA defined FFERRTAG( 'I','N','D','A').
The rest of the error codes are in that file and I've pasted them below here :
#define AVERROR_BSF_NOT_FOUND FFERRTAG(0xF8,'B','S','F') ///< Bitstream filter not found
#define AVERROR_BUG FFERRTAG( 'B','U','G','!') ///< Internal bug, also see AVERROR_BUG2
#define AVERROR_BUFFER_TOO_SMALL FFERRTAG( 'B','U','F','S') ///< Buffer too small
#define AVERROR_DECODER_NOT_FOUND FFERRTAG(0xF8,'D','E','C') ///< Decoder not found
#define AVERROR_DEMUXER_NOT_FOUND FFERRTAG(0xF8,'D','E','M') ///< Demuxer not found
#define AVERROR_ENCODER_NOT_FOUND FFERRTAG(0xF8,'E','N','C') ///< Encoder not found
#define AVERROR_EOF FFERRTAG( 'E','O','F',' ') ///< End of file
#define AVERROR_EXIT FFERRTAG( 'E','X','I','T') ///< Immediate exit was requested; the called function should not be restarted
#define AVERROR_EXTERNAL FFERRTAG( 'E','X','T',' ') ///< Generic error in an external library
#define AVERROR_FILTER_NOT_FOUND FFERRTAG(0xF8,'F','I','L') ///< Filter not found
#define AVERROR_INVALIDDATA FFERRTAG( 'I','N','D','A') ///< Invalid data found when processing input
#define AVERROR_MUXER_NOT_FOUND FFERRTAG(0xF8,'M','U','X') ///< Muxer not found
#define AVERROR_OPTION_NOT_FOUND FFERRTAG(0xF8,'O','P','T') ///< Option not found
#define AVERROR_PATCHWELCOME FFERRTAG( 'P','A','W','E') ///< Not yet implemented in FFmpeg, patches welcome
#define AVERROR_PROTOCOL_NOT_FOUND FFERRTAG(0xF8,'P','R','O') ///< Protocol not found
#define AVERROR_STREAM_NOT_FOUND FFERRTAG(0xF8,'S','T','R') ///< Stream not found
#define AVERROR_BUG2 FFERRTAG( 'B','U','G',' ')
#define AVERROR_UNKNOWN FFERRTAG( 'U','N','K','N') ///< Unknown error, typically from an external library
#define AVERROR_EXPERIMENTAL (-0x2bb2afa8) ///< Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it.
#define AVERROR_INPUT_CHANGED (-0x636e6701) ///< Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED)
#define AVERROR_OUTPUT_CHANGED (-0x636e6702) ///< Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED)
#define AVERROR_HTTP_BAD_REQUEST FFERRTAG(0xF8,'4','0','0')
#define AVERROR_HTTP_UNAUTHORIZED FFERRTAG(0xF8,'4','0','1')
#define AVERROR_HTTP_FORBIDDEN FFERRTAG(0xF8,'4','0','3')
#define AVERROR_HTTP_NOT_FOUND FFERRTAG(0xF8,'4','0','4')
#define AVERROR_HTTP_OTHER_4XX FFERRTAG(0xF8,'4','X','X')
#define AVERROR_HTTP_SERVER_ERROR FFERRTAG(0xF8,'5','X','X')
first you need to call av_read_frame until you get to EOF. So you need av_read_frame in the loop.
Let me explain how decoding works:
you open formatcontext, codeccontext and decoder. that is the easy part.
in a loop you read packets form one stream. so you need
while(av_read_frame(sound, &avpkt))
in this loop you want to decode the data from the packet. but care, you need to check from which stream the data in the packet is. so its always better to check if the packet contains data from the audiostream
if (avpkt.stream_index == aud_stream_idx)
now you can decode and process the audio.
exmaple:
AVFrame * decoded_frame = av_frame_alloc();
AVPacket avpkt;
av_init_packet(&avpkt);
avpkt.data = NULL;
avpkt.size = 0;
while(av_read_frame(sound, &avpkt))
{
if (avpkt.stream_index == aud_stream_idx)
{
int got_frame;
int len = avcodec_decode_audio4(audioCC, decoded_frame, &got_frame, &avpkt);
}
}
Thats all the the magic :)
PS: to find a stream just call
av_find_best_stream(sound, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0)
PPS: did not tested code. just codec here in window :D
PPPS: read the examples. this helped me a lot :)
sniffex.c is a program that is based on libpcap , to sniff and display some packet information. How do i modify it so as to print the values of TCP flags - urg , ack , psh , rst , syn and fin ? please help..
If you check this code where sniff_tcp is used, make sure to print out
th_flags member of this structure which contians flags you need.
/* TCP header */
struct sniff_tcp {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
u_char th_offx2; /* data offset, rsvd */
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
};
Generally you will have something like this (a bit ugly, you can do it better):
//this is already there in the code:
printf(" Src port: %d\n", ntohs(tcp->th_sport));
printf(" Dst port: %d\n", ntohs(tcp->th_dport))
//you add:
if (tcp->th_flags & TH_ECE){
printf(" Flag: TH_ECE");
}
if (tcp->th_flags & TH_RST){
printf(" Flag: TH_RST");
}