nexa/nexa_new.c

264 lines
6.1 KiB
C
Raw Normal View History

2020-04-25 17:55:38 +00:00
/*
* Copyright (c) 2012, Jonas Widén (jonas.widen@widens.eu)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "nexa_new.h"
#include <stdint.h>
#include <unistd.h>
#include <wiringPi.h>
#define NEXA_DELAY_HIGH 250
#define NEXA_DELAY_ZERO 1250
#define NEXA_DELAY_ONE 250
#define NEXA_DELAY_SYNC 2500
#define NEXA_RESENDS 6
#define NEXA_CLASS_1 (0x5)
#define NEXA_CLASS_2 (0x6)
#define NEXA_CLASS_3 (0x9)
#define NEXA_CLASS_4 (0xa)
static void send_zero(void)
{
digitalWrite(NEXA_PIN, HIGH);
usleep(NEXA_DELAY_HIGH);
digitalWrite(NEXA_PIN, LOW);
usleep(NEXA_DELAY_ZERO);
}
static void send_one(void)
{
digitalWrite(NEXA_PIN, HIGH);
usleep(NEXA_DELAY_HIGH);
digitalWrite(NEXA_PIN, LOW);
usleep(NEXA_DELAY_ONE);
}
static void send_sync(void)
{
digitalWrite(NEXA_PIN, HIGH);
usleep(NEXA_DELAY_HIGH);
digitalWrite(NEXA_PIN, LOW);
usleep(NEXA_DELAY_SYNC);
}
static void send_nibble(uint8_t nibble)
{
if (nibble & 0x08) send_one(); else send_zero();
if (nibble & 0x04) send_one(); else send_zero();
if (nibble & 0x02) send_one(); else send_zero();
if (nibble & 0x01) send_one(); else send_zero();
}
static void send_id(void)
{
uint8_t i;
uint8_t id[7] = {0x96, 0xa5, 0x55, 0xa5, 0x55, 0x55, 0x6};
for (i = 0; i < 7; ++i) {
if (i < 6) {
send_nibble((id[i] >> 4) & 0x0f);
}
send_nibble(id[i] & 0x0f);
}
}
static void send_group(bool group_mode)
{
if (group_mode) {
send_zero();
send_one();
}
else {
send_one();
send_zero();
}
}
static void send_activation(nexa_activation_t mode)
{
switch(mode) {
case NEXA_ACTIVATION_OFF:
send_one();
send_zero();
break;
case NEXA_ACTIVATION_ON:
send_zero();
send_one();
break;
case NEXA_ACTIVATION_DIM:
send_one();
send_one();
break;
default:
send_one();
send_zero();
break;
}
}
static void send_dim_level(nexa_dim_level_t level)
{
switch(level) {
case NEXA_DIM_LEVEL_1:
send_nibble(NEXA_CLASS_1);
send_nibble(NEXA_CLASS_2);
break;
case NEXA_DIM_LEVEL_2:
send_nibble(NEXA_CLASS_3);
send_nibble(NEXA_CLASS_2);
break;
case NEXA_DIM_LEVEL_3:
send_nibble(NEXA_CLASS_2);
send_nibble(NEXA_CLASS_2);
break;
case NEXA_DIM_LEVEL_4:
send_nibble(NEXA_CLASS_4);
send_nibble(NEXA_CLASS_2);
break;
case NEXA_DIM_LEVEL_5:
send_nibble(NEXA_CLASS_1);
send_nibble(NEXA_CLASS_4);
break;
case NEXA_DIM_LEVEL_6:
send_nibble(NEXA_CLASS_3);
send_nibble(NEXA_CLASS_4);
break;
case NEXA_DIM_LEVEL_7:
send_nibble(NEXA_CLASS_2);
send_nibble(NEXA_CLASS_4);
break;
case NEXA_DIM_LEVEL_8:
send_nibble(NEXA_CLASS_4);
send_nibble(NEXA_CLASS_4);
break;
case NEXA_DIM_LEVEL_9:
send_nibble(NEXA_CLASS_1);
send_nibble(NEXA_CLASS_3);
break;
case NEXA_DIM_LEVEL_10:
send_nibble(NEXA_CLASS_3);
send_nibble(NEXA_CLASS_3);
break;
case NEXA_DIM_LEVEL_11:
send_nibble(NEXA_CLASS_2);
send_nibble(NEXA_CLASS_3);
break;
case NEXA_DIM_LEVEL_12:
send_nibble(NEXA_CLASS_4);
send_nibble(NEXA_CLASS_3);
break;
case NEXA_DIM_LEVEL_13:
send_nibble(NEXA_CLASS_2);
send_nibble(NEXA_CLASS_1);
break;
case NEXA_DIM_LEVEL_14:
send_nibble(NEXA_CLASS_4);
send_nibble(NEXA_CLASS_1);
break;
case NEXA_DIM_LEVEL_15:
send_nibble(NEXA_CLASS_3);
send_nibble(NEXA_CLASS_1);
break;
case NEXA_DIM_LEVEL_16:
send_nibble(NEXA_CLASS_1);
send_nibble(NEXA_CLASS_1);
break;
}
}
static void send_channel(nexa_channel_t channel)
{
switch(channel) {
case NEXA_CHANNEL_1:
send_nibble(NEXA_CLASS_1);
break;
case NEXA_CHANNEL_2:
send_nibble(NEXA_CLASS_2);
break;
case NEXA_CHANNEL_3:
send_nibble(NEXA_CLASS_3);
break;
case NEXA_CHANNEL_4:
send_nibble(NEXA_CLASS_4);
break;
default:
send_nibble(NEXA_CLASS_1);
break;
}
}
static void send_button(nexa_button_t channel)
{
switch(channel) {
case NEXA_BUTTON_1:
send_nibble(NEXA_CLASS_1);
break;
case NEXA_BUTTON_2:
send_nibble(NEXA_CLASS_2);
break;
case NEXA_BUTTON_3:
send_nibble(NEXA_CLASS_3);
break;
case NEXA_BUTTON_4:
send_nibble(NEXA_CLASS_4);
break;
default:
send_nibble(NEXA_CLASS_1);
break;
}
}
void nexa_new_init(void)
{
wiringPiSetup();
pinMode(NEXA_PIN, OUTPUT);
digitalWrite(NEXA_PIN, LOW);
}
void nexa_new_transmit(nexa_channel_t channel,
nexa_button_t button,
nexa_activation_t activation,
nexa_dim_level_t level,
bool group_mode)
{
uint8_t i;
for (i = 0; i < NEXA_RESENDS; ++i) {
send_sync();
send_id();
send_group(group_mode);
send_activation(activation);
send_channel(channel);
send_button(button);
if (activation == NEXA_ACTIVATION_DIM) {
send_dim_level(level);
}
send_zero();
usleep(10);
}
}