Konwersja kodu z Pythona na Java - sprawdzenie

Konwersja kodu z Pythona na Java - sprawdzenie
Burdzi0
  • Rejestracja:prawie 9 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Futurama
  • Postów:887
0

Witajcie!
Mam ostatnio (mówiąc ostatnio mam na myśli 2 tygodnie) bardzo duży problem z moim wyświetlaczem LCD do Raspberry Pi 3.
Żaden znaleziony w necie kod nie działa, wszelkie próby napisania go własnoręcznie legły w gruzach. Pojawił się jednak promyk nadziei - mam kod w Pythonie, który działa. Spróbowałem go przepisać na Javę i spróbować go wykonać.

Hardware

Software
Działający kod w Pythonie

Kopiuj
#!/usr/bin/python

import smbus
import time

# Define some device parameters
I2C_ADDR = 0x3f  # I2C device address
LCD_WIDTH = 16  # Maximum characters per line

# Define some device constants
LCD_CHR = 1  # Mode - Sending data
LCD_CMD = 0  # Mode - Sending command

LCD_LINE_1 = 0x80  # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0  # LCD RAM address for the 2nd line
LCD_LINE_3 = 0x94  # LCD RAM address for the 3rd line
LCD_LINE_4 = 0xD4  # LCD RAM address for the 4th line

LCD_BACKLIGHT = 0x08  # On
# LCD_BACKLIGHT = 0x00  # Off

ENABLE = 0b00000100  # Enable bit

# Timing constants
E_PULSE = 0.0005
E_DELAY = 0.0005

# Open I2C interface
# bus = smbus.SMBus(0)  # Rev 1 Pi uses 0
bus = smbus.SMBus(1)  # Rev 2 Pi uses 1


def lcd_init():
    # Initialise display
    lcd_byte(0x33, LCD_CMD)  # 110011 Initialise
    lcd_byte(0x32, LCD_CMD)  # 110010 Initialise
    lcd_byte(0x06, LCD_CMD)  # 000110 Cursor move direction
    lcd_byte(0x0C, LCD_CMD)  # 001100 Display On,Cursor Off, Blink Off
    lcd_byte(0x28, LCD_CMD)  # 101000 Data length, number of lines, font size
    lcd_byte(0x01, LCD_CMD)  # 000001 Clear display
    time.sleep(E_DELAY)


def lcd_byte(bits, mode):
    # Send byte to data pins
    # bits = the data
    # mode = 1 for data
    #        0 for command

    bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
    bits_low = mode | ((bits << 4) & 0xF0) | LCD_BACKLIGHT

    # High bits
    bus.write_byte(I2C_ADDR, bits_high)
    lcd_toggle_enable(bits_high)

    # Low bits
    bus.write_byte(I2C_ADDR, bits_low)
    lcd_toggle_enable(bits_low)


def lcd_toggle_enable(bits):
    # Toggle enable
    time.sleep(E_DELAY)
    bus.write_byte(I2C_ADDR, (bits | ENABLE))
    time.sleep(E_PULSE)
    bus.write_byte(I2C_ADDR, (bits & ~ENABLE))
    time.sleep(E_DELAY)


def lcd_string(message, line):
    # Send string to display

    message = message.ljust(LCD_WIDTH, " ")

    lcd_byte(line, LCD_CMD)

    for i in range(LCD_WIDTH):
        lcd_byte(ord(message[i]), LCD_CHR)


def main():
    # Main program block

    # Initialise display
    lcd_init()

    while True:
        # Send some test
        lcd_string("RPiSpy         <", LCD_LINE_1)
        lcd_string("I2C LCD        <", LCD_LINE_2)

        time.sleep(3)

        # Send some more text
        lcd_string(">         RPiSpy", LCD_LINE_1)
        lcd_string(">        I2C LCD", LCD_LINE_2)

        time.sleep(3)


if __name__ == '__main__':

    try:
        main()
    except KeyboardInterrupt:
        pass
    finally:
        lcd_byte(0x01, LCD_CMD)

