wxWidgets with MVC Error code SIGSEGV when calling controller function - c++

I use wxWidgets with MVC pattern and im having trouble when i call the controller functions in the View
compareRGB(...),compareALPHA(...) and compareHSV(...)
for compare two images with a tolerance.Basically when the functions are called the program crash with code error
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
I've tried every solution but the error is still here.
In this moment the function only print a word on terminal.
This is the code that cause error(the other functions work perfectly):
void View::compareImages(wxCommandEvent &event){
int imagesActive = imagesActivatedCount();
wxString mode = getMode();
double tolerance = colorToleranceSlider->GetValue();
if(imagesActive < 2){
wxMessageBox(_("SELEZIONARE DUE IMMAGINI DA COMPARARE"),_("ERRORE"),wxOK | wxICON_EXCLAMATION);
}
else if(mode.IsSameAs(_("RGB"))){
wxString pathImage1 = *activeImages;
wxString pathImage2 = *(activeImages + 1);
controller.compareRGB(pathImage1,pathImage2,tolerance);
}
else if(mode.IsSameAs(_("HSV"))){
wxString pathImage1 = *activeImages;
wxString pathImage2 = *(activeImages + 1);
controller.compareHSV(pathImage1,pathImage2,tolerance);
}
else if(mode.IsSameAs(_("ALPHA"))){
wxString pathImage1 = *activeImages;
wxString pathImage2 = *(activeImages + 1);
controller.compareAlpha(pathImage1,pathImage2,tolerance);
}
else{
wxMessageBox(_("SCEGLIERE METODO DI COMPARAZIONE"),_("ERRORE"),wxOK | wxICON_EXCLAMATION);
}
}
The complete source:
#include "View.h"
enum{
PANEL_ID,
BUTTON_ADD,
BUTTON_REMOVE,
BUTTON_ACTIVATE,
BUTTON_COMPARE,
SLIDER_COLOR,
MODE_SELECTOR,
LIST_ID,
ABOUT,
STATIC_ID,
VALUE_SLIDER
};
/*Event table of the view*/
wxBEGIN_EVENT_TABLE(View,wxFrame)
EVT_BUTTON(BUTTON_ADD,View::loadImages)
EVT_BUTTON(BUTTON_REMOVE,View::removeImages)
EVT_BUTTON(BUTTON_ACTIVATE,View::activateSelectedImages)
EVT_BUTTON(BUTTON_COMPARE,View::compareImages)
EVT_BUTTON(BUTTON_ACTIVATE,View::activateSelectedImages)
EVT_MENU(ABOUT,View::onAbout)
EVT_MENU(wxID_EXIT,View::onExit)
EVT_SLIDER(SLIDER_COLOR,View::onSliderUpdate)
wxEND_EVENT_TABLE()
View::View(const std::string title, const wxPoint &pos, const wxSize &size, AbstractModel& model, AbstractController& c):model(model),controller(c) ,wxFrame(NULL,wxID_ANY,title,pos,size) {
model.registerObserver(this); //registration view for successive notification
//View implementation
}
void View::update(int eventCode) {
}
/*Delete the selected images
* the while cicle it afflict only the image selected*/
void View::removeImages(wxCommandEvent& event){
long item;
while((item = list->GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED)) != -1){
list->DeleteItem(item);
}
}
/*load images on storage
* It load the paths in the list view but in the model there is a map that associate
* the wxImage object with his relative path*/
void View::loadImages(wxCommandEvent& event){
wxFileDialog* fileDialog=new wxFileDialog(this, _("Scegli una o più foto"),wxEmptyString,wxEmptyString,wxFileSelectorDefaultWildcardStr,wxFD_MULTIPLE);
if(fileDialog->ShowModal() == wxID_CANCEL){
return;
}
wxArrayString paths;
fileDialog->GetPaths(paths);
try {
for (auto iterator = paths.begin(); iterator < paths.end(); ++iterator) {
list->InsertItem(0,*iterator);
}
}
catch (std::exception& error) {
std::cout << "Caught exception: " << error.what() << std::endl;
}
}
int View::imagesActivatedCount() {
int count = 0;
long item = -1;
while((item = list->GetNextItem(item,wxLIST_NEXT_ALL,wxLIST_STATE_DONTCARE)) != -1){
if (list->GetItemText(item,1).IsSameAs(_("*")))
{
count++;
}
}
return count;
}
/*Deselect the activated images
* this function is called on activatedSelectImages function for deselect before activate the new images
* For practical reasons the function scan every row in the list and if in the column next to him is present the "*"
* symbol it deselect him and clear the activated images array
*/
void View::deselectImages() {
long item = -1;
while((item = list->GetNextItem(item,wxLIST_NEXT_ALL,wxLIST_STATE_DONTCARE)) != -1){
if(list->GetItemText(item,1).IsSameAs(_("*"))){
list->SetItem(item,1,_(""));
}
}
}
void View::activateSelectedImages(wxCommandEvent& event) {
int imageActive = imagesActivatedCount();
int itemCount=0;
long item = -1;
wxString arr[2];
if(imageActive >= 2 || list->GetSelectedItemCount() >= 2)
{
deselectImages();
imageActive = 0;
}
while((item = list->GetNextItem(item,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED)) != -1){
if(itemCount < 2){
list->SetItem(item,1,_("*"));
itemCount++;
imageActive++;
}
}
if (imageActive == 2)
{
itemCount = 0;
item = -1;
wxString text;
while((item = list->GetNextItem(item,wxLIST_NEXT_ALL,wxLIST_STATE_DONTCARE)) != -1){
text = list->GetItemText(item,1);
if (text.IsSameAs(_("*"))){
arr[itemCount]=list->GetItemText(item);
itemCount++;
}
}
activeImages = arr;
std::cout<< *activeImages << std::endl;
std::cout << *(activeImages + 1) << std::endl;
}
}
void View::compareImages(wxCommandEvent &event){
int imagesActive = imagesActivatedCount();
wxString mode = getMode();
double tolerance = colorToleranceSlider->GetValue();
if(imagesActive < 2){
wxMessageBox(_("SELEZIONARE DUE IMMAGINI DA COMPARARE"),_("ERRORE"),wxOK | wxICON_EXCLAMATION);
}
else if(mode.IsSameAs(_("RGB"))){
wxString pathImage1 = *activeImages;
wxString pathImage2 = *(activeImages + 1);
controller.compareRGB(pathImage1,pathImage2,tolerance);
}
else if(mode.IsSameAs(_("HSV"))){
wxString pathImage1 = *activeImages;
wxString pathImage2 = *(activeImages + 1);
controller.compareHSV(pathImage1,pathImage2,tolerance);
}
else if(mode.IsSameAs(_("ALPHA"))){
wxString pathImage1 = *activeImages;
wxString pathImage2 = *(activeImages + 1);
controller.compareAlpha(pathImage1,pathImage2,tolerance);
}
else{
wxMessageBox(_("SCEGLIERE METODO DI COMPARAZIONE"),_("ERRORE"),wxOK | wxICON_EXCLAMATION);
}
}
}
The controller source:
#include "Controller.h"
Controller::Controller(AbstractModel& model) : model(model){}
void Controller::removeImages(wxArrayString paths) {
for(int it = 0; it < paths.size();it++){
model.removeImage(paths[it]);
}
}
void Controller::loadImages(wxArrayString paths) {
for(int it = 0; it < paths.size(); it++){
model.loadImage(paths[it]);
}
}
void Controller::compareRGB(wxString path1, wxString path2, double tolerance) {
std::cout<<"A"<<std::endl;
}
void Controller::compareAlpha(wxString path1, wxString path2, double tolerance) {
std::cout<<"B"<<std::endl;
}
void Controller::compareHSV(wxString path1, wxString path2, double tolerance) {
std::cout<<"C"<<std::endl;
}

