// led blink example Copyright (C) 2014 Diego Herranz #define NO_BIT_DEFINES #include #include #include // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN), // disable watchdog, // and DO NOT disable low voltage programming. // The rest of fuses are left as default. __code uint16_t __at (_CONFIG1) __configword = _FOSC_INTOSC & _CLKOUTEN_OFF & _WDTE_OFF & _BOREN_ON & _CP_OFF; #define LED_PORT PORTAbits.RA5 #define HASCH PIR1bits.RCIF // board layout: // mosfets clockwise from power feed: // RA5, RA4, RC2, RC3 // 'input' pin: RC5 // microsecond delay. static inline void delay(uint8_t us) { TMR1L = 0; while(TMR1L < us && !HASCH); } #define ADDTOUINT16(REG, LIT) __asm \ BANKSEL REG \ MOVLW LIT \ ADDWF _##REG##L, F \ CLRW \ ADDWFC _##REG##H, F \ __endasm #define SUBFROMUINT16(REG, LIT) __asm \ BANKSEL REG \ MOVLW LIT \ SUBWF _##REG##L, F \ CLRW \ SUBWFB _##REG##H, F \ __endasm #define PPSO_PWM1 3 #define STX 0x02 #define ETX 0x03 uint8_t animating = 0; struct animate_data { uint8_t stepH; uint8_t stepL; uint8_t countH; uint8_t countL; uint8_t interval; } animate_data[4]; void handle_input(unsigned char input) { static uint8_t cnt = 0; static uint8_t buf[7]; // STX CMD A B C D PARITY ETX // STX 01__ abcd PWMxDCH PWMxDCL PWMxPRH PWMxPRL ignored PARITY ETX // abcd = applicable pwm's // STX 11__ abcd stepH stepL countH countL interval PARITY ETX switch (cnt) { case 0: if (input == STX) { cnt++; } return; case 1: case 2: case 3: case 4: case 5: case 6: buf[cnt - 1] = input; cnt++; return; case 7: // check parity cnt++; return; case 8: cnt = 0; if (input != ETX) return; if ((buf[0] & 0xC0) == 0x40) { // echo -n -e '\x02O\x90\x13\xFF\xFF\x00\x00\x03' > /dev/ttyUSB0 // SET packet if (buf[0] & 0x8) { // A PWM1DCH = buf[1]; PWM1DCL = buf[2]; PWM1PRH = buf[3]; PWM1PRL = buf[4]; PWM1LDCON = 0x80; // load armed } if (buf[0] & 0x4) { // B } if (buf[0] & 0x2) { // C } if (buf[0] & 0x1) { // D } return; } if ((buf[0] & 0xC0) == 0xC0) { // ANIMATE packet if (buf[0] & 0x8) { // A animate_data[0].stepH = buf[1]; animate_data[0].stepL = buf[2]; animate_data[0].countH = buf[3]; animate_data[0].countL = buf[4]; animate_data[0].interval = buf[5]; animating |= 1; } } } } unsigned char getch() { // will freeze if you call this without any byte being available while(PIR1bits.RCIF == 0); PIR1bits.RCIF = 0; // framing error: TODO // if (RCSTAbits.FERR) yolo // deal with overflow error // TODO: should you do this before reading RCREG? if (RCSTAbits.OERR) { RCSTAbits.CREN = 0; RCSTAbits.CREN = 1; } return RCREG; } // messages: // set PR DC // fade period step void main(void) { OSCCON = 0xf0; TRISCbits.TRISC5 = 1; T1CON = 0x31; // timer1 at 1 mhz, so 1us ANSELA = 0; ANSELC = 0; TRISA = 0; //SLRCONC = 0; LED_PORT = 0; PWM1CLKCON = 0x00; // From Fosc w/o prescaler PWM1PRH = PWM1PRL = 0xFF; // period: 32 mhz / 65535 = 488 Hz PWM1PH = 0; PWM1DCH = PWM1DCL = 0; PWM1OF = 0; PWM1INTE = 0x00; // no interrupts enabled PWM1INTF = 0x00; // clear interrupt flag PWM1LDCON = 0x80; // load armed PWM1OFCON = 0x00; // independent run mode PWM1CON = 0x80; // enable, standard PWM mode, active high output RA5PPS = PPSO_PWM1; BAUDCONbits.BRG16 = 1; TXSTAbits.BRGH = 0; SPBRGH = 3; // 832, baud rate 2400.96 SPBRGL = 64; RCSTAbits.CREN = 1; TXSTAbits.SYNC = 0; RCSTAbits.SPEN = 1; while(1) { if (HASCH) handle_input(getch()); if (animating & 0x1) { ADDTOUINT16(PWM1DC, 1); PWMLD = 1; } delay(50); } /* while(1) { */ /* while (PWM1DCL < 0xFF || PWM1DCH < 0xFE) { */ /* ADDTOUINT16(PWM1DC, 1); */ /* PWMLD = 1; */ /* delay(50); */ /* } */ /* while (PWM1DCL > 0 || PWM1DCH > 0) { */ /* SUBFROMUINT16(PWM1DC, 1); */ /* PWMLD = 1; */ /* delay(50); */ /* } */ /* } */ }