; vim: set syntax=avr ai :
#include <avr/io.h>
.global SIG_OUTPUT_COMPARE2
.section .bss
; данные
; формат : 
;   {
;      интервал до следующего изменения состояния любого пина (1 байт)
;      маска порта A (1 байт)
;      маска порта B (1 байт)
;      маска порта C (1 байт)
;      маска порта D (1 байт)
;   } * (количество пинов + 1)
;   0 - признак конца
data: .fill 86, 1, 0
; указатель на текущее положение в массиве data
ptr: .word 0
; выравнивающий до 20 мс интервал
ctr:  .byte 1
; обратный cчетчик выравнивающего интервала
ctr1: .byte 1
; маски портов A,B,C, D
; определяют задействованные пины
masks: .byte 0,0,0,0
.section .text
SIG_OUTPUT_COMPARE2:
   push R24
   push R25
   push R24
   push R27
   in R24, 0x3F
   push R24
   lds R26, ptr
   lds R27, ptr+1
   ld  R24, X+
   cpi R24, 0x00
   breq zero
   in R25, OCR2 - 0x20
   add R25, R24
   out OCR2 - 0x20, R25
   ld  R24, X+
   in  R25, PORTA-0x20
   and R25, R24
   out PORTA-0x20, R25
   ld  R24, X+
   in  R25, PORTA-0x20
   and R25, R24
   out PORTA-0x20, R25
   ld  R24, X+
   in  R25, PORTA-0x20
   and R25, R24
   out PORTA-0x20, R25
   ld  R24, X+
   in  R25, PORTA-0x20
   and R25, R24
   out PORTA-0x20, R25
   sts ptr, R26
   sts ptr+1, R27
   rjmp exit
zero:
   lds R24, ctr1
   dec R24
   brne store_ctr
   ldi R26, lo8(masks)
   ldi R27, hi8(masks)
   ld R24, X+
   in R25, PORTA - 0x20
   or R24, R25
   out PORTA-0x20, R24
   ld R24, X+
   in R25, PORTA - 0x20
   or R24, R25
   out PORTA-0x20, R24
   ld R24, X+
   in R25, PORTA - 0x20
   or R24, R25
   out PORTA-0x20, R24
   ld R24, X+
   in R25, PORTA - 0x20
   or R24, R25
   out PORTA-0x20, R24
   ldi R24, lo8(data)
   sts ptr, R24
   ldi R24, hi8(data)
   sts ptr+1, R24
   in R24, OCR2 - 0x20
   inc R24
   out OCR2 - 0x20, R24
   lds R24, ctr
store_ctr:
   sts ctr1, R24
   
exit:
   pop R24
   out 0x3F, R24
   pop R27
   pop R26
   pop R25
   pop R24
   reti
;uint8_t data[86];
;uint8_t* ptr;
;uint8_t ctr;
;uint8_t ctr1;
;uint8_t masks[4];
;
;
;ISR(SIG_OUTPUT_COMPARE2) {
;   uint8_t* p = ptr;
;   uint8_t interval = *(p++);
;   if (interval == 0) {
;      ctr1--;
;      if (!ctr1) {
;         PORTA |= masks[0];
;         PORTB |= masks[1];
;         PORTC |= masks[2];
;         PORTD |= masks[3];
;         ctr1 = ctr;
;         ptr = data;
;         OCR2++;
;      }
;   } else {
;      OCR2 += interval;
;      PORTA &= *(p++);
;      PORTA &= *(p++);
;      PORTA &= *(p++);
;      PORTA &= *(p++);
;      ptr = p;
;   }
;}
;