As you mention in the comment,
activeImages is a wxString*
So there you have it: activeImages = arr. The latter is a local variable which will be freed at the end of activateSelectedImages(). When using activeImages later in compareImages(), you are getting undefined behavior.

Related

In Visual Studio, After passing parameters by pointer or reference of visual studio function, the access parameter value in the function is null

This is the main code where error happened:
void VRInputRemapping::DigitalInputConfig() {
bool orginput = this->curVRConfig->GetorgDigitalInput();
uint32_t deviceId = this->curVRConfig->GetcurDeviceId();
uint32_t buttonId = this->curVRConfig->GetcurButtonId();
printf("Digital orginput: %d device:%d butonid:%d\n", orginput, deviceId, buttonId);
vrinputemulator::DigitalInputRemapping* m_currentRemapping =new vrinputemulator::DigitalInputRemapping(true);
vrinputemulator::DigitalBinding* m_currentBinding = new vrinputemulator::DigitalBinding;
if (orginput == false) {
m_currentBinding->type = vrinputemulator::DigitalBindingType::Disabled;
memset(&m_currentBinding->data, 0, sizeof(m_currentBinding->data));
m_currentBinding->data.openvr.buttonId = buttonId;
m_currentBinding->toggleEnabled = false;
m_currentBinding->toggleDelay = 0;
m_currentBinding->autoTriggerEnabled = false;
m_currentBinding->autoTriggerFrequency = 1;
m_currentRemapping->binding = *m_currentBinding;
}
else if (orginput == true) {
m_currentBinding->type = vrinputemulator::DigitalBindingType::NoRemapping;
memset(&m_currentBinding->data, 0, sizeof(m_currentBinding->data));
m_currentBinding->data.openvr.buttonId = buttonId;
m_currentBinding->toggleEnabled = false;
m_currentBinding->toggleDelay = 0;
m_currentBinding->autoTriggerEnabled = false;
m_currentBinding->autoTriggerFrequency = 1;
m_currentRemapping->binding = *m_currentBinding;
}
printf(" void VRInputRemapping::DigitalInputConfig() m_currentRemapping->binding.type:%d device:%d buttonId:%d remapping.data.openvr.buttonId%d\n", m_currentRemapping->binding.type, deviceId, buttonId, m_currentRemapping->binding.data.openvr.buttonId);
//<--------------------Here is the function call-------------------------------------->
this->inputEmulator->setDigitalInputRemapping(deviceId, buttonId, m_currentRemapping);
//<--------------------Here is the function call-------------------------------------->
printf(" void VRInputRemapping::DigitalInputConfig() m_currentRemapping->binding.type:%d device:%d buttonId:%d remapping.data.openvr.buttonId%d\n", m_currentRemapping->binding.type, deviceId, buttonId, m_currentRemapping->binding.data.openvr.buttonId);
delete m_currentBinding;
delete m_currentRemapping;
Sleep(1);
}
This is the Function:
void VRInputEmulator::setDigitalInputRemapping(uint32_t deviceId, uint32_t buttonId, DigitalInputRemapping* remapping, bool modal) {
printf("VRInputEmulator::setDigitalInputRemapping Digital orginput: %d device:%d butonid:%d remapping->binding.data.openvr.buttonId%d\n", remapping->binding.type, deviceId, buttonId, remapping->binding.data.openvr.buttonId);
if (_ipcServerQueue) {
ipc::Request message(ipc::RequestType::InputRemapping_SetDigitalRemapping);
memset(&message.msg, 0, sizeof(message.msg));
message.msg.ir_SetDigitalRemapping.clientId = m_clientId;
message.msg.ir_SetDigitalRemapping.messageId = 0;
message.msg.ir_SetDigitalRemapping.controllerId = deviceId;
message.msg.ir_SetDigitalRemapping.buttonId = buttonId;
message.msg.ir_SetDigitalRemapping.remapData = *remapping;
if (modal) {
uint32_t messageId = _ipcRandomDist(_ipcRandomDevice);
message.msg.ir_SetDigitalRemapping.messageId = messageId;
std::promise<ipc::Reply> respPromise;
auto respFuture = respPromise.get_future();
{
std::lock_guard<std::recursive_mutex> lock(_mutex);
_ipcPromiseMap.insert({ messageId, std::move(respPromise) });
}
_ipcServerQueue->send(&message, sizeof(ipc::Request), 0);
auto resp = respFuture.get();
{
std::lock_guard<std::recursive_mutex> lock(_mutex);
_ipcPromiseMap.erase(messageId);
}
std::stringstream ss;
ss << "Error while setting digital input remapping: ";
if (resp.status == ipc::ReplyStatus::InvalidId) {
ss << "Invalid device id";
throw vrinputemulator_invalidid(ss.str(), (int)resp.status);
} else if (resp.status == ipc::ReplyStatus::NotFound) {
ss << "Device not found";
throw vrinputemulator_notfound(ss.str(), (int)resp.status);
} else if (resp.status != ipc::ReplyStatus::Ok) {
ss << "Error code " << (int)resp.status;
throw vrinputemulator_exception(ss.str(), (int)resp.status);
}
} else {
_ipcServerQueue->send(&message, sizeof(ipc::Request), 0);
}
} else {
throw vrinputemulator_connectionerror("No active connection.");
}
}
You can See the Printf I had use before and after the function call, also used in the head of the dunction,This is the output:
void VRInputRemapping::DigitalInputConfig() m_currentRemapping->binding.type:0 device:1 buttonId:32 remapping.data.openvr.buttonId: 32
VRInputEmulator::setDigitalInputRemapping Digital orginput: 0 device:1 butonid:32 remapping->binding.data.openvr.buttonId: 0
void VRInputRemapping::DigitalInputConfig() m_currentRemapping->binding.type 0 device:1 buttonId:32 remapping.data.openvr.buttonId: 32
The output in the consloe

error C2664: cannot convert argument 1 from 'NvPhysicalGpuHandle'

