Перейти к содержанию
    

Декодер манчестерского кода на ассемблере

Введение:

Взял себе плату BeagleBone с процессором AM335x. У него на борту есть два реал-тайм ядра PRU (PRU0 и PRU1). Хочу через GPIO научить их обмениваться данными. Данный кодируются в манчестерском коде. У прушек свой компилятор - pasm. Частота работы ядер 200 МГц

 

Проблема:

Понятно, что алгоритм передачи написать не так сложно: сначала переводит байт в МК(манчестерский код), потом передаем бит за битом. С приемом, естественно, немного сложнее, но идея проста: принимаем стартовую последовательность, а далее делаем некоторое количество отсчетов за 1/3 периода. Записываем значение счетчика и сравниваем с следующим отсчетом.

В коде я сделал немного иначе и вместо 1/3 взял чуть меньше 1/2. Вот пример кода:

LISEN:                            // прослушка линии
    QBEQ START, r9, 15    // если принято 16 бит, то выход
    MOV r2, 0                   // обнуляем счетчик длительности 
    QBBC CLR0, IN           // проверка на 0-ь. 
    QBBS SET1, IN           // проверка на 1-цу
CLR0:                // метка установки 0
    ADD r2, r2, 1        // счетчик длительности
    QBBC CLR0, IN        // проверяет текущий уровень
    QBGE CLR10, r2, 50   //  считаем, что  половина периода -  150 нс. Тогда переход на CLR10, если 0 длится больше 150
    CLR r5.t16                // устанавливаем 0
    LSR r5, r5, 1        // сдвигаем
    ADD r9, r9, 1        // счетчик принятых бит
    QBA LISEN        // возвращаемся на прослушку
CLR10:                // пришло два нуля
    CLR r5.t16        // устанавливаем и сдвигаем
    LSR r5, r5, 1        
    CLR r5.t16
    LSR r5, r5, 1
    ADD r9, r9, 2        // принято 2 бита
    QBA LISEN        // возврат на прослушку
//--------------------------------------------------------------------------
SET1:                // метка установки 1
    ADD r2, r2, 1        // счетчик длительности
    QBBS SET1, IN        // проверяет текущий уровень
    QBGE SET01, r2, 50   //  считаем, что период 150 нс.
    SET r5.t16                // устанавливаем 1
    LSR r5, r5, 1        // сдвигаем
    ADD r9, r9, 1        // счетчик принятых бит
    QBA LISEN                // возвращаемся на прослушку
SET01:                // пришло две 1-ы
    SET r5.t16        // устанавливаем и сдвигаем
    LSR r5, r5, 1        
    SET r5.t16
    LSR r5, r5, 1
    ADD r9, r9, 2        // принято 2 бита
    QBA LISEN        // возврат на прослушку

Код, естественно, работает не совсем корректно, поэтому для теста я написал тестовую программку для 4-ех бит, а именно ситуаций, когда в линии 0011, 1100, 1001, 0110. Мне думается, что весь мой косяк в том, что я не правильно произвожу выборку.

 

Глоссарии:

SBCO - команда записи данных в память

QBBS, QBBC - команды перехода на метку, если 1 или 0

QBNE - переход на метку, пока не ровно.

QBGE - переход на метку, если больше.

 

Недочеты кода:

переход на метки SET01 и CLR10 происходит в тот момент, когда переход от 1 к 0, тогда в линии у нас 1001, либо от 0 к 1, тогда 0110. . Как только условия соблюдены, у нас происходит ещё 9 тактов - это доп. смещение, которое ломает общий алгоритм. Либо нужно увеличивать длительность сигнала, либо придумать компенсацию. А может я ошибаюсь..

 

UPD: перед входом к метке LISEN стоит команда WBS IN. Вход в метку будет в тот момент, когда по линии придет единица. Если смогу принять одни байт информации, то можно будет уже перейти на пакеты.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Передатчик можно написать, исходя из кода приемника. Это не самое трудное.

Далее, нужно добавить пару строчек перевода кода манчестера в классический.

// приемник для передачи сигнала со скоростью 2 мегабита
.origin 0
.entrypoint PRE

#include "GPIOCTR.hp"
#include "TRSBNI.hp"

#define USR0 21                // led 0
#define USR1 22                // led 1
#define USR2 23                // led 2
#define USR3 24                // led 3
#define GPIO1 0x4804C000    // адресс регистров GPIO1
#define PRU1_ARM_INT 20        // значение прерывания от PRU1 to ARM


#define RAM0 C24        // Локальная память PRU1
#define RAM1 C25        // Локальная память PRU0
#define IN r31.t6        // входной GPIO

//Определим основные регистры
#define REQ r1             // в этот регистр будет помещаться информация от PRU0
#define COUNT r2        // считает колличество принятых байт
#define VALUE r3
//Приветствуем в программа приемника кода на PRU
PRE:
    MOV R4, 2