Prawie działający kod w Javie:

Kopiuj
package com.burdzi0;

import com.pi4j.io.i2c.I2CBus;
import com.pi4j.io.i2c.I2CDevice;
import com.pi4j.io.i2c.I2CFactory;
import com.pi4j.io.i2c.I2CFactoryProviderRaspberry;
import com.sun.org.apache.bcel.internal.generic.I2C;

import java.io.IOException;

public class LCDController {

    int I2C_ADDR = 0x3f;
    int LCD_WIDTH = 16;

    int LCD_CHR = 1;
    int LCD_CMD = 0;

    int LCD_LINE_1 = 0x80;
    int LCD_LINE_2 = 0xC0;

    int LCD_BACKLIGHT_ON = 0x08;
    int LCD_BACKLIGHT_OFF = 0x00;

    int ENABLE = 0b00000100;

    int E_PULSE = 5;
    int E_DELAY = 5;

    I2CBus bus;
    I2CDevice dev;

    public LCDController() throws IOException, InterruptedException {
        bus = I2CFactory.getInstance(I2CBus.BUS_1);
        dev = bus.getDevice(I2C_ADDR);
        init();
    }

    void init() throws InterruptedException, IOException {
        lcd_byte(0x33, LCD_CMD);
        lcd_byte(0x32, LCD_CMD);
        lcd_byte(0x06, LCD_CMD);
        lcd_byte(0x0C, LCD_CMD);
        lcd_byte(0x28, LCD_CMD);
        lcd_byte(0x01, LCD_CMD);
        Thread.sleep(E_DELAY);
    }

    void lcd_byte(int bits, int mode) throws IOException, InterruptedException {
        int bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT_ON;
        int bits_low = mode | ((bits << 4) & 0xF0) | LCD_BACKLIGHT_ON;

        dev.write(I2C_ADDR, (byte) bits_high);
        lcd_toggle_enable((byte) bits_high);

        dev.write(I2C_ADDR, (byte) bits_low);
        lcd_toggle_enable((byte) bits_low);
    }

    void lcd_toggle_enable(byte bits) throws InterruptedException, IOException {
        Thread.sleep(E_DELAY);
        dev.write(I2C_ADDR, (byte) (bits | ENABLE));
        Thread.sleep(E_PULSE);
        dev.write(I2C_ADDR, (byte) (bits & ~ENABLE));
        Thread.sleep(E_DELAY);
    }

    void lcd_string(String message, int line) throws IOException, InterruptedException {
        lcd_byte(line, LCD_CMD);
        for (int i = 0; i < LCD_WIDTH; i++) {
            lcd_byte(message.charAt(i), LCD_CHR);
        }
    }

