/*------------------------------- i r c . c -------------------------------*/ /* Experimental interrupt handler. */ /* This routine sets up a level 2 interrupt server that is triggered by the */ /* ACK pin of the parallel port going low. The interrupt server then uses */ /* Timer B in CIA-B to time reading in data from the parallel port. */ /* The ACK and one data input pin on the parallel port are tied */ /* together by the hardware I built. Initially the ACK interrupt is */ /* enabled and the software sits and waits for something to happen. */ /* */ /* NEED TO CHECK RESOURCES ---- FREEMEM!!!!!!!!!!!!!!!!*/ /*--------------------------------------------------------------------------*/ /*--- Includes and Defines. */ #include "irc.h" #include "IRMaster.h" /* Definitions of Screen, Window and gadgets. */ /* DBG = 1 --> Turn on debug printf's, DBG = 0 --> Turn off debug printf's. */ #define DBG 1 /* Set DEBUG to 0 to comment out code related to opening screen and window.*/ #define DEBUG 1 #define NOERROR 0 #define ERROR 1 /*--- NSAMPLES is the number of data samples to be read into buffer. */ #define NSAMPLES 3000 /*--- TOLERENCE is the number of samples difference that is tolerated in */ /*--- order to match two patterns. */ #define TOLERENCE 50 /*--- External system variables. */ extern struct Custom custom; extern struct CIA ciab; extern struct GfxBase *GfxBase; extern struct IntuitionBase *IntuitionBase; extern struct WBStartup *WBenchMsg; /* For Workbench startup. */ /**********************************************************/ /***************** Timer B Interrupt code *****************/ /**********************************************************/ /* Update Timer every TIME_SLICE microseconds. TIME_SLICE = 1.397 * (desired # of microseconds) [71 = 100us] 71, 50 work. */ #define TIME_SLICE ((unsigned short)35) /* Defines to make the code more readable. */ #define ciatlo ciab.ciatblo #define ciathi ciab.ciatbhi #define ciacr ciab.ciacrb #define ciaicr ciab.ciaicr int TimerSigBit = -1; /* Allocated signal bit. */ ULONG TimerSigMask; /* TimerSigBit converted into a mask. */ static struct Library *CIAResource = NULL; struct Task *thisTask; int NSamples; /* Number of samples in buffer. */ int SetUpTimer() { char temp; unsigned short micros; /*--- Check to see if timer B in CIA-B is already in use. */ /*--- If START bit is set timer is probably being used. */ #if DBG printf("\n Timer B control register = %X",ciab.ciacrb); #endif if(ciab.ciacrb & 0x01) { printf("\n Timer B is already allocated. Proceding anyway."); } /*--- Set latched value for timer to count down from. */ micros = TIME_SLICE; #if DBG printf("\n Sampling interval = %d * 1.397 microseconds", micros); #endif ciatlo = micros & 0xFF; ciathi = micros >> 8; /*--- Get ID for this task so can send it a signal. */ thisTask = NULL; thisTask = FindTask(NULL); if(thisTask == NULL) { printf("\n Error - Can't find this task ID."); return(ERROR); } /*--- Get a signal bit. */ if((TimerSigBit = AllocSignal(-1L)) == -1) { printf("\n Timer: AllocSignal failed."); StopTime(); /* Deallocate resources. */ return(ERROR); } TimerSigMask = 1L << TimerSigBit; /*--- Open the CIA resource. */ if((CIAResource = OpenResource(CIABNAME)) == NULL) { printf("\n Timer: Couldn't open %s.", CIABNAME); StopTime(); /* Deallocate resources. */ return(ERROR); } /*--- Interrupts have been enabled so may already */ /*--- have an interrupt. So do this... */ ciab.ciacrb &= ~CIACRBF_START; /* stop timer */ temp = ciaicr; /* Read IRC register to clear interrupt. */ SetSignal(0, TimerSigMask); /* clear signal */ #if DBG printf("\n About to set RUNMODE"); #endif ciacr &= ~CIACRBF_RUNMODE; /* Set it to reload upon underflow. */ ciacr &= ~CIACRBF_PBON; /* Output line PB7 is left alone. */ ciacr &= ~CIACRBF_INMODE0; /* Count clock pulses. */ ciacr &= ~CIACRBF_INMODE1; /* Count clock pulses. */ #if DBG printf("\n About to strobe LOAD"); #endif ciacr |= CIACRBF_LOAD; /* Strobe Load to latch in countdown value. */ #if DBG printf("\n About to enable timer b interrupts"); #endif ciaicr = 0x7D; /* Disable all other CIA-B interrupts. */ ciaicr = CIAICRF_SETCLR|CIAICRF_TB; /* Enable timer B interrupts. */ #if DBG printf("\n Enabled timer b interrupts"); #endif return(NOERROR); } int StopTime() { if(thisTask != NULL) { /*--- Disable timer B interrupts. */ #if DBG printf("\n Stopping timer B."); #endif ciaicr = CIAICRF_TB; /*--- Halt timer. */ ciacr &= ~CIACRBF_START; /*--- Free resources. */ if(TimerSigBit != -1) { #if DBG printf("\n Freeing signal bit."); #endif FreeSignal(TimerSigBit); } } return(NOERROR); } /**********************************************************/ /***************** LEVEL 2 Interrupt code *****************/ /**********************************************************/ extern void ircserver(); struct Interrupt intrpt; int AddINT2Server() { /*--- init NODE structure */ intrpt.is_Node.ln_Type = NT_INTERRUPT; /* Was 0 but glasses flickered. 3 fixed it. */ intrpt.is_Node.ln_Pri = 127; intrpt.is_Node.ln_Name = "WWB"; intrpt.is_Code = ircserver; intrpt.is_Data = NULL; #if DBG printf("\n About to add interrupt server..."); #endif AddIntServer(INTB_PORTS, &intrpt); /* Add server to chain */ #if DBG printf("\n Added interrupt server."); #endif return(NOERROR); } int RemoveServer() { RemIntServer(INTB_PORTS, &intrpt); return(NOERROR); } /**********************************************************/ /************************** MAIN **************************/ /**********************************************************/ unsigned char *buffer; /* Pointer to storage for data to be read in. */ unsigned char zuffer[NSAMPLES]; /* Storage for data to be read in. */ unsigned char pattern[20][NSAMPLES]; /* Stored signal patterns. */ char *address, mask; struct Screen *Screen = NULL; struct Window *Window = NULL; struct RastPort *WRPort; struct ViewPort *WVPort; struct IntuiMessage *message; ULONG class; USHORT code; struct Gadget *igad; USHORT gadget_id; extern int BackGround(); int helptxt(); int IRButtonOff(); /* Unhighlight button. */ int IRButtonOn(); /* Highlight button. */ int IRButtonLabel(); /* Relabel button. */ int GetPattern(); /* Get signal pattern. */ int DisplayPattern(); /* Draw the signal pattern. */ int DPattern(); /* Debug. */ /*--- Buffers for area fill and text. */ WORD chip areaArray[100]; /* Max of 20 vertices times 5 words per vertex. */ struct AreaInfo myAreaInfo; PLANEPTR workspace; struct TmpRas myTmpRas; #define NOTHING 0 int active[21] = /* Used to remember which buttons have patterns. */ { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }; main(argc, argv) int argc; char **argv; { int it, error, iz, is, try; int diff[4], match, smallest; BOOL exitflag; int mode; /* Current mode of program (LEARN, NOTHING, etc. ) */ int IRButtonSelected = -1; /* Index of button currently selected. */ /*--- Ignore CTRL-C and CTRL-D. */ signal(SIGINT, SIG_IGN); /*--- Open graphics and Intuition Libraries. */ GfxBase = NULL; GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 33); if(GfxBase == NULL) { printf("\n Error opening graphics library."); goto ShutDown; } IntuitionBase = NULL; IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 33); if(IntuitionBase == NULL) { printf("\n Error opening Intuition library."); goto ShutDown; } /*--- Open a new screen. */ Screen = (struct Screen *) OpenScreen(&NewScreenStructure); if(Screen == 0L) { printf("\n Error opening a new screen."); goto ShutDown; } #if DEBUG /*--- Open window in screen. */ NewWindowStructure1.Screen = Screen; Window = (struct Window *) OpenWindow(&NewWindowStructure1); if(Window == 0L) { printf("\nError opening a new window"); goto ShutDown; } /*--- Get pointers to window structures. */ WRPort = Window->RPort; /* Get pointer to windows' RastPort. */ WVPort = (struct ViewPort *)ViewPortAddress(Window); /* Get pointer to window viewport. */ /*--- Set up area fill and text work buffers. */ InitArea(&myAreaInfo, &areaArray[0], 20); WRPort->AreaInfo = &myAreaInfo; workspace = AllocRaster(640, 200); if(workspace == 0) { printf("\n Error - No space for temporary raster."); goto ShutDown; } else { InitTmpRas(&myTmpRas, workspace, RASSIZE(640,200)); WRPort->TmpRas = &myTmpRas; } /*--- Set color map. */ LoadRGB4(WVPort, Palette, (SHORT)16); /*--- Draw raised background areas. */ BackGround(); /*--- Redraw the gadgets on top of the raised background. */ RefreshGadgets(&ARexx, Window, 0); #endif /*DEBUG*/ /*--- Allocate the parallel port resource so that other tasks know it */ /*--- is taken. (This might not be a good idea. Online! allocates the */ /*--- the parallel port and this prevents me from doing */ /*--- "copy file to par:" in a seperate window. So leave it out for */ /*--- now. User will know if one program walks over another. */ /***************** MR_ALLOCMISCRESOURCE(MR_PARALLELPORT, "IRMaster"); MR_ALLOCMISCRESOURCE(MR_PARALLELBITS, "IRMaster"); *****************/ /*--- Set up pointer to data buffer for SoftHandler(). */ /*--- Assembler doesn't seem to recognize zuffer but DOES buffer. */ buffer = &zuffer[0]; #if DBG printf("\n buffer = %X", buffer); #endif /*--- Set up all the interrupt servers. */ AddINT2Server(); error = SetUpTimer(); if(error)goto Fini; /*--- Explicitly enable level6 and level2 interrupts (even though */ /*--- they already seem to be enabled by default). */ /********* Causes sometimes guru. Disable(); custom.intena |= INTF_SETCLR | INTF_EXTER; custom.intena |= INTF_SETCLR | INTF_SOFTINT; Enable(); *********/ #if DBG /* This is slightly dangerous since it might clear any pending interrupts. */ /*printf("\n Enabled interrupts are: %X", custom.intenar);*/ #endif /*--- Set address for IRC register (used in GetSample.) */ address = (char *)0xBFED01;/* Address of the Interrupt Control Register in 8520-A */ /*--- MAIN PROGRAM LOOP. */ /*--- Get messages from window until user presses CloseWindow gadget. */ #if DEBUG exitflag = FALSE; mode = NOTHING; while(exitflag == FALSE) { /*--- If in DOIT mode wait for IR input. */ if(mode == DOIT) { /*--- Wait for user to press a button. */ GetSample(); /*--- Match input to stored samples. */ match = find_match(); } /*--- Check for user action. */ message = (struct IntuiMessage *)GetMsg(Window->UserPort); if(message != 0) { class = message->Class; code = message->Code; igad = (struct Gadget *)message->IAddress;/*get pointer to gadget */ ReplyMsg((struct Message *)message); if(class == GADGETUP) { gadget_id = igad->GadgetID; /* get my gadget code */ switch(gadget_id) { case COMMANDSTR3: #if DBG printf("COMMANDSTR3\n"); #endif break; case COMMANDSTR1: #if DBG printf("COMMANDSTR1 = %s\n", commandstr1SIBuff); #endif /*--- Change the label on the button. */ IRButtonLabel(commandstr1SIBuff, IRButtonSelected); /*--- Prompt user for next action. */ helptxt("Now press the button on your handheld IR remote control", "that you want memorized."); /*--- Get verified signal sample from the IR receiver. */ GetPattern(IRButtonSelected); /*--- Remember which buttons have patterns stored. */ active[IRButtonSelected] = TRUE; /*--- Unhighlight the control button. */ IRButtonOff(&IRButtonSelected); mode = NOTHING; break; case COMMANDSTR2: #if DBG printf("COMMANDSTR2\n"); #endif break; default: break; } /* switch(gadget_id) */ } /* if(GADGETUP) */ if(class == GADGETDOWN) { gadget_id = igad->GadgetID; /* get my gadget code */ switch(gadget_id) { case EXIT: #if DBG printf("EXIT\n"); #endif goto Fini; break; case AUTHOR: #if DBG printf("AUTHOR\n"); #endif break; case DOIT: #if DBG printf("DOIT\n"); #endif mode = DOIT; break; case GETSET: #if DBG printf("GETSET\n"); #endif break; case SAVESET: #if DBG printf("SAVESET\n"); #endif break; case LEARN: #if DBG printf("LEARN\n"); #endif helptxt("Press one of the twenty control buttons above.",""); mode = LEARN; break; case AREXX: #if DBG printf("AREXX\n"); #endif break; case IR20: case IR19: case IR18: case IR17: case IR16: case IR15: case IR14: case IR13: case IR12: case IR11: case IR10: case IR9: case IR8: case IR7: case IR6: case IR5: case IR4: case IR3: case IR2: case IR1: /*--- Unhighlight any currently selected button. */ IRButtonOff(&IRButtonSelected); /*--- Set current button to highlight and highlight it. */ IRButtonSelected = (gadget_id - IR1) + 1; IRButtonOn(IRButtonSelected); #if DBG printf("IR-%d\n", (gadget_id - IR1) + 1); #endif if(mode == LEARN) { /*--- Prompt user. */ helptxt("Enter the label name for the control button,", "then press RETURN."); } else { helptxt("Please choose a function button first.", ""); } break; default: mode = NOTHING; printf("Error - Got a hit on an unknown gadget\n"); printf(" Gadget id was: hex: %X decimal: %d\n", gadget_id, gadget_id); break; } /* switch(gadget_id) */ } /* if(message) */ } /* if(class...) */ } /* while(GetMsg) */ #endif /*DEBUG*/ #if DBG printf("\n Timer B control register = %X",ciab.ciacrb); printf("\n buffer = %X", buffer); #endif /*--- Shut down timer B */ Fini: StopTime(); /*--- Turn off the 8520's recognition of the ACK as an interrupt. */ mask = 0x10; /* Hex 10 = 00010000 Should disable the 8520 FLAG interrupt. */ *address = mask; /* Disable the interrupt. */ /*--- Remove the level2 interrupt server from server chain. */ RemoveServer(); /*--- Exit cleanly. */ ShutDown: /*--- Deallocate parallel port resource. Commented out for reasons above. */ /***************** MR_FREEMISCRESOURCE(MR_PARALLELPORT); MR_FREEMISCRESOURCE(MR_PARALLELBITS); *****************/ /*--- Close window and screen. */ #if DEBUG if(Window)CloseWindow(Window); if(Screen)CloseScreen(Screen); #endif /*DEBUG*/ /*--- Close libraries. */ if(GfxBase)CloseLibrary((struct Library *)GfxBase); if(IntuitionBase)CloseLibrary((struct Library *)IntuitionBase); /*--- Free allocated memory. */ #if DEBUG if(workspace != 0)FreeRaster(workspace, 640, 200); #endif /*DEBUG*/ return(0); /* To keep compiler happy. */ } /* End of main(). */ int GetSample() { int idx; /*--- Set up for taking another sample. */ #if DBG printf("\n Setting up for next sample."); #endif for(idx=0; idx= 1) && (*button <= 20)) { /*--- Remove currently selected gadget from list. */ position = RemoveGList(Window, IR[*button-1], 1L); /*--- Unselect the gadget. */ IR[*button-1]->Flags &= (~SELECTED); /*--- Put the gadget back into the same place in the list. */ AddGList(Window, IR[*button-1], (LONG)position, 1L, NULL); /*--- Refresh gadgets on display. */ RefreshGList(IR[*button-1], Window, NULL, 1L); /*--- Set currently selected gadget to none. */ *button = -1; } return(TRUE); } /*---------------------- I R B u t t o n s O n . c -----------------------*/ /* This routine highlights the currently selected control button. */ /*------------------------------------------------------------------------*/ int IRButtonOn(button) int button; /* Button number to highlight. */ { USHORT position; if((button >= 1) && (button <= 20)) { /*--- Remove the selected gadget from list. */ position = RemoveGList(Window, IR[button-1], 1L); /*--- Select the gadget. */ IR[button-1]->Flags |= SELECTED; /*--- Put the gadget back into the same place in the list. */ AddGList(Window, IR[button-1], (LONG)position, 1L, NULL); /*--- Refresh gadgets on display. */ RefreshGList(IR[button-1], Window, NULL, 1L); } return(TRUE); } /*------------------- I R B u t t o n L a b e l . c -------------------*/ /* This routine relabels the selected button. */ /*---------------------------------------------------------------------*/ int IRButtonLabel(buffer, button) UBYTE *buffer; int button; { USHORT position; if((button >= 1) && (button <= 20)) { /*--- Remove the selected gadget from list. */ position = RemoveGList(Window, IR[button-1], 1L); /*--- Change the label. */ strncpy(IR[button-1]->GadgetText->IText , (char *)buffer, 7); /*--- Put the gadget back into the same place in the list. */ AddGList(Window, IR[button-1], (LONG)position, 1L, NULL); /*--- Refresh gadgets on display. */ RefreshGList(IR[button-1], Window, NULL, 1L); } return(TRUE); } /*------------------ G e t P a t t e r n . c ---------------------*/ /* This routine gets a signal sample from the IR receiver and */ /* then tries up to four times to verify it. */ /*----------------------------------------------------------------*/ GetPattern(button) int button; /* Currently selected control button. */ { int it, iz, is, try; int diff[4], match, smallest; #if DBG printf("\n\n **** Storing pattern %d ****", button); #endif /*--- Get a sample. */ GetSample(); /*--- Plot data on screen. */ helptxt("Data received.", ""); /*DPattern(button, 1);*/ DisplayPattern(button, 0); #if DBG printf("\n NSamples=%d", NSamples); #endif /*--- Transfer data to storage. */ #if DBG printf("\n Xferring to pattern memory."); #endif for(iz=0; iz TOLERENCE) { #if DBG printf("\n Samples do not match:%d Please try again.",diff[try]); #endif helptxt("Samples do not match. Please press button again.", ""); if(diff[try] < smallest) { /*--- Store the best pattern so far. */ smallest = diff[try]; for(iz=0; iz