//----------------------------------------------------------------------------- // A little toolbar-style window that pops up to allow the user to set the // simulated value of an ADC pin. //----------------------------------------------------------------------------- void ShowAnalogSliderPopup(char *name) { WNDCLASSEX wc; memset(&wc, 0, sizeof(wc)); wc.cbSize = sizeof(wc); wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_OWNDC | CS_DBLCLKS; wc.lpfnWndProc = (WNDPROC)AnalogSliderDialogProc; wc.hInstance = Instance; wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW; wc.lpszClassName = "LDmicroAnalogSlider"; wc.lpszMenuName = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); RegisterClassEx(&wc); POINT pt; GetCursorPos(&pt); SWORD currentVal = GetAdcShadow(name); SWORD maxVal; if(Prog.mcu) { maxVal = Prog.mcu->adcMax; } else { maxVal = 1023; } if(maxVal == 0) { Error(_("No ADC or ADC not supported for selected micro.")); return; } int left = pt.x - 10; // try to put the slider directly under the cursor (though later we might // realize that that would put the popup off the screen) int top = pt.y - (15 + (73*currentVal)/maxVal); RECT r; SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); if(top + 110 >= r.bottom) { top = r.bottom - 110; } if(top < 0) top = 0; AnalogSliderMain = CreateWindowClient(0, "LDmicroAnalogSlider", "I/O Pin", WS_VISIBLE | WS_POPUP | WS_DLGFRAME, left, top, 30, 100, NULL, NULL, Instance, NULL); AnalogSliderTrackbar = CreateWindowEx(0, TRACKBAR_CLASS, "", WS_CHILD | TBS_AUTOTICKS | TBS_VERT | TBS_TOOLTIPS | WS_CLIPSIBLINGS | WS_VISIBLE, 0, 0, 30, 100, AnalogSliderMain, NULL, Instance, NULL); SendMessage(AnalogSliderTrackbar, TBM_SETRANGE, FALSE, MAKELONG(0, maxVal)); SendMessage(AnalogSliderTrackbar, TBM_SETTICFREQ, (maxVal + 1)/8, 0); SendMessage(AnalogSliderTrackbar, TBM_SETPOS, TRUE, currentVal); EnableWindow(MainWindow, FALSE); ShowWindow(AnalogSliderMain, TRUE); SetFocus(AnalogSliderTrackbar); DWORD ret; MSG msg; AnalogSliderDone = FALSE; AnalogSliderCancel = FALSE; SWORD orig = GetAdcShadow(name); while(!AnalogSliderDone && (ret = GetMessage(&msg, NULL, 0, 0))) { SWORD v = (SWORD)SendMessage(AnalogSliderTrackbar, TBM_GETPOS, 0, 0); if(msg.message == WM_KEYDOWN) { if(msg.wParam == VK_RETURN) { AnalogSliderDone = TRUE; break; } else if(msg.wParam == VK_ESCAPE) { AnalogSliderDone = TRUE; AnalogSliderCancel = TRUE; break; } } else if(msg.message == WM_LBUTTONUP) { if(v != orig) { AnalogSliderDone = TRUE; } } SetAdcShadow(name, v); TranslateMessage(&msg); DispatchMessage(&msg); } if(!AnalogSliderCancel) { SWORD v = (SWORD)SendMessage(AnalogSliderTrackbar, TBM_GETPOS, 0, 0); SetAdcShadow(name, v); } EnableWindow(MainWindow, TRUE); DestroyWindow(AnalogSliderMain); ListView_RedrawItems(IoList, 0, Prog.io.count - 1); }
//----------------------------------------------------------------------------- // Evaluate a circuit, calling ourselves recursively to evaluate if/else // constructs. Updates the on/off state of all the leaf elements in our // internal tables. Returns when it reaches an end if or an else construct, // or at the end of the program. //----------------------------------------------------------------------------- static void SimulateIntCode(void) { for(; IntPc < IntCodeLen; IntPc++) { IntOp *a = &IntCode[IntPc]; switch(a->op) { case INT_SIMULATE_NODE_STATE: if(*(a->poweredAfter) != SingleBitOn(a->name1)) NeedRedraw = TRUE; *(a->poweredAfter) = SingleBitOn(a->name1); break; case INT_SET_BIT: SetSingleBit(a->name1, TRUE); break; case INT_CLEAR_BIT: SetSingleBit(a->name1, FALSE); break; case INT_COPY_BIT_TO_BIT: SetSingleBit(a->name1, SingleBitOn(a->name2)); break; case INT_SET_VARIABLE_TO_LITERAL: if(GetSimulationVariable(a->name1) != a->literal && a->name1[0] != '$') { NeedRedraw = TRUE; } SetSimulationVariable(a->name1, a->literal); break; case INT_READ_SFR_LITERAL: case INT_WRITE_SFR_LITERAL: case INT_SET_SFR_LITERAL: case INT_CLEAR_SFR_LITERAL: case INT_TEST_SFR_LITERAL: case INT_READ_SFR_VARIABLE: case INT_WRITE_SFR_VARIABLE: case INT_SET_SFR_VARIABLE: case INT_CLEAR_SFR_VARIABLE: case INT_TEST_SFR_VARIABLE: case INT_TEST_C_SFR_LITERAL: case INT_WRITE_SFR_LITERAL_L: case INT_WRITE_SFR_VARIABLE_L: case INT_SET_SFR_LITERAL_L: case INT_SET_SFR_VARIABLE_L: case INT_CLEAR_SFR_LITERAL_L: case INT_CLEAR_SFR_VARIABLE_L: case INT_TEST_SFR_LITERAL_L: case INT_TEST_SFR_VARIABLE_L: case INT_TEST_C_SFR_VARIABLE: case INT_TEST_C_SFR_LITERAL_L: case INT_TEST_C_SFR_VARIABLE_L: break; case INT_SET_VARIABLE_TO_VARIABLE: if(GetSimulationVariable(a->name1) != GetSimulationVariable(a->name2)) { NeedRedraw = TRUE; } SetSimulationVariable(a->name1, GetSimulationVariable(a->name2)); break; case INT_INCREMENT_VARIABLE: IncrementVariable(a->name1); break; { SWORD v; case INT_SET_VARIABLE_ADD: v = GetSimulationVariable(a->name2) + GetSimulationVariable(a->name3); goto math; case INT_SET_VARIABLE_SUBTRACT: v = GetSimulationVariable(a->name2) - GetSimulationVariable(a->name3); goto math; case INT_SET_VARIABLE_MULTIPLY: v = GetSimulationVariable(a->name2) * GetSimulationVariable(a->name3); goto math; case INT_SET_VARIABLE_DIVIDE: if(GetSimulationVariable(a->name3) != 0) { v = GetSimulationVariable(a->name2) / GetSimulationVariable(a->name3); } else { v = 0; Error(_("Division by zero; halting simulation")); StopSimulation(); } goto math; math: if(GetSimulationVariable(a->name1) != v) { NeedRedraw = TRUE; SetSimulationVariable(a->name1, v); } break; } #define IF_BODY \ { \ IfConditionTrue(); \ } else { \ IfConditionFalse(); \ } case INT_IF_BIT_SET: if(SingleBitOn(a->name1)) IF_BODY break; case INT_IF_BIT_CLEAR: if(!SingleBitOn(a->name1)) IF_BODY break; case INT_IF_VARIABLE_LES_LITERAL: if(GetSimulationVariable(a->name1) < a->literal) IF_BODY break; case INT_IF_VARIABLE_EQUALS_VARIABLE: if(GetSimulationVariable(a->name1) == GetSimulationVariable(a->name2)) IF_BODY break; case INT_IF_VARIABLE_GRT_VARIABLE: if(GetSimulationVariable(a->name1) > GetSimulationVariable(a->name2)) IF_BODY break; case INT_SET_PWM: // Dummy call will cause a warning if no one ever assigned // to that variable. (void)GetSimulationVariable(a->name1); break; // Don't try to simulate the EEPROM stuff: just hold the EEPROM // busy all the time, so that the program never does anything // with it. case INT_EEPROM_BUSY_CHECK: SetSingleBit(a->name1, TRUE); break; case INT_EEPROM_READ: case INT_EEPROM_WRITE: oops(); break; case INT_READ_ADC: // Keep the shadow copies of the ADC variables because in // the real device they will not be updated until an actual // read is performed, which occurs only for a true rung-in // condition there. SetSimulationVariable(a->name1, GetAdcShadow(a->name1)); break; case INT_UART_SEND: if(SingleBitOn(a->name2) && (SimulateUartTxCountdown == 0)) { SimulateUartTxCountdown = 2; AppendToUartSimulationTextControl( (BYTE)GetSimulationVariable(a->name1)); } if(SimulateUartTxCountdown == 0) { SetSingleBit(a->name2, FALSE); } else { SetSingleBit(a->name2, TRUE); } break; case INT_UART_RECV: if(QueuedUartCharacter >= 0) { SetSingleBit(a->name2, TRUE); SetSimulationVariable(a->name1, (SWORD)QueuedUartCharacter); QueuedUartCharacter = -1; } else { SetSingleBit(a->name2, FALSE); } break; case INT_END_IF: case INT_ELSE: return; case INT_COMMENT: break; default: oops(); break; } } }