/* ***************************************************** * * * nokia 3310 LCD scope * * THIS IS IT!!! :-) june 1 , 2009 * * * B0 - uS/Div switch * B1 - Y pos * B2 - sw soft GAIN * B4 - spst sw HOLD function /hold MODE open sw * B5 - trigger LVL button / 5 & 128 WHATS NEW/UPGRADED: =================== shows a PROPER square wave has switchable GAIN FS=5V and FS=2.6V has also TRIGGER/hold function by: master Regulus Berdin A.K.A zer0w1ng much accurate; Tosc = 32 @ 20MHz bus clock 100ms 50mS 20mS 10mS 2mS 500uS us/Div -ADD trigger TOGGLE function (done!) -ADD better HOLD function (done!) -ADD toggle function to softGAIN (done!) ***************************************************** Changes: -long press */ #include <18F452.h> #device adc=8 #use delay(clock=20M) //#FUSES NOWDT,NOPROTECT,NOOSCSEN,BROWNOUT,BORV20,STVREN,NODEBUG,NOWRT,NOWRTD,NOWRTB //#FUSES NOWRTC,NOCPD,NOCPB,NOEBTR,NOEBTRB #FUSES NOWDT, HS, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG #use fast_io(b) #define LCD_SCLK 4 #define LCD_SDA 2 #define LCD_DC 3 #define LCD_CS 1 #define LCD_RES 0 #byte lcdport = 0xF83 #byte lcdport_tris = 0xF95 #bit nok_sclk = lcdport.LCD_SCLK //pin2 LCD port_D4 #bit nok_sda = lcdport.LCD_SDA //pin3 LCD port_D2 #bit nok_dc = lcdport.LCD_DC //pin4 LCD port_D3 #bit nok_cs = lcdport.LCD_CS //pin5 LCD port_D1 #bit nok_res = lcdport.LCD_RES //pin8 LCD port_D0 //============================================================ //#include <2465.C> #include "3310.c" #define speaker pin_C7 #define TIMEOUT 1000 #define DEFAULT_TRIGGER_DELAY 1 #define BTN_MASK (1<<5 | 1<<4 | 1<<3 | 1<<2 | 1<<1 | 1) #define DEBOUNCE_MS 30 #define MINIMUM_ADC_TIME 15 #define TRIGGER_LED_PORT PIN_D7 /* 100ms, 50ms, 20ms, 10ms, 2ms, 500uS */ #define INTERVAL_COUNT 6 #define INTERVAL_DEFAULT 2 #define INTERVAL_STR_SIZE 6 #define SCALE_COUNT 4 #define SCALE_DEFAULT 0 #define SCALE_STR_SIZE 6 #define TRIGGER_DEFAULT 16 unsigned char samples[84]; unsigned int8 i; unsigned int scale; unsigned int8 trigger_level = TRIGGER_DEFAULT; signed int8 position = 0; unsigned int8 interval = INTERVAL_DEFAULT; unsigned int8 scale_index = SCALE_DEFAULT; unsigned int8 scale_dc_level = (128 >> (3-SCALE_DEFAULT)); unsigned int16 timer_value; unsigned int8 timer_divider; typedef struct { unsigned int16 value; char *str; } val_str_t; const unsigned int16 const interval_delay[INTERVAL_COUNT] = { 1000, 500, 200, 100, 20, 5 }; const unsigned int8 const scale_value[SCALE_COUNT] = {8,4,2,1}; void view_settings(); void beep(); void plot_samples(void); signed int8 compute_y(unsigned int8 v); void scope_settings() { delay_ms(50); //switch debounce nokia_clean_ddram(); view_settings(); } //------------------------ void show_scale(void) { nokia_gotoxy(25,5); switch (scale) { case 8: printf(nokia_printchar, " 5V "); break; case 4: printf(nokia_printchar, " 2V5"); break; case 2: printf(nokia_printchar, "1V25"); break; case 1: printf(nokia_printchar, "V625"); break; } } void show_interval(void) { unsigned int8 interv; interv = interval_delay[interval]/10; nokia_gotoxy(53,5); if (interv) printf(nokia_printchar, "%3ums", interv); else printf(nokia_printchar, "500us"); } void erase_trigger(void) { nokia_gotoxy(0, (trigger_level/8)); nokia_write_data(0x00); nokia_gotoxy(1, (trigger_level/8)); nokia_write_data(0x00); nokia_gotoxy(0,5); printf(nokia_printchar," "); } void show_trigger(void) { LcdPixel(0, trigger_level); LcdPixel(1, trigger_level); nokia_gotoxy(0,5); printf(nokia_printchar,"t%u", 31-trigger_level); } void clear_status_line(void) { nokia_gotoxy(0,5); printf(nokia_printchar," "); } void view_settings() { clear_status_line(); show_interval(); show_scale(); show_trigger(); } enum { STATE_FIND_LOW, STATE_FIND_TRIGGER, STATE_COUNTING_LOW, STATE_COUNTING_HIGH, STATE_DUMMY }; void show_frequency() { unsigned int16 cnt; unsigned int8 i, state; float d, intv; signed int8 y, tr; state = STATE_COUNTING_LOW; cnt = 0; tr = compute_y(samples[0]); for (i=0;i<84;++i) { y = compute_y(samples[i]); switch (state) { case STATE_COUNTING_LOW: ++cnt; if (y>tr) state = STATE_COUNTING_HIGH; break; case STATE_COUNTING_HIGH: ++cnt; if (y<=tr) i=100; break; } } #if 0 printf(nokia_printchar,"%Lu :%Lu %Lu", cnt, timer_value,timer_divider); #else //timer_divider if (i>=100) { d = timer_value/84.0; intv = cnt; intv *= timer_divider; printf(nokia_printchar,"Freq:%2.3gkHz", 5000.0/(intv * d)); } else { printf(nokia_printchar,"Freq: invalid"); } #endif } //=================================================================== signed int8 compute_y(unsigned int8 v) { #if 1 return position + 15 - ((v >> (3-scale_index)) - scale_dc_level) ; #else v >>= (3-scale_index); return position + 31 - v; #endif } unsigned char debounce_pin(unsigned char bmask) { if ((input_b() & bmask)) return 0; delay_ms(DEBOUNCE_MS); if ((input_b() & bmask)) return 0; return 1; } unsigned int8 wait_for_release(void) { if ((input_b() & BTN_MASK) != BTN_MASK) return 1; delay_ms(DEBOUNCE_MS); if ((input_b() & BTN_MASK) != BTN_MASK) return 1; return 0; } void adjust_trigger(void) { erase_trigger(); if (trigger_level>1) --trigger_level; else trigger_level = 30; show_trigger(); } void adjust_position(void) { --position; if (position<-40) position = 40; plot_samples(); nokia_gotoxy(60,5); printf(nokia_printchar," "); nokia_gotoxy(60,5); printf(nokia_printchar,"%d", -position); } void adjust_interval(void) { ++interval; if (interval>=INTERVAL_COUNT) interval = 0; show_interval(); } void check_buttons(void) { unsigned int8 tmr; //check for any buttons pressed if ((input_b() & BTN_MASK) == BTN_MASK) return; //position if (debounce_pin(1<<1)) { nokia_gotoxy(0,5); printf(nokia_printchar,"Position: "); adjust_position(); tmr = 34; /* 500ms long press*/ while(wait_for_release()) { delay_ms(15); if (tmr) --tmr; else adjust_position(); } view_settings(); } //trigger level if (debounce_pin(1<<5)) { adjust_trigger(); tmr = 10; /* 500ms long press*/ while(wait_for_release()) { delay_ms(50); if (tmr) --tmr; else adjust_trigger(); } } //Gain/scale if (debounce_pin(1<<2)) { ++scale_index; if (scale_index >= SCALE_COUNT) scale_index = 0; scale = scale_value[scale_index]; scale_dc_level = (128 >> (3-scale_index)); show_scale(); while(wait_for_release()) continue; } //Hold if (debounce_pin(1<<4)) { nokia_gotoxy(0,5); printf(nokia_printchar,"H "); while(wait_for_release()) continue; view_settings(); } //interval if (debounce_pin(1)) { adjust_interval(); while(wait_for_release()) continue; } //freq if (debounce_pin(1<<3)) { clear_status_line(); nokia_gotoxy(0,5); show_frequency(); while(wait_for_release()) continue; view_settings(); } } void trigger(void) { unsigned int16 timeout1, timeout2; output_high(TRIGGER_LED_PORT); //wait until reading gets below mid timeout1 = TIMEOUT; do { check_buttons(); read_adc(adc_start_only); delay_us(MINIMUM_ADC_TIME + 30); if (compute_y(read_adc(adc_read_only))>=trigger_level) break; } while (--timeout1); //wait until reading gets above mid timeout2 = TIMEOUT; do { check_buttons(); read_adc(adc_start_only); delay_us(MINIMUM_ADC_TIME + 30); if (compute_y(read_adc(adc_read_only))31 && y2>31) /* || (y1>31 && y2<0) || (y2>31 && y1<0) */ ) continue; if (y1>31) y1 = 31; if (y2>31) y2 = 31; if (y1<0) y1 = 0; if (y2<0) y2 = 0; lcd_fast_vertical_line(x,y1,y2); } } void get_samples(void) { unsigned int8 i; unsigned int16 pinterval; pinterval = interval_delay[interval]; if (pinterval