schedule the starting time of events as accurately as possible - real-time

I would like to schedule a series of events such that to about the nearest 5ms, the starting time of event N is t0 + dt*N, where t0 is some arbitrary time after the process starts. If the events were output to a terminal, they would occur regularly without pauses or speedups. If they were noises, it would produce a regular rhythm. This is my first attempt.
#include <stdio.h>
#include <time.h>
#include <math.h>
void fsleep(double t)
{
time_t sec = floor(t);
long nsec = 1e9*(t - sec);
struct timespec s;
s.tv_sec = sec;
s.tv_nsec = nsec;
nanosleep(&s, NULL);
}
int main(int argc, const char **argv)
{
for (unsigned i = 0;; i++) {
printf("%d\n", i);
fflush(stdout);
fsleep(0.334);
}
}
It is total garbage, even at realtime priority (nice -n -20). There are noticeable jitters the entire time, with pauses of up to 1 second, after which a whole bunch of numbers are printed in a row. To test whether it was my terminal, I made the following script:
from time import sleep
from sys import stdin
def raw_stdin():
"""Switches stdin to a non-buffering, non-echoing mode,
handing keystrokes directly to the program as soon as they're
received and printing nothing to the terminal."""
import termios as t
f = t.tcgetattr(stdin)
f[3] &= ~(t.ICANON|t.ECHO)
t.tcsetattr(stdin, t.TCSANOW, f)
raw_stdin()
for i in range(10000000):
#sleep(.334)
stdin.read(1)
print(i)
If I hit any key regularly, i.e. with the same time intervals between strokes down to the nearest 10ms or so, I get regular outputs, with zero hesitations. This proves the terminal is more than responsive enough, and that what I'm trying to do is possible. I have a hard time imagining the computer can't do something I can do with my left index finger.
I think it might have something to do with my linux kernel. I'd be interested to know what happens if this is run in windows, or on other linux kernels.

I figured it out. It was my terminal all along (xfce4-terminal). There's a bug in it that messes up realtime output. See https://stackoverflow.com/a/47744798/1840698 for more.

Related

What happens if i set 'raspicam_node/image' queue size to 1?