I'm trying to add Nvidia API into kodi for HDR switching.
I don't have much knowledge of code, I'm trying to adapt a project HDR Switcher into kodi functions.
When compiling the HDR Switcher into an exe with visual studio it works and triggers HDR.
Now I need to make it work with kodi for seamless HDR pasthrough playback.
This uses the NVidia private APIs.
Please help this will be valuable for many users if it gets implemented.
The error:
error C2664: 'NvAPI_St
atus NvAPI_GPU_GetConnectedDisplayIds(NvPhysicalGpuHandle,NV_GPU_DISPLAYIDS *,NvU32 *,NvU32)': cannot convert argument
1 from 'NvPhysicalGpuHandle [64]' to 'NvPhysicalGpuHandle'
#include "WinRenderer.h"
#include "RenderCapture.h"
#include "RenderFactory.h"
#include "RenderFlags.h"
#include "rendering/dx/RenderContext.h"
#include "settings/Settings.h"
#include "settings/SettingsComponent.h"
#include "utils/log.h"
#include "windows/RendererDXVA.h"
#include "windows/RendererSoftware.h"
#include "windows/RendererShaders.h"
#include "windowing/GraphicContext.h"
#include "windowing/WinSystem.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include "DeviceManager.h"
#include "nvapi.h"
#include "uhdDisplay.h"
struct render_details
{
using map = std::map<RenderMethod, int>;
using weights_fn = std::function<void(map&, const VideoPicture&)>;
using create_fn = std::function<CRendererBase*(CVideoSettings&)>;
RenderMethod method;
std::string name;
create_fn create;
weights_fn weights;
template<class T>
constexpr static render_details get(RenderMethod method, const std::string& name)
{
return { method, name, T::Create, T::GetWeight };
}
};
static std::vector<render_details> RenderMethodDetails =
{
render_details::get<CRendererSoftware>(RENDER_SW, "Software"),
render_details::get<CRendererShaders>(RENDER_PS, "Pixel Shaders"),
render_details::get<CRendererDXVA>(RENDER_DXVA, "DXVA"),
};
CBaseRenderer* CWinRenderer::Create(CVideoBuffer*)
{
return new CWinRenderer();
}
bool CWinRenderer::Register()
{
VIDEOPLAYER::CRendererFactory::RegisterRenderer("default", Create);
return true;
}
CWinRenderer::CWinRenderer()
{
m_format = AV_PIX_FMT_NONE;
PreInit();
}
CWinRenderer::~CWinRenderer()
{
CWinRenderer::UnInit();
}
CRendererBase* CWinRenderer::SelectRenderer(const VideoPicture& picture)
{
int iRequestedMethod = CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_VIDEOPLAYER_RENDERMETHOD);
CLog::LogF(LOGDEBUG, "requested render method: %d", iRequestedMethod);
std::map<RenderMethod, int> weights;
for (auto& details : RenderMethodDetails)
details.weights(weights, picture);
RenderMethod method;
switch (iRequestedMethod)
{
case RENDER_METHOD_SOFTWARE:
if (weights[RENDER_SW])
{
method = RENDER_SW;
break;
}
// fallback to PS
case RENDER_METHOD_D3D_PS:
if (weights[RENDER_PS])
{
method = RENDER_PS;
break;
}
//fallback to DXVA
case RENDER_METHOD_DXVA:
if (weights[RENDER_DXVA])
{
method = RENDER_DXVA;
break;
}
// fallback to AUTO
case RENDER_METHOD_AUTO:
default:
{
const auto it = std::max_element(weights.begin(), weights.end(),
[](auto& w1, auto& w2) { return w1.second < w2.second; });
if (it != weights.end())
{
method = it->first;
break;
}
// there is no elements in weights, so no renderer which supports incoming video buffer
CLog::LogF(LOGERROR, "unable to select render method for video buffer");
return nullptr;
}
}
const auto it = std::find_if(RenderMethodDetails.begin(), RenderMethodDetails.end(),
[method](render_details& d) { return d.method == method; });
if (it != RenderMethodDetails.end())
{
CLog::LogF(LOGDEBUG, "selected render method: {}", it->name);
return it->create(m_videoSettings);
}
// something goes really wrong
return nullptr;
}
CRect CWinRenderer::GetScreenRect() const
{
CRect screenRect(0.f, 0.f,
static_cast<float>(CServiceBroker::GetWinSystem()->GetGfxContext().GetWidth()),
static_cast<float>(CServiceBroker::GetWinSystem()->GetGfxContext().GetHeight()));
switch (CServiceBroker::GetWinSystem()->GetGfxContext().GetStereoMode())
{
case RENDER_STEREO_MODE_SPLIT_HORIZONTAL:
screenRect.y2 *= 2;
break;
case RENDER_STEREO_MODE_SPLIT_VERTICAL:
screenRect.x2 *= 2;
break;
default:
break;
}
return screenRect;
}
bool CWinRenderer::Configure(const VideoPicture &picture, float fps, unsigned int orientation)
{
m_sourceWidth = picture.iWidth;
m_sourceHeight = picture.iHeight;
m_renderOrientation = orientation;
m_fps = fps;
m_iFlags = GetFlagsChromaPosition(picture.chroma_position)
| GetFlagsColorMatrix(picture.color_space, picture.iWidth, picture.iHeight)
| GetFlagsColorPrimaries(picture.color_primaries)
| GetFlagsStereoMode(picture.stereoMode);
m_format = picture.videoBuffer->GetFormat();
// calculate the input frame aspect ratio
CalculateFrameAspectRatio(picture.iDisplayWidth, picture.iDisplayHeight);
SetViewMode(m_videoSettings.m_ViewMode);
// if (picture.hasDisplayMetadata || picture.hasLightMetadata) {
SetHdrMonitorMode(true);
// }
ManageRenderArea();
m_renderer.reset(SelectRenderer(picture));
if (!m_renderer || !m_renderer->Configure(picture, fps, orientation))
{
m_renderer.reset();
return false;
}
m_bConfigured = true;
return true;
}
static bool first = true;
void CWinRenderer::SetHdrMonitorMode(bool enableHDR)
{
if (first)
{
NvAPI_Initialize();
first = false;
}
NvAPI_Status nvStatus = NVAPI_OK;
NvDisplayHandle hNvDisplay = NULL;
// get first display handle which should work for all NVAPI calls for all GPUs
if ((nvStatus = NvAPI_EnumNvidiaDisplayHandle(0, &hNvDisplay)) != NVAPI_OK)
{
printf("NvAPI_EnumNvidiaDisplayHandle returned error code %d\r\n", nvStatus);
return;
}
NvU32 gpuCount = 0;
NvU32 maxDisplayIndex = 0;
NvPhysicalGpuHandle ahGPU[NVAPI_MAX_PHYSICAL_GPUS] = {};
// get the list of displays connected, populate the dynamic components
nvStatus = NvAPI_EnumPhysicalGPUs(ahGPU, &gpuCount);
if (NVAPI_OK != nvStatus)
{
printf("NvAPI_EnumPhysicalGPUs returned error code %d\r\n", nvStatus);
return;
}
for (NvU32 i = 0; i < gpuCount; ++i)
{
NvU32 displayIdCount = 16;
NvU32 flags = 0;
NV_GPU_DISPLAYIDS displayIdArray[16] = {};
displayIdArray[0].version = NV_GPU_DISPLAYIDS_VER;
nvStatus = NvAPI_GPU_GetConnectedDisplayIds(ahGPU, displayIdArray, &displayIdCount, flags);
if (NVAPI_OK == nvStatus)
{
printf("Display count %d\r\n", displayIdCount);
for (maxDisplayIndex = 0; maxDisplayIndex < displayIdCount; ++maxDisplayIndex)
{
printf("Display tested %d\r\n", maxDisplayIndex);
NV_HDR_CAPABILITIES hdrCapabilities = {};
hdrCapabilities.version = NV_HDR_CAPABILITIES_VER;
if (NVAPI_OK == NvAPI_Disp_GetHdrCapabilities(displayIdArray[maxDisplayIndex].displayId, &hdrCapabilities))
{
if (hdrCapabilities.isST2084EotfSupported)
{
printf("Display %d supports ST2084 EOTF\r\n", maxDisplayIndex);
NV_HDR_COLOR_DATA hdrColorData = {};
memset(&hdrColorData, 0, sizeof(hdrColorData));
hdrColorData.version = NV_HDR_COLOR_DATA_VER;
hdrColorData.cmd = NV_HDR_CMD_SET;
hdrColorData.static_metadata_descriptor_id = NV_STATIC_METADATA_TYPE_1;
hdrColorData.hdrMode = enableHDR ? NV_HDR_MODE_UHDBD : NV_HDR_MODE_OFF;
nvStatus = NvAPI_Disp_HdrColorControl(displayIdArray[maxDisplayIndex].displayId, &hdrColorData);
if (NVAPI_OK == nvStatus)
{
printf("NvAPI_Disp_SethdrColorData call has succeeded: ");
}
else
{
NvAPI_ShortString szDesc;
NvAPI_GetErrorMessage(nvStatus, szDesc);
printf("NvAPI_Disp_HdrColorControl returned %s (%x)\r\n", szDesc, nvStatus);
}
}
}
else
{
NvAPI_ShortString szDesc;
NvAPI_GetErrorMessage(nvStatus, szDesc);
printf("NvAPI_Disp_GetHdrCapabilities returned %s (%x)\r\n", szDesc, nvStatus);
}
}
}
else
{
NvAPI_ShortString szDesc;
NvAPI_GetErrorMessage(nvStatus, szDesc);
printf("NvAPI_GPU_GetConnectedDisplayIds returned %s (%x)\r\n", szDesc, nvStatus);
}
}
}
int CWinRenderer::NextBuffer() const
{
return m_renderer->NextBuffer();
}
void CWinRenderer::AddVideoPicture(const VideoPicture &picture, int index)
{
m_renderer->AddVideoPicture(picture, index);
}
void CWinRenderer::Update()
{
if (!m_bConfigured)
return;
ManageRenderArea();
m_renderer->ManageTextures();
}
void CWinRenderer::RenderUpdate(int index, int index2, bool clear, unsigned int flags, unsigned int alpha)
{
if (!m_bConfigured)
return;
if (clear)
CServiceBroker::GetWinSystem()->GetGfxContext().Clear(DX::Windowing()->UseLimitedColor() ? 0x101010 : 0);
DX::Windowing()->SetAlphaBlendEnable(alpha < 255);
ManageRenderArea();
m_renderer->Render(index, index2, DX::Windowing()->GetBackBuffer(),
m_sourceRect, m_destRect, GetScreenRect(), flags);
}
bool CWinRenderer::RenderCapture(CRenderCapture* capture)
{
if (!m_bConfigured)
return false;
capture->BeginRender();
if (capture->GetState() != CAPTURESTATE_FAILED)
{
const CRect destRect(0, 0, static_cast<float>(capture->GetWidth()), static_cast<float>(capture->GetHeight()));
m_renderer->Render(capture->GetTarget(), m_sourceRect, destRect, GetScreenRect());
capture->EndRender();
return true;
}
return false;
}
void CWinRenderer::SetBufferSize(int numBuffers)
{
if (!m_bConfigured)
return;
m_renderer->SetBufferSize(numBuffers);
}
void CWinRenderer::PreInit()
{
CSingleLock lock(CServiceBroker::GetWinSystem()->GetGfxContext());
m_bConfigured = false;
UnInit();
}
void CWinRenderer::UnInit()
{
CSingleLock lock(CServiceBroker::GetWinSystem()->GetGfxContext());
m_renderer.reset();
m_bConfigured = false;
}
bool CWinRenderer::Flush(bool saveBuffers)
{
if (!m_bConfigured)
return false;
return m_renderer->Flush(saveBuffers);
}
bool CWinRenderer::Supports(ERENDERFEATURE feature)
{
if(feature == RENDERFEATURE_BRIGHTNESS)
return true;
if(feature == RENDERFEATURE_CONTRAST)
return true;
if (feature == RENDERFEATURE_STRETCH ||
feature == RENDERFEATURE_NONLINSTRETCH ||
feature == RENDERFEATURE_ZOOM ||
feature == RENDERFEATURE_VERTICAL_SHIFT ||
feature == RENDERFEATURE_PIXEL_RATIO ||
feature == RENDERFEATURE_ROTATION ||
feature == RENDERFEATURE_POSTPROCESS ||
feature == RENDERFEATURE_TONEMAP)
return true;
return false;
}
bool CWinRenderer::Supports(ESCALINGMETHOD method)
{
if (!m_bConfigured)
return false;
return m_renderer->Supports(method);
}
bool CWinRenderer::WantsDoublePass()
{
if (!m_bConfigured)
return false;
return m_renderer->WantsDoublePass();
}
bool CWinRenderer::ConfigChanged(const VideoPicture& picture)
{
if (!m_bConfigured)
return true;
return picture.videoBuffer->GetFormat() != m_format;
}
CRenderInfo CWinRenderer::GetRenderInfo()
{
if (!m_bConfigured)
return {};
return m_renderer->GetRenderInfo();
}
void CWinRenderer::ReleaseBuffer(int idx)
{
if (!m_bConfigured)
return;
m_renderer->ReleaseBuffer(idx);
}
bool CWinRenderer::NeedBuffer(int idx)
{
if (!m_bConfigured)
return false;
return m_renderer->NeedBuffer(idx);
}
´´´
Change
nvStatus = NvAPI_GPU_GetConnectedDisplayIds(ahGPU, displayIdArray, &displayIdCount, flags);
to
nvStatus = NvAPI_GPU_GetConnectedDisplayIds(ahGPU[i], displayIdArray, &displayIdCount, flags);
Thanks to #1201ProgramAlarm

