diff --git a/pic/ACT-34B/ACT-34B.c b/pic/ACT-34B/ACT-34B.c new file mode 100644 index 0000000..c37818e --- /dev/null +++ b/pic/ACT-34B/ACT-34B.c @@ -0,0 +1,174 @@ +/* micro-controller firmware fot the Linear ACT-34B remote + Copyright (C) 2014 Kévin Redon + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +/* libraries */ +#define __12f617 +#include +#include + +/* the peripherals connected to the pins */ +#define SWITCH1 _GP0 +#define SWITCH2 _GP3 +// note: SWITCH3 will behave as pressed when SWITCH4 is pressed +#define SWITCH3 _GP1 +#define SWITCH4 _GP2 +// note: CLOCK will be enable also if only TX is enabled +#define CLOCK _GP5 +#define TX _GP4 + +/* simple functions */ +#define clock_on() GPIO |= CLOCK; +#define clock_off() GPIO &= ~CLOCK; +#define tx_on() GPIO |= TX; +#define tx_off() GPIO &= ~TX; +#define sleep() __asm sleep __endasm + +/* variables */ +// a megacode is 3 bytes long (MSB of byte 1 is 1) +# define CODE 0xc917c2 +// transmitting (0: do not transmit, 1: transmit, -1: finish transmiting) +volatile int8_t transmit = 0; + // the 4 phases of the bit (2ms pause, 1ms pulse, 2ms pause, 1ms pulse. only transmit during one of the two pulse periode depending on the bit value) +volatile uint8_t phase = 0; +// save the GPIO state to be able to figure out which changed +volatile last_gpio = GPIO; + +/* configuration bits */ +uint16_t __at(_CONFIG) __CONFIG = _WRT_OFF & // entire memory write protected + _BOREN_OFF & // brown-out reset off + _IOSCFS_4MHZ & // set internal oscillator to 4MHz + _CP_OFF & // no code protection + _MCLRE_OFF & // disable master clear reset + _PWRTE_ON & // enable power-up timer + _WDTE_OFF & // disable watchdog + _INTRC_OSC_NOCLKOUT; // use internal oscillator and both I/O pins + +/* set timer in ms */ +#define TICKS_PER_MS 125UL // the number of timer 1 ticks to wait for 1ms, using the internal 4MHz clock and a prescaler of 8, and hand tuning + +void timer_1ms() { + TMR1ON = 0; // disable timer 1 (to write value safely) + TMR1L = (0xffff-1*TICKS_PER_MS); // set time + TMR1H = (0xffff-1*TICKS_PER_MS)>>8; // set time + TMR1ON = 1; // start timer 1 +} + +void timer_2ms() { + TMR1ON = 0; // disable timer 1 (to write value safely) + TMR1L = (0xffff-2*TICKS_PER_MS); // set time + TMR1H = (0xffff-2*TICKS_PER_MS)>>8; // set time + TMR1ON = 1; // start timer 1 +} + +/* transmit the megacode */ +void megacode (void) { + uint8_t bit = phase/4; + if (transmit != 0) { + if (bit<24) { // transmit bit + if (phase%2) { + uint8_t pulse = (CODE>>(23-bit))&0x01; + if ((phase%4==1 && !pulse) || (phase%4==3 && pulse)) { + tx_on(); + } + timer_1ms(); + } else { + tx_off(); + timer_2ms(); + } + } else if (bit==24) { // 25th bit is a blank + tx_off(); + timer_2ms(); + } else { // restart after 25th bit + phase = 0xff; // phase will be 0 after incrementing + if (transmit == -1) { // stop transmiting if requested + transmit = 0; // stop transmiting + clock_off(); // stop clock + } + timer_1ms(); + } + phase++; // go to next phase + } +} + +/* initialize micro-conroller */ +void init (void) { + ANSEL = 0; // all pins are digital + TRISIO |= SWITCH1|SWITCH2|SWITCH3|SWITCH4; // switches are inputs (per default) + TRISIO &= ~(CLOCK|TX); // all other are outputs + NOT_GPPU = 0; // enable global weak pull-up for inputs + WPU |= SWITCH1|SWITCH3|SWITCH4; // use internal pull-up on switches (the external are weak) + // SWITCH2 pull-up is not enabled because pins is not used as MCLR + GPIO &= ~(CLOCK|TX); // clear output + + IOC |= (SWITCH1|SWITCH2|SWITCH3|SWITCH4); // enable interrupt for the switches + GPIE = 1; // enable interrupt on GPIO + last_gpio = GPIO; // save current state + + T1CON = _T1CKPS1 | _T1CKPS0; // set prescaler to 8 + // 0 is set per default, but just be sure + TMR1ON = 0; // stop timer 1 + TMR1GE = 0; // enable timer 1 + TMR1CS = 0; // use internal clock / 4 (=1MHz) + TMR1IF = 0; // clear interrupt + PIE1 = 1; // enable timer 1 interrupt + PEIE = 1; // enable timer interrupt + + GIE = 1; // enable interrups + +} + +// funcion called on interrupts +// interrupt 0 is only one on PIC12 +static void interrupt(void) __interrupt 0 +{ + if (GPIF) { // pin state changed + last_gpio ^= GPIO; // figure out which GPIO changed + if (last_gpio&SWITCH2) { // switch 1 (bigger button on top right) changed + if (GPIO&SWITCH2) { // button released, stop transmission + if (transmit == 1) { // currently transmitting + transmit = -1; // stop transmitting after last transmition + } + } else { // switch is pressed, start transmission + if (transmit == 0) { // only transmit if code is loaded + transmit = 1; // start transmission procedure + phase = 0; // start from beginning + clock_on(); // start clock and leave it on during the whole transmission + megacode(); // start sending megacode + } + } + } + last_gpio = GPIO; // save current state + GPIF = 0; // clear interrupt + } + if (TMR1IF) { // timer 1 overflow + megacode(); // continue sending megacode + TMR1IF = 0; // clean interrupt + } + +} + +void main (void) +{ + init(); // configure micro-controller + transmit = 0; // disable transmission initialy + + while (1) { // a microcontroller runs forever + if (transmit == 0) { +// sleep(); // sleep to save power. this will shut down timer 1, but button press will wake it up + } + } +} diff --git a/pic/ACT-34B/Makefile b/pic/ACT-34B/Makefile new file mode 100644 index 0000000..eb7e488 --- /dev/null +++ b/pic/ACT-34B/Makefile @@ -0,0 +1,32 @@ +# variables +TARGET = ACT-34B +PIC = 12f617 +# software verion used: +# pk2cmd: 1.21 +# sdcc: 3.4.0 +# gputils: 1.3.0 + +all: off flash on + +# flash program +flash: $(TARGET).hex + pk2cmd -PPIC$(PIC) -F$< -M + +# power on remote +on: + pk2cmd -PPIC$(PIC) -T + +# power off remote +off: + pk2cmd -PPIC$(PIC) -V0 + +# compile program +compile: $(TARGET).hex + +# compile program C source code (includes a default code) +$(TARGET).hex: $(TARGET).c + sdcc --std-c99 --opt-code-size --use-non-free -mpic14 -p$(PIC) $< + +# remove temporary files +clean: + rm -f $(TARGET).hex $(TARGET).lst $(TARGET).asm $(TARGET).adb $(TARGET).o $(TARGET).cod