    public static void main(String[] args) {
        LCDController lcd = null;
        try {
            lcd = new LCDController();
            lcd.init();
            while (true) {
                lcd.lcd_string("RPiSpy         <", lcd.LCD_LINE_1);
                lcd.lcd_string("I2C LCD        <", lcd.LCD_LINE_2);
                Thread.sleep(3000);
                lcd.lcd_string(">         RPiSpy", lcd.LCD_LINE_1);
                lcd.lcd_string(">        I2C LCD", lcd.LCD_LINE_2);
                Thread.sleep(3000);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            try {
                lcd.lcd_byte(0x01, lcd.LCD_CMD);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

Wiem, że kod nie jest ładny, ale ma być przede wszystkim funkcjonalny. Efektem tego kodu jest:
IMG_20170913_123509.jpgIMG_20170913_123512.jpgIMG_20170913_123514.jpg
Gdzie popełniłem błąd?


Bite my shiny metal ass!
Life throws you an error code like that, you don't have the luxury of a ZnVja2luZw== pop-up explanation *Robię projekty studenckie, pisz priv ;) *
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

Bierzesz pod uwagę ze int javie jest signed? Może druga strona oczekuje że jednak unsigned?


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
Burdzi0
  • Rejestracja:prawie 9 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Futurama
  • Postów:887
0

@Shalom: Co w takim wypadku byś zaproponował? long nie mogę użyć, bo metoda oczekuje int. Jak to obejść?


Bite my shiny metal ass!
Life throws you an error code like that, you don't have the luxury of a ZnVja2luZw== pop-up explanation *Robię projekty studenckie, pisz priv ;) *
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
0
Burdzi0 napisał(a):

@Shalom: Co w takim wypadku byś zaproponował? long nie mogę użyć, bo metoda oczekuje int. Jak to obejść?

Nie jestem Shalom, ale mała podpowiedź: "char" jest nieznakowanym 16-bitowym integerem w Javie.

Burdzi0
  • Rejestracja:prawie 9 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Futurama
  • Postów:887
0

Próbowałem zmienić i nic. Wróciłem do kodu i nic. Ewidentnie coś innego wywoływało poprzedni stan. Teraz wygląda na to, że mój kod nie działa wcale :/


Bite my shiny metal ass!
Life throws you an error code like that, you don't have the luxury of a ZnVja2luZw== pop-up explanation *Robię projekty studenckie, pisz priv ;) *
Burdzi0
  • Rejestracja:prawie 9 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Futurama
  • Postów:887
0

Jakieś pomysły? Cokolwiek? Jestem w kropce, a żaden z przykładów w necie nie pomaga...


Bite my shiny metal ass!
Life throws you an error code like that, you don't have the luxury of a ZnVja2luZw== pop-up explanation *Robię projekty studenckie, pisz priv ;) *
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
1

Zrób to metodą "dupa debuging" (po angielsku "tracing").
Dla każdego bajtu który fizycznie wychodzi na urządzenie zapisz czas względny od momentu startu apki (w ms lub ns) i wartość bajtu.
Zrób to po stronie Pythona i Javy.
Porównaj wyniki.
Popraw Jave.

Czyli tutaj - zastąp "dev.write" swoją metodą "lcd_write" i tam umieść "dev.write" oraz tracing.

edytowany 3x, ostatnio: vpiotr
jarekczek
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad 4 lata
  • Lokalizacja:Siemianowice Śląskie
  • Postów:500
1

Dumpy porób z obu programów i porównaj. Np. wszystkie wywołania write_byte.


Przeważnie ignoruję niezarejestrowanych użytkowników.
Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 11 godzin
1

Zamiast patrzeć się w kod w nieskończoność zrób testy jednostkowe.

Kiedyś pracowałem nad komunikacją (przez Ethernet) z czytnikiem kart płatniczych i dzięki testom jednostkowym wykryłem parę błędów w kodzie zanim w ogóle dostałem sprzęt do ręki.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 1x, ostatnio: Wibowit
S9
W sumie to chyba takie testy nie sa łatwe do napisania (gdzie jest komunikacja, operacje IO a nie jakas logika biznesowa)
Wibowit
Wręcz przeciwnie. Wystarczy, że na czas testu jednostkowego podmienię dev.write na listaIntów.add, a na końcu testu porównam wynikową listę z predefiniowaną i już mam podstawowy test. Nieco trudniej by było gdybyśmy sprawdzali też jednocześnie odstępy czasowe, ale tylko nieco. Wtedy można by zrobić listę przechowującą jakiś typ podstawowy np Wrapped mający dwa podtypy WrappedData i WrappedDelay, a potem można porównywać nagrane wartości z predefiniowanymi tak samo jak w wariancie podstawowym. Banalne byłoby też przeniesienie takich testów z Pythona do Javy.
Burdzi0
@Wibowit: Brzmi fajnie, ale z moimi umiejętnościami niemożliwe do stworzenia. Mam sprawdzać czy coś się wyświetla? Mogę to zrobić tylko ręcznie. Wystarczy, że na czas testu jednostkowego podmienię dev.write na listaIntów.add, a na końcu testu porównam wynikową listę z predefiniowaną i już mam podstawowy test. w tym wypadku nie mam czegoś takiego jak lista predefiniowana, brodzę po ciemku w tym momencie, w każdym razie dzięki za pomysł ;)
Wibowit
Skoro w Pythonie działa dobrze, to nagraj listy do testów w Pythonie, przenieś testy do Javy i odpal je.
vpiotr
@Burdzi0: To nie byłoby takie trudne. Jakbyś zrobił taką samą rejestrację (tracing) w obu językach to w Pythonie zapisujesz ten trace do pliku, w Javie go wczytujesz i porównujesz z tym co Ci wyszło w trakcie testu w Javie. Jak zrobisz plik CSV to będzie to w miarę proste (liczba-porządkowa, adres, wartość). Tam masz trochę tych przeliczanek tych bajtów. Poza tym na początku testuj na prostszych danych - np. jeden znak.
0

Jak nie poradzisz sobie z tym, to zrób niskopoziomową obsługę w c/c++ na pewno będzie więcej przykładów, opakuj to w jni native, a logikę napisz w javie.

Burdzi0
  • Rejestracja:prawie 9 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Futurama
  • Postów:887
2

Matkomoja działa :D
2 tygodnie chrzanienia się:

  • ze sposobem połączenia
  • ze sposobem debugowania
  • z różnymi znaleźnymi kodami
    i wreszcie działa :D

Problem polegał na zmianie:

Kopiuj
dev.write(I2C_ADDR, (byte) bits_high);

na:

Kopiuj
dev.write(LCD_LINE_1, (byte) bits_high);

Cały przykładowy kod wygląda teraz tak:

Kopiuj
import com.pi4j.io.i2c.I2CBus;
import com.pi4j.io.i2c.I2CDevice;
import com.pi4j.io.i2c.I2CFactory;
import org.apache.log4j.Logger;

import java.io.IOException;
 
public class LCDController {
 
    int I2C_ADDR = 0x3f;
    int LCD_WIDTH = 16;
 
    int LCD_CHR = 1;
    int LCD_CMD = 0;
 
    int LCD_LINE_1 = 0x80;
    int LCD_LINE_2 = 0xC0;
 
    int LCD_BACKLIGHT_ON = 0x08;
    int LCD_BACKLIGHT_OFF = 0x00;
 
    int ENABLE = 0b00000100;
 
    int E_PULSE = 5;
    int E_DELAY = 5;
 
    I2CBus bus;
    I2CDevice dev;

    public LCDController() throws IOException, InterruptedException, I2CFactory.UnsupportedBusNumberException {
        bus = I2CFactory.getInstance(I2CBus.BUS_1);
        dev = bus.getDevice(I2C_ADDR);
        init();
    }
 
    void init() throws InterruptedException, IOException {
        lcd_byte(0x33, LCD_CMD);
        lcd_byte(0x32, LCD_CMD);
        lcd_byte(0x06, LCD_CMD);
        lcd_byte(0x0C, LCD_CMD);
        lcd_byte(0x28, LCD_CMD);
        lcd_byte(0x01, LCD_CMD);
        Thread.sleep(E_DELAY);
    }
 
    void lcd_byte(int bits, int mode) throws IOException, InterruptedException {
        int bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT_ON;
        int bits_low = mode | ((bits << 4) & 0xF0) | LCD_BACKLIGHT_ON;

        dev.write(LCD_LINE_1, (byte) bits_high);
        lcd_toggle_enable((byte) bits_high);
 
        dev.write(LCD_LINE_1, (byte) bits_low);
        lcd_toggle_enable((byte) bits_low);
    }
 
    void lcd_toggle_enable(byte bits) throws InterruptedException, IOException {
        dev.write(LCD_LINE_1, (byte) (bits | ENABLE));
        dev.write(LCD_LINE_1, (byte) (bits & ~ENABLE));
    }
 
    void lcd_string(String message, int line) throws IOException, InterruptedException {
        lcd_byte(line, LCD_CMD);
        for (int i = 0; i < LCD_WIDTH; i++) {
            lcd_byte(message.charAt(i), LCD_CHR);
        }
    }
 
    public static void main(String[] args) {
        LCDController lcd = null;
        try {
            lcd = new LCDController();
            lcd.init();
            lcd.lcd_string("4programmers.net", lcd.LCD_LINE_1);
            lcd.lcd_string("     Burdzi0    ", lcd.LCD_LINE_2);
            Thread.sleep(2000);
            lcd.lcd_string("Bardzo  dziekuje", lcd.LCD_LINE_1);
            lcd.lcd_string("  za  pomoc  :D ", lcd.LCD_LINE_2);
            Thread.sleep(2000);
            lcd.lcd_string("     Shalom     ", lcd.LCD_LINE_1);
            lcd.lcd_string("     vpiotr     ", lcd.LCD_LINE_2);
            Thread.sleep(2000);
            lcd.lcd_string("    jarekczek   ", lcd.LCD_LINE_1);
            lcd.lcd_string("     Wibowit    ", lcd.LCD_LINE_2);
            Thread.sleep(2000);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (I2CFactory.UnsupportedBusNumberException e) {
            e.printStackTrace();
        } finally {
            try {
                lcd.lcd_byte(0x01, lcd.LCD_CMD);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
 
}

Przykład podziękowań w zipie ;)
VID_20170913_184414.mp4.zip


Bite my shiny metal ass!
Life throws you an error code like that, you don't have the luxury of a ZnVja2luZw== pop-up explanation *Robię projekty studenckie, pisz priv ;) *
edytowany 1x, ostatnio: Burdzi0
Zobacz pozostałe 2 komentarze
vpiotr
A tak ogólnie to zazdraszczam projektu, bo nie dość że Raspberry Pi to jeszcze kawałek elektroniki.
Burdzi0
@vpiotr: W planach mam napisanie mini gry 2d i zrobienie kontrolerów na bazie GPIO ;)
Burdzi0
@vpiotr: Swoją drogą to nie aż tak drogie, zwłaszcza, że nie trzeba a kupować wszystkiego naraz
vpiotr
@Burdzi0: no tak, ale raczej mi brakuje czasu niż pieniędzy na to.
Burdzi0
@vpiotr: Rozumiem, mam ciągle wakacje i nie mogę się przestawić na to, że inni ni, wybacz :|
Burdzi0
  • Rejestracja:prawie 9 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Futurama
  • Postów:887
0
Kopiuj
    void lcd_byte(int bits, int mode) throws IOException, InterruptedException {
        int bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT_ON;
        int bits_low = mode | ((bits << 4) & 0xF0) | LCD_BACKLIGHT_ON;

        dev.write((byte) bits_high);
        lcd_toggle_enable((byte) bits_high);
 
        dev.write((byte) bits_low);
        lcd_toggle_enable((byte) bits_low);
    }
 
    void lcd_toggle_enable(byte bits) throws InterruptedException, IOException {
        dev.write((byte) (bits | ENABLE));
        dev.write((byte) (bits & ~ENABLE));
    }

Taka zmiana kodu pozwala na przyspieszenie zmiany tekstu - nie ma opóźnienia


Bite my shiny metal ass!
Life throws you an error code like that, you don't have the luxury of a ZnVja2luZw== pop-up explanation *Robię projekty studenckie, pisz priv ;) *
jarekczek
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad 4 lata
  • Lokalizacja:Siemianowice Śląskie
  • Postów:500
0

To można fajnie rozpracować bez Pi. Na początku zamiast import wpisać:

Kopiuj
class smbus:
  def __init__(self):
    pass
  @staticmethod
  def SMBus(i):
    return smbus()
  def write_byte(self, a, b):
    print a, b

class time:
  def __init__(self):
    pass
  @staticmethod
  def sleep(i):
    pass

i jeszcze jeden break w while True

A Pythona też trzeba umieć bo używa go Oracle w Oracle'u. :)
Edit: Nie, nie w Oracle'u. W WebLogicu. Web Logic Scripting Tool.


Przeważnie ignoruję niezarejestrowanych użytkowników.
edytowany 1x, ostatnio: jarekczek
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)