/******************************************************************************* * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package hr.fer.zemris.vhdllab.applets.simulations; import java.awt.Graphics; /** * Crtanje valnog oblika * * @author Boris Ozegovic */ class WaveForm { /** Svi oblici koji su jednaki nuli pripadaju grupi nula */ private static final byte ZERO_SHAPES = 1; /** Svi oblici koji su jedinic pripadaju grupi jedinica */ private static final byte ONE_SHAPES = 2; /** Svi oblici koji predstavljaju vektor ili su neinicijalizirani */ private static final byte HEXAGON_SHAPES = 3; /** Valni oblik koji ima visoku impedanciju */ private static final byte HIGH_IMPEDANCE = 4; /** Nepoznata vrijednost */ private static final byte UNKNOWN = 5; /** Valni oblici U, H, L, W */ private static final byte OTHERS = 6; /** Trajanje u pikselima */ private int[] durationsInPixels; /** Pocetna tocka crtanja valnog oblika */ private static final int WAVE_START_POINT_IN_PIXELS = 0; /** Duljina ekrana u pikselima */ private int screenSizeInPixels; /** Vrijednosti valnih oblika */ private String[] values; /** * Tocka od koje pocinje iscrtavanje. Valni oblici se ne iscrtavaju * kompletno vec u ovisnosti u trenutnom offsetu */ private int screenStartPointInPixels; /** Iscrtavanje zavrsava ovisno u velicini ekrana, tj. o rezoluciji */ private int screenEndPointInPixels; /** Svi valni oblici */ private Shape[] shapes; /** * Objekt koji cuva promjene svih signala */ SignalChangeTracker signalChangeTracker; /** * Indeks signala. Ako je cisti skalar ili vektor, bit ce oblika "broj"; npr. "3"; * ako je druga komponenta vektora koji je na poziciji tri, bit ce "3_2". */ String signalIndex; /** * Kljuc za dohvat podataka iz signalChangeTracker-a. */ String signalKey; long[] transitionPoints; long maxUnscaledSimulationTime; /** * Constructor * * @param values polje vrijednosti za svaki signal * @param durationsInPixels vrijeme trajanja u pikselima * @param signalChangeTracker sve promjene po svim signalima * @param signalIndex identifikator ovog konkretnog signala */ public WaveForm (String[] values, int[] durationsInPixels, Shape[] shapes, SignalChangeTracker signalChangeTracker, String signalIndex, long[] transitionPoints, long maxUnscaledSimulationTime) { this.values = values; this.durationsInPixels = durationsInPixels; this.shapes = shapes; this.signalKey = "!sig:"+signalIndex; this.transitionPoints = transitionPoints; this.signalChangeTracker = signalChangeTracker; this.maxUnscaledSimulationTime = maxUnscaledSimulationTime; } /** * Metoda koja odlucuje koji dio valnih oblika ce se iscrtati u ovisnosti u * screenEndPointInPixels * * @param g Graphics * @param yAxis na koji dio y-osi se crta * @param offsetXAxis ovisno o offsetu crta dio ekrana * @param durationsInPixels trajanje dobivena iz skale * @param waveEndPointInPixels dobivenu iz skale */ public void drawWave (Graphics g, int screenWidth, int yAxis, int offsetXAxis, int[] durationsInPixels, int waveEndPointInPixels) { /* * postoji sadasnja i sljedeca grupa, jer postoji vise vrsta oblika, * npr. jedinica koja slijedi iza nule drugacije je od jednice koja * slijedi iza vektora */ byte previousGroup = 0; byte presentGroup = 0; this.durationsInPixels = durationsInPixels; screenStartPointInPixels = offsetXAxis; screenSizeInPixels = screenWidth + 200; screenEndPointInPixels = screenStartPointInPixels + screenSizeInPixels; int x1 = WAVE_START_POINT_IN_PIXELS; int y1 = yAxis; int x2; /* * samo ako nije jednak nuli screenStartPointInPixels je umanjen za * jedan zato da ne iscrta na ekranu pocetak signala, vec treba ostaviti * dojam da signal traje od prije */ if (screenStartPointInPixels != WAVE_START_POINT_IN_PIXELS) { screenStartPointInPixels -= 1 ; } SignalChangeEvent[] changes = signalChangeTracker.get(signalKey); if(changes==null) { System.out.println("Error: nemam podatke za iscrtati signal ["+signalKey+"]."); return; } int currTimeIndex = 0; for(int changeIndex = 0; changeIndex < changes.length; changeIndex++) { SignalChangeEvent ev = changes[changeIndex]; long endTime = changeIndex==changes.length-1 ? maxUnscaledSimulationTime : changes[changeIndex+1].getTimestamp(); x2 = x1; while(currTimeIndex<transitionPoints.length-1 && transitionPoints[currTimeIndex]<endTime) { x2 += this.durationsInPixels[currTimeIndex]; currTimeIndex++; } String string = ev.getValue(); if (string.equals("0")) { presentGroup = ZERO_SHAPES; } else if (string.equals("1")) { presentGroup = ONE_SHAPES; } else if (string.toUpperCase().equals("Z")) { presentGroup = HIGH_IMPEDANCE; } else if (string.toUpperCase().equals("X")) { presentGroup = UNKNOWN; } else if (string.toUpperCase().equals("U") || string.toUpperCase().equals("H") || string.toUpperCase().equals("L") || string.toUpperCase().equals("W")) { presentGroup = OTHERS; } else { presentGroup = HEXAGON_SHAPES; } /* * ako je x2 manji od pocetka na kojem treba iscrtati jednostavno * ignorira te signale */ if (x2 > screenStartPointInPixels) { /* * ako neki signal ide preko ekrana pocinje njegovo iscrtavanje, * medutim, treba ograniciti jer signal moze trajati po tisucu * piksela, a moze biti i i manji od screenEndPointInPixels */ if (x2 < screenEndPointInPixels) { draw(g, string, previousGroup, presentGroup, screenStartPointInPixels - offsetXAxis, y1, x2 - offsetXAxis); } else { /* ako je screenEndPointInPixels jednak tocno kraju skale */ if (screenEndPointInPixels == waveEndPointInPixels) { draw(g, string, previousGroup, presentGroup, screenStartPointInPixels - offsetXAxis, y1, screenEndPointInPixels - offsetXAxis); } /* * inace crta s jednim prosirenim pikselom koji daje dojam * da signal ne zavrsava, vec se nastavlja */ else { draw(g, string, previousGroup, presentGroup, screenStartPointInPixels - offsetXAxis, y1, screenEndPointInPixels + 1 - offsetXAxis); break; } } screenStartPointInPixels = x2; } previousGroup = presentGroup; x1 = x2; } /* * int i = 0; /* za svaku pojedinu vrijednost signala *-/ for (String string : values) { x2 = x1 + this.durationsInPixels[i]; if (this.durationsInPixels[i] == 0) { i++; continue; } if (string.equals("0")) { presentGroup = ZERO_SHAPES; } else if (string.equals("1")) { presentGroup = ONE_SHAPES; } else if (string.toUpperCase().equals("Z")) { presentGroup = HIGH_IMPEDANCE; } else if (string.toUpperCase().equals("X")) { presentGroup = UNKNOWN; } else if (string.toUpperCase().equals("U") || string.toUpperCase().equals("H") || string.toUpperCase().equals("L") || string.toUpperCase().equals("W")) { presentGroup = OTHERS; } else { presentGroup = HEXAGON_SHAPES; } /* * ako je x2 manji od pocetka na kojem treba iscrtati jednostavno * ignorira te signale *-/ if (x2 > screenStartPointInPixels) { /* * ako neki signal ide preko ekrana pocinje njegovo iscrtavanje, * medutim, treba ograniciti jer signalmoze trajati po tisucu * piksela, a moze biti i i manji od screenEndPointInPixels *-/ if (x2 < screenEndPointInPixels) { draw(g, string, previousGroup, presentGroup, screenStartPointInPixels - offsetXAxis, y1, x2 - offsetXAxis); } else { /* ako je screenEndPointInPixels jednak tocno kraju skale *-/ if (screenEndPointInPixels == waveEndPointInPixels) { draw(g, string, previousGroup, presentGroup, screenStartPointInPixels - offsetXAxis, y1, screenEndPointInPixels - offsetXAxis); } /* * inace crta s jednim prosirenim pikselom koji daje dojam * da signal ne zavrsava, vec se nastavlja *-/ else { draw(g, string, previousGroup, presentGroup, screenStartPointInPixels - offsetXAxis, y1, screenEndPointInPixels + 1 - offsetXAxis); break; } } screenStartPointInPixels = x2; } previousGroup = presentGroup; x1 = x2; i++; } * */ } /** * Metoda za samo iscrtavanje * * @param g Graphics * @param string vrijednost signala * @param previousGroup prijasnja grupa * @param presentGroup sadasnja grupa * @param x1 vrijednost od koje pocinje crtanje * @param y1 vrijednost po y-osi * @param x2 trajanje ove vrijednosti signala u pikselima */ public void draw (Graphics g, String string, int previousGroup, int presentGroup, int x1, int y1, int x2) { switch (previousGroup) { case ZERO_SHAPES : switch (presentGroup) { case ZERO_SHAPES : shapes[0].draw(g, x1, y1, x2); break; case ONE_SHAPES : shapes[4].draw(g, x1, y1, x2); break; case HEXAGON_SHAPES : shapes[8].draw(g, x1, y1, x2); shapes[8].putLabel(g, string, x1, y1, x2); break; case HIGH_IMPEDANCE : shapes[10].draw(g, x1, y1, x2); shapes[10].putLabel(g, string, x1, y1, x2); break; case OTHERS : shapes[14].draw(g, x1, y1, x2); shapes[14].putLabel(g, string, x1, y1, x2); break; case UNKNOWN : shapes[12].draw(g, x1, y1, x2); break; } break; case ONE_SHAPES : switch (presentGroup) { case ZERO_SHAPES : shapes[1].draw(g, x1, y1, x2); break; case ONE_SHAPES : shapes[3].draw(g, x1, y1, x2); break; case HEXAGON_SHAPES : shapes[7].draw(g, x1, y1, x2); shapes[7].putLabel(g, string, x1, y1, x2); break; case HIGH_IMPEDANCE : shapes[11].draw(g, x1, y1, x2); shapes[11].putLabel(g, string, x1, y1, x2); break; case OTHERS : shapes[15].draw(g, x1, y1, x2); shapes[15].putLabel(g, string, x1, y1, x2); break; case UNKNOWN : shapes[12].draw(g, x1, y1, x2); break; } break; case HEXAGON_SHAPES : switch (presentGroup) { case ZERO_SHAPES : shapes[2].draw(g, x1, y1, x2); break; case ONE_SHAPES : shapes[5].draw(g, x1, y1, x2); break; case HEXAGON_SHAPES : shapes[6].draw(g, x1, y1, x2); shapes[6].putLabel(g, string, x1, y1, x2); break; case HIGH_IMPEDANCE : shapes[9].draw(g, x1, y1, x2); shapes[9].putLabel(g, string, x1, y1, x2); break; case OTHERS : shapes[13].draw(g, x1, y1, x2); shapes[13].putLabel(g, string, x1, y1, x2); break; case UNKNOWN : shapes[12].draw(g, x1, y1, x2); break; } break; case HIGH_IMPEDANCE : switch (presentGroup) { case ZERO_SHAPES : shapes[2].draw(g, x1, y1, x2); break; case ONE_SHAPES : shapes[5].draw(g, x1, y1, x2); break; case HEXAGON_SHAPES : shapes[6].draw(g, x1, y1, x2); shapes[6].putLabel(g, string, x1, y1, x2); break; case HIGH_IMPEDANCE : shapes[9].draw(g, x1, y1, x2); break; case OTHERS : shapes[13].draw(g, x1, y1, x2); shapes[13].putLabel(g, string, x1, y1, x2); break; case UNKNOWN : shapes[12].draw(g, x1, y1, x2); break; } break; case OTHERS : switch (presentGroup) { case ZERO_SHAPES : shapes[2].draw(g, x1, y1, x2); break; case ONE_SHAPES : shapes[5].draw(g, x1, y1, x2); break; case HEXAGON_SHAPES : shapes[6].draw(g, x1, y1, x2); shapes[6].putLabel(g, string, x1, y1, x2); break; case HIGH_IMPEDANCE : shapes[9].draw(g, x1, y1, x2); shapes[9].putLabel(g, string, x1, y1, x2); break; case OTHERS : shapes[13].draw(g, x1, y1, x2); break; case UNKNOWN : shapes[12].draw(g, x1, y1, x2); break; } break; case UNKNOWN : switch (presentGroup) { case ZERO_SHAPES : shapes[0].draw(g, x1, y1, x2); break; case ONE_SHAPES : shapes[3].draw(g, x1, y1, x2); break; case HEXAGON_SHAPES : shapes[6].draw(g, x1, y1, x2); shapes[6].putLabel(g, string, x1, y1, x2); break; case HIGH_IMPEDANCE : shapes[9].draw(g, x1, y1, x2); shapes[9].putLabel(g, string, x1, y1, x2); break; case OTHERS : shapes[13].draw(g, x1, y1, x2); shapes[13].putLabel(g, string, x1, y1, x2); break; case UNKNOWN : shapes[12].draw(g, x1, y1, x2); break; } break; default : switch (presentGroup) { case ZERO_SHAPES : shapes[0].draw(g, x1, y1, x2); break; case ONE_SHAPES : shapes[4].draw(g, x1, y1, x2); break; case HEXAGON_SHAPES : shapes[6].draw(g, x1, y1, x2); shapes[6].putLabel(g, string, x1, y1, x2); break; case HIGH_IMPEDANCE : shapes[9].draw(g, x1, y1, x2); shapes[9].putLabel(g, string, x1, y1, x2); break; case OTHERS : shapes[13].draw(g, x1, y1, x2); shapes[13].putLabel(g, string, x1, y1, x2); break; case UNKNOWN : shapes[12].draw(g, x1, y1, x2); break; } } } /** * Metoda postavlja nove vrijednosti * * @param values Vrijednosti po signalima */ public void setSignalValues (String[] values) { this.values = values; } }