INIT:
    MOV REQ, 0
    MOV COUNT, 8
    MOV VALUE, 0
    LBCO REQ, RAM0, 0, 1        // выход из программы.
    QBEQ EXIT, REQ, 0
START:
// Знаем, что в линии, если ничего не приходит идет сигнал низкого уровня
// Длительность задержки 45 нс. Проверяющий сигнал между байтами равен 9 мкс
// Или 4.5 HIGH и 4.5 LOW. Для начала будем ждать сигнал от PRU0, что он начал передачу
    
    LBCO REQ, RAM0, 1, 1             // сюда помещаем разрешающее значения 
    QBNE START, REQ, 0            // Пока не будет установлен 0, будет прыгать на старт.
    
// в начале посылки каждого байта будем получать переход из 1 в 0. Задержка кажого сигнала 4.5 мкс
    WBS IN        // ждем 4.5 мкс
    WBC IN        // после этого нужно поставить задержку, равную 100
    CDELAY 101    // компенсация задержки хоста 100+1. CDELAY 1 - 45 нс.
POOL:
    REC9 IN, VALUE, COUNT        //макрос приемника
    SBCO VALUE, RAM0, R4, 1        // запись в память
    ADD R4, R4, 1                // добавляем 1 в счетчик бит
    QBEQ EXIT, R4, 35
    QBA INIT
// Дальше начинают приходить биты с длительностью от 480 до 500 нс (-45 нс)
EXIT:                // Ждем прерывания от хоста и выключаем PRU 
    MOV r31.b0, 20+16
    HALT

 

Синтаксис макроса REC9 (REC9 - это приемник с задержкой 9):

.macro REC9            // Макрос приема данных с задержкой 9            
.mparam IN, OUT, COUNT      // входные параметры: IN - вход GPIO; OUT - выходной регистр;
// COUNT - регистр, содержащий в себе число бит.
RECIVE:
    QBBS SET1X, IN   // проверяем 1 сейчас. Если нет, то сразу переход на 0
    QBEQ BACK, COUNT, 0
SET0X:
    WBC IN        // проверям, точно ли 0.
    CDELAY 9    // ждем 405 НС. До смены остается ещё 30 НС
    WBC IN        // вторая проверка. Debbug точка
    CDELAY 1    // после неё станет ясно, что пришло. Сигнал уже как 20 нс новый.
    QBBC SET00, IN  // пришел 0? Если нет, значит 1-ца. -25 нс.
SET01:            // ЗАписываем переход из 0 в 1
    CLR OUT.t1    // Записываем 01
    SET OUT.t0
    LSL OUT, OUT, 2    //смещаем. -45нс.
    CDELAY 9         // Сигналу осталось минимум 30 нс. -405-40+480
    SUB COUNT, COUNT, 2    // принято 2-а байта. 25 нс.
    CDELAY 1        // -20 нс нового сигнала
    QBA RECIVE        // возвращаемся на прием. -25
SET00:                //записываем переход из 0 в 0
    CLR OUT.t1
    CLR OUT.t0
    LSL OUT, OUT, 2
    CDELAY 9
    SUB COUNT, COUNT, 2
    CDELAY 1
    QBA RECIVE        // возвращаемся на прием -25
SET1X:            // для установки 1-ы и....
    WBS IN        // аналогично с нулем
    CDELAY 9
    WBS IN
    CDELAY 1
    QBBS SET11, IN
SET10:
    SET OUT.t1
    CLR OUT.t0
    LSL OUT, OUT, 2
    CDELAY 9
    SUB COUNT, COUNT, 2
    CDELAY 1
    QBA RECIVE    // переход на прием
SET11:
    SET OUT.t1
    SET OUT.t0
    LSL OUT, OUT, 2
    CDELAY 9
    SUB COUNT, COUNT, 2
    CDELAY 1
    QBA RECIVE     // переход на прием
BACK:            // метка записи значения
    LSR OUT, OUT, 2 // когда приходят последний 2 бита, то он сдвигаются влево. Это необходимо учесть

.endm

 

Тему можно закрывать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вообще, зачем Вам Манчестер? Чем Вам обычный UART не подходит? Вы, что, соединяетесь через трансформатор?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вообще, зачем Вам Манчестер? Чем Вам обычный UART не подходит? Вы, что, соединяетесь через трансформатор?

Для того объекта, с которым будет вестись обмен, не предусмотрен UART для обмена данными. Для этого бы приходилось влазить в "ту" систему. А это, пока что, исключено.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вообще, зачем Вам Манчестер? Чем Вам обычный UART не подходит? Вы, что, соединяетесь через трансформатор?

А вообще, да. Через трансформатор.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...