A simple oscilloscope using Adafruit 2.8" TFT with touch. Runs on FRDM-KL25Z, FRDM-K22F, FRDM-K64F, NUCLEO-F411RE. 2 channel analog inputs with 4 trigger modes and time division.
Dependencies: SPI_STMPE610 UniGraphic mbed vt100
My first attempt of implementing an oscilloscope using FRDM-KL25Z and Adafruit 2.8" TFT with touch.
FRDM-KL25Z と Adafruit 2.8" TFT with touch を使用して作ってみた最初のオシロスコープです。
On 25-Sep-2017, wrong calculation of trigger pos/val fixed.
On 25-Nov-2015, FRDM-K64F and NUCLEO-F411RE platforms were added.
On 26-Nov-2015, FRDM-K22F is added (tested).
Note: Now ch2 is A2 instead of A1!
25-Sep-2017, トリガー値と位置の計算の誤りを修正しました。
25-Nov-2015, FRDM-K64F と NUCLEO-F411RE でも動くようになりました。
26-Nov-2015, FRDM-K22F でも動作確認が出来ました。
※一身上の都合で、アナログ入力の ch2 は A1 から A2 に変更しましたので、ご注意ください。m(_ _)m
This supports two analog inputs A0 for channel 1 and A2 for channel 2
and four trigger modes (NONE, RISE, FALL, LEVEL),
time division is 30us to 20ms per pixel which will make 300us/div to 200.0ms/div (as 10 pixels per div)
A0と A2 のアナログ2入力にて、
4種類のトリガーモード(NONE: フリーラン RISE: 立ち上がりエッジ、FALL: 立下りエッジ、LEVEL: レベル) 。
サンプリングは30us から 20ms, チャートの1メモリが10ピクセルなので、300us/dev から 200.0ms/div となっています。
The analog signals and gnd was picked at the pins in the picture above.
Note: now you need to pick A0 and A2 instead of A0 and A1.
信号は上記の写真のように、Adafruit のピンからつまみました。
変更により、A0とA2が入力となります。
When powered on or reset, the program starts in Trigger Mode = NONE (Free Run Mode)
電源投入、リセット後 プログラムはトリガーモード NONE (フリーランモード) で起動します。
To change trigger mode and/or time division, press run/stop button.
トリガーモードを変えたり、サンプリング時間を変えるのには run/stop ボタンを押してください。
Each time you push Trig button, the trigger mode changes
NONE -> RISE -> FALL -> LEVEL ( -> NONE).
トリガーボタンを押すたびにトリガーモードは
NONE(フリーラン) -> RISE (立ち上がりエッジ) -> FALL (立下りエッジ) -> LEVEL (レベル)
と変化します。
When trigger mode is not NONE,
to specify the trigger position, level and channel, push inside the wave frame.
Then green trigger marks will be shown and value of trigger position and voltage will be printed.
トリガーモードが NONE でないときに、チャネルの枠内をタッチしますと、
その位置がトリガーのポジション、レベル、チャネルになります。
そして、緑色のトリガーマークが表示され、下部にはトリガーの具体的なポジションとボルテージが表示されます。
To change time division push
"1/2" to Zoom Out (sampling interval will be bigger) or
"x2" to Zoom In (Sampling interval will be smaller).
サンプリングタイムを変更するのには
"1/2" ズームアウト (サンプリング間隔が長くなります) か
"x2" ズームイン (サンプリング間隔が短くなります。) を押してください。
On 7-Mar-2015 updated to UniGraphic library version!
2015年3月7日 UniGraphic ライブラリ使用版にアップデートしました。
FRDM-KL25Z
FRDM-K64F
NUCLEO-F411RE
Revision 0:2b9a6c5fcd52, committed 2015-01-10
- Comitter:
- Rhyme
- Date:
- Sat Jan 10 15:08:38 2015 +0000
- Child:
- 1:14b6ffd807f6
- Commit message:
- commit before publish
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SPI_STMPE610.lib Sat Jan 10 15:08:38 2015 +0000 @@ -0,0 +1,1 @@ +SPI_STMPE610#55c757e043f0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SPI_TFT_ILI9341.lib Sat Jan 10 15:08:38 2015 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/Rhyme/code/SPI_TFT_ILI9341/#61fa73a34834
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/TFTMenu.cpp Sat Jan 10 15:08:38 2015 +0000
@@ -0,0 +1,178 @@
+/** mbed oscilloscope my implementation of a oscillo scope
+ * Copyright (c) 2014, 2015 Motoo Tanaka @ Design Methodology Lab
+ *
+ * TFTMenu.cpp
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "mbed.h"
+#include "SPI_TFT_ILI9341.h"
+#include "SPI_STMPE610.h"
+#include "Arial12x12.h"
+#include "Arial24x23.h"
+#include "Arial28x28.h"
+#include "font_big.h"
+#include "vt100.h"
+#include <string.h>
+
+#include "TFTMenu.h"
+
+extern SPI_TFT_ILI9341 TFT ;
+extern SPI_STMPE610 TSC ;
+extern vt100 *tty ;
+
+
+TFTMenuItem::TFTMenuItem(int x1, int y1, int x2, int y2, FuncPtr fnc,
+ char *name, uint16_t mcolor, uint16_t fcolor )
+{
+ left = x1 ;
+ right = x2 ;
+ top = y1 ;
+ bottom = y2 ;
+ if (name) {
+ label = new char[strlen(name)+1] ;
+ strcpy(label, name) ;
+ font_color = fcolor ;
+ }
+ menu_color = mcolor ;
+
+ left_margin = 7 ;
+ top_margin = 10 ;
+ func = fnc ;
+}
+
+TFTMenuItem::~TFTMenuItem()
+{
+ left = 0 ;
+ right = 0 ;
+ top = 0 ;
+ bottom = 0 ;
+ if (label) {
+ free(label) ;
+ }
+}
+
+TFTRadioButton::TFTRadioButton(int x1, int y1, int x2, int y2, FuncPtr fnc,
+ char *name, uint16_t mcolor, uint16_t fcolor,
+ char *altname, uint16_t altmcolor, uint16_t altfcolor,
+ bool sel) : TFTMenuItem(x1,y1,x2,y2,fnc,name,mcolor,fcolor)
+{
+ if (altname) {
+ alt_label = new char[strlen(altname) + 1] ;
+ strcpy(alt_label, altname) ;
+ } else {
+ alt_label = 0 ;
+ }
+ alt_font_color = altfcolor ;
+ alt_menu_color = altmcolor ;
+ selected = sel ;
+}
+
+TFTRadioButton::~TFTRadioButton()
+{
+ left = 0 ;
+ right = 0 ;
+ top = 0 ;
+ bottom = 0 ;
+ if (label) {
+ delete label ;
+ }
+ if (alt_label) {
+ delete alt_label ;
+ }
+}
+
+bool TFTRadioButton::hit(int x, int y)
+{
+ bool result = false ;
+ if ((left <= x)&&(x <= right)&&(top <= y)&&(y <= bottom)) {
+ result = true ;
+ if (selected) {
+ selected = false ;
+ } else {
+ selected = true ;
+ }
+ draw() ;
+ }
+ return( result ) ;
+}
+
+void TFTRadioButton::select(bool value)
+{
+ selected = value ;
+}
+
+uint16_t TFTMenuItem::getColor(void)
+{
+ return(menu_color) ;
+}
+
+bool TFTMenuItem::hit(int x, int y)
+{
+ bool result = false ;
+ if ((left <= x)&&(x <= right)&&(top <= y)&&(y <= bottom)) {
+ result = true ;
+ draw() ;
+ }
+// draw() ;
+ return( result ) ;
+}
+
+void TFTMenuItem::doIt(void)
+{
+ if (func) {
+ func() ;
+ }
+}
+
+void TFTMenuItem::draw(int offset_x, int offset_y)
+{
+ TFT.fillrect(left+offset_x, top+offset_y, right+offset_x, bottom+offset_y, Black) ;
+ TFT.fillrect(left+offset_x, top+offset_y, right+offset_x, bottom+offset_y, menu_color) ;
+ wait(0.1) ;
+ TFT.locate(left+offset_x+left_margin, top+offset_y+top_margin) ;
+ TFT.foreground(font_color) ;
+ TFT.background(menu_color) ;
+ TFT.set_font((unsigned char *)Arial12x12) ;
+ wait(0.1) ;
+ TFT.printf(label) ;
+}
+
+void TFTRadioButton::draw(int offset_x, int offset_y)
+{
+ if (selected) {
+ TFT.fillrect(left+offset_x, top+offset_y, right+offset_x, bottom+offset_y, Black) ;
+ TFT.fillrect(left+offset_x, top+offset_y, right+offset_x, bottom+offset_y, alt_menu_color) ;
+ wait(0.1) ;
+ TFT.locate(left+offset_x+left_margin, top+offset_y+top_margin) ;
+ TFT.foreground(alt_font_color) ;
+ TFT.background(alt_menu_color) ;
+ TFT.set_font((unsigned char *)Arial12x12) ;
+ wait(0.1) ;
+ TFT.printf(alt_label) ;
+ } else {
+ TFTMenuItem::draw(offset_x, offset_y) ;
+ }
+}
+
+
+void TFTMenuItem::highlight(int offset_x, int offset_y)
+{
+ TFT.rect(left+offset_x, top+offset_y, right+offset_x, bottom+offset_y, font_color) ;
+/*
+ TFT.fillrect(left+offset_x, top+offset_y, right+offset_x, bottom+offset_y, font_color) ;
+ wait(0.1) ;
+ TFT.locate(left+offset_x+left_margin, top+offset_y+top_margin) ;
+ TFT.foreground(menu_color) ;
+ TFT.background(font_color) ;
+ TFT.set_font((unsigned char *)Arial12x12) ;
+ wait(0.1) ;
+ TFT.printf(label) ;
+*/
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/TFTMenu.h Sat Jan 10 15:08:38 2015 +0000
@@ -0,0 +1,73 @@
+/** mbed oscilloscope my implementation of a oscillo scope
+ * Copyright (c) 2014, 2015 Motoo Tanaka @ Design Methodology Lab
+ *
+ * TFTMenu.h
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef _TFT_MENU_H_
+#define _TFT_MENU_H_ defined
+
+typedef void (*FuncPtr)(void) ;
+
+class TFTMenuItem {
+public:
+TFTMenuItem(int x1, int y1, int x2, int y2, FuncPtr fnc,
+ char *name, uint16_t mc, uint16_t fc) ;
+~TFTMenuItem() ;
+virtual bool hit(int x, int y) ;
+virtual void draw(int offset_x = 0, int offset_y = 0) ;
+void highlight(int offset_x = 0, int offset_y = 0) ;
+uint16_t getColor(void) ;
+void doIt(void) ;
+
+protected:
+char *label ;
+uint16_t font_color ;
+uint16_t menu_color ;
+int top ;
+int bottom ;
+int left ;
+int right ;
+int left_margin ;
+int top_margin ;
+FuncPtr func ;
+private:
+} ;
+
+class TFTRadioButton : public TFTMenuItem {
+public:
+TFTRadioButton(int x1, int y1, int x2, int y2, FuncPtr fnc,
+ char *name, uint16_t mc, uint16_t fc,
+ char *altname = 0, uint16_t altmc = 0, uint16_t altfc = 0,
+ bool sel = false) ;
+~TFTRadioButton() ;
+
+virtual bool hit(int x, int y) ;
+virtual void draw(int offset_x = 0, int offset_y = 0) ;
+
+void select(bool value) ;
+
+protected:
+bool selected ;
+char *alt_label ;
+uint16_t alt_font_color ;
+uint16_t alt_menu_color ;
+// FuncPtr alt_func ;
+private:
+} ;
+
+class TFTMenu {
+public:
+TFTMenu() ; // constructor
+~TFTMenu() ; // destructor
+private:
+} ;
+
+#endif /* _TFT_MENU_H_ */
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TFT_fonts.lib Sat Jan 10 15:08:38 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/dreschpe/code/TFT_fonts/#76774250fcec
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Sat Jan 10 15:08:38 2015 +0000
@@ -0,0 +1,287 @@
+/** mbed oscilloscope my implementation of a oscillo scope
+ * Copyright (c) 2014, 2015 Motoo Tanaka @ Design Methodology Lab
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "mbed.h"
+#include "SPI_TFT_ILI9341.h"
+#include "SPI_STMPE610.h"
+#include "Arial12x12.h"
+#include "Arial24x23.h"
+#include "Arial28x28.h"
+#include "font_big.h"
+#include "vt100.h"
+#include "TFTMenu.h"
+#include "menu.h"
+#include "trig.h"
+#include "view.h"
+#include "main.h"
+
+vt100 tty ;
+AnalogIn *ach[NUM_MAX_ANALOG_CH] ;
+Ticker timer ;
+
+DigitalOut backlight(PTA12) ;
+SPI_TFT_ILI9341 TFT(PIN_MOSI, PIN_MISO, PIN_SCLK, PIN_CS_TFT, PIN_BL_TFT, PIN_DC_TFT) ;
+SPI_STMPE610 TSC(PIN_MOSI, PIN_MISO, PIN_SCLK, PIN_CS_TSC) ;
+TFTMenuItem *menu[NUM_MAX_MENU] ;
+int numMenu = 0 ;
+
+float vref = 3.28 ; // input range 0 - 3.3V
+uint16_t udata[2][NUM_MAX_ANALOG_CH][CHART_LEN] ; // data storage ;
+uint16_t bor[2] = {0, 0} ; // begin of ring buffer
+int data_index = 0 ;
+int numAnalogIn = 2 ;
+int memLength = CHART_LEN ;
+int us_interval = MIN_INTERVAL ; // 20us = 50KHz
+bool frame_full = false ;
+int page = 0 ; //
+int prev_page = 0 ;
+int mode = MODE_RUN ;
+
+void sampleAD(void) ;
+void drawMenu(void) ;
+// void eraseGraphFrames(void) ;
+
+/**
+ * u2v unsigned int data value to voltage conversion
+ */
+float u2v(uint16_t uvalue)
+{
+ return( vref * (float)uvalue / 65535.0 ) ;
+}
+
+/**
+ * v2u voltage to unsigned int data conversion
+ */
+uint16_t v2u(float voltage)
+{
+ return(0xFFFF * voltage / vref) ;
+}
+
+/**
+ * u2f unsigned int to float (0 - 1.0) conversion
+ */
+float u2f(uint16_t value)
+{
+ return( (float)value / 65535.0 ) ;
+}
+
+void initADC(void)
+{
+ if (numAnalogIn > 0) {
+ ach[0] = new AnalogIn(PTB0) ;
+ }
+ if (numAnalogIn > 1) {
+ ach[1] = new AnalogIn(PTB1) ;
+ }
+
+ ADC0->CFG1 = ADC0->CFG1 & (
+ ~(
+ 0x80 // LDLPC = 0 ; no low-power mode
+ | 0x60 // ADIV = 1
+ | 0x10 // Sample time short
+ | 0x03 // input clock = BUS CLK
+ )
+ ) ; // clkdiv <= 1
+ ADC0->CFG2 = ADC0->CFG2
+ | 0x03 ; // Logsample Time 11 = 2 extra ADCK
+ ADC0->SC3 = ADC0->SC3
+ & (~(0x03)) ; // hardware avarage off
+}
+
+void envChanged(void)
+{
+ timer.detach() ;
+
+ eraseGraphFrames() ;
+ drawGraphFrames() ;
+
+ data_index = 0 ;
+ page = 0 ;
+ prev_page = 0 ;
+ frame_full = false ;
+ if (trig_mode == TRIG_MODE_NONE) {
+ sampling_status = ST_TRIG_HIT ;
+ post_trig_index = 0 ;
+ } else {
+ sampling_status = ST_PRE_TRIG ;
+ }
+/*
+ if (mode == MODE_RUN) {
+ timer.attach_us(&sampleAD, us_interval) ;
+ }
+*/
+}
+
+bool checkTrigger(void)
+{
+ bool result = false ;
+ int prev_index ;
+ uint16_t current, prev ;
+ if (data_index > 0) {
+ prev_index = data_index - 1 ;
+ } else {
+ prev_index = memLength - 1 ; // memLength - 1 ;
+ }
+ current = udata[page][trig_ch][data_index] ;
+ prev = udata[page][trig_ch][prev_index] ;
+
+ switch(trig_mode) {
+ case TRIG_MODE_NONE: // no trigger, return true at the beggining
+ trig_index = 0 ;
+ result = true ;
+ break ;
+ case TRIG_MODE_RISE:
+ if ((prev < utrig_level)&&(utrig_level <= current)) {
+ result = true ;
+ }
+ break ;
+ case TRIG_MODE_FALL:
+ if ((prev > utrig_level)&&(utrig_level >= current)) {
+ result = true ;
+ }
+ break ;
+ case TRIG_MODE_LEVEL:
+ if (current > trig_level_margin) {
+ if (((current + trig_level_margin) >= utrig_level)&&(utrig_level >= (current - trig_level_margin))) {
+ result = true ;
+ }
+ } else {
+ if ((current + trig_level_margin) >= utrig_level) {
+ result = true ;
+ }
+ }
+ break ;
+ default:
+ printf("Error: Unknown trigger mode %d\n", trig_mode) ;
+ break ;
+ }
+ return( result ) ;
+}
+
+void sampleAD(void)
+{
+ if (frame_full) {
+ return ;
+ }
+// timer.detach() ;
+ for (int i = 0 ; i < numAnalogIn ; i++ ) {
+ udata[page][i][data_index] = ach[i]->read_u16() ;
+ }
+// timer.attach_us(&sampleAD, us_interval) ;
+ switch(sampling_status) {
+ case ST_PRE_TRIG:
+ if (data_index >= trig_pos) {
+ sampling_status = ST_TRIG_WAIT ;
+ } else {
+ data_index = (data_index + 1) % memLength ;
+ }
+ break ;
+ case ST_TRIG_WAIT:
+ if (checkTrigger()) {
+ trig_index = data_index ;
+ post_trig_index = 0 ;
+ sampling_status = ST_TRIG_HIT ;
+ } else {
+ data_index = (data_index + 1) % memLength ;
+ }
+ break ;
+ case ST_TRIG_HIT:
+ post_trig_index++ ;
+ if (post_trig_index >= post_trig_len) {
+ sampling_status = ST_BUF_FULL ;
+ frame_full = true ;
+ bor[page] = (memLength + trig_index - trig_pos) % memLength ;
+ post_trig_index = 0 ;
+ data_index = 0 ;
+ } else {
+ data_index = (data_index + 1) % memLength ;
+ }
+ break ;
+ case ST_BUF_FULL:
+ printf("mode = ST_BUF_FULL\n\r") ;
+ break ;
+ default:
+ printf("unknown sample status %d\n", sampling_status) ;
+ break ;
+ }
+}
+
+
+bool doTrigValue(int x, int y)
+{
+ int i, y_offset ;
+ bool result = false ;
+ for (i = 0 ; i < numAnalogIn ; i++ ) {
+ if (inChFrame(i, x, y)) {
+ result = true ;
+ trig_ch = i ;
+ trig_pos = x - left_margin;
+ post_trig_len = memLength - trig_pos ;
+ y_offset = head_h + (pane_h + 5) * i + 1;
+ trig_level = vref *(1 - ((float)(y - y_offset) / (float)(pane_h - 2))) ;
+ if (trig_level > vref) {
+ trig_level = vref ;
+ } else if (trig_level < 0.0) {
+ trig_level = 0.0 ;
+ }
+ utrig_level = v2u( trig_level ) ;
+ break ;
+ }
+ }
+ return( result ) ;
+}
+
+void hello()
+{
+ printf("=== simple oscilloscope ===\n\r") ;
+ printf("built: %s\n\r",__DATE__) ;
+}
+
+int main()
+{
+ int touched ;
+ uint16_t x, y ;
+ bool result ;
+ tty.cls() ;
+ backlight = 0 ;
+ initTFT() ;
+ initADC() ;
+ initMenu() ;
+
+ us_interval = MIN_INTERVAL ;
+
+ drawGraphFrames() ;
+ drawMenu() ;
+
+ backlight = 1 ;
+ hello() ;
+ timer.attach_us(&sampleAD, us_interval) ;
+
+ while(1) {
+ drawChart() ;
+ touched = TSC.getPoint(&x, &y) ;
+ if (touched) {
+ timer.detach() ;
+ result = doMenu(x, y) ;
+ if (result != true) {
+ result = doTrigValue(x, y) ;
+ if (result) {
+ drawTrigMark() ;
+ printTrigMode() ;
+ }
+ }
+ if (mode == MODE_RUN) {
+ timer.attach_us(&sampleAD, us_interval) ;
+ }
+ }
+ wait(0.1) ;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.h Sat Jan 10 15:08:38 2015 +0000 @@ -0,0 +1,68 @@ +/** mbed oscilloscope my implementation of a oscillo scope + * Copyright (c) 2014, 2015 Motoo Tanaka @ Design Methodology Lab + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef _MAIN_H_ +#define _MAIN_H_ inluded + +#define PIN_MOSI PTD2 +#define PIN_MISO PTD3 +#define PIN_SCLK PTD1 +#define PIN_CS_TFT PTD0 +#define PIN_DC_TFT PTD5 +#define PIN_BL_TFT PTC9 +#define PIN_CS_SD PTA4 +#define PIN_CS_TSC PTA13 +#define PIN_TSC_INTR PTC9 + +#define CHART_LEN 198 + +// NOTE: in case MIN_INTERVAL is too small +// the program hangs during ADC and timer interrupt +#define MIN_INTERVAL 30 +#define MAX_INTERVAL 20000 +#define NUM_MAX_MENU 20 +#define NUM_MAX_ANALOG_CH 2 +#define MODE_RUN 1 +#define MODE_STOP 0 + +extern vt100 tty ; +extern AnalogIn *ach[] ; +extern Ticker timer ; + +extern DigitalOut backlight ; +extern SPI_TFT_ILI9341 TFT ; +extern SPI_STMPE610 TSC ; +extern TFTMenuItem *menu[] ; +extern int numMenu ; + +extern float vref ; // input range 0 - 3.3V + +extern uint16_t udata[2][NUM_MAX_ANALOG_CH][CHART_LEN] ; +extern int data_index ; +extern uint16_t bor[2] ; // begin of ring buffer + +extern int numAnalogIn ; +extern int memLength ; +extern int us_interval ; // 20us = 50KHz +extern bool frame_full ; +extern int page ; // +extern int prev_page ; +extern int mode ; + +float u2v(uint16_t uvalue) ; +uint16_t v2u(float voltage) ; +float u2f(uint16_t value) ; + +void initADC(void) ; +void envChanged(void) ; +bool checkTrigger(void) ; +void sampleAD(void) ; +#endif /* _MAIN_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sat Jan 10 15:08:38 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/4fc01daae5a5 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/menu.cpp Sat Jan 10 15:08:38 2015 +0000
@@ -0,0 +1,155 @@
+/** mbed oscilloscope my implementation of a oscillo scope
+ * Copyright (c) 2014, 2015 Motoo Tanaka @ Design Methodology Lab
+ *
+ * menu.cpp
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "mbed.h"
+#include "SPI_TFT_ILI9341.h"
+#include "SPI_STMPE610.h"
+#include "Arial12x12.h"
+#include "Arial24x23.h"
+#include "Arial28x28.h"
+#include "font_big.h"
+#include "vt100.h"
+#include "TFTMenu.h"
+#include "menu.h"
+#include "trig.h"
+#include "view.h"
+#include "main.h"
+
+void doubleTime(void)
+{
+ if (mode == MODE_RUN) {
+ timer.detach() ;
+ }
+ envChanged() ;
+ us_interval *= 2 ;
+ if (us_interval > MAX_INTERVAL) {
+ us_interval = MAX_INTERVAL ;
+ }
+ printTimeDiv() ;
+ if (mode == MODE_RUN) {
+ timer.attach_us(&sampleAD, us_interval) ;
+ }
+}
+
+void halfTime(void)
+{
+ if (mode == MODE_RUN) {
+ timer.detach() ;
+ }
+ envChanged() ;
+ us_interval /= 2 ;
+ if (us_interval < MIN_INTERVAL) {
+ us_interval = MIN_INTERVAL ;
+ }
+ printTimeDiv() ;
+ if (mode == MODE_RUN) {
+ timer.attach_us(&sampleAD, us_interval) ;
+ }
+}
+
+void doStart(void)
+{
+ if (mode == MODE_RUN) {
+ mode = MODE_STOP ;
+ timer.detach() ;
+ printMode() ;
+ } else {
+ mode = MODE_RUN ;
+ printMode() ;
+ timer.attach_us(&sampleAD, us_interval) ;
+ }
+
+}
+
+void doubleAmp(void)
+{
+}
+
+void halfAmp(void)
+{
+}
+
+void doTrigger(void)
+{
+ trig_mode = (trig_mode + 1) % NUM_TRIG_MODE ;
+ drawTrigMark() ;
+ printTrigMode() ;
+}
+
+void doStop(void)
+{
+ timer.detach() ;
+ mode = MODE_STOP ;
+ printMode() ;
+}
+
+void TrigLevelDown(void)
+{
+ trig_level -= 0.1 ;
+ if (trig_level < 0.0) {
+ trig_level = 0.0 ;
+ }
+ printTrigLevel() ;
+}
+
+void TrigLevelUp(void)
+{
+ trig_level += 0.1 ;
+ if (trig_level > vref) {
+ trig_level = vref ;
+ }
+ printTrigLevel() ;
+}
+
+void initMenu(void)
+{
+ numMenu = 0 ;
+ menu[numMenu++] = new TFTRadioButton( 20, 190, 60, 220, doStart, "Run", Blue, White, "Stop", Red, White, true) ;
+ // menu[numMenu++] = new TFTMenuItem(180, 180, 220, 210, doStop, "Stop", Red, White) ;
+ menu[numMenu++] = new TFTMenuItem( 20, 230, 55, 260, doubleTime, "1/2", Blue, White) ;
+ menu[numMenu++] = new TFTMenuItem(180, 230, 215, 260, halfTime, "x2", Blue, White) ;
+ menu[numMenu++] = new TFTMenuItem( 20, 270, 60, 300, doTrigger, "Trig", Green, Black) ;
+// menu[numMenu++] = new TFTMenuItem(170, 260, 190, 290, TrigLevelUp, "^", Blue, White) ;
+// menu[numMenu++] = new TFTMenuItem(200, 260, 220, 290, TrigLevelDown, "V", Blue, White) ;
+
+}
+
+void drawMenu(void)
+{
+ for (int i = 0 ; i < numMenu ; i++ ) {
+ menu[i]->draw() ;
+ }
+ printMode() ;
+ printTimeDiv() ;
+ printTrigMode() ;
+}
+
+bool doMenu(uint16_t x, uint16_t y)
+{
+ bool result = false ;
+/*
+ if ((x == 0)&&(y ==0)) {
+ return
+ }
+*/
+ for (int i = 0 ; i < numMenu ; i++ ) {
+ if (menu[i]->hit(x, y)) {
+// menu[i]->highlight() ;
+ menu[i]->doIt() ;
+ menu[i]->draw() ;
+ result = true ;
+ break ;
+ }
+ }
+ return( result ) ;
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menu.h Sat Jan 10 15:08:38 2015 +0000 @@ -0,0 +1,27 @@ +/** mbed oscilloscope my implementation of a oscillo scope + * Copyright (c) 2014, 2015 Motoo Tanaka @ Design Methodology Lab + * + * menu.h + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef _MENU_H_ +#define _MENU_H_ included + +void doubleTime(void) ; +void halfTime(void) ; +void doubleAmp(void) ; +void halfAmp(void) ; +void doTrigger(void) ; +void doStart(void) ; +void doStop(void) ; +void initMenu(void) ; +void drawMenu(void) ; +bool doMenu(uint16_t x, uint16_t y) ; +#endif /* _MENU_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/trig.cpp Sat Jan 10 15:08:38 2015 +0000
@@ -0,0 +1,28 @@
+/** mbed oscilloscope my implementation of a oscillo scope
+ * Copyright (c) 2014, 2015 Motoo Tanaka @ Design Methodology Lab
+ *
+ * trig.cpp
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "trig.h"
+
+// trigger related values
+int trig_mode = TRIG_MODE_NONE ;
+int sampling_status = ST_TRIG_HIT ;
+int trig_ch = 0 ;
+int trig_pos = 0 ;
+int post_trig_len = memLength ;
+float trig_level = 0.0 ;
+uint16_t utrig_level = 0 ;
+int trig_index = 0 ;
+int post_trig_index = 0 ;
+int trig_level_margin = 100 ;
+
+char *trig_name[] = { " NONE ", " RISE ", " FALL ", " LEVEL" } ;
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trig.h Sat Jan 10 15:08:38 2015 +0000 @@ -0,0 +1,82 @@ +/** mbed oscilloscope my implementation of a oscillo scope + * Copyright (c) 2014, 2015 Motoo Tanaka @ Design Methodology Lab + * + * trig.h + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* + * About the ring buffer and trigger + * + * use data memory of memLength as a ring buffer + * trig_pos: the trigger position on the display + * trig_index: the data index where the trigger hit + * bor: begin of ring_buffer + * eor: end of ring_buffer (do we really need this?) + * data_index: the data index of current data sampling + * + * Display = absolute memory placement + * +-+----------------+--------+-----------+-----------+ + * |0| |trig_pos| |memLength-1| + * +-+----------------+--------+-----------+-----------+ + * if trig_pos == trig_index + * 0 + * +---+--------------+----------+-----------------+---+ + * |bor| |trig_index| |eor| + * +---+--------------+----------+-----------------+---+ + * if trig_pos > trig_index + * 0 + * +---+--------------+----------+-----------------+---+ + * |bor| |trig_index| |eor| + * +---+--------------+----------+-----------------+---+ + * if trig_pos < trig_index + * 0 0 + * +---+--------------+----------+-----------------+---+ + * |bor| |trig_index| |eor| + * +---+--------------+----------+-----------------+---+ + * the buffer length = memLength ; + * status(s) + * 0: pre_trigger: for the beginning of sampling, before trig_pos + * 1: trigger_wait: if check_trigger() move to trigger_hit + * 2: tigger_hit: trigger has been hit, sampling data till data_full + * 3: buffer_full: stop sampling and wait for the data to be consumed + */ +#ifndef _TRIG_H_ +#define _TRIG_H_ defined +#include "mbed.h" + +// Trigger modes +#define TRIG_MODE_NONE 0 +#define TRIG_MODE_RISE 1 +#define TRIG_MODE_FALL 2 +#define TRIG_MODE_LEVEL 3 +#define NUM_TRIG_MODE 4 + +// ST: Sampling Status +#define ST_PRE_TRIG 0 +#define ST_TRIG_WAIT 1 +#define ST_TRIG_HIT 2 +#define ST_BUF_FULL 3 + +// trigger related values +extern int sampling_status ; +extern int trig_mode ; +extern int trig_ch ; +extern int trig_pos ; +extern float trig_level ; +extern uint16_t utrig_level ; +extern int trig_index ; +extern int post_trig_index ; +extern int post_trig_len ; // length between trig_pos to end of display +extern int trig_level_margin ; +extern int memLength ; + +extern char *trig_name[] ; + +#endif /* _TRIG_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/view.cpp Sat Jan 10 15:08:38 2015 +0000
@@ -0,0 +1,320 @@
+/** mbed oscilloscope my implementation of a oscillo scope
+ * Copyright (c) 2014, 2015 Motoo Tanaka @ Design Methodology Lab
+ *
+ * view.cpp
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "mbed.h"
+#include "SPI_TFT_ILI9341.h"
+#include "SPI_STMPE610.h"
+#include "Arial12x12.h"
+#include "Arial24x23.h"
+#include "Arial28x28.h"
+#include "font_big.h"
+#include "vt100.h"
+#include "TFTMenu.h"
+#include "main.h"
+#include "trig.h"
+#include "view.h"
+
+int pane_w = 200 ;
+int pane_h = 70 ; // height per channel
+int head_h = 20 ; // header height
+int foot_h = 20 ; // footer height
+int right_margin = 10 ;
+int left_margin = 30 ;
+
+void initTFT(void)
+{
+ //Configure the display driver
+ TFT.background(Black);
+ TFT.foreground(White);
+ wait(0.01) ;
+ TFT.cls();
+}
+
+
+void eraseChFrame(int ch)
+{
+ int x1, x2, y1, y2 ;
+ x1 = left_margin ;
+ x2 = left_margin + pane_w ;
+ y1 = head_h + (pane_h + 5) * ch ;
+ y2 = y1 + pane_h ;
+ TFT.fillrect(x1,y1,x2, y2, Black) ;
+}
+
+void eraseGraphFrames(void)
+{
+ int ch ;
+ for (ch = 0 ; ch < numAnalogIn ; ch++) {
+ eraseChFrame(ch) ;
+ }
+}
+
+void drawChFrame(int ch)
+{
+ int x1, x2, y1, y2,y_offset ;
+ x1 = left_margin ;
+ x2 = left_margin + pane_w ;
+ y1 = head_h + (pane_h + 5) * ch ;
+ y2 = y1 + pane_h ;
+ TFT.set_font((unsigned char*) Arial12x12);
+ TFT.background(Black) ;
+ TFT.foreground(White) ;
+ TFT.locate(5, y1+5) ;
+ TFT.printf("3.0") ;
+ TFT.locate(15, (y1+y2)/2) ;
+ TFT.printf("V") ;
+ TFT.locate(5, y2-10) ;
+ TFT.printf("0.0") ;
+ TFT.rect(x1,y1,x2,y2,Blue) ;
+ y_offset = head_h + 1;
+
+ for (int i = 0 ; i < pane_w ; i += 10) {
+ x1 = left_margin + i ;
+ x2 = x1 ;
+ if ((i % 100) == 0) {
+ y1 = head_h - 5 ;
+ } else {
+ y1 = head_h - 2 ;
+ }
+ y2 = head_h ;
+ TFT.line(x1, y1, x2, y2, Blue) ;
+ y1 = head_h + (pane_h + 5) * 2 - 5 ;
+ if ((i % 100) == 0) {
+ y2 = y1 + 5 ;
+ } else {
+ y2 = y1 + 2 ;
+ }
+ TFT.line(x1, y1, x2, y2, Blue) ;
+ }
+
+ for (float f = 0.0 ; f < vref ; f += 1.0) {
+ y_offset = head_h + 1;
+ y1 = ((pane_h - 2) * (1.0 - f/vref)) + y_offset ;
+ y2 = y1 ;
+ x1 = left_margin - 3 ;
+ x2 = left_margin ;
+ TFT.line(x1, y1, x2, y2, Blue) ;
+ y_offset = head_h + (pane_h + 5) + 1;
+ y1 = ((pane_h - 2) * (1.0 - f/vref)) + y_offset ;
+ y2 = y1 ;
+ TFT.line(x1, y1, x2, y2, Blue) ;
+ }
+}
+
+bool inChFrame(int ch, int x, int y)
+{
+ bool result = false ;
+ int x1, x2, y1, y2 ;
+ x1 = left_margin ;
+ x2 = left_margin + pane_w ;
+ y1 = head_h + (pane_h + 5) * ch ;
+ y2 = y1 + pane_h ;
+ if ((x1 <= x)&&(x < x2)&&(y1 <= y)&&(y < y2)) {
+ result = true ;
+ }
+ return( result ) ;
+}
+
+void plotCh_line(int turn, int ch, int index, int color)
+{
+ int x[2], y[2] ;
+ int y_offset, data_pos, prev_pos ;
+
+ y_offset = head_h + (pane_h + 5) * ch + 1;
+ data_pos = (bor[turn] + index) % memLength ;
+ prev_pos = (memLength + bor[turn] + index - 1) % memLength ;
+
+ x[1] = left_margin + index + 1;
+ y[1] = ((pane_h - 2) * (1.0 - u2f(udata[turn][ch][data_pos]))) + y_offset ;
+
+ if (index == 0) {
+ x[0] = x[1] ;
+ y[0] = y[1] ;
+ } else {
+ x[0] = left_margin + index ;
+ y[0] = ((pane_h - 2) * (1.0 - u2f(udata[turn][ch][prev_pos]))) + y_offset ;
+ }
+ TFT.line(x[0],y[0],x[1],y[1], color) ;
+}
+
+void drawGraphFrames(void)
+{
+ for (int i = 0 ; i < numAnalogIn ; i++ ) {
+ drawChFrame(i) ;
+ }
+}
+
+void drawChart(void)
+{
+ int i, ch ;
+ if (!frame_full) {
+ return ;
+ }
+ if (mode == MODE_RUN) {
+ timer.detach() ;
+ }
+
+ for (i = 0 ; i < memLength ; i++ ) {
+ for (ch = 0 ; ch < numAnalogIn ; ch++ ) {
+ plotCh_line(prev_page, ch, i, Black) ; // erase prev
+ plotCh_line(page, ch, i, White) ;
+ }
+ }
+ prev_page = page ;
+ page = (page + 1)%2 ;
+ sampling_status = ST_PRE_TRIG ;
+ frame_full = false ;
+ trig_index = 0 ;
+ data_index = 0 ;
+ if (mode == MODE_RUN) {
+ timer.attach_us(&sampleAD, us_interval) ;
+ }
+}
+
+void printMode(void)
+{
+ TFT.locate(80, 200) ;
+ TFT.background(Black) ;
+
+ if (mode == MODE_STOP) {
+ TFT.foreground(Yellow) ;
+ TFT.printf(" Stopped") ;
+ } else if (mode == MODE_RUN) {
+ TFT.foreground(White) ;
+ TFT.printf(" Running") ;
+ }
+}
+
+void printTimeDiv(void)
+{
+ char str[32] ;
+ int ival, dotval ;
+ if (us_interval < 100) { // 10 * us_interval < 1ms
+ sprintf(str, " %3d us/div", 10 *us_interval) ;
+ } else if (us_interval < 100000) { // 10 * us_interval >= 1ms
+ ival = us_interval / 100 ;
+ dotval = us_interval % 100 ;
+ sprintf(str, " %3d.%0d ms/div", ival, dotval) ;
+ }
+ TFT.fillrect(65, 240, 175, 260, Black) ;
+
+ TFT.background(Black) ;
+ TFT.foreground(White) ;
+
+ TFT.locate(65, 240) ;
+ TFT.printf(str) ;
+}
+
+void printTrigMode(void)
+{
+ char str[60] ;
+ TFT.fillrect(65, 280, 235, 310, Black) ;
+
+ TFT.background(Black) ;
+ TFT.foreground(White) ;
+
+ if (trig_mode == TRIG_MODE_NONE) {
+ sprintf(str, "%6s",
+ trig_name[trig_mode]) ;
+ } else {
+ sprintf(str, "%6s ch%1d (%d, %.1f)",
+ trig_name[trig_mode], trig_ch+1, trig_pos, trig_level) ;
+ }
+ TFT.locate(65, 280) ;
+ TFT.printf(str) ;
+}
+
+void printTrigLevel(void)
+{
+ char str[16] ;
+ TFT.locate(140, 280) ;
+ TFT.background(Black) ;
+ TFT.foreground(White) ;
+ sprintf(str, " %.1f", trig_level) ;
+ TFT.printf(str) ;
+}
+
+void eraseTrigMark(void)
+{
+ int x1, x2, y1, y2 ;
+ x1 = left_margin - 3 ;
+ x2 = left_margin + pane_w + 3 ;
+ y1 = 1 ;
+ y2 = head_h - 5 ;
+ TFT.fillrect(x1,y1,x2, y2, Black) ;
+ y1 = (head_h + (pane_h + 5)*2) + 5 ;
+ y2 = y1 + 13 ;
+ TFT.fillrect(x1,y1,x2, y2, Black) ;
+ x1 = left_margin + pane_w + 1 ;
+ x2 = x1 + 10 ;
+ y1 = 0 ;
+ y2 = head_h + (pane_h + 5) * (2) + 1;
+ TFT.fillrect(x1, y1, x2, y2, Black) ;
+}
+
+void drawTrigPos()
+{
+ uint16_t color = Green ;
+ int x1, x2, y1, y2 ;
+ int y_offset ;
+// draw down arrow
+ x1 = left_margin + trig_pos + 1 ;
+ x2 = x1 ;
+ y1 = 5 ;
+ y2 = head_h - 8 ;
+ TFT.line(x1, y1, x2, y2, color) ;
+ x1 = x2 - 3 ;
+ y1 = y2 - 4 ;
+ TFT.line(x1, y1, x2, y2, color) ;
+ x1 = x2 + 3 ;
+ TFT.line(x1, y1, x2, y2, color) ;
+// draw up arrow
+ x1 = x2 ;
+ y1 = (head_h + (pane_h + 5)*2) + 5 ;
+ y2 = y1 + 7 ;
+ TFT.line(x1, y1, x2, y2, color) ;
+ x2 = x1 - 3 ;
+ y2 = y1 + 3 ;
+ TFT.line(x1, y1, x2, y2, color) ;
+ x2 = x1 + 3 ;
+ TFT.line(x1, y1, x2, y2, color) ;
+// draw level mark
+ x1 = left_margin + pane_w + 3 ;
+ x2 = x1 + 7 ;
+ y_offset = head_h + (pane_h + 5) * (trig_ch+1) + 1;
+ y1 = ((pane_h - 2) * (1.0 - trig_level)) + y_offset ;
+ y2 = y1 ;
+ TFT.line(x1, y1, x2, y2, color) ;
+ x2 = x1 + 3 ;
+ y2 = y1 - 3 ;
+ TFT.line(x1, y1, x2, y2, color) ;
+ y2 = y1 + 3 ;
+ TFT.line(x1, y1, x2, y2, color) ;
+}
+
+void drawTrigMark(void)
+{
+ eraseTrigMark() ;
+ switch(trig_mode) {
+ case TRIG_MODE_NONE:
+ break ;
+ case TRIG_MODE_RISE:
+ case TRIG_MODE_FALL:
+ case TRIG_MODE_LEVEL:
+ drawTrigPos() ;
+ break ;
+ default:
+ printf("Unkown trigger mode %d\n\r",trig_mode) ;
+ break ;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/view.h Sat Jan 10 15:08:38 2015 +0000 @@ -0,0 +1,38 @@ +/** mbed oscilloscope my implementation of a oscillo scope + * Copyright (c) 2014, 2015 Motoo Tanaka @ Design Methodology Lab + * + * view.h + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef _VIEW_H_ +#define _VIEW_H_ defined + +extern int pane_w ; +extern int pane_h ; // height per channel +extern int head_h ; // header height +extern int foot_h ; // footer height +extern int right_margin ; +extern int left_margin ; + +void initTFT(void) ; +void eraseChFrame(int ch) ; +void eraseGraphFrames(void) ; +void drawChFrame(int ch) ; +bool inChFrame(int ch, int x, int y) ; +void plotCh_line(int turn, int ch, int index, int color) ; +void drawGraphFrames(void) ; +void drawChart(void) ; +void printMode(void) ; +void printTimeDiv(void) ; +void printTrigMode(void) ; +void printTrigLevel(void) ; +void drawTrigMark(void) ; +void eraseTrigMark(void) ; +#endif /* _VIEW_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vt100.lib Sat Jan 10 15:08:38 2015 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/Rhyme/code/vt100/#94253645a02a