How can I use both keyboard arrows and mouse clicks for two different widgets in FLTK?

I am using FLTK with C++ to write a program to scroll through a folder of images. I have a next button with the thumbnail for the next image, and the same for the previous button. I want to be able to go through the images by clicking the previous and next buttons as well as using the left and right arrows on the keyboard.
I succeeded in doing this, however not at the same time. When I only write a callback function like so:
void buttonCallback(Fl_Widget* widget, void* viewerPtr) {
Viewer* viewer = static_cast<Viewer*>(viewerPtr);
viewer->navPressed(widget);
viewer->redraw();
}
I can click the respective buttons to go forward and backwards, however when I overload the handle function to handle the keyboard arrows like so:
int Viewer::handle(int e) {
switch(e) {
case FL_FOCUS:
case FL_UNFOCUS:
return 1;
case FL_KEYBOARD:
if ( Fl::event_key() == FL_Left) {
prev->do_callback();
return(1);
} else if (Fl::event_key() == FL_Right) {
next->do_callback();
return(1);
}
return 1;
case FL_RELEASE:
do_callback();
return 1;
}
return Fl_Widget::handle(e);
}
I can use the arrows, however I cannot figure out how to use both arrows and clicking on the buttons. I have tried passing the Fl_Widget *w through to the handle function and back up to the callback, and I was able to click on the buttons, but could no longer use the arrows.
Here is the Viewer.cpp file:
#include <iostream>
#include "Viewer.h"
using namespace std;
void buttonCallback(Fl_Widget* widget, void* viewerPtr) {
//cout << "Callback called" << endl;
Viewer* viewer = static_cast<Viewer*>(viewerPtr);
viewer->navPressed(widget);
viewer->redraw();
}
Viewer::Viewer(string imageFolder, vector<string> imageFilenames, int width = 800, int height = 600) :
Fl_Window(width, height, "Image Viewer"), imageFolder(imageFolder), imageFilenames(imageFilenames), currentIndex(0), nextIndex(1), prevIndex(imageFilenames.size()-1),
prev(nullptr), next(nullptr), imageBox(nullptr), pic(nullptr) {
prev = new NavButton(getPathFilename(imageFilenames.at(prevIndex), true), "Previous Button", borderSize, this->h() - borderSize - thumbnailSize - borderSize, thumbnailSize, imageFilenames.size() - 1);
next = new NavButton(getPathFilename(imageFilenames.at(nextIndex), true), "Next Button",
this->w() - borderSize - thumbnailSize - borderSize, this->h() - borderSize - thumbnailSize - borderSize, thumbnailSize, imageFilenames.size()-1);
imageBox = new Fl_Box(borderSize, borderSize, this->w() - (2*borderSize), this->h() - (2*borderSize) - thumbnailSize - 2*borderSize);
//imageBox->box(FL_BORDER_BOX); // useful to see where the full size of the widget holding the images
pic = new Fl_JPEG_Image(getPathFilename(imageFilenames.at(currentIndex)).c_str());
imageBox->image(pic);
this->end();
prev->callback(buttonCallback, static_cast<void*>(this));
next->callback(buttonCallback, static_cast<void*>(this));
}
string Viewer::getPathFilename(string filename, bool thumb) {
string thumbPart = "";
if (thumb) thumbPart = "t_";
return imageFolder + "/" + thumbPart+ filename;
}
void Viewer::navPressed(Fl_Widget *widget) {
NavButton* b = dynamic_cast<NavButton*>(widget);
// adds to the click counts to keep track of them
b->addClickCount(); b->addTotalClicks();
cout << b->getLabel() << " has been pressed " << b->getClickCount() << " times." << endl;
cout << "All buttons have been pressed " << b->getTotClicks() << " times." << endl;
// determines which button is pressed
if (b->getLabel() == "Next Button") {
changeAllInds(true);
// check to see if at end of list
if ((nextIndex) > imageFilenames.size()-1) {
nextIndex = 0;
} else if (currentIndex > imageFilenames.size()-1) {
currentIndex = 0;
} else if (prevIndex > imageFilenames.size()-1) {
prevIndex = 0;
}
// changes main image
pic = new Fl_JPEG_Image(getPathFilename(imageFilenames.at(currentIndex)).c_str());
imageBox->image(pic);
// changes thumbnails
prev->setImage(getPathFilename(imageFilenames.at(prevIndex), true).c_str());
next->setImage(getPathFilename(imageFilenames.at(nextIndex), true).c_str());
} else {
changeAllInds(false);
// check to see if at end of list
if ((nextIndex) < 0) {
nextIndex = imageFilenames.size()-1;
} else if (currentIndex < 0) {
currentIndex = imageFilenames.size()-1;
} else if (prevIndex < 0) {
prevIndex = imageFilenames.size()-1;
}
// changes main image
pic = new Fl_JPEG_Image(getPathFilename(imageFilenames.at(currentIndex)).c_str());
imageBox->image(pic);
// changes thumbnails
prev->setImage(getPathFilename(imageFilenames.at(prevIndex), true).c_str());
next->setImage(getPathFilename(imageFilenames.at(nextIndex), true).c_str());
}
//cout << currentIndex << endl;
cout << endl;
}
void Viewer::changeAllInds(bool increase) {
if (increase) {
currentIndex++; nextIndex++; prevIndex++;
} else {
currentIndex--; nextIndex--; prevIndex--;
}
}
int Viewer::handle(int e) {
switch(e) {
case FL_FOCUS:
case FL_UNFOCUS:
return 1;
case FL_KEYBOARD:
if ( Fl::event_key() == FL_Left) {
prev->do_callback();
return(1);
} else if (Fl::event_key() == FL_Right) {
next->do_callback();
return(1);
}
return 1;
case FL_RELEASE:
do_callback();
return 1;
}
return Fl_Widget::handle(e);
}
And here is Viewer.h:
#ifndef VIEWER_H
#define VIEWER_H
#include <vector>
#include <string>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include "NavButton.h"
class Viewer : public Fl_Window {
std::vector<std::string> imageFilenames;
Fl_Box *imageBox; // Holds image being shown
Fl_JPEG_Image *pic; // Image being shown
NavButton* prev; // Button to go to previous item
// Image is thumbnail of previous image
NavButton* next; // Button to go to next item
// Image is thumbnail of next image
int currentIndex; // Index of the image currently shown
int nextIndex; // Index of next image
int prevIndex; // Index of previous image
// private helper functions
std::string imageFolder;
std::string getPathFilename(std::string filename, bool thumb=false);
public:
static const int thumbnailSize = 50; // size of NavButton
static const int borderSize = 10; // size of border between window edge and widgets
void navPressed(Fl_Widget* widget);
// constructor
Viewer(std::string, std::vector<std::string>, int, int);
virtual int handle(int e);
//int key_handle(int e, int key);
//int mouse_handle(int e);
void changeAllInds(bool increase);
};
#endif
Please let me know if you need any more info to assist me, and thank you in advance!
This may achieve what you want. Add a third routine to do the navigation
int Navigate(int key)
{
if ( key == FL_Left) {
prev->do_callback();
return(1);
} else if (key == FL_Right) {
next->do_callback();
return(1);
}
return 1;
}
Then change the other two to call it. In your handler
int Viewer::handle(int e) {
switch(e) {
...
case FL_KEYBOARD:
return Navigate(Fl::event_key());
case FL_RELEASE:
...
}
...
In navpressed,
...
if (b->getLabel() == "Next Button") {
...
Navigate(FL_Right);
}
else {
...
Navigate(FL_Left);
}

Shared memory ring buffer crashes

I wrote a shared memory ringbuffer with QT and I turns out it works great in a single process with one consumer and one writer. If I try to read data from a second process I the first one which connected crashes with a seg fault. Maybe I'm overlooking something?
The Header File
#ifndef SHAREDMEMORYRINGBUFFER_H
#define SHAREDMEMORYRINGBUFFER_H
#include <QObject>
#include <QSharedMemory>
class SharedMemoryRingBuffer : public QObject
{
Q_OBJECT
public:
struct SharedMemoryAttributes {
int32_t readPosition;
int32_t writePosition;
int32_t size;
int32_t* data;
};
explicit SharedMemoryRingBuffer(QString sharedMemoryName, int32_t size, QObject *parent = 0);
~SharedMemoryRingBuffer();
int write(int32_t frame);
int32_t read();
int32_t length();
int32_t readPosition();
int32_t writePosition();
int avaibleSize();
int isEmpty();
void empty();
int isFull();
private:
SharedMemoryAttributes *_attributes;
int32_t _writePosition;
int32_t _readPosition;
int32_t _length;
QSharedMemory *_sharedMemory;
int _headSize;
signals:
void readFrame(QString name);
public slots:
};
#endif // SHAREDMEMORYRINGBUFFER_H
And the CPP File:
#include "sharedmemoryringbuffer.h"
#include <QDebug>
#define DEBUGGINGNAME "[SharedMemoryRingbuffer]"
SharedMemoryRingBuffer::SharedMemoryRingBuffer(QString sharedMemoryName, int32_t size, QObject *parent) : QObject(parent)
{
int sizeOfData = sizeof(int32_t) * (size);
int sizeOfHeader = sizeof(SharedMemoryAttributes);
_sharedMemory = new QSharedMemory(sharedMemoryName);
if (!_sharedMemory->attach()) {
if (!_sharedMemory->create(sizeOfData+sizeOfHeader, QSharedMemory::ReadWrite )) {
qDebug() << DEBUGGINGNAME << "Could not create shared memory object, aborting ...";
qDebug() << DEBUGGINGNAME << _sharedMemory->errorString();
//TODO: exit call
return;
}
}
_sharedMemory->lock();
_attributes = reinterpret_cast<SharedMemoryAttributes*>(_sharedMemory->data());
_attributes->readPosition = 0;
_attributes->writePosition = 0;
_attributes->size = size + 1;
_attributes->data = (int32_t*) _sharedMemory->data() + sizeOfHeader;
_sharedMemory->unlock();
}
SharedMemoryRingBuffer::~SharedMemoryRingBuffer()
{
_sharedMemory->detach();
delete _sharedMemory;
}
int SharedMemoryRingBuffer::write(int32_t frame)
{
_sharedMemory->lock();
if ( !isFull() ) {
_attributes->data[writePosition()] = frame;
if (writePosition() + 1 >= _attributes->size) _attributes->writePosition = 0;
else _attributes->writePosition += 1;
_sharedMemory->unlock();
return 1;
}
_sharedMemory->unlock();
return 0;
}
/**
* #brief SharedMemoryRingBuffer::read
* #return
* if the buffer is empty this functions returns the last readable value
*
*/
int32_t SharedMemoryRingBuffer::read()
{
_sharedMemory->lock();
int32_t frame = _attributes->data[readPosition()];
if ( readPosition() != writePosition() ) {
if (readPosition() + 1 >= _attributes->size ) _attributes->readPosition = 0;
else _attributes->readPosition += 1;
emit readFrame(_sharedMemory->key());
}
_sharedMemory->unlock();
return frame;
}
int32_t SharedMemoryRingBuffer::length()
{
if(readPosition() <= writePosition()) {
return writePosition() - readPosition();
} else {
return readPosition() - writePosition();
}
}
int32_t SharedMemoryRingBuffer::readPosition()
{
return _attributes->readPosition;
}
int32_t SharedMemoryRingBuffer::writePosition()
{
return _attributes->writePosition;
}
int SharedMemoryRingBuffer::avaibleSize()
{
return -1;
}
int SharedMemoryRingBuffer::isEmpty()
{
if ( readPosition() == writePosition() ) return 1;
else return 0;
}
void SharedMemoryRingBuffer::empty()
{
}
int SharedMemoryRingBuffer::isFull()
{
if ((writePosition() + 1) % _attributes->size == readPosition()) return 1;
else return 0;
}
This initialization:
_attributes->size = size + 1;
looks incorrect since the size you pass to _sharedMemory->create() is only allocating enough "data" space for size elements, not size + 1. Why is the +1 there?
So I found a solution which was pretty obvious. If a second process connects to to the shared memory it should NOT set the head and tail position to 0.
This is the fixed code, which works well :)
#include "sharedmemoryringbuffer.h"
#include <QDebug>
#define DEBUGGINGNAME "[SharedMemoryRingbuffer]"
SharedMemoryRingBuffer::SharedMemoryRingBuffer(QString sharedMemoryName, int32_t size, QObject *parent) : QObject(parent)
{
int sizeOfData = sizeof(int32_t) * (size);
int sizeOfHeader = sizeof(SharedMemoryAttributes);
_sharedMemory = new QSharedMemory(sharedMemoryName);
if (_sharedMemory->isAttached()) _sharedMemory->detach();
if (!_sharedMemory->attach()) {
_sharedMemory->lock();
_attributes = reinterpret_cast<SharedMemoryAttributes*>(_sharedMemory->data());
_attributes->readPosition = 0;
_attributes->writePosition = 0;
_attributes->size = size;
_sharedMemory->unlock();
if (!_sharedMemory->create(sizeOfData+sizeOfHeader, QSharedMemory::ReadWrite )) {
qDebug() << DEBUGGINGNAME << "Could not create shared memory object, aborting ...";
qDebug() << DEBUGGINGNAME << _sharedMemory->errorString();
//TODO: exit call
return;
}
}
_attributes->data = (int32_t*) _sharedMemory->data() + sizeOfHeader;
}
SharedMemoryRingBuffer::~SharedMemoryRingBuffer()
{
_sharedMemory->detach();
delete _sharedMemory;
}
int SharedMemoryRingBuffer::write(int32_t frame)
{
_sharedMemory->lock();
if ( !isFull() ) {
_attributes->data[writePosition()] = frame;
if (writePosition() + 1 >= _attributes->size) _attributes->writePosition = 0;
else _attributes->writePosition += 1;
_sharedMemory->unlock();
return 1;
}
_sharedMemory->unlock();
return 0;
}
/**
* #brief SharedMemoryRingBuffer::read
* #return
* if the buffer is empty this functions return the last readable value
*
*/
int32_t SharedMemoryRingBuffer::read()
{
_sharedMemory->lock();
int32_t frame = _attributes->data[readPosition()];
if ( readPosition() != writePosition() ) {
if (readPosition() + 1 >= _attributes->size ) _attributes->readPosition = 0;
else _attributes->readPosition += 1;
emit readFrame(_sharedMemory->key());
}
_sharedMemory->unlock();
return frame;
}
int32_t SharedMemoryRingBuffer::length()
{
if(readPosition() <= writePosition()) {
return writePosition() - readPosition();
} else {
return readPosition() - writePosition();
}
}
int32_t SharedMemoryRingBuffer::readPosition()
{
return _attributes->readPosition;
}
int32_t SharedMemoryRingBuffer::writePosition()
{
return _attributes->writePosition;
}
int SharedMemoryRingBuffer::avaibleSize()
{
return -1;
}
int SharedMemoryRingBuffer::isEmpty()
{
if ( readPosition() == writePosition() ) return 1;
else return 0;
}
void SharedMemoryRingBuffer::empty()
{
}
int SharedMemoryRingBuffer::isFull()
{
if ((writePosition() + 1) % _attributes->size == readPosition()) return 1;
else return 0;
}

