This repository has been archived on 2024-09-18. You can view files and clone it, but cannot push or open issues or pull requests.
sdp-scheduler/utils.h

447 lines
18 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef SDP_SCHEDULER_UTILS_H
#define SDP_SCHEDULER_UTILS_H
// Все зоны линии
enum Zones {
ZONE_LOAD_1 = 0, // загрузка 0, используется как точка появления барабанов
ZONE_LOAD_2, // загрузка 1, используется как конечная точка барабанов
ZONE_DEGREASING, // обезжиривание
ZONE_WASHING_1A, // промывка 1А
ZONE_WASHING_1B, // промывка 1Б
ZONE_ETCHING_1, // травление 1
ZONE_ETCHING_2, // травление 2
ZONE_WASHING_2A, // промывка 2А
ZONE_WASHING_2B, // промывка 2Б
ZONE_GALVANIZING_1, // цинкование 1
ZONE_GALVANIZING_2, // цинкование 2
ZONE_GALVANIZING_3, // цинкование 3
ZONE_GALVANIZING_4, // цинкование 4
ZONE_GALVANIZING_5, // цинкование 5
ZONE_GALVANIZING_6, // цинкование 6
ZONE_GALVANIZING_7, // цинкование 7
ZONE_GALVANIZING_8, // цинкование 8
ZONE_WASHING_3A, // промывка 3А
ZONE_WASHING_3B, // промывка 3Б
ZONE_PASSIVATION, // пассивация
ZONE_WASHING_4A, // промывка 4A
ZONE_WASHING_4B, // промывка 4Б
ZONE_UNLOAD, // зона выгрузки
};
#define BARRELS_COUNT 10
union barrel_flags {
short raw_word;
struct {
char is_exist: 1;
char is_up: 1; // для панели
char robot: 2; // обслуживающий робот
char is_night: 1; // ночной барабан, имеет такой статус если он в промывке в ночном режиме или в промывке,
// но пока не дождался очереди на выход из ночного режима
char is_empty: 1; // пустой барабан, нужен для работы операции возврата
};
};
struct barrel {
union barrel_flags flags;
short zone;
// программный таймер, тикает сразу у всех барабанов,
short software_timer;
// время процессов
short time_degreasing; // Время обезжиривания
short time_washing_1a; // Время промывки 1А
short time_washing_1b; // Время промывки 1Б
short time_etching; // Время травления
short time_washing_2a; // Время промывки 2А
short time_washing_2b; // Время промывки 2Б
short time_galvanizing; // Время цинкования
short time_washing_3a; // Время промывки 3А
short time_washing_3b; // Время промывки 3Б
short time_passivation; // Время пассивации
short time_washing_4a; // Время промывки 4А
short time_washing_4b; // Время промывки 4Б
};
union robot_regs_mx {
short raw_word;
struct {
char correct_status: 1;
char last_cmd_executed: 1;
char correct_sensor: 1;
char move_to_zone: 1;
char move_to_offset: 1;
char move_to_precise: 1;
char do_correct: 1;
char do_parking: 1;
char hla_left: 1;
char hla_right: 1;
char auto_mode: 1;
char error: 1;
};
};
union robot_regs_dx {
short raw_data[6];
struct {
short current_zone;
short target_zone;
short left_max;
short right_max;
short output_current;
short output_freq;
};
};
union robot_regs_mz {
short raw_word;
struct {
char correct_status: 1;
char last_cmd_executed: 1;
char is_up: 1;
char move_up: 1;
char move_down: 1;
char do_correct: 1;
char hla_up: 1;
char hla_down: 1;
char auto_mode: 1;
char error: 1;
};
};
union robot_regs_dz {
short raw_data[3];
struct {
short current_zone;
short output_current;
short output_freq;
};
};
struct robot_regs {
union robot_regs_mx mx;
union robot_regs_dx dx;
union robot_regs_mz mz;
union robot_regs_dz dz;
};
// NOTE первой командой на любую транзакцию должна стоять команда опустить траверсу (в 22 зоне по идее никогда не закончим)
struct robot_code {
short barrel_id; // если требуются операции с барабаном, то для корректного исполнения нужно указать значение >= 0
short PC; // когда -1, код не выполняется
unsigned short code[16]; // формат кода: [команды] <команда 0>
};
#ifdef __cplusplus
extern "C" {
#endif
#ifdef EMULATOR
extern struct barrel barrels[BARRELS_COUNT];
extern struct robot_regs robot1;
extern struct robot_regs robot2;
extern struct robot_code robot1_code;
extern struct robot_code robot2_code;
// времена для барабанов, нужно копировать их только при создании барабанов
extern short hla_time_degreasing;
extern short hla_time_washing_1a;
extern short hla_time_washing_1b;
extern short hla_time_etching;
extern short hla_time_washing_2a;
extern short hla_time_washing_2b;
extern short hla_time_galvanizing;
extern short hla_time_washing_3a;
extern short hla_time_washing_3b;
extern short hla_time_passivation;
extern short hla_time_washing_4a;
extern short hla_time_washing_4b;
// времена скапывания, одинаковые для всех барабанов
extern short hla_time_digging;
extern short hla_time_reagent;
extern short hla_time_washing_1;
extern short hla_time_washing_2;
// выбор зоны промежуточной с панели
extern short hla_exchange_zone;
// выбор отключенных зон
extern short hla_disabled_zones;
extern char hla_robot1_en;
extern char hla_robot2_en;
// пауза для автоматического режима, при паузе идут таймера, но команды не могут быть выданы
extern char auto_mode_pause;
// Кнопки с панели
extern char hla_night_mode;
extern char hla_correct_command;
extern char hla_zinc_again;
// разрешение на работу планировщика
extern char scheduler_en;
// сигнал инициализации планировщика, должен быть установлен по фронту разрешения на работу
extern char scheduler_start_signal;
extern short scheduler_stage;
#else
#define barrels ((struct barrel*)barrels_array)
#define robot1 (*((struct robot_regs*)&robot1_reg_mx))
#define robot2 (*((struct robot_regs*)&robot2_reg_mx))
#define robot1_code (*((struct robot_code*)_robot1_code_struct))
#define robot2_code (*((struct robot_code*)_robot2_code_struct))
// времена для барабанов, нужно копировать их только при создании барабанов
#define hla_time_degreasing _c_hla_time_degreasing
#define hla_time_washing_1a _c_hla_time_washing_1a
#define hla_time_washing_1b _c_hla_time_washing_1b
#define hla_time_etching _c_hla_time_etching
#define hla_time_washing_2a _c_hla_time_washing_2a
#define hla_time_washing_2b _c_hla_time_washing_2b
#define hla_time_galvanizing _c_hla_time_galvanizing
#define hla_time_washing_3a _c_hla_time_washing_3a
#define hla_time_washing_3b _c_hla_time_washing_3b
#define hla_time_passivation _c_hla_time_passivation
#define hla_time_washing_4a _c_hla_time_washing_4a
#define hla_time_washing_4b _c_hla_time_washing_4b
// времена скапывания, одинаковые для всех барабанов
#define hla_time_digging _c_hla_time_digging
#define hla_time_reagent _c_hla_time_reagent
#define hla_time_washing_1 _c_hla_time_washing_1
#define hla_time_washing_2 _c_hla_time_washing_2
#define hla_exchange_zone _c_hla_exchange_zone
#define hla_disabled_zones _c_hla_disabled_zones
#define hla_robot1_en _c_hla_robot1_en
#define hla_robot2_en _c_hla_robot2_en
#define auto_mode_pause _c_auto_mode_pause
#define hla_night_mode _c_hla_night_mode
#define hla_zinc_again _c_hla_zinc_again
#define hla_correct_command _c_hla_correct_command
#define scheduler_stage _c_scheduler_stage
#endif
extern const short NIGHT_ZONES[9];
/* ======================== ROBOT CODE ======================== */
#define ROBOT_CMD_MASK 0xF000U
#define ROBOT_CMD_END_code 0x0000U
#define ROBOT_CMD_MOVE_TO_ZONE_code 0x1000U
#define ROBOT_CMD_MOVE_OFF_code 0x2000U
#define ROBOT_CMD_MOVE_ACCURATE_code 0x3000U
#define ROBOT_CMD_UP_code 0x4000U
#define ROBOT_CMD_DOWN_code 0x5000U
#define ROBOT_CMD_WAIT_code 0x6000U
#define ROBOT_CMD_TMR_SET_code 0x7000U
#define ROBOT_CMD_SET_LOCK_ZONE_code 0x8000U
#define ROBOT_CMD_CORRECT_AXIS_code 0x9000U
#define ROBOT_CMD_INC_ZONE_code 0xA000U
// перемещение с барабаном
#define ROBOT_WITH_BARREL 0x0800U
// опции зон
#define ROBOT_ZONE_ETCH 0x0400U
#define ROBOT_ZONE_GAL 0x0200U
#define ROBOT_ZONE_PARKING 0x0100U
// опции коррекции осей
#define ROBOT_AXIS_X 1
#define ROBOT_AXIS_Z 2
// макросы для генерации команд
#define ROBOT_CMD_END() (ROBOT_CMD_END_code)
#define ROBOT_CMD_MOVE_TO_ZONE(zone) (ROBOT_CMD_MOVE_TO_ZONE_code | (unsigned short)(zone & 0x00FF))
#define ROBOT_CMD_MOVE_TO_ZONE_WITH_BARREL(zone) (ROBOT_CMD_MOVE_TO_ZONE_code | ROBOT_WITH_BARREL | (unsigned short)(zone & 0x00FF))
#define ROBOT_CMD_MOVE_TO_PARKING() (ROBOT_CMD_MOVE_TO_ZONE_code | ROBOT_ZONE_PARKING)
#define ROBOT_CMD_MOVE_OFF() (ROBOT_CMD_MOVE_OFF_code)
#define ROBOT_CMD_MOVE_ACCURATE() (ROBOT_CMD_MOVE_ACCURATE_code)
#define ROBOT_CMD_UP() (ROBOT_CMD_UP_code)
#define ROBOT_CMD_UP_WITH_BARREL() (ROBOT_CMD_UP_code | ROBOT_WITH_BARREL)
#define ROBOT_CMD_DOWN() (ROBOT_CMD_DOWN_code)
#define ROBOT_CMD_DOWN_WITH_BARREL() (ROBOT_CMD_DOWN_code | ROBOT_WITH_BARREL)
#define ROBOT_CMD_WAIT(time) (ROBOT_CMD_WAIT_code | (unsigned short)(time & 0x0FFF))
#define ROBOT_CMD_TMR_SET(time) ((ROBOT_CMD_TMR_SET_code) | (unsigned short)(time & 0x0FFF))
#define ROBOT_CMD_SET_LOCK_ZONE(zone) ((ROBOT_CMD_SET_LOCK_ZONE_code) | (unsigned short)(zone & 0x00FF))
#define ROBOT_CMD_CORRECT_AXIS(axis) (ROBOT_CMD_CORRECT_AXIS_code | (unsigned short)axis)
#define ROBOT_CMD_INC_ZONE(arg) (ROBOT_CMD_INC_ZONE_code | (unsigned short)(arg))
/* ======================== DISABLED ZONES ======================== */
#define DISABLED_ETCH_1 0x0001
#define DISABLED_ETCH_2 0x0002
#define DISABLED_ETCH 0x0003
#define DISABLED_GAL_1 0x0004
#define DISABLED_GAL_2 0x0008
#define DISABLED_GAL_3 0x0010
#define DISABLED_GAL_4 0x0020
#define DISABLED_GAL_5 0x0040
#define DISABLED_GAL_6 0x0080
#define DISABLED_GAL_7 0x0100
#define DISABLED_GAL_8 0x0200
#define DISABLED_GAL 0x03FC
/* ======================== IO ======================== */
#define ROBOT1_X 1
#define ROBOT1_Z 2
#define ROBOT2_X 3
#define ROBOT2_Z 4
#define VFD_REG_D0_ADDR 4096
#define VFD_REG_M0_ADDR 2048
#define MB_CMD_WRITE_FLAG 5
#define MB_CMD_WRITE_REG 6
#define VFD_REG_D0_ADDR 4096
#define VFD_REG_M0_ADDR 2048
// смещение регистров M относительно M0
#define ROBOT_Z_CORRECT_STATUS_OFFSET 0
#define ROBOT_Z_CMD_EXECUTED_OFFSET 1
#define ROBOT_Z_CMD_UP_OFFSET 3
#define ROBOT_Z_CMD_DOWN_OFFSET 4
#define ROBOT_Z_CMD_CORRECT_OFFSET 5
#define ROBOT_X_CORRECT_STATUS_OFFSET 0
#define ROBOT_X_CMD_EXECUTED_OFFSET 1
#define ROBOT_X_CORRECT_SENSOR_OFFSET 2
#define ROBOT_X_CMD_MOVE_TO_ZONE_OFFSET 3
#define ROBOT_X_CMD_MOVE_TO_OFF_POS_OFFSET 4 // встать в смещенную позицию
#define ROBOT_X_CMD_MOVE_TO_COR_POS_OFFSET 5 // встать в точную позицию
#define ROBOT_X_CMD_CORRECT_OFFSET 6
#define ROBOT_X_CMD_CMD_PARKING_OFFSET 7
// смещение регистров D относительно D0
#define ROBOT_X_TARGET_ZONE_OFFSET 2
// адреса регистров в частотнике
#define ROBOT_Z_CORRECT_STATUS_ADDR VFD_REG_M0_ADDR
#define ROBOT_Z_CMD_EXECUTED_ADDR (VFD_REG_M0_ADDR + 1)
#define ROBOT_Z_CMD_UP_ADDR (VFD_REG_M0_ADDR + 3)
#define ROBOT_Z_CMD_DOWN_ADDR (VFD_REG_M0_ADDR + 4)
#define ROBOT_Z_CMD_CORRECT_ADDR (VFD_REG_M0_ADDR + 5)
#define ROBOT_X_CORRECT_STATUS_ADDR VFD_REG_M0_ADDR
#define ROBOT_X_CMD_EXECUTED_ADDR (VFD_REG_M0_ADDR + ROBOT_X_CMD_EXECUTED_OFFSET)
#define ROBOT_X_CORRECT_SENSOR_ADDR (VFD_REG_M0_ADDR + ROBOT_X_CORRECT_SENSOR_OFFSET)
#define ROBOT_X_CMD_MOVE_TO_ZONE_ADDR (VFD_REG_M0_ADDR + ROBOT_X_CMD_MOVE_TO_ZONE_OFFSET)
#define ROBOT_X_CMD_MOVE_TO_OFF_ADDR (VFD_REG_M0_ADDR + ROBOT_X_CMD_MOVE_TO_OFF_POS_OFFSET)
#define ROBOT_X_CMD_MOVE_TO_COR_ADDR (VFD_REG_M0_ADDR + ROBOT_X_CMD_MOVE_TO_COR_POS_OFFSET)
#define ROBOT_X_CMD_CORRECT_ADDR (VFD_REG_M0_ADDR + ROBOT_X_CMD_CORRECT_OFFSET)
#define ROBOT_X_CMD_PARKING_ADDR (VFD_REG_M0_ADDR + ROBOT_X_CMD_CMD_PARKING_OFFSET)
#define ROBOT_X_TARGET_ZONE_ADDR (VFD_REG_D0_ADDR + ROBOT_X_TARGET_ZONE_OFFSET)
/* ======================== UTILS FUNCTIONS ======================== */
/**
* Занята ли зона. Учитываются только барабаны, которые внизу
* @param zone зона для обнаружения
* @return true если занята, в противном случае false
*/
char zone_is_busy(short zone);
#define ROBOT_1 1
#define ROBOT_2 2
#define ROBOT_NONE -1
/**
* Функция, определяющая можно ли переместить барабан и куда его нужно переместить.
* @param bar указатель на барабан
* @param robot_id ID робота, нужно передавать всегда, в режиме одного робота учитывается время, в режиме двух роботов
* учитываются рабочие границы роботов. Для отключения учета времени и границ следует передать <code>ROBOT_NONE</code>.
* @return Зону, куда нужно переместить барабан. Если значение < 0, то барабан переместить в данный момент невозможно.
*/
short can_move(struct barrel *bar, char robot_id);
/**
* Получить приоритет для операции перемещения барабана. Учитывает взаимное положение барабанов на линии и аттрибуты барабана
* @note Вызывать следует только если барабан подлежит перемещению (<code>can_move</code> вернул значение >= 0)
* @param barrel_id номер барабана, для которого нужно вычислить приоритет.
* @return Приоритет операции. Чем больше число тем выше приоритет.
*/
short get_operation_priority(short barrel_id);
/**
* Удаление барабана из зоны, учитывает блокировку барабана роботом и положение барабана (нельзя удалить висящий барабан).
* @param zone Зона, из которой требуется удалить барабана.
* @return true, если барабан был удален, в противном случае false.
*/
char remove_barrel_from_zone(short zone);
/**
* Создание операции на перемещение барабана.
* @param barrel_id индекс барабана в структуре барабана, функцией напрямую не учитывается, но копируется в структуру кода робота
* @param start_zone зона, откуда нужно переместить барабан
* @param dest_zone зона, куда нужно переместить барабан (если ZONE_PASSIVATION то фактически после операции барабан окажется в зоне промывки 4а)
* @param robot_id ID робота, который должен выполнить операцию
*/
void create_operation(short barrel_id, const short start_zone, const short dest_zone, const short robot_id);
/**
* Активна ли зона цинкования или травления
* @param zone ROBOT_ZONE_ETCH или ROBOT_ZONE_GAL. Для других значений функция вернет false.
* @return true, если выбранная зона цинкования или травления доступна
*/
char is_accessible_zone(short zone);
/**
* Инкрементировать зону цинкования или зону травления.
* @param zone ROBOT_ZONE_ETCH или ROBOT_ZONE_GAL. Для других значений функция вернет false.
* @return true, если существует хотя бы одна зона, куда можно положить баран. При любых ошибках вернет false.
*/
char increment_zone(short zone);
/**
* Получение первой ночной зоны, то есть зоны куда нужно ложить ночной барабан
* @return номер зоны, либо -1 если зона занята или еще нужна для обслуживания других барабанов
*/
short get_first_night_zone();
#ifdef EMULATOR
/**
* Вывод структуры кода робота, работает только в эмуляторе.
* @param code структура кода робота, именно ее и будет выводить функция
* @param robot_id ID робота (1 или 2), нужно для вывода отладочной информации
* @param fd file descriptor, устройство куда нужно записать весь вывод
*/
void debug_print_robot_code(const struct robot_code *code, const short robot_id, int fd);
#endif
#ifdef __cplusplus
}
#endif
#endif //SDP_SCHEDULER_UTILS_H