I can't get real-time image from raspberry pi cam.
So I adjusted the Queue Size from 100 to 1.
Then there was an improvement in performance.
I wonder why there was a performance improvement.
int main(int argc, char** argv)
{
ros::init(argc, argv, "lane_driving");
ros::NodeHandle nh, nhp;
image_transport::ImageTransport it(nh);
pub = nhp.advertise<geometry_msgs::Twist>("/cmd_vel", 100);
subAD = nh.subscribe("arrowDetecter", 1,&arrowMessage);
subScan = nh.subscribe("/scan",1,&scanMsgCallback);
subOdom = nh.subscribe("/odom", 1,&odomMsgCallback);
image_transport::Subscriber sub = it.subscribe("/raspicam_node/image", 1, &poseMessageReceived, ros::VoidPtr(), image_transport::TransportHints("compressed"));
while(ros::ok()){
baseCmd.linear.x = 0.01;
pub.publish(baseCmd);
ros::spin();
}
If the number of messages that arrive on the /raspicam_node/image topics in a single ros::spin() is greater than the queue_size, the extra messages will be discarded. What this means is that your callback is probably not running for every image that comes from your camera. So you are probably "dropping" (not analyzing) some of the camera frames. This would give the performance improvement you observed.
Whether or not this is what you want depends on your application.

What initialises the contents of the STM32's USB BTABLE when the __HAL_RCC_USB_CLK_ENABLE() macro is executed in HAL_PCD_MspInit()?

I have used STM32CubeMX/IDE to generate a USB HID project for the STM32F3DISCOVERY board.
The USB BTABLE register is zero, indicating that the BTABLE is at the start of the Packet Memory Area.
(I zero the whole PMA at program start, to avoid stale values.)
Just before the execution of the __HAL_RCC_USB_CLK_ENABLE macro (in HAL_PCD_MspInit() in usbd_conf.c) the values of the BTABLE (at index zero onwards, in the PMA are:
After that macro is executed, the values are:
The macro expands to:
do { \
volatile uint32_t tmpreg; \
((((RCC_TypeDef *) ((0x40000000UL + 0x00020000UL) + 0x00001000UL))->APB1ENR) |= ((0x1UL << (23U))));\
/* Delay after an RCC peripheral clock enabling */ \
tmpreg = ((((RCC_TypeDef *) ((0x40000000UL + 0x00020000UL) + 0x00001000UL))->APB1ENR) & ((0x1UL << (23U))));\
(void)tmpreg; \
} while(0U)
How does this macro cause the BTABLE to be initialised?
(I need pma[12] to be 0x100 instead of 0x0 as I want to use endpoint 3 for the HID interface in a composite device. I am using this simple HID device to test the use of a different endpoint. Changing 0x81 to 0x83 in USBD_LL_Init() and #define HID_EPIN_ADDR are not sufficient to change the value of pma[12]. The incorrect TX pointer at pma[12] is used and corrupt data is observed in wireshark.)
Update:
If I add code to manually set pma[12] to 0x100:
HAL_StatusTypeDef HAL_PCDEx_PMAConfig(PCD_HandleTypeDef *hpcd,
uint16_t ep_addr,
uint16_t ep_kind,
uint32_t pmaadress)
...
/* Here we check if the endpoint is single or double Buffer*/
if (ep_kind == PCD_SNG_BUF)
{
/* Single Buffer */
ep->doublebuffer = 0U;
/* Configure the PMA */
ep->pmaadress = (uint16_t)pmaadress;
// correct PMA BTABLE
uint32_t *btable = (uint32_t *) USB_PMAADDR; // Test this.
if (ep->is_in) {
btable[ep->num * 4] = pmaadress;
}
}
The value at pam[12] does get set, but it later gets overwritten:
__HAL_RCC_USB_CLK_ENABLE() enables clocks for the USB block. Before it is enabled, all peripheral locations are read as zeroes. After clock is enabled, the actual PMA content becomes visible, whatever was written there before reset or random garbage left after the power up. So executing __HAL_RCC_USB_CLK_ENABLE() has nothing to do with your problem.
I don't know where the TX buffer address for endpoint 3 gets overwritten, but I guess it is the Cube sets it when it decides to send data on the endpoint. I am not familiar with the Cube, does it have an API to send a USB packet?
Also, double-check that your pma array has the right definition. On F1 and I likely F3, there is a 2-byte value at each of the 32-bit location.
UPD: Sorry, I saw this question first, but your real problem is why TX addr gets overwritten or not set up correctly.

select but without wait (POSIX)

I have the typical setup for file io which works well with select like:
int retval = select(maxfd +1 , &read_set, &write_set, &error_set, 0); // timeout==0 -> endless
But now I have a situation where I want to loop and check on every cycle if one of the file selectors become ready. I do not want to start a separate thread for that! Is there something in posix/linux which can be used, hopefully with the same FD_SET like data structures which checks for file state without waiting for them?
Yes, I can set timeout for select to a minimal value, but I hope it can be done without that.
POSIX says:
To effect a poll, the timeout parameter should not be a null pointer, and should point to a zero-valued timespec structure.
So for your application, it should be sufficient to call select like this:
struct timeval zero = { 0, 0 };
int retval = select(maxfd +1 , &read_set, &write_set, &error_set, &zero);

MSP430 Music Player Can't Produce Note Higher than Certain Frequency

I'm trying to complete an assignment that requires me to make a music player using the MSP430 microprocessor and Launchpad kit. I have the player completely working, but for some reason when I try to play above a certain note, it outputs rapid clicking instead of the tone.
I know the speaker can produce a higher tone, so I am fairly certain it's an issue with my software, probably creating some sort of math error. Here is my code (at least the part that handles the notes):
asm(" .length 10000");
asm(" .width 132");
#include "msp430g2553.h"
//-----------------------
// define the bit mask (within P1) corresponding to output TA0
#define TA0_BIT 0x02
// define the port and location for the button (this is the built in button)
// specific bit for the button
#define BUTTON_BIT 0x04
#define PLUS_BUTTON 0x08 //Defines the "GO FASTER" button to P1.3
#define MINUS_BUTTON 0x10 //Defines the "SLOW DOWN" button to P1.4
#define SHIFT 0x20
//----------------------------------
// Some global variables (mainly to look at in the debugger)
volatile unsigned halfPeriod; // half period count for the timer
volatile unsigned long intcount=0; // number of times the interrupt has occurred
volatile unsigned soundOn=0; // state of sound: 0 or OUTMOD_4 (0x0080)
volatile int noteCount = 0;
volatile int noteLength = 0;
volatile int deltaHP=1; // step in half period per half period
volatile unsigned int plus_on;
volatile unsigned int minus_on;
volatile double speed = 1;
volatile int shiftkey = 0;
static const int noteArray[] = {800, 1000, 900, 800}; //THESE ARE THE NOTES
static const int noteLengths[] = {200, 500, 500, 500};
void init_timer(void); // routine to setup the timer
void init_button(void); // routine to setup the button
// ++++++++++++++++++++++++++
void main(){
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
BCSCTL1 = CALBC1_1MHZ; // 1Mhz calibration for clock
DCOCTL = CALDCO_1MHZ;
//halfPeriod=noteArray[0]; // initial half-period at lowest frequency
init_timer(); // initialize timer
init_button(); // initialize the button
_bis_SR_register(GIE+LPM0_bits);// enable general interrupts and power down CPU
}
// +++++++++++++++++++++++++++
// Sound Production System
void init_timer(){ // initialization and start of timer
TA0CTL |=TACLR; // reset clock
TA0CTL =TASSEL1+ID_0+MC_2; // clock source = SMCLK, clock divider=1, continuous mode,
TA0CCTL0=soundOn+CCIE; // compare mode, outmod=sound, interrupt CCR1 on
TA0CCR0 = TAR+noteArray[0]; // time for first alarm
P1SEL|=TA0_BIT; // connect timer output to pin
P1DIR|=TA0_BIT;
}
// +++++++++++++++++++++++++++
void interrupt sound_handler(){
TACCR0 += (noteArray[noteCount]); // advance 'alarm' time
if (soundOn){ // change half period if the sound is playing
noteLength++;
if (noteLength >= (speed* noteLengths[noteCount])) {
noteLength=0;
noteCount++;
if (noteCount == sizeof(noteArray)/sizeof(int)) {
//halfPeriod += deltaHP;
noteCount = 0;
//deltaHP=-deltaHP;
}
}
}
TA0CCTL0 = CCIE + soundOn; // update control register with current soundOn
++intcount; // advance debug counter
}
ISR_VECTOR(sound_handler,".int09") // declare interrupt vector
Currently I have just 4 random notes in there with 4 random lengths to demonstrate the error. The strange clicking noise happens somewhere between a note value of 800 and 900. Am I just missing something in my code that would produce an error for a number smaller than 8xx? I don't see any spots for division errors or the like but I could be wrong.
Thank you.
ALSO: I should note that when the error occurs, the clicking lasts a very long time, much longer than the corresponding length for that note, but it isn't permanent. Eventually the player moves on to the next note and plays it normally as long as it's larger than 900 or so.
If the interrupt handler does not execute fast enough, the setting of the next event (TACCR0 += noteArray[...]) will come too late, i.e., after that timer value has already been reached. So the next timer interrupt will fire not after 800 ticks but after 216+800 ticks.
You might try to optimize the interrup handler function.
In particular, floating-point emulation can take hundreds of cycles; remove speed.
However, instead of toggling the output in software, you should take advantage of the hardware capabilites, and generate the waveform with the PWM function: run the timer in Up mode, and use set/reset output mode for the second CCR (see section 12.2.5.2 of the User's Guide).
(This implies that you need timer interrupts only to start/stop notes, so to fit into the 216 limit, you probably want to use a second timer based on a much slower clock.)

Help with live-updating sound on the iPhone

My question is a little tricky, and I'm not exactly experienced (I might get some terms wrong), so here goes.
I'm declaring an instance of an object called "Singer". The instance is called "singer1". "singer1" produces an audio signal. Now, the following is the code where the specifics of the audio signal are determined:
OSStatus playbackCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
//Singer *me = (Singer *)inRefCon;
static int phase = 0;
for(UInt32 i = 0; i < ioData->mNumberBuffers; i++) {
int samples = ioData->mBuffers[i].mDataByteSize / sizeof(SInt16);
SInt16 values[samples];
float waves;
float volume=.5;
for(int j = 0; j < samples; j++) {
waves = 0;
waves += sin(kWaveform * 600 * phase)*volume;
waves += sin(kWaveform * 400 * phase)*volume;
waves += sin(kWaveform * 200 * phase)*volume;
waves += sin(kWaveform * 100 * phase)*volume;
waves *= 32500 / 4; // <--------- make sure to divide by how many waves you're stacking
values[j] = (SInt16)waves;
values[j] += values[j]<<16;
phase++;
}
memcpy(ioData->mBuffers[i].mData, values, samples * sizeof(SInt16));
}
return noErr;
}
99% of this is borrowed code, so I only have a basic understanding of how it works (I don't know about the OSStatus class or method or whatever this is. However, you see those 4 lines with 600, 400, 200 and 100 in them? Those determine the frequency. Now, what I want to do (for now) is insert my own variable in there in place of a constant, which I can change on a whim. This variable is called "fr1". "fr1" is declared in the header file, but if I try to compile I get an error about "fr1" being undeclared. Currently, my technique to fix this is the following: right beneath where I #import stuff, I add the line
fr1=0.0;//any number will work properly
This sort of works, as the code will compile and singer1.fr1 will actually change values if I tell it to. The problems are now this:A)even though this compiles and the tone specified will play (0.0 is no tone), I get the warnings "Data definition has no type or storage class" and "Type defaults to 'int' in declaration of 'fr1'". I bet this is because for some reason it's not seeing my previous declaration in the header file (as a float). However, again, if I leave this line out the code won't compile because "fr1 is undeclared". B)Just because I change the value of fr1 doesn't mean that singer1 will update the value stored inside the "playbackcallback" variable or whatever is in charge of updating the output buffers. Perhaps this can be fixed by coding differently? C)even if this did work, there is still a noticeable "gap" when pausing/playing the audio, which I need to eliminate. This might mean a complete overhaul of the code so that I can "dynamically" insert new values without disrupting anything. However, the reason I'm going through all this effort to post is because this method does exactly what I want (I can compute a value mathematically and it goes straight to the DAC, which means I can use it in the future to make triangle, square, etc waves easily). I have uploaded Singer.h and .m to pastebin for your veiwing pleasure, perhaps they will help. Sorry, I can't post 2 HTML tags so here are the full links.
(http://pastebin.com/ewhKW2Tk)
(http://pastebin.com/CNAT4gFv)
So, TL;DR, all I really want to do is be able to define the current equation/value of the 4 waves and re-define them very often without a gap in the sound.
Thanks. (And sorry if the post was confusing or got off track, which I'm pretty sure it did.)
My understanding is that your callback function is called every time the buffer needs to be re-filled. So changing fr1..fr4 will alter the waveform, but only when the buffer updates. You shouldn't need to stop and re-start the sound to get a change, but you will notice an abrupt shift in the timbre if you change your fr values. In order to get a smooth transition in timbre, you'd have to implement something that smoothly changes the fr values over time. Tweaking the buffer size will give you some control over how responsive the sound is to your changing fr values.
Your issue with fr being undefined is due to your callback being a straight c function. Your fr variables are declared as objective-c instance variables as part of your Singer object. They are not accessible by default.
take a look at this project, and see how he implements access to his instance variables from within his callback. Basically he passes a reference to his instance to the callback function, and then accesses instance variables through that.
https://github.com/youpy/dowoscillator
notice:
Sinewave *sineObject = inRefCon;
float freq = sineObject.frequency * 2 * M_PI / samplingRate;
and:
AURenderCallbackStruct input;
input.inputProc = RenderCallback;
input.inputProcRefCon = self;
Also, you'll want to move your callback function outside of your #implementation block, because it's not actually part of your Singer object.
You can see this all in action here: https://github.com/coryalder/SineWaver