/* * main.c * * Description: * This is driver for the ISD4003 chip using SPI. * * Author: Martin Dubuc * * Creation date: January 4, 2001 */ #include <16f877.h> /* Microcontroller configuration bits */ #fuses HS,NOPROTECT,NOWDT,BROWNOUT,PUT,NOLVP #ORG 0x1F00,0x1FFF {} /* Reserve memory for bootloader for the 8k 16F876/7 */ #device PIC16F877 *=16 /* Allow RAM to expand beyond 256 bytes */ /* The 20_MHZ_CLOCK define is used to indicate whether we are using a 4 MHz or 20 MHz clock */ #undef 20_MHZ_CLOCK /* Set the clock speed. */ #ifdef 20_MHZ_CLOCK #use delay(clock=20000000) #else #use delay(clock=4000000) #endif /* Directive for RS-232 interface */ #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) /* ISD4003 definitons */ // Pin definition #define ISD_SS (PIN_A5) #define ISD_MOSI (PIN_C5) #define ISD_MISO (PIN_C4) #define ISD_SCLK (PIN_C3) #define ISD_INT (PIN_B0) #define ISD_RAC (PIN_B1) // Opcode defintion #define ISD_OPCODE_POWERUP (0b00100) #define ISD_OPCODE_SETPLAY (0b00111) #define ISD_OPCODE_PLAY (0b01111) #define ISD_OPCODE_SETREC (0b00101) #define ISD_OPCODE_REC (0b01101) #define ISD_OPCODE_SETMC (0b10111) #define ISD_OPCODE_MC (0b11111) #define ISD_OPCODE_STOP (0b01100) #define ISD_OPCODE_STOPPWRDN (0b01000) #define ISD_OPCODE_RINT (0b01100) // Following are time definitions. All values are in milliseconds // except when stated otherwise. #define TPUD (50) #define TRAC (400) #define TRACLO (50) #define TRACM (250) // microseconds #define TRACML (31250) // 31.25 microseconds /* Application definitions */ #define RECORD_LED (PIN_B2) #define RECORD_BUTTON (PIN_D0) #define PLAY_BUTTON (PIN_D1) #define INFINITE (0xffff) /* Type definitions */ typedef short int BIT; typedef int uint8_t; typedef long uint16_t; /* Variable definitions */ BIT ovm, eom; BOOLEAN record = false; BOOLEAN play = false; /* Public interface */ void main(void); void isd_record(uint16_t address); void isd_play(uint16_t address); void isd_stop(void); void isd_send_command(uint8_t command, uint16_t address); void isd_read(uint16_t *data); #int_ext void ext_interrupt_handler(void); void main(void) { uint16_t address = 0x0; int i; /* Initialization */ enable_interrupts(GLOBAL); enable_interrupts(INT_EXT); ext_int_edge(H_TO_L); /* set direction of ports, All Out */ set_tris_a(0b00110010); set_tris_b(0b00000011); /* Port B0 and B1 are inputs. B3 is output. */ #if 1 set_tris_c(0b00010000); #endif output_low(RECORD_LED); output_high(ISD_SS); setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16); for ( ; ; ) { if (!input(RECORD_BUTTON) && !record && !play) { if (play) { isd_stop(); } isd_record(address); } if (input(RECORD_BUTTON) && record) { isd_stop(); } if (!input(PLAY_BUTTON) && !play && !record) { // Play recorded stream isd_play(address); } if (input(PLAY_BUTTON) && play) { isd_stop(); } } } /* main */ void isd_record(uint16_t address) { printf("record\r\n"); output_high(RECORD_LED); record = true; isd_send_command(ISD_OPCODE_POWERUP, 0); delay_ms(TPUD); isd_send_command(ISD_OPCODE_POWERUP, 0); delay_ms(2 * TPUD); isd_send_command(ISD_OPCODE_SETREC, address); isd_send_command(ISD_OPCODE_REC, 0); } // isd_record void isd_play(uint16_t address) { printf("play\r\n"); play = true; isd_send_command(ISD_OPCODE_POWERUP, 0); delay_ms(TPUD); isd_send_command(ISD_OPCODE_SETPLAY, address); isd_send_command(ISD_OPCODE_PLAY, 0); } // isd_play void isd_stop(void) { printf("stop\r\n"); output_low(RECORD_LED); play = false; record = false; isd_send_command(ISD_OPCODE_STOP, 0); } // isd_stop void isd_send_command(uint8_t command, uint16_t address) { output_low(ISD_SS); spi_write(address & 0xff); spi_write(((address & 0xff00) >> 3) | command); output_high(ISD_SS); } // isd_send_command void isd_read(uint16_t *data) { uint8_t b1, b2; output_low(ISD_SS); b1 = spi_read(); b2 = spi_read(); output_high(ISD_SS); *data = (b1 << 8) | b2; } // isd_read #int_ext void ext_interrupt_handler(void) { uint16_t data; // The external interrupt is triggered when there OVM or EOM occurs. // If pin is set to low, then OVF or EOM is detected. printf("OVF or EOM\r\n"); play = false; // To read the OVM and EOM flags, issue the RINT command. isd_send_command(ISD_OPCODE_RINT, 0); isd_read(&data); ovm = data >> 15; eom = (data >> 14) & 1; printf("Interrupt status = 0x%02x\r\n", data); } // ext_interrupt_handler