@@ -925,6 +925,31 @@ describe('timer', () => {
925925 expect ( cpu . cycles ) . toEqual ( 2 ) ;
926926 } ) ;
927927
928+ it ( 'should set OCF1C flag when timer equals OCRC' , ( ) => {
929+ const cpu = new CPU ( new Uint16Array ( 0x1000 ) ) ;
930+ const OCR1C = 0x8c ;
931+ const OCR1CH = 0x8d ;
932+ const OCF1C = 1 << 3 ;
933+ new AVRTimer ( cpu , {
934+ ...timer1Config ,
935+ OCRC : OCR1C ,
936+ OCFC : OCF1C ,
937+ } ) ;
938+ cpu . writeData ( TCNT1H , 0 ) ;
939+ cpu . writeData ( TCNT1 , 0x10 ) ;
940+ cpu . writeData ( OCR1C , 0x11 ) ;
941+ cpu . writeData ( OCR1CH , 0x11 ) ;
942+ cpu . writeData ( TCCR1A , 0x0 ) ; // WGM: (Normal)
943+ cpu . writeData ( TCCR1B , CS00 ) ; // Set prescaler to 1
944+ cpu . cycles = 1 ;
945+ cpu . tick ( ) ;
946+ cpu . cycles = 2 ;
947+ cpu . tick ( ) ;
948+ expect ( cpu . data [ TIFR1 ] ) . toEqual ( OCF1C ) ;
949+ expect ( cpu . pc ) . toEqual ( 0 ) ;
950+ expect ( cpu . cycles ) . toEqual ( 2 ) ;
951+ } ) ;
952+
928953 it ( 'should generate an overflow interrupt if timer overflows and interrupts enabled' , ( ) => {
929954 const cpu = new CPU ( new Uint16Array ( 0x1000 ) ) ;
930955 new AVRTimer ( cpu , timer1Config ) ;
@@ -1034,6 +1059,55 @@ describe('timer', () => {
10341059 expect ( gpioCallback ) . toHaveBeenCalledWith ( 2 , PinOverrideMode . Toggle ) ;
10351060 } ) ;
10361061
1062+ it ( 'should toggle OC1C on Compare Match' , ( ) => {
1063+ const OCR1C = 0x8c ;
1064+ const OCR1CH = 0x8d ;
1065+ const OCF1C = 1 << 3 ;
1066+ const { program, lines, instructionCount } = asmProgram ( `
1067+ ; Set waveform generation mode (WGM) to Normal, top 0xFFFF
1068+ LDI r16, 0x04 ; TCCR1A = (1 << COM1C0);
1069+ STS ${ TCCR1A } , r16
1070+ LDI r16, 0x1 ; TCCR1B = (1 << CS00);
1071+ STS ${ TCCR1B } , r16
1072+ LDI r16, 0x0 ; OCR1CH = 0x0;
1073+ STS ${ OCR1CH } , r16
1074+ LDI r16, 0x4a ; OCR1C = 0x4a;
1075+ STS ${ OCR1C } , r16
1076+ LDI r16, 0x0 ; TCNT1H = 0x0;
1077+ STS ${ TCNT1H } , r16
1078+ LDI r16, 0x49 ; TCNT1 = 0x49;
1079+ STS ${ TCNT1 } , r16
1080+
1081+ NOP ; TCNT1 will be 0x49
1082+ NOP ; TCNT1 will be 0x4a
1083+ ` ) ;
1084+
1085+ const cpu = new CPU ( program ) ;
1086+ new AVRTimer ( cpu , {
1087+ ...timer1Config ,
1088+ OCRC : OCR1C ,
1089+ OCFC : OCF1C ,
1090+ compPortC : portBConfig . PORT ,
1091+ compPinC : 3 ,
1092+ } ) ;
1093+
1094+ // Listen to Port B's internal callback
1095+ const portB = new AVRIOPort ( cpu , portBConfig ) ;
1096+ const gpioCallback = jest . spyOn ( portB , 'timerOverridePin' ) ;
1097+
1098+ const nopCount = lines . filter ( ( line ) => line . bytes == nopOpCode ) . length ;
1099+ const runner = new TestProgramRunner ( cpu ) ;
1100+ runner . runInstructions ( instructionCount - nopCount ) ;
1101+
1102+ expect ( cpu . readData ( TCNT1 ) ) . toEqual ( 0x49 ) ;
1103+ expect ( gpioCallback ) . toHaveBeenCalledWith ( 3 , PinOverrideMode . Enable ) ;
1104+ gpioCallback . mockClear ( ) ;
1105+
1106+ runner . runInstructions ( 1 ) ;
1107+ expect ( cpu . readData ( TCNT1 ) ) . toEqual ( 0x4a ) ;
1108+ expect ( gpioCallback ) . toHaveBeenCalledWith ( 3 , PinOverrideMode . Toggle ) ;
1109+ } ) ;
1110+
10371111 it ( 'should only update OCR1A when TCNT1=BOTTOM in PWM Phase/Frequency Correct mode (issue #76)' , ( ) => {
10381112 const { program, instructionCount } = asmProgram ( `
10391113 LDI r16, 0x0 ; OCR1AH = 0x0;
0 commit comments