/* COP8C Code Development System Sample Application for National Semiconductor: Flash Device This code may be adapted for any purpose when used with the COP8C Code Development System. No warranty is implied or given as to their usability for any purpose. (c) Copyright 2000 Byte Craft Limited 421 King St.N., Waterloo, ON, Canada, N2J 4E4 VOICE: 1 (519) 888 6911 FAX : 1 (519) 746 6751 email: support@bytecraft.com REVISION HISTORY V1.00 AL 06/00 Initial version */ #pragma option f0 /* no page breaks in listing file */ #pragma option CALLMAP /* add call map to listing file */ /* This sample application plays a .wav audio file on a speaker using the COP8's high speed PWM. The wave data is obtained using a hex dump utility and an awk script $ hexdump -x beat.wav > beak.dump $ awk -f wave.awk beat.dump > beat.c #### wave.awk #### BEGIN { star_count = 0 } BEGIN {print "#asm"} BEGIN {print "beat_wave_table"} BEGIN {byte_count=0} BEGIN {start_skip_count=0} { if (star_count==0) { ++start_skip_count } } { # add three '*'s to the dump to mark # where you want to start playing # add one more '*' to mark the end if ($1 == "*") { ++star_count } } { if ( (star_count == 3) || (start_skip_count > 64) ) { for (i=2;i<=NF;i++) { print " db 0x" substr($i,1,2) print " db 0x" substr($i,3,2) ++byte_count ++byte_count } } } END { print "#endasm"} END { print "#define BEAT_WAVE_TABLE_SIZE " byte_count } #### wave.awk #### The .WAV file used must be 8khz 8bit mono. The sound is synthesized by applying a new 8bit sample voltage every 125us (8khz). Timer 2 is configured to generate an interrupt every 125us. calculations: The sample voltage needs to be changed at a rate of 8khz. 1/8khz = 125us At 10Mhz every cycly requires 1us. 125us/1us = 125 = 0x007d Inside the timer 2 interrupt, timer 3 is set up to generate a PWM voltage on the speaker corresponding the the current wave sample. The PWM generates a 40khz carrier frequency. The sample determines the duty cycle. calculations: The square wave period is 0x100 cycles. At 10Mhz in high speed mode every cycle is 100ns. This gives a 100ns * 0x100 = 25.6us ~= 40khz carrier frequency. If the sample is 0x40. Time on is 0x40*100ns. Time off is (0x100-0x40)*100ns. */ #include "cop8.h" /* Device Header File */ #include #include #include #include #include #include #include /* library function aliases */ #define getch() uart_getch() #define putch(CHAR) lcd_putch(CHAR) #define itoa(VAL,DEST,RADIX) ui8toa(VAL,DEST,RADIX) /* unsigned 8 bit integer */ #define uart_clrscr() uart_putch('\f'); #define lcd_clrscr() lcd_send_control(LCDCLR) #define clrscr() lcd_clrscr() /* startup initialization */ #define CNTRL_STARTUP_DATA 0x08 /* init microwire */ #define PORTA_STARTUP_DATA 0b00000000 /* DEFAULT DATA */ #define PORTA_STARTUP_CONF IIIIIIII /* ALL WEEK PULL-UP INP */ #define PORTB_STARTUP_DATA 0b00000000 /* DEFAULT DATA */ #define PORTB_STARTUP_CONF IIIOOOOO /* SET TO LOW (OP AS VOLTAGE FOLLOWER) */ #define PORTC_STARTUP_DATA 0b00101011 /* DEFAULT DATA */ #define PORTC_STARTUP_CONF IOIOIIOI /* ROTARY ENCODER INP WKP,ANALOG POWER OUTPUT ON */ #define PORTD_STARTUP_DATA 0b00000000 /* DEFAULT DATA ALL LOW */ #define PORTE_STARTUP_DATA 0b11000000 /* DEFAULT DATA */ #define PORTE_STARTUP_CONF OOIIOOII /* SCL AND SDA OUTPUT LOW ALL OTHER HZ INP */ #define PORTF_STARTUP_DATA 0b00000011 /* DEFAULT DATA */ #define PORTF_STARTUP_CONF IIIIOOII /* PB INP WP, RADIO/IRDA SD LOW (OFF) */ #define PORTG_STARTUP_DATA 0b00000101 #define PORTG_STARTUP_CONF IIOOOOIO /* DEFAULT DATA */ #define PORTL_STARTUP_DATA 0b00101000 /* DEFAULT DATA */ #define PORTL_STARTUP_CONF IOIOIOOO /* LOW SPEED OSC MUST BE HZ TO WORK */ #define LIGHT_SWITCH_PORT PORTLP #define LIGHT_SWITCH_PIN 7 #include "beat.c" /* beat wave table */ #include "greeting.c" /* greeting wave table */ enum wave_table_enum { BEAT_WAVE , GREETING_WAVE }; const long wave_tables[] = { beat_wave_table , greeting_wave_table }; const long wave_table_sizes[] = { BEAT_WAVE_TABLE_SIZE, GREETING_WAVE_TABLE_SIZE }; bit sound_enabled; /* PWM reload value to get 8k interrupts * per second */ #define TIMER_RELOAD_8khz_LO 0x7D #define TIMER_RELOAD_8khz_HI 0x00 unsigned long register sample_index; #define TICKS_PER_SECOND 488 unsigned long register tick_counter; const char id_clock[] = "ZBCL 56789012345"; char new_id_clock[sizeof(id_clock)]; char clock_hours; char clock_minutes; char clock_seconds; char id1,id2,id3,id4; /* ID bytes */ /* hardware UART ring buffer */ char uart_receive_buffer[20]; char far * uart_receive_pointer_in; char far * uart_receive_pointer_out; #define BUTTON1_PIN 0 #define BUTTON2_PIN 1 #define BUTTON1_PORT PORTFP #define BUTTON2_PORT PORTFP #define BUTTON1 1 #define BUTTON2 2 #define BOTH_BUTTONS 3 #define CANCEL_BUTTON BUTTON1 #define OK_BUTTON BUTTON2 /* host commands */ #define HOST_SET_TIME 0x01 #define HOST_GET_ADC 0x03 #define HOST_PLAY_AUDIO 0x05 #define HOST_SET_ID 0x0d #define HOST_SEND_ID 0x0b #define ENTER_MENU 0x80 #define EXIT_MENU 0x40 int register menu_selection; int register item_selection; bit refresh_display; bit do_click; #define MAIN_MENU_SIZE 4 #define ADC_MENU_SIZE 16 #define AUDIO_MENU_SIZE 3 #define TIME_MENU_SIZE 3 #define ABOUT_MENU_SIZE 3 const int menu_sizes[] = { MAIN_MENU_SIZE-1, ADC_MENU_SIZE-1, AUDIO_MENU_SIZE-1, TIME_MENU_SIZE-1, ABOUT_MENU_SIZE-1 }; enum menu_function_index { show_adc_index, play_wave_loop_index, play_wave_index, toggle_sound_index, show_time_index, store_time_index, set_time_index, show_compile_time_index, show_compile_date_index, show_ROM_id_index, not_handled_index }; enum MENUS { MAIN_MENU=0, ADC_MENU, AUDIO_MENU, TIME_MENU, ABOUT_MENU, NUMBER_OF_MENUES }; char current_menu_item[NUMBER_OF_MENUES]; enum ITEMS { SELECT_ADC_MENU=0, SELECT_AUDIO_MENU, SELECT_TIME_MENU, SELECT_ABOUT_MENU, VIEW_CHANNEL_0=0, VIEW_CHANNEL_1, VIEW_CHANNEL_2, VIEW_CHANNEL_3, VIEW_CHANNEL_4, VIEW_CHANNEL_5, VIEW_CHANNEL_6, VIEW_CHANNEL_7, VIEW_CHANNEL_8, VIEW_CHANNEL_9, VIEW_CHANNEL_10, VIEW_CHANNEL_11, VIEW_CHANNEL_12, VIEW_CHANNEL_13, VIEW_CHANNEL_14, VIEW_CHANNEL_15, PLAY_BEAT=0, PLAY_GREETING, TOGGLE_AUDIO, SHOW_TIME=0, STORE_TIME, SET_TIME, COMPILE_TIME=0, COMPILE_DATE, SHOW_ROM_ID }; const char far * menu_strings[] = { "Main Menu", "View ADC", "Audio", "Time", "About", "View ADC", "Channel 0", "Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Audio", "Play a Beat", "Play Greeting", "Toggle Sound", "Time", "Show Time", "Store Time", "Set Time", "About", "Compile Time", "Compile Date", "ID" }; const char ok_menu_selection_table[] = { /* MENU, ITEM, FUNCTION HANDLER, */ MAIN_MENU, SELECT_ADC_MENU, ENTER_MENU| ADC_MENU, MAIN_MENU, SELECT_AUDIO_MENU, ENTER_MENU| AUDIO_MENU, MAIN_MENU, SELECT_TIME_MENU, ENTER_MENU| TIME_MENU, MAIN_MENU, SELECT_ABOUT_MENU, ENTER_MENU| ABOUT_MENU, ADC_MENU, VIEW_CHANNEL_0, show_adc_index, ADC_MENU, VIEW_CHANNEL_1, show_adc_index, ADC_MENU, VIEW_CHANNEL_2, show_adc_index, ADC_MENU, VIEW_CHANNEL_3, show_adc_index, ADC_MENU, VIEW_CHANNEL_3, show_adc_index, ADC_MENU, VIEW_CHANNEL_4, show_adc_index, ADC_MENU, VIEW_CHANNEL_5, show_adc_index, ADC_MENU, VIEW_CHANNEL_6, show_adc_index, ADC_MENU, VIEW_CHANNEL_7, show_adc_index, ADC_MENU, VIEW_CHANNEL_8, show_adc_index, ADC_MENU, VIEW_CHANNEL_9, show_adc_index, ADC_MENU, VIEW_CHANNEL_10, show_adc_index, ADC_MENU, VIEW_CHANNEL_11, show_adc_index, ADC_MENU, VIEW_CHANNEL_12, show_adc_index, ADC_MENU, VIEW_CHANNEL_13, show_adc_index, ADC_MENU, VIEW_CHANNEL_14, show_adc_index, ADC_MENU, VIEW_CHANNEL_15, show_adc_index, AUDIO_MENU, PLAY_BEAT, play_wave_loop_index, AUDIO_MENU, PLAY_GREETING, play_wave_index, AUDIO_MENU, TOGGLE_AUDIO, toggle_sound_index, TIME_MENU, SHOW_TIME, show_time_index, TIME_MENU, STORE_TIME, store_time_index, TIME_MENU, SET_TIME, set_time_index, ABOUT_MENU, COMPILE_TIME, show_compile_time_index, ABOUT_MENU, COMPILE_DATE, show_compile_date_index, ABOUT_MENU, SHOW_ROM_ID, show_ROM_id_index }; const char cancel_menu_selection_table[] = { /* MENU, ITEM, FUNCTION HANDLER, */ MAIN_MENU, SELECT_ADC_MENU, not_handled_index, MAIN_MENU, SELECT_AUDIO_MENU, not_handled_index, MAIN_MENU, SELECT_TIME_MENU, not_handled_index, MAIN_MENU, SELECT_ABOUT_MENU, not_handled_index, ADC_MENU, VIEW_CHANNEL_0, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_1, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_2, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_3, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_4, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_5, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_6, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_7, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_8, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_9, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_10, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_11, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_12, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_13, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_14, EXIT_MENU| MAIN_MENU, ADC_MENU, VIEW_CHANNEL_15, EXIT_MENU| MAIN_MENU, AUDIO_MENU, PLAY_BEAT, EXIT_MENU| MAIN_MENU, AUDIO_MENU, PLAY_GREETING, EXIT_MENU| MAIN_MENU, AUDIO_MENU, TOGGLE_AUDIO, EXIT_MENU| MAIN_MENU, TIME_MENU, SHOW_TIME, EXIT_MENU| MAIN_MENU, TIME_MENU, STORE_TIME, EXIT_MENU| MAIN_MENU, TIME_MENU, SET_TIME, EXIT_MENU| MAIN_MENU, ABOUT_MENU, COMPILE_TIME, EXIT_MENU| MAIN_MENU, ABOUT_MENU, COMPILE_DATE, EXIT_MENU| MAIN_MENU, ABOUT_MENU, SHOW_ROM_ID, EXIT_MENU| MAIN_MENU }; char str[128]; /* temporary string buffer */ /* This interrupt handling routine samples the dial position * and updates a tick counter for the real time clock */ void __TIMERT0(void) { int register dial_position; /* position reading of dial */ int register dial_previous; /* previous position reading */ SaveContext(); const char dial_position_states[] = { 0x0,0x1,0x9,0x8 }; ICNTRL.T0PND=0; dial_position=PORTCP&0b1001; /* read dial */ if( dial_position_states[dial_previous&3]!=dial_position) { if(dial_position_states[(dial_previous+1)&3]==dial_position) { if(item_selection>0) { item_selection--; refresh_display=1; do_click=1; } dial_previous++; } else { if(item_selectionTICKS_PER_SECOND) { PSW.GIE=0; tick_counter-=TICKS_PER_SECOND; PSW.GIE=1; clock_seconds++; } else if(clock_seconds>=60) { clock_seconds-=60; ++clock_minutes; } else if(clock_minutes>=60) { clock_minutes-=60; ++clock_hours; } else if(clock_hours>=24) clock_hours-=24; } void uart_putch(char ch) { while(ENU.TBMT==0); /* wait while transmission in progress */ TBUF=ch; } char kbhit(void) { /* check for chacter in buffer */ if(uart_receive_pointer_in!=uart_receive_pointer_out) return(1); else return(0); } char uart_getch(void) { char ch; while(uart_receive_pointer_in==uart_receive_pointer_out); /* wait for a character */ ch=*uart_receive_pointer_out; /* get character from buffer */ /* remove character from buffer */ if( uart_receive_pointer_out == (uart_receive_buffer+sizeof(uart_receive_buffer)-1) ) uart_receive_pointer_out=uart_receive_buffer; else uart_receive_pointer_out++; return(ch) } /* read_button's