//----------------------------------------------------------------------------- // Copyright 2007 Jonathan Westhues // // This file is part of LDmicro. // // LDmicro is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // LDmicro is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with LDmicro. If not, see . //------ // // Dialog for setting the overall PLC parameters. Mostly this relates to // timing; to set up the timers we need to know the desired cycle time, // which is configurable, plus the MCU clock (i.e. crystal frequency). // Jonathan Westhues, Nov 2004 //----------------------------------------------------------------------------- #include #include #include #include //#include #include "ldmicro.h" using namespace std; static QDialog* ConfDialog; static QLineEdit* CrystalTextbox; static QLineEdit* CycleTextbox; static QLineEdit* BaudTextbox; static QDialogButtonBox* ButtonBox; static LONG_PTR PrevCrystalProc; static LONG_PTR PrevCycleProc; static LONG_PTR PrevBaudProc; QGridLayout* ConfGrid; static inline void DestroyWindow() { delete ConfDialog; delete CrystalTextbox; delete CycleTextbox; delete BaudTextbox; delete ButtonBox; delete ConfGrid; } static void MakeControls(void) { // Creating text labels QLabel* textLabel = new QLabel(_("Cycle Time (ms):")); QLabel* textLabel2 = new QLabel(_("Crystal Frequency (MHz):")); QLabel* textLabel3 = new QLabel(_("UART Baud Rate (bps):")); CycleTextbox = new QLineEdit(); CrystalTextbox = new QLineEdit(); BaudTextbox = new QLineEdit(); CycleTextbox->setValidator( new QRegExpValidator( QRegExp("[0-9]+"))); CrystalTextbox->setValidator( new QRegExpValidator( QRegExp("[0-9]+"))); BaudTextbox->setValidator( new QRegExpValidator( QRegExp("[0-9]+"))); if(!UartFunctionUsed()) { BaudTextbox->setEnabled(FALSE); textLabel3->setEnabled(FALSE); } if(Prog.mcu && (Prog.mcu->whichIsa == ISA_ANSIC || Prog.mcu->whichIsa == ISA_INTERPRETED)) { CrystalTextbox->setEnabled(FALSE); textLabel2->setEnabled(FALSE); } ButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Vertical, ConfDialog); char explanation[1024] = ""; if(UartFunctionUsed()) { if(Prog.mcu && Prog.mcu->uartNeeds.rxPin != 0) { sprintf(explanation, _("Serial (UART) will use pins %d and %d.\r\n\r\n"), Prog.mcu->uartNeeds.rxPin, Prog.mcu->uartNeeds.txPin); } else { strcpy(explanation, _("Please select a micro with a UART.\r\n\r\n")); } } else { strcpy(explanation, _("No serial instructions (UART Send/UART Receive) " "are in use; add one to program before setting baud rate.\r\n\r\n") ); } strcat(explanation, _("The cycle time for the 'PLC' runtime generated by LDmicro is user-" "configurable. Very short cycle times may not be achievable due " "to processor speed constraints, and very long cycle times may not " "be achievable due to hardware overflows. Cycle times between 10 ms " "and 100 ms will usually be practical.\r\n\r\n" "The compiler must know what speed crystal you are using with the " "micro to convert between timing in clock cycles and timing in " "seconds. A 4 MHz to 20 MHz crystal is typical; check the speed " "grade of the part you are using to determine the maximum allowable " "clock speed before choosing a crystal.")); QLabel* textLabel4 = new QLabel(explanation); textLabel4->setAlignment(Qt::AlignJustify); textLabel4->setMaximumWidth(310); textLabel4->setWordWrap(TRUE); // Creating required containers for packing ConfGrid->addWidget(textLabel, 0,0); ConfGrid->addWidget(CycleTextbox, 0,1); ConfGrid->addWidget(ButtonBox, 0, 2, 0, 2); ConfGrid->addWidget(textLabel2, 1, 0); ConfGrid->addWidget(CrystalTextbox, 1, 1); ConfGrid->addWidget(textLabel3, 2, 0); ConfGrid->addWidget(BaudTextbox, 2, 1); ConfGrid->addWidget(textLabel4, 3, 0, 2, 0, Qt::AlignJustify); NiceFont(ConfDialog); CycleTextbox->setFocus(); // int height = textLabel4->pos().y(); // printf("Height:%d\n", height); // ConfDialog->setSize(ConfGrid->sizeHint()); ConfDialog->adjustSize(); QObject::connect(ButtonBox, SIGNAL(accepted()), ConfDialog, SLOT(accept())); QObject::connect(ButtonBox, SIGNAL(rejected()), ConfDialog, SLOT(reject())); // PrevCycleProc = SetWindowLongPtr(CycleTextbox, GWLP_WNDPROC, // (LONG_PTR)MyNumberProc); // PrevCrystalProc = SetWindowLongPtr(CrystalTextbox, GWLP_WNDPROC, // (LONG_PTR)MyNumberProc); // PrevBaudProc = SetWindowLongPtr(BaudTextbox, GWLP_WNDPROC, // (LONG_PTR)MyNumberProc); } /* //----------------------------------------------------------------------------- // Don't allow any characters other than 0-9. in the text boxes. //----------------------------------------------------------------------------- void ConfDialogMyNumberProc (GtkEditable *editable, gchar *NewText, gint length, gint *position, gpointer data){ gtk_widget_set_sensitive (MainWindow, TRUE); for (int i = 0; i < length; i++){ if (!(isdigit (NewText[i]) || NewText[i] == '.' || NewText[i] == '\b')){ g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text"); return; } } } // Gets data from the text boxes void ConfDialogGetData (GtkWidget* widget, gpointer data){ char* buf; buf = const_cast (gtk_entry_get_text (GTK_ENTRY (CycleTextbox))); Prog.cycleTime = (int)(1000*atof(buf) + 0.5); if(Prog.cycleTime == 0) { Error(_("Zero cycle time not valid; resetting to 10 ms.")); Prog.cycleTime = 10000; } buf = const_cast (gtk_entry_get_text (GTK_ENTRY(CrystalTextbox))); Prog.mcuClock = (int)(1e6*atof(buf) + 0.5); buf = const_cast (gtk_entry_get_text (GTK_ENTRY(BaudTextbox))); Prog.baudRate = atoi(buf); DestroyWindow (ConfDialog); ProgramChanged(); } // Checks for the required key press gboolean ConfDialogKeyPress (GtkWidget* widget, GdkEventKey* event, gpointer data){ if (event -> keyval == GDK_KEY_Return){ ConfDialogGetData(NULL, NULL); } else if (event -> keyval == GDK_KEY_Escape){ DestroyWindow (ConfDialog); ProgramChanged(); gtk_widget_set_sensitive (MainWindow, TRUE); } return FALSE; } void ConfCallDestroyWindow (HWID widget, gpointer data){ DestroyWindow (ConfDialog); ProgramChanged(); gtk_widget_set_sensitive (MainWindow, TRUE); } // Consists of all the signal calls void ConfDialogSignalCall () { g_signal_connect (G_OBJECT(CycleTextbox), "insert-text", G_CALLBACK(ConfDialogMyNumberProc), NULL); g_signal_connect (G_OBJECT(CrystalTextbox), "insert-text", G_CALLBACK(ConfDialogMyNumberProc), NULL); g_signal_connect (G_OBJECT(BaudTextbox), "insert-text", G_CALLBACK(ConfDialogMyNumberProc), NULL); g_signal_connect (G_OBJECT (ConfDialog), "key-press-event", G_CALLBACK(ConfDialogKeyPress), NULL); g_signal_connect (G_OBJECT (OkButton), "clicked", G_CALLBACK(ConfDialogGetData), NULL); g_signal_connect (G_OBJECT (CancelButton), "clicked", G_CALLBACK(ConfCallDestroyWindow), NULL); g_signal_connect (ConfDialog, "delete_event", G_CALLBACK (ConfCallDestroyWindow), NULL); } */ void ShowConfDialog(void) { // The window's height will be resized later, to fit the explanation text. ConfDialog = CreateWindowClient(_("PLC Configuration"), 100, 100, 0, 0, MainWindow); ConfGrid = new QGridLayout(ConfDialog); MakeControls(); char buf[16]; sprintf(buf, "%.1f", (Prog.cycleTime / 1000.0)); CycleTextbox->setText(buf); sprintf(buf, "%.6f", Prog.mcuClock / 1e6); CrystalTextbox->setText(buf); sprintf(buf, "%d", Prog.baudRate); BaudTextbox->setText(buf); int ret = ConfDialog->exec(); switch(ret) { case QDialog::Accepted: { char buf[16]; strncpy(buf, CycleTextbox->text().toStdString().c_str(),16); Prog.cycleTime = (int)(1000*atof(buf) + 0.5); if(Prog.cycleTime == 0) { Error(_("Zero cycle time not valid; resetting to 10 ms.")); Prog.cycleTime = 10000; } strncpy(buf, CrystalTextbox->text().toStdString().c_str(),16); Prog.mcuClock = (int)(1e6*atof(buf) + 0.5); strncpy(buf, BaudTextbox->text().toStdString().c_str(),16); Prog.baudRate = atoi(buf); } break; case QDialog::Rejected: break; } // DestroyWindow(); /* GdkEventKey* event; ConfDialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(ConfDialog), "PLC Configuration"); gtk_window_set_default_size(GTK_WINDOW(ConfDialog), 200, 250); gtk_window_set_resizable (GTK_WINDOW (ConfDialog), FALSE); gtk_container_add(GTK_CONTAINER(ConfDialog), ConfPackingBox); gtk_widget_add_events (ConfDialog, GDK_KEY_PRESS_MASK); gtk_widget_add_events (ConfDialog, GDK_BUTTON_PRESS_MASK); char buf[16]; sprintf(buf, "%.1f", (Prog.cycleTime / 1000.0)); gtk_entry_set_text (GTK_ENTRY (CycleTextbox), buf); sprintf(buf, "%.6f", Prog.mcuClock / 1e6); gtk_entry_set_text (GTK_ENTRY (CrystalTextbox), buf); sprintf(buf, "%d", Prog.baudRate); gtk_entry_set_text (GTK_ENTRY (BaudTextbox), buf); gtk_widget_set_sensitive (MainWindow, FALSE); gtk_widget_grab_focus (OkButton); gtk_widget_set_state_flags (CycleTextbox, GTK_STATE_FLAG_FOCUSED, TRUE); gtk_widget_grab_focus (CycleTextbox); gtk_widget_show_all (ConfDialog); ConfDialogSignalCall(); return;*/ }