I am working on MSP430 and processing internal flash.
I have a doubt with MSP430 flash write lib.
In my opinion, with this implementation, the last byte might not be written in some cases.
This is function implementation.
void FlashCtl_write8(uint8_t *data_ptr,uint8_t *flash_ptr,uint16_t count){
//Clear Lock bit
HWREG16(FLASH_BASE + OFS_FCTL3) = FWKEY;
//Enable byte/word write mode
HWREG16(FLASH_BASE + OFS_FCTL1) = FWKEY + WRT;
while(count > 0)
{
//test busy
while(HWREG8(FLASH_BASE + OFS_FCTL3) & BUSY)
{
;
}
//Write to Flash
*flash_ptr++ = *data_ptr++;
count--;
}
//Clear WRT bit
HWREG16(FLASH_BASE + OFS_FCTL1) = FWKEY;
//Set LOCK bit
HWREG16(FLASH_BASE + OFS_FCTL3) = FWKEY + LOCK;
}
Is it a better solution if the function is implemented as below :
void FlashCtl_write8(uint8_t *data_ptr,uint8_t *flash_ptr,uint16_t count){
//Clear Lock bit
HWREG16(FLASH_BASE + OFS_FCTL3) = FWKEY;
//Enable byte/word write mode
HWREG16(FLASH_BASE + OFS_FCTL1) = FWKEY + WRT;
//test busy
while(HWREG8(FLASH_BASE + OFS_FCTL3) & BUSY)
{
;
}
while(count > 0)
{
//Write to Flash
*flash_ptr++ = *data_ptr++;
while(HWREG8(FLASH_BASE + OFS_FCTL3) & BUSY)
{
;
}
count--;
}
//Clear WRT bit
HWREG16(FLASH_BASE + OFS_FCTL1) = FWKEY;
//Set LOCK bit
HWREG16(FLASH_BASE + OFS_FCTL3) = FWKEY + LOCK;
}
Section 7.3.3.1 of the User's Guide says:
A byte or word write operation can be initiated from within flash memory or from RAM. When initiating from within flash memory, all timing is controlled by the flash controller, and the CPU is held while the write completes. After the write completes, the CPU resumes code execution with the instruction following
the write.
That code works because it is not actually necessary to check the BUSY bit.
As CL mentioned, as long as you run the code from flash, busywaiting is not necessary.
If, on the other hand, you would execute that code from RAM - for example, to dynamically rewrite the binary program code itself - you would need full locking.
The code below will do the same job. It is also slightly optimized for speed - no need to decrement another variable in the body of the loop.
void FlashCtl_write8(uint8_t *data_ptr, uint8_t *flash_ptr, uint16_t count)
{
const uint8_t *end = data_ptr + count;
// Clear Lock bit
HWREG16(FLASH_BASE + OFS_FCTL3) = FWKEY;
// Enable byte/word write mode
HWREG16(FLASH_BASE + OFS_FCTL1) = FWKEY + WRT;
while(data_ptr < end)
{
// Write to flash
*flash_ptr++ = *data_ptr++;
}
// Clear WRT bit
HWREG16(FLASH_BASE + OFS_FCTL1) = FWKEY;
// Set LOCK bit
HWREG16(FLASH_BASE + OFS_FCTL3) = FWKEY + LOCK;
}
Related
I work with usb device and use async functions of usbdk driver for I/O operations. I have a problem with canceling of operations on some win platforms. Im using function CancelIoEx for that and it works fine for some part of users but for some it doesn't work. The data is either transmitted completely or not transmitted at all. No intermediate values. CancelIoEx returns 1 in both cases. AbortPipe by usbdk lib doesn't work at all.
HANDLE redirectHandle = usbdk_helper.StartRedirect(&devID);
HANDLE systemHandle = usbdk_helper.GetRedirectorSystemHandle(redirectHandle);
unsigned char* buffer = static_cast<unsigned char*>(std::malloc(0x08 + length));
OVERLAPPED overlapped;
USB_DK_TRANSFER_REQUEST request { 0 };
DWORD overlappedTransfered = 0;
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, L"USBEVENT");
...
...
...
request.Buffer = buffer;
request.BufferLength = 0x08 + length;
request.TransferType = ControlTransferType;
auto res = usbdk_helper.WritePipe(redirectHandle, &request, &overlapped); //return TransferSuccessAsync
auto abort_res = CancelIoEx(systemHandle, &overlapped); //Return TRUE
auto event_res = WaitForSingleObject(overlapped.hEvent, INFINITE); //return WAIT_OBJECT_0
std::cout << "count transfered bytes: " << std::dec << request.Result.GenResult.BytesTransferred << std::endl; //0 or full for "bad", or 0 or intermediate for "correct"
I'm struggling with an issue where an ESP32 is running as a AP with AsyncTCP connecting multiple ESP32 clients. The AP receives some JSON data and replies with some JSON data. Without the handleData() function, the code runs 100% fine with no issues. Heap is static when no clients connect and issues only occur when clients start connecting.
Can anyone see anything with my code that could be causing heap corruption or other memory weirdness?
static void handleData(void* arg, AsyncClient* client, void *data, size_t len) {
int i = 0, j = 0;
char clientData[CLIENT_DATA_MAX];
char packetData[len];
char *packetBuf;
packetBuf = (char *)data;
clientData[0] = '\0';
for (i=0;i <= len;i++) {
packetData[j] = packetBuf[i]; //packetBuf[i];
if ((packetData[j] == '\n') || (i == len)) {
packetData[j] = '\0';
if ((j > 0) && (packetData[0] != '\n') && (packetData[0] != '\r')) {
// See sensorData() below...
parseData.function(packetData, clientData);
if (clientData != NULL) {
// TCP reply to client
if (client->space() > 32 && client->canSend()) {
client->write(clientData);
}
}
}
j = 0;
} else
j++;
}
}
void sensorData(void *data, void *retData) {
StaticJsonDocument<CLIENT_DATA_MAX> fields;
StaticJsonDocument<CLIENT_DATA_MAX> output;
char sensor[15] = "\0";
char MAC[18] = "\0";
char value[20] = "\0";
bool sendOK = false;
memcpy((char *)retData, "\0", 1);
DeserializationError error = deserializeJson(fields, (char *)data, CLIENT_DATA_MAX);
if (error) {
DEBUG_PRINTLN(F("deserializeJson() failed"));
return;
}
if (fields["type"])
strcpy(sensor, fields["type"]);
switch (sensor[0]) {
case 'C':
if (fields["value"])
strcpy(value, fields["value"]);
sendOK = true;
break;
case 'T': //DEBUG_PRINT(F("Temp "));
setExtTempSensor(fields["value"]);
sendOK = true;
break;
case 'N':
output["IT"] = intTempC; //Internal temp
output["B1"] = battLevels[0];
serializeJson(output, (char *)retData, CLIENT_DATA_MAX-1);
break;
}
if (sendOK) {
output["Resp"] = "Ok";
serializeJson(output, (char *)retData, CLIENT_DATA_MAX-1);
}
strcat((char *)retData, "\n");
}
static void handleNewClient(void* arg, AsyncClient* client) {
client->setRxTimeout(1000);
client->setAckTimeout(500);
client->onData(&handleData, NULL);
client->onError(&handleError, NULL);
client->onDisconnect(&handleDisconnect, NULL);
client->onTimeout(&handleTimeOut, NULL);
}
void startServer() {
server = new AsyncServer(WIFI_SERVER_PORT);
server->onClient(&handleNewClient, &server)
}
Using AsyncTCP on the ESP32 was having multiple issues. Heap issues, socket issues, assert issues, ACK timeouts, connection timeouts, etc. Swapping to AsyncUDP using the exact same code as shown above with romkey's changes, resolved all of my issues. (Just using romkey's fixes did not fix the errors I was having with AsyncTCP.) I don't believe the issue is with AsyncTCP but with ESP32 libraries.
Either you should declare packetData to be of length len + 1 or your for loop should iterate until i < len. Because the index starts at 0, packetData[len] is actually byte len + 1, so you'll overwrite something random when you store something in packetData[len] if the array is only len chars long.That something random may be the pointer stored in packetBuf, which could easily cause heap corruption.
You should always use strncpy() and never strcpy(). Likewise use strncat() rather than strcat(). Don't depend on having done the math correctly or on sizes not changing as your code evolves. strncpy() and strncat() will guard against overflows. You'll need to pass a length into sensorData() to do that, but sensorData() shouldn't be making assumptions about the available length of retData.
Your test
if (clientData != NULL) {
will never fail because clientData is the address of array and cannot change. I'm not sure what you're trying to test for here but this if will always succeed.
You can just write:
char sensor[15] = "";
you don't need to explicitly assign a string with a null byte in it.
And
memcpy((char *)retData, "\0", 1);
is equivalent to
((char *)retData)[0] = '\0';
What's the point of declaring retData to be void * in the arguments to sensorData()? Your code starts out with it being a char* before calling sensorData() and uses it as a char* inside sensorData(). void * is meant to be an escape hatch for passing around pointers without worrying about their type. You don't need that here and end up needing to extra casts back to char* because of it. Just declare the argument to be char* and don't worry about casting it again.
You didn't share the code that calls handleData() so there may well be issues outside of these functions.
Sometimes I am getting "underrun occured" from ALSA lib and that means the audioouput is not getting the values on time to play. Alsa then repeats the old buffer values on the speaker.
How can I avoid underruns on QAudioOuput?
I am using Qt5.9.1 and ARM Based CPU running on Debian 8.
I tried to change the buffersize:
audioOutput->setBufferSize(144000);
qDebug()<<"buffersize "<<audioOutput->bufferSize()<<" period size" .
<<audioOutput->periodSize();
I get: buffersize 144000 period size 0
and after audiOutput->start() I get: buffersize 19200 period size 3840
Here is what I am doing:
audioOutput->setBufferSize(144000);
qDebug()<<"buffersize "<<audioOutput->bufferSize()<<" period size" .
<<audioOutput->periodSize();
m_audioInput = audioInput->start();
m_audioOutput = audioOutput->start();
qDebug()<<"buffersize "<<audioOutput->bufferSize()<<" period size"<
<<audioOutput->periodSize();
connect(m_audioInput, SIGNAL(readyRead()), SLOT(readBufferSlot()));
Once audio data gets recorded I write to the QIODevice m_audioOutput the values from QIODevice m_audioInput.
So I think I have a timing issue sometimes and the audio interval for both is 1000ms before and after start().
Why cant I increase the buffer size? And how can I avoid underrun?
Based on my experience with QAudioOutput, it's buffer is intended just to keep real-time playing, you can't for example drop 1 minute of sound directly to the QIODevice expecting it gets buffered and played sequentially, but it do not means that you can't buffer sound, just means that you need to do it by yourself.
I made the following example in "C-Style" to make an all-in-one solution, it buffers 1000 milliseconds (1 second) of the input before play it.
The event loop needs to be available to process the Qt SIGNALs.
In my tests, 1 second buffering is fairly enough to avoid under runs.
#include <QtCore>
#include <QtMultimedia>
#define MAX_BUFFERED_TIME 1000
static inline int timeToSize(int ms, const QAudioFormat &format)
{
return ((format.channelCount() * (format.sampleSize() / 8) * format.sampleRate()) * ms / 1000);
}
struct AudioContext
{
QAudioInput *m_audio_input;
QIODevice *m_input_device;
QAudioOutput *m_audio_output;
QIODevice *m_output_device;
QByteArray m_buffer;
QAudioDeviceInfo m_input_device_info;
QAudioDeviceInfo m_output_device_info;
QAudioFormat m_format;
int m_time_to_buffer;
int m_max_size_to_buffer;
int m_size_to_buffer;
bool m_buffer_requested = true; //Needed
bool m_play_called = false;
};
void play(AudioContext *ctx)
{
//Set that last async call was triggered
ctx->m_play_called = false;
if (ctx->m_buffer.isEmpty())
{
//If data is empty set that nothing should be played
//until the buffer has at least the minimum buffered size already set
ctx->m_buffer_requested = true;
return;
}
else if (ctx->m_buffer.size() < ctx->m_size_to_buffer)
{
//If buffer doesn't contains enough data,
//check if exists a already flag telling that the buffer comes
//from a empty state and should not play anything until have the minimum data size
if (ctx->m_buffer_requested)
return;
}
else
{
//Buffer is ready and data can be played
ctx->m_buffer_requested = false;
}
int readlen = ctx->m_audio_output->periodSize();
int chunks = ctx->m_audio_output->bytesFree() / readlen;
//Play data while it's available in the output device
while (chunks)
{
//Get chunk from the buffer
QByteArray samples = ctx->m_buffer.mid(0, readlen);
int len = samples.size();
ctx->m_buffer.remove(0, len);
//Write data to the output device after the volume was applied
if (len)
{
ctx->m_output_device->write(samples);
}
//If chunk is smaller than the output chunk size, exit loop
if (len != readlen)
break;
//Decrease the available number of chunks
chunks--;
}
}
void preplay(AudioContext *ctx)
{
//Verify if exists a pending call to play function
//If not, call the play function async
if (!ctx->m_play_called)
{
ctx->m_play_called = true;
QTimer::singleShot(0, [=]{play(ctx);});
}
}
void init(AudioContext *ctx)
{
/***** INITIALIZE INPUT *****/
//Check if format is supported by the choosen input device
if (!ctx->m_input_device_info.isFormatSupported(ctx->m_format))
{
qDebug() << "Format not supported by the input device";
return;
}
//Initialize the audio input device
ctx->m_audio_input = new QAudioInput(ctx->m_input_device_info, ctx->m_format, qApp);
ctx->m_input_device = ctx->m_audio_input->start();
if (!ctx->m_input_device)
{
qDebug() << "Failed to open input audio device";
return;
}
//Call the readyReadPrivate function when data are available in the input device
QObject::connect(ctx->m_input_device, &QIODevice::readyRead, [=]{
//Read sound samples from input device to buffer
ctx->m_buffer.append(ctx->m_input_device->readAll());
preplay(ctx);
});
/***** INITIALIZE INPUT *****/
/***** INITIALIZE OUTPUT *****/
//Check if format is supported by the choosen output device
if (!ctx->m_output_device_info.isFormatSupported(ctx->m_format))
{
qDebug() << "Format not supported by the output device";
return;
}
int internal_buffer_size;
//Adjust internal buffer size
if (ctx->m_format.sampleRate() >= 44100)
internal_buffer_size = (1024 * 10) * ctx->m_format.channelCount();
else if (ctx->m_format.sampleRate() >= 24000)
internal_buffer_size = (1024 * 6) * ctx->m_format.channelCount();
else
internal_buffer_size = (1024 * 4) * ctx->m_format.channelCount();
//Initialize the audio output device
ctx->m_audio_output = new QAudioOutput(ctx->m_output_device_info, ctx->m_format, qApp);
//Increase the buffer size to enable higher sample rates
ctx->m_audio_output->setBufferSize(internal_buffer_size);
//Compute the size in bytes to be buffered based on the current format
ctx->m_size_to_buffer = int(timeToSize(ctx->m_time_to_buffer, ctx->m_format));
//Define a highest size that the buffer are allowed to have in the given time
//This value is used to discard too old buffered data
ctx->m_max_size_to_buffer = ctx->m_size_to_buffer + int(timeToSize(MAX_BUFFERED_TIME, ctx->m_format));
ctx->m_output_device = ctx->m_audio_output->start();
if (!ctx->m_output_device)
{
qDebug() << "Failed to open output audio device";
return;
}
//Timer that helps to keep playing data while it's available on the internal buffer
QTimer *timer_play = new QTimer(qApp);
timer_play->setTimerType(Qt::PreciseTimer);
QObject::connect(timer_play, &QTimer::timeout, [=]{
preplay(ctx);
});
timer_play->start(10);
//Timer that checks for too old data in the buffer
QTimer *timer_verifier = new QTimer(qApp);
QObject::connect(timer_verifier, &QTimer::timeout, [=]{
if (ctx->m_buffer.size() >= ctx->m_max_size_to_buffer)
ctx->m_buffer.clear();
});
timer_verifier->start(qMax(ctx->m_time_to_buffer, 10));
/***** INITIALIZE OUTPUT *****/
qDebug() << "Playing...";
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
AudioContext ctx;
QAudioFormat format;
format.setCodec("audio/pcm");
format.setSampleRate(44100);
format.setChannelCount(1);
format.setSampleSize(16);
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
ctx.m_format = format;
ctx.m_input_device_info = QAudioDeviceInfo::defaultInputDevice();
ctx.m_output_device_info = QAudioDeviceInfo::defaultOutputDevice();
ctx.m_time_to_buffer = 1000;
init(&ctx);
return a.exec();
}
I am working with an Arduino and Processing with the Arduino library.
I get the error "The function bitWrite(byte, int, int) does not exist.";
it seams that processing + Arduino bitWrite function are not working together.
its raised due to this line:
arduino.bitWrite(data,desiredPin,desiredState);
my goal in this project is modifying a music reactive sketch to work with shift registers.
Here is my full code:
Arduino_Shift_display
import ddf.minim.*;
import ddf.minim.analysis.*;
import processing.serial.*;
import cc.arduino.*;
int displayNum = 8;
Arduino arduino;
//Set these in the order of frequency - 0th pin is the lowest frequency,
//while the final pin is the highest frequency
int[] lastFired = new int[displayNum];
int datapin = 2;
int clockpin = 3;
int latchpin = 4;
int switchpin = 7;
byte data = 0;
//Change these to mess with the flashing rates
//Sensitivity is the shortest possible interval between beats
//minTimeOn is the minimum time an LED can be on
int sensitivity = 75;
int minTimeOn = 50;
String mode;
String source;
Minim minim;
AudioInput in;
AudioPlayer song;
BeatDetect beat;
//Used to stop flashing if the only signal on the line is random noise
boolean hasInput = false;
float tol = 0.005;
void setup(){
// shift register setup
arduino.pinMode(datapin, arduino.OUTPUT);
arduino.pinMode(clockpin, arduino.OUTPUT);
arduino.pinMode(latchpin, arduino.OUTPUT);
arduino.digitalWrite(switchpin, arduino.HIGH);
//Uncomment the mode/source pair for the desired input
//Shoutcast radio stream
//mode = "radio";
//source = "http://scfire-ntc-aa05.stream.aol.com:80/stream/1018";
//mode = "file";
//source = "/path/to/mp3";
mode = "mic";
source = "";
size(512, 200, P2D);
minim = new Minim(this);
arduino = new Arduino(this, Arduino.list()[1]);
minim = new Minim(this);
if (mode == "file" || mode == "radio"){
song = minim.loadFile(source, 2048);
song.play();
beat = new BeatDetect(song.bufferSize(), song.sampleRate());
beat.setSensitivity(sensitivity);
} else if (mode == "mic"){
in = minim.getLineIn(Minim.STEREO, 2048);
beat = new BeatDetect(in.bufferSize(), in.sampleRate());
beat.setSensitivity(sensitivity);
}
}
void shiftWrite(int desiredPin, int desiredState)
// This function lets you make the shift register outputs
// HIGH or LOW in exactly the same way that you use digitalWrite().
// Like digitalWrite(), this function takes two parameters:
// "desiredPin" is the shift register output pin
// you want to affect (0-7)
// "desiredState" is whether you want that output
// to be HIGH or LOW
// Inside the Arduino, numbers are stored as arrays of "bits",
// each of which is a single 1 or 0 value. Because a "byte" type
// is also eight bits, we'll use a byte (which we named "data"
// at the top of this sketch) to send data to the shift register.
// If a bit in the byte is "1", the output will be HIGH. If the bit
// is "0", the output will be LOW.
// To turn the individual bits in "data" on and off, we'll use
// a new Arduino commands called bitWrite(), which can make
// individual bits in a number 1 or 0.
{
// First we'll alter the global variable "data", changing the
// desired bit to 1 or 0:
arduino.bitWrite(data,desiredPin,desiredState);
// Now we'll actually send that data to the shift register.
// The shiftOut() function does all the hard work of
// manipulating the data and clock pins to move the data
// into the shift register:
arduino.shiftOut(datapin, clockpin, MSBFIRST, data);
// Once the data is in the shift register, we still need to
// make it appear at the outputs. We'll toggle the state of
// the latchPin, which will signal the shift register to "latch"
// the data to the outputs. (Latch activates on the high-to
// -low transition).
arduino.digitalWrite(latchpin, arduino.HIGH);
arduino.digitalWrite(latchpin, arduino.LOW);
}
void draw(){
if (mode == "file" || mode == "radio"){
beat.detect(song.mix);
drawWaveForm((AudioSource)song);
} else if (mode == "mic"){
beat.detect(in.mix);
drawWaveForm((AudioSource)in);
}
if (hasInput){ //hasInput is set within drawWaveForm
for (int i=0; i<displayNum-1; i++){
if ( beat.isRange( i+1, i+1, 1) ){
shiftWrite(i, 1);
lastFired[i] = millis();
} else {
if ((millis() - lastFired[i]) > minTimeOn){
shiftWrite(i, 0);
}
}
}
}
} //End draw method
//Display the input waveform
//This method sets 'hasInput' - if any sample in the signal has a value
//larger than 'tol,' there is a signal and the lights should flash.
//Otherwise, only noise is present and the lights should stay off.
void drawWaveForm(AudioSource src){
background(0);
stroke(255);
hasInput = false;
for(int i = 0; i < src.bufferSize() - 1; i++)
{
line(i, 50 + src.left.get(i)*50, i+1, 50 + src.left.get(i+1)*50);
line(i, 150 + src.right.get(i)*50, i+1, 150 + src.right.get(i+1)*50);
if (!hasInput && (abs(src.left.get(i)) > tol || abs(src.right.get(i)) > tol)){
hasInput = true;
}
}
}
void resetPins(){
for (int i=0; i<ledPins.length; i++){
arduino.digitalWrite(ledPins[i], Arduino.LOW);
}
}
void stop(){
resetPins();
if (mode == "mic"){
in.close();
}
minim.stop();
super.stop();
}
BeatListener
class BeatListener implements AudioListener
{
private BeatDetect beat;
private AudioPlayer source;
BeatListener(BeatDetect beat, AudioPlayer source)
{
this.source = source;
this.source.addListener(this);
this.beat = beat;
}
void samples(float[] samps)
{
beat.detect(source.mix);
}
void samples(float[] sampsL, float[] sampsR)
{
beat.detect(source.mix);
}
}
You can achieve the same thing using standard bitwise operators. To turn a bit on:
data |= 1 << bitNumber;
The right-hand side (1 << bitNumber) is a bit-shift operation to create a suitable bit-mask. It takes the single '1' bit and moves it left until it reaches the desired position. The bitwise-or assignment (|=) combines that new bit-mask with the existing bits in data. This turns the desired bit on, but leaves the rest untouched.
The code to turn a bit off is slightly different:
data &= ~(1 << bitNumber);
You can see the same bit-shift operation here. However, it's preceded by the unary negation operator (~). This swaps all the 1's for 0's, and all the 0's for 1's. The result is the exact opposite of the bit-mask we used before. You can't do a bitwise-or operation this time though, or else you'll turn all the other bits on. The bitwise-and assignment (&=) is used instead to combine this mask with the data variable. This ensures the desired bit is turned off, and the rest are untouched.
In your code, desiredPin is the equivalent of bitNumber.
A full explanation of how bitwise operations work can be quite lengthy. I'd recommend looking for a good tutorial online if you need more help with that.
There are also the bitSet and bitClear Arduino macros that make the code a little more readable than bit shifting and using AND and OR. The format is either bitSet(what_to_modify,bit_number) and bitClear(what_to_modify,bit_number). These translate into very efficient code and can be used to manipulate both, variables and hardware registers. So for example, if you wanted to turn on pin 13 on the Arduino UNO, you would first need to look up that Arduino pin 13 is actually pin 5 on PORTB of the Atmel atmega328 chip. So the command would be:
bitSet(PORTB,5);
I've wrote a program in C to connect the pc with a device by bluetooth. The program runs from terminal and the data received is shown in terminal as well. So far so good.
Now I've created a gui in qt, in which the main aim is to present the information which was before shown in terminal, now in qwtplots.
Well, I can so far connect the device with pc with the gui, but when I request the information form the device, it is shown in the terminal but the gui starts non responding.
here's the slot that requests the information from the device:
// Main Bluetooth
void gui::main_b()
{
// BLUETOOTH STUFF
int status, bytes_read;
int conta = 0;
FILE *data = NULL;
fd_set readmask;
struct timeval tv;
char buf[101];
int v, v1, v2;
tv.tv_sec = 0;
tv.tv_usec = 100000;
// Standard messages
char *startstr = "#START,0060,FF,12;";
write (sock, startstr, strlen (startstr));
data = fopen ("data.txt", "w");
while (conta < 100)
{
int i;
memset (buf, 0, 100);
FD_ZERO (&readmask);
FD_SET (sock, &readmask);
if (select (255, &readmask, NULL, NULL, &tv) > 0)
{
if (FD_ISSET (sock, &readmask))
{
int numb;
numb = read (sock, buf, 100);
// 12 bits
if (ui->comboBox->currentIndex() == 1)
{
if (numb == 14)
{
conta++;
//printf ("received %d bytes:\n", numb);
// print of counter
//printf ("%d,", buf[0]);
fprintf (data, "%d,", buf[0]);
for (i = 1; i < numb-1; i += 3)
{
v1 = buf[i] | ((buf[i + 1] & 0x0F) << 8);
v2 = buf[i + 2];
v2 = (v2 << 4) | ((buf[i + 1] & 0xf0) >> 4);
printf ("%d,%d,", v1, v2);
//fprintf (data, "%d,%d,", v1, v2);
}
printf ("\n");
//fprintf (data, "\n");
}
}
}
}
}
fclose (data);
}
so, when i click the button which calls this slot, it will never let me use the gui again.
This works in terminal.
thanks in advance.
Instead of your own select, you should use QSocketNotifier class and give your own file handles for Qt event loop.
You can also use this overload of QFile::open to turn your socket into a QIODevice instance.
Third choice is to put your own select loop into a different thread, so it does not block the Qt main event loop. But that is going to bring quite a lot of extra complexity, so I'd do that only as a last resort.
You are running the while loop in the same thread as the GUI so the event queue is blocked. You have two choices:
During the loop, call QCoreApplication::processEvents(). This forces the event queue to be processed.
Separate the while loop logic into it's own thread.
The first one is much simpler, but is generally considered inefficient, as just all about all computers have multiple cores.