Unexpected Program Stoppage on Arduino

I have an issue where my Arduino program hangs for no reason. I run my program, and at some undetermined point, the Serial Monitor stops printing output. Here's what I've tested so far:
In my "com.init_drone()" method, I've commented everything out except for the last line, which signals that the method returned. When I do this, my program hangs somewhere else but still it doesn't get to the infinite while loop.
I've been outputting memory usage, and I'm getting numbers no lower than 450 -- this tells me that I'm not using an absurd amount of memory.
I've tried removing the Timer1 instantiation, interrupt attach/detach, bu that has had no effect on the program.
My .ino file(and Command) is located here for anyone that wants a fuller picture and doesn't want to scroll through all this code I'm going to post below.
Here's my log output so far. Notice the truncation!:
AT&F
AT+NMAC=00:1d:c9:10:39:6f
AT+WM=0
AT+NDHCP=1
AT+WA=ardrone_279440
AT+NCUDP=192.168.1.1,5556
S0AT*CONFIG=1,"general:navdata_demo","TRUE"
EAT*CONFIG=1,"general:navdata_demo","TRUE"
638
S0AT*CONFIG=2,"control:altitude_max","2000"
EAT*CONFIG=2,"control:altitude_max","2000"
638
S0AT*CONFIG=3,"control:euler_angle_max","0.35"
EAT*CONFIG=3,"control:euler_angle_max","0.35"
586
S0AT*CONFIG=4,"control:outdoor","FALSE"
EAT*CONFIG=4,"control:outdoor","FALSE"
635
S0AT*CONFIG=5,"control:flight_without_shell","FALSE"
EAT*CONFIG=5,"control:flight_without_shell","FALSE"
574
S0AT*CTRL=6,4,0
EAT*CTRL=6,4,0
629
S0AT*CTRL=7,0,0
EAT*CTRL=7,0,0
629
S0AT*CTRL=8,4,0
EAT*CTRL=8,4,0
629
S0AT*COMWDG=9
EAT*COMWDG=9
629
S0AT*COMWDG=10
EAT*COMWDG=10
629
S0AT*COMWDG=11
EAT*COMWDG=11
629
S0AT*COMWDG=12
EAT*COMWDG=12
629
S0AT*COMWDG=13
EAT*COMWDG=13
629
S0AT*FTRIM=14
EAT*FTRIM=14
629
Here is my .ino file:
#include "Command.h"
#include "Streaming.h"
int debug = 1;
extern ring_buffer rx_buf;
extern resultint_ resultint;
Command com;
int sequenceNumber = 1;
String atcmd = "";
#include "TimerOne.h"
#define LEDpin 13
void setup()
{
PCsrl.begin(9600);
com.start_wifi_connection();
com.drone_is_init = com.init_drone();
Timer1.initialize(COMWDG_INTERVAL_USEC);
Timer1.attachInterrupt(watchdog_timer);
}
void watchdog_timer() {
com.sendwifi(com.makeComwdg());
}
void loop()
{
if (com.drone_is_init == 0) {
if (debug) {
// never use three ! together in arduino code
PCsrl.println("Drone wasn't initlized before loop() was called. Initalizing now.\r\n");
}
} else {
com.drone_takeoff();
com.drone_takeoff();
com.sendwifi(com.makePcmd(1,0,0,0,0));
com.sendwifi(com.makePcmd(1,0,0,0,0));
delay(5000);
com.moveForward(1);
com.moveRotate(180);
com.moveForward(1);
com.moveRotate(180);
delay(500);
com.drone_landing();
com.drone_landing();
delay(500);
//end of program
Timer1.detachInterrupt();
PCsrl.println("Program finished");
while (1){};
}
}
And my Command.cpp
#ifndef GAINSPAN
#define GAINSPAN
#include "Command.h"
extern int sequenceNumber;
extern int debug;
ring_buffer rx_buf= {{0}, 0, 0};
resultint_ resultint;
Command::Command()
{
at = "";
command = "";
s2ip_running = 0;
drone_is_init = 0;
drone_is_hover = 0;
emergency = 0;
}
void Command::sendwifi(String s) {
WIFIsrl.write(27); //esc
WIFIsrl.print("S0"); //choose connection CID 0
WIFIsrl.print(s);
WIFIsrl.write(27);
WIFIsrl.print("E");
if(debug) PCsrl.println(s);
WIFIsrl.println(memoryTest());
}
int Command::start_wifi_connection()
{
WIFIsrl.begin(9600);
WIFIsrl.println("");
WIFIsrl.println("AT&F");
//WIFIsrl.println("ATE0"); //turn off echo
WIFIsrl.print("AT+NMAC=00:1d:c9:10:39:6f\r"); //set MAC address
WIFIsrl.println("AT+WM=0");
WIFIsrl.println("AT+NDHCP=1");
/* drone's network profile, change if needed*/
WIFIsrl.println("AT+WA=ardrone_279440");
WIFIsrl.println("AT+NCUDP=192.168.1.1,5556");
readARsrl();
delay(3000); //need 3 seconds for connection to establish
return 0;
}
String Command::makeComwdg()
{
at = "AT*COMWDG=";
command = at + getSequenceNumber() + "\r\n";
return command;
}
void Command::sendComwdg_t(int msec)
{
for (int i = 0; i < msec; i+=20) {
sendwifi(makeComwdg());
delay(20);
}
}
void Command::sendFtrim()
{
at = "AT*FTRIM=";
command = at + getSequenceNumber() + "\r\n";
sendwifi(command);
}
void Command::sendConfig(String option, String value)
{
at = "AT*CONFIG=";
command = at + getSequenceNumber() + ",\"" + option + "\",\"" + value + "\"\r\n";
sendwifi(command);
}
void Command::sendRef(flying_status fs)
{
at = "AT*REF=";
if(fs == TAKEOFF){
command = at + getSequenceNumber() + ",290718208\r\n"; //takeoff
}
else if(fs == LANDING){
command = at + getSequenceNumber() + ",290717696\r\n"; //landing
} else if (fs == EMERGENCY_TOGGLE){
command = at + getSequenceNumber() + ",290717952\r\n"; //landing
}
// emergency -> 290717952
sendwifi(command);
}
void Command::send_control_commands(){
at = "AT*CTRL=";
sendwifi(at+getSequenceNumber()+",4,0\r\n");
sendwifi(at+getSequenceNumber()+",0,0\r\n");
sendwifi(at+getSequenceNumber()+",4,0\r\n");
}
void Command::drone_emergency_reset()
{
at = "AT*REF=";
command = at + getSequenceNumber() + ",290717952\r\n";
sendwifi(command);
}
/** Movement functions **/
int Command::moveForward(float distanceInMeters)
{
float i = 0;
String moveForward = makePcmd(1, 0, -.855, 0, 0);
delay(1000*distanceInMeters);
sendPcmd(moveForward);
return 1;
}
int Command::moveRotate(float yawInDegrees)
{
int i = 0;
while (i < yawInDegrees) {
String stayRotate = makePcmd(1, 0, 0, 0, 0.17);
sendPcmd(stayRotate);
delay(150);
i += 8;
}
return 1;
}
String Command::makePcmd(int enable, float roll, float pitch, float gaz, float yaw)
{
at = "AT*PCMD=";
command = at + getSequenceNumber() + "," + enable + "," + fl2int(roll) + "," + fl2int(pitch) + "," + fl2int(gaz) + "," + fl2int(yaw) + "\r";
return command;
}
void Command::sendPcmd(String command)
{
previousCommand = command;
sendwifi(command);
}
void Command::sendPcmd(int enable, float roll, float pitch, float gaz, float yaw)
{
at = "AT*PCMD=";
command = at + getSequenceNumber() + "," + enable + "," + fl2int(roll) + "," + fl2int(pitch) + "," + fl2int(gaz) + "," + fl2int(yaw) + "\r";
sendwifi(command);
}
String Command::makeAnim(anim_mayday_t anim, int time)
{
at = "AT*ANIM=";
command = at + getSequenceNumber() + "," + anim + "," + time + "\r\n";
return command;
}
void Command::doLEDAnim(int animseq, int duration)
{
PCsrl << "calling LEDAnim" << endl;
at = "AT*LED=";
command = at + getSequenceNumber() + "," + animseq + ",1073741824," + duration + "\r\n";
sendwifi(command);
}
int Command::start_s2ip()
{
char temp;
//delay(20000); //wait for drone to start
readARsrl();
if (debug) {
PCsrl << "trying to start s2ip" << endl;
}
ARsrl.print("\r\n");
delay(500);
ARsrl.print("\r\n");
delay(500);
ARsrl << "cd ~" << endl;
if (debug) {
readARsrl();
}
delay(500);
ARsrl << "cd data/video/apps/" << endl;
delay(500);
ARsrl << "./s2ip.arm" << endl;
while ((int) temp != 2) {
temp = ARsrl.read();
if (temp == 2) {
PCsrl << "s2ip is running" << endl;
ARsrl << "bullshit\r\n"; //to fix a delay bug
break;
}
//PCsrl << "s2ip not running" << endl;
}
if (debug) {
while (ARsrl.available()) {
PCsrl.write(ARsrl.read());
}
}
return 1;
}
void Command::quit_s2ip()
{
ARsrl.println("EXIT");
while (ARsrl.available()) {
PCsrl.write(ARsrl.read());
}
}
int Command::init_drone()
{
sendConfig("general:navdata_demo","TRUE");
sendConfig("control:altitude_max","2000");
sendConfig("control:euler_angle_max","0.35");
sendConfig("control:outdoor","FALSE");
sendConfig("control:flight_without_shell","FALSE");
send_control_commands();
sendComwdg_t(90);
sendFtrim();
drone_emergency_reset(); //clear emergency flag
return 1;
}
int Command::drone_takeoff()
{
sendRef(TAKEOFF);
int i = 0;
return 1;
}
int Command::drone_hover(int msec)
{
int i = 0;
while (i < msec) {
sendwifi(makePcmd(1, 0, 0, 0, 0));
delay(100);
i += 100;
}
return 1;
}
int Command::drone_landing()
{
sendRef(LANDING);
return 1;
}
int Command::drone_move_up(int centimeter)
{
int i = 0;
while (i < centimeter) {
ARsrl << makePcmd(1, 0, 0, 0.6, 0);
delay(100);
i += 10;
}
return 1;
}
int Command::drone_move_down(int centimeter)
{
int i = 0;
while (i < centimeter) {
sendwifi(makePcmd(1, 0, 0, -0.5, 0));
delay(100);
i += 10;
}
return 1;
}
long Command::fl2int(float value)
{
resultint.i = 0;
if (value < -1 || value > 1) {
resultint.f = 1;
} else {
resultint.f=value;
}
return resultint.i;
}
void Command::readARsrl()
{
while (ARsrl.available()) {
if (debug) {
PCsrl.write(ARsrl.read());
}
}
}
//Memory test code from : http://www.faludi.com/2007/04/18/arduino-available-memory-test/
int Command::memoryTest() {
int byteCounter = 0; // initialize a counter
byte *byteArray; // create a pointer to a byte array
// More on pointers here: http://en.wikipedia.org/wiki/Pointer#C_pointers
// use the malloc function to repeatedly attempt
// allocating a certain number of bytes to memory
// More on malloc here: http://en.wikipedia.org/wiki/Malloc
while ( (byteArray = (byte*) malloc (byteCounter * sizeof(byte))) != NULL ) {
byteCounter++; // if allocation was successful, then up the count for the next try
free(byteArray); // free memory after allocating it
}
free(byteArray); // also free memory after the function finishes
return byteCounter; // send back the highest number of bytes successfully allocated
}
int Command::getSequenceNumber(){
return sequenceNumber++;
}
// Volatile, since it is modified in an ISR.
volatile boolean inService = false;
void SrlRead()
{
if (inService) {
PCsrl.println("timer kicked too fast");
return;
}
interrupts();
inService = true;
while(ARsrl.available()) {
unsigned char k = ARsrl.read();
store_char(k, &rx_buf);
}
inService = false;
}
void read_rx_buf()
{
while (rx_buf.tail != rx_buf.head) {
if (debug) {
PCsrl.write(rx_buf.buffer[rx_buf.tail]);
}
rx_buf.tail = (unsigned int) (rx_buf.tail+ 1) % SERIAL_BUFFER_SIZE;
}
}
inline void store_char(unsigned char c, ring_buffer *buffer)
{
int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE;
// if we should be storing the received character into the location
// just before the tail (meaning that the head would advance to the
// current location of the tail), we're about to overflow the buffer
// and so we don't write the character or advance the head.
if (i != buffer->tail) {
buffer->buffer[buffer->head] = c;
buffer->head = i;
}
else {
Serial.println("ring buffer is too small");
}
}
#endif
I know it sounds weird but, sometimes this happens when arduino is not getting enough power supply. Try connecting the arduino to a power source different from USB.
As soon as I started to put things in prog memory my program started to clear up it's hiccups. It seems it was a memory issue.
I had the same problem, but the issue was with Timer1.initialize(). Try this:
com.drone_is_init = com.init_drone();
Serial.println("One");
Serial.println("Two");
Serial.println("Three");
Timer1.initialize(COMWDG_INTERVAL_USEC);
Timer1.attachInterrupt(watchdog_timer);
Open serial monitor and see... it will show until "Two", and then Arduino will hang.
The issue was I calling some functions of the LiquidCrystal_I2C library, that need interrupt routines. Check if your timer ISR is using some interrupts. If so, you should move this code to